wince6.0下kernelIOctl()的調用過程分析
一初始化部分:
1.LoaderInit() //:private/winceos/coreos/nk/kernel/loader.c
{
.........
// load OAL ioctl dll; this is valid only if image has coredll
LockLoader (g_pprcNK);
if (pMod = LoadOneLibrary (OALIOCTL_DLL, 0, LOAD_LIBRARY_IN_KERNEL)) {
pMod = (*g_pfnDoImports) (pMod);
VERIFY (g_pfnOalIoctl = (PFN_Ioctl) GetProcAddressA ((HMODULE)pMod, OALIOCTL_DLL_IOCONTROL));
/*************************************************************************************************
上條語句是將OALIOCTL_DLL文件裏的IOCONTROL函數的地址
賦(D:/WINCE600/PLATFORM/seeker2/SRC/COMMON/OALIOCTL/oalioctl.cpp裏的IOControl)給g_pfnOalIoctl
*************************************************************************************************/
VERIFY (((PFN_DllMain) pMod->startip) ((HMODULE)pMod, DLL_PROCESS_ATTACH, (DWORD) &(OEMIoControl)));
/**************************************************************************************************
上條語句是將調用OALIOCTL_DLL庫的DLLmain函數,由此對該庫的全局變量初始化:
****************************************************************************************************/
}
..........
}
2.DllMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls((HINSTANCE)hDll);
g_pfnExtOALIoctl = (PFN_Ioctl) lpReserved;//該庫的全局變量初始化,也就是OEMIoControl函數地址
break;
case DLL_PROCESS_DETACH:
default:
break;
}
return TRUE;
}
二.執行過程:
kernelIOcontrol() //EXTkernelIoctl()函數爲其內核中的實現函數,
|
|
|
IOConTrol() //seeker2/src/common/oalioctl/oalioctl.cpp
|
|
|
OEMIOControl() //platform/common/src/common/ioctl/ioctl.c
|
|
|
ioctrolFUN //自己定義的ioctro函數,在g_oalIoCtlTable[]添加該函數與其ioctrol宏的映射。
1.EXTKernelIoctl的實現
static BOOL EXTKernelIoctl (DWORD dwIoControlCode, LPVOID lpInBuf, DWORD nInBufSize, LPVOID lpOutBuf, DWORD nOutBufSize, LPDWORD lpBytesReturned)
{
BOOL fRet = FALSE;
PPROCESS pprc = SwitchActiveProcess (g_pprcNK);
switch (dwIoControlCode) {
// KITL ioctls
case IOCTL_EDBG_REGISTER_CLIENT:
case IOCTL_EDBG_DEREGISTER_CLIENT:
case IOCTL_EDBG_REGISTER_DFLT_CLIENT:
case IOCTL_EDBG_SEND:
case IOCTL_EDBG_RECV:
case IOCTL_EDBG_SET_DEBUG:
fRet = (g_pfnExtKITLIoctl) ?
(*g_pfnExtKITLIoctl) (dwIoControlCode, lpInBuf, nInBufSize, lpOutBuf, nOutBufSize, lpBytesReturned)
: FALSE;
break;
default:
// OEM ioctls
fRet = (g_pfnOalIoctl) ?
(*g_pfnOalIoctl)(dwIoControlCode, lpInBuf, nInBufSize, lpOutBuf, nOutBufSize, lpBytesReturned)
: FALSE;
//調用OALIOCTL_DLL庫IOControl函數
break;
}
SwitchActiveProcess (pprc);
return fRet;
}
2.IOControl()的實現
EXTERN_C
BOOL
IOControl(
DWORD dwIoControlCode,
PBYTE pInBuf,
DWORD nInBufSize,
PBYTE pOutBuf,
DWORD nOutBufSize,
PDWORD pBytesReturned
)
{
BOOL fRet = FALSE;
//
// By default the following ioctls are supported for user mode threads.
// If a new ioctl is being added to this list, make sure the corresponding
// data associated with that ioctl is marshalled properly to the OAL
// ioctl implementation. In normal cases, one doesn't need any
// marshaling as first level user specified buffers are already validated
// by kernel that:
// -- the buffers are within the user process space
// Check out IsValidUsrPtr() function in vmlayout.h for details on kernel
// validation of user specified buffers. Kernel doesn't validate that the
// buffers are accessible; it only checks that the buffer start and end
// addresses are within the user process space.
//
switch (dwIoControlCode) {
case IOCTL_POCKETSTOREII_CMD:
case IOCTL_HAL_POSTINIT:
// request is to service the ioctl - forward the call to OAL code
// OAL code will set the last error if there is a failure
SetLastError(ERROR_NOT_SUPPORTED); //注意這裏是我們自己項目BSP中該函數的代碼,主要爲了簡化ioctl,所以和D:/WINCE600/PUBLIC/COMMON/OAK/OALIOCTL/oalioctl.cpp代碼,剛好相反,
//但這樣做,比較方便我們添加ioctrol,但給安全,不推薦。開個的權限太大了。呵呵
break;
default:
fRet = (*g_pfnExtOALIoctl)(dwIoControlCode, pInBuf, nInBufSize, pOutBuf, nOutBufSize, pBytesReturned);
break;
}
return fRet;
3.OEMIOControl()的實現 ,D:/WINCE600/PLATFORM/COMMON/SRC/COMMON/IOCTL/ioctl.c
//這個函數去逐個查找你所定義的ioctrol的宏和對應的處理函數,然後去執行。
// Function: OEMIoControl
//
// The function is called by kernel a device driver or application calls
// KernelIoControl. The system is fully preemtible when this function is
// called. The kernel does no processing of this API. It is provided to
// allow an OEM device driver to communicate with kernel mode code.
//
BOOL OEMIoControl(
DWORD code, VOID *pInBuffer, DWORD inSize, VOID *pOutBuffer, DWORD outSize,
DWORD *pOutSize
) {
BOOL rc = FALSE;
UINT32 i;
OALMSG(OAL_IOCTL&&OAL_FUNC, (
L"+OEMIoControl(0x%x, 0x%x, %d, 0x%x, %d, 0x%x)/r/n",
code, pInBuffer, inSize, pOutBuffer, outSize, pOutSize
));
//Initialize g_ioctlState.cs when IOCTL_HAL_POSTINIT is called. By this time,
//the kernel is up and ready to handle the critical section initialization.
if (!g_ioctlState.postInit && code == IOCTL_HAL_POSTINIT) {
// Initialize critical section
InitializeCriticalSection(&g_ioctlState.cs);
g_ioctlState.postInit = TRUE;
}
// Search the IOCTL table for the requested code.
for (i = 0; g_oalIoCtlTable[i].pfnHandler != NULL; i++) {
if (g_oalIoCtlTable[i].code == code) break;
}
// Indicate unsupported code
if (g_oalIoCtlTable[i].pfnHandler == NULL) {
NKSetLastError(ERROR_NOT_SUPPORTED);
OALMSG(OAL_IOCTL, (
L"OEMIoControl: Unsupported Code 0x%x - device 0x%04x func %d/r/n",
code, code >> 16, (code >> 2)&0x0FFF
));
goto cleanUp;
}
// Take critical section if required (after postinit & no flag)
if (
g_ioctlState.postInit &&
(g_oalIoCtlTable[i].flags & OAL_IOCTL_FLAG_NOCS) == 0
) {
// Take critical section
EnterCriticalSection(&g_ioctlState.cs);
}
// Execute the handler
rc = g_oalIoCtlTable[i].pfnHandler(
code, pInBuffer, inSize, pOutBuffer, outSize, pOutSize
);
// Release critical section if it was taken above
if (
g_ioctlState.postInit &&
(g_oalIoCtlTable[i].flags & OAL_IOCTL_FLAG_NOCS) == 0
) {
// Release critical section
LeaveCriticalSection(&g_ioctlState.cs);
}
cleanUp:
OALMSG(OAL_IOCTL&&OAL_FUNC, (L"-OEMIoControl(rc = %d)/r/n", rc ));
return rc;
}
http://blog.csdn.net/bbw2008/archive/2010/03/03/5342837.aspx
如果有什麼理解錯誤的地方,歡迎各位看客不吝賜教。在此謝謝了。
歡迎轉載,轉載請指明源出處。謝謝