Wince6.0 添加IOCTL

来源:互联网 发布:网络借贷的风险 编辑:程序博客网 时间:2024/05/22 11:46

在WinCE5.0中,应用程序和驱动程序可以通过调用KernelIoControl(..)函数来访问WinCE内核,导致调用OEMIoControl函数,这样应用程序和驱动程序就可以访问到OAL中的资源了。但在WinCE6.0中,提供了更好的安全性,应用程序能够访问OEMIoControl中的case受到了限制,只有下面的这些case是可以让应用程序访问的:

IOCTL_HAL_GET_CACHE_INFO
IOCTL_HAL_GET_DEVICE_INFO
IOCTL_HAL_GET_DEVICEID
IOCTL_HAL_GET_UUID
IOCTL_PROCESSOR_INFORMATION
 

如果用户在应用程序中试图访问其他的case,肯定会返回失败的。在WinCE6.0中,驱动程序还像以前一样,可以访问OEMIoControl中的任何case。也许有人会问,那么我们如何让应用程序也访问到一些case呢?既然微软已经公开了这些代码,我们就可以修改了,哈哈!以下以我添加用户设置UUID为例,详细讲解如何添加IOCTL了:

1. D:/WINCE600/PUBLIC/COMMON/OAK/INC/pkfuncs.h 添加要设置的IOCTL:

#define IOCTL_SET_KERNEL_COMM_DEV               CTL_CODE(FILE_DEVICE_HAL, 12, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_HAL_GET_UUID                      CTL_CODE(FILE_DEVICE_HAL, 13, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_HAL_SET_UUID                      CTL_CODE(FILE_DEVICE_HAL, 3000, METHOD_BUFFERED, FILE_ANY_ACCESS) //Hugo
 

2.  D:/WINCE600/PUBLIC/COMMON/OAK/OALIOCTL/oalioctl.cpp 添加我们定义的IOCTL:

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_HAL_GET_CACHE_INFO:

        case IOCTL_HAL_GET_DEVICE_INFO:

        case IOCTL_HAL_GET_DEVICEID:

        case IOCTL_HAL_GET_UUID:

        case IOCTL_HAL_SET_UUID: //Hugo

        case IOCTL_PROCESSOR_INFORMATION:

            // request is to service the ioctl - forward the call to OAL code

            // OAL code will set the last error if there is a failure

            fRet = (*g_pfnExtOALIoctl)(dwIoControlCode, pInBuf, nInBufSize, pOutBuf, nOutBufSize, pBytesReturned);

        break;

        default:

            SetLastError(ERROR_NOT_SUPPORTED);

        break;

    }

    return fRet;

}

这些IOCTL 都是用户可以调用的;

3. 到OAL 层的oalioctl.cpp 里添加我们定义的IOCTL :

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_HAL_GET_CACHE_INFO:
        case IOCTL_HAL_GET_DEVICE_INFO:
        case IOCTL_HAL_GET_DEVICEID:
        case IOCTL_HAL_GET_UUID:
           
        case IOCTL_HAL_SET_UUID: //Hugo
                   
        case IOCTL_PROCESSOR_INFORMATION:
        case IOCTL_SET_RTC_WAKEUP_TIME:
        case IOCTL_HAL_GET_SYS_CLOCK_INFO:
        case IOCTL_HAL_GET_BTMACADDR:
        case IOCTL_HAL_GET_CUSTOMERNUM:
        case IOCTL_HAL_GET_FURTURENUM:
        case IOCTL_HAL_GET_OEMVALUE:
                   
    case IOCTL_HAL_GET_RTC:
        case IOCTL_HAL_GET_DBG_DATA_BUF: 
                   
           case IOCTL_HAL_GET_REG_CLK_EN:
                                      
        case IOCTL_HAL_REBOOT:
            // request is to service the ioctl - forward the call to OAL code
            // OAL code will set the last error if there is a failure
            fRet = (*g_pfnExtOALIoctl)(dwIoControlCode, pInBuf, nInBufSize, pOutBuf, nOutBufSize, pBytesReturned);
            break;
        default:
            SetLastError(ERROR_NOT_SUPPORTED);
            break;
    }
    return fRet;
}


这些IOCTL 都是驱动可以调用的;

4. D:/WINCE600/PLATFORM/COMMON/SRC/INC/oal_ioctl_tab.h 添加 IOCTL 对应的函数:

{ IOCTL_HAL_GET_CACHE_INFO,                 0,  OALIoCtlHalGetCacheInfo     },
{ IOCTL_HAL_GET_DEVICEID,                   0,  OALIoCtlHalGetDeviceId      },
{ IOCTL_HAL_GET_DEVICE_INFO,                0,  OALIoCtlHalGetDeviceInfo    },
{ IOCTL_HAL_GET_UUID,                       0,  OALIoCtlHalGetUUID          },
{ IOCTL_HAL_SET_UUID,                       0,  OALIoCtlHalSetUUID          }, //Hugo


5. D:/WINCE600/PLATFORM/COMMON/SRC/INC/oal_ioctl.h 添加函数声明:

BOOL OALIoCtlHalReboot(UINT32, VOID*, UINT32, VOID*, UINT32, UINT32*);
BOOL OALIoCtlHalGetUUID (UINT32, VOID *, UINT32, VOID *, UINT32, UINT32 *);
BOOL OALIoCtlHalSetUUID (UINT32, VOID *, UINT32, VOID *, UINT32, UINT32 *); //Hugo
BOOL OALIoCtlHalUpdateMode(UINT32, VOID *, UINT32, VOID *, UINT32, UINT32 *);


6.  D:/WINCE600/PLATFORM/COMMON/SRC/COMMON/IOCTL/uuid.c 添加函数定义:

//------------------------------------------------------------------------------
//
//  Function:  OALIoCtlHalSetUUID
//
//  Implements the IOCTL_HAL_SET_UUID handler. This function fills in a
//  GUID structure.
//
BOOL OALIoCtlHalSetUUID (
                            UINT32 code,
                            VOID *pInpBuffer,
                            UINT32 inpSize,
                            VOID *pOutBuffer,
                            UINT32 outSize,
                            UINT32 *pOutSize
                        )
{
    BOOL rc = FALSE;
    static const GUID guidPattern = {0x600cc7d0, 0xde3a, 0x4713, {
        0xa5, 0xb0, 0x56, 0xe, 0x6c, 0x36, 0x4e, 0xde
    }};
    GUID *pUuid;   
    UINT32 length;
   
    RETAILMSG(1, (_T("Hugo warn:Set the UUID! /r/n")));
    if (NULL == pInpBuffer || inpSize < sizeof(GUID))
    {
        NKSetLastError(ERROR_INSUFFICIENT_BUFFER);
        OALMSG(OAL_WARN, (L"WARN: OALIoCtlHalSetUUID: Buffer too small/r/n"));
        goto cleanUp;
    }
   
    //Does the BSP UUID exist?
    pUuid = OALArgsQuery(OAL_ARGS_QUERY_UUID);
    if (NULL == pUuid)
    {
        RETAILMSG(1, (_T("Hugo Error:BSP UUID doesn't exit! /r/n")));
        goto cleanUp;
    }
    else
    {
        RETAILMSG(1, (_T("Hugo BSP UUID exit, now change it! /r/n")));
        length = sizeof(GUID);
        memcpy(pUuid, pInpBuffer, length);
    }
   
    //Done
    rc = TRUE;
   
cleanUp:
    return rc;
}

OK, 到了这里,rebuild 一下我们的os image 就可以在应用层调用KernelIoControl(..) 设置UUID了,so easy? ^_^!!!

原创粉丝点击