Wince6.0 添加IOCTL
作者:hugohong
在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;
}
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
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 *);
//------------------------------------------------------------------------------
//
// 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? ^_^!!! |