深入剖析wince6.0下kernelIOctl()的調用過程分析

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

如果有什麼理解錯誤的地方,歡迎各位看客不吝賜教。在此謝謝了。

歡迎轉載,轉載請指明源出處。謝謝

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章