WinCE6下的kernelIoControl可不是谁都可以调的。
这个可能很多人曾经知道,但是老是忘记,比如我,哈哈。
kerneliocontrol以前在CE5下面耍惯了,用这个接口,AP简直可以无法无天啊,动不动就reset你,哼!who怕who(AP不要 kernelicontrol还是可以无法无天,fullkernel啊,哈哈)
最近加了一个CE6下的kerneliocontrol,这种事情不晓得做过多少啦,所以信手拈来。
1.加IOCTL的code定义
2.加ioctl_tab.h里面的table里面code和function的关联
3.加ioctl.c里面function的实现。
4.在AP里面调用kerneliocontrol,参数是code,试图访问这个function
结果发现,AP每次调用kerneliocontrol都是fail,但是参数全部正确啊,晕。
NND,毛了,在function里面加了一堆debug信息,重新出image,哼看你出不出来!
结果发现,压根没进function。
晕again!第一反应是哪里没有加全或者有代码修改了但是build不到位。
check了n遍,还是不行,开始怀疑自己老年痴呆了!?
迷茫中突然想到CE6之前不是有篇文章说过,AP不能随便调用kerneliocontrol的。
逐翻出此文。发现果然有门道在其中,但是那篇文章不够详细,没有告诉我怎么才能改变权限。
翻了翻BSP(CSP),果然找到真的有那么一个地方来决定哪些IOCTL的code是允许被AP call的。
PFN_Ioctl g_pfnExtOALIoctl;
//------------------------------------------------------------------------------
// Function: IOControl
//
// Arguments: Same signature as KernelIoControl
// DWORD dwIoControlCode: io control code
// PBYTE pInBuf: pointer to input buffer
// DWORD nInBufSize: length of input buffer in bytes
// PBYTE pOutBuf: pointer to out buffer
// DWORD nOutBufSize: length of output buffer in bytes
// PDWORD pBytesReturned: number of bytes returned in output buffer
//
// Return Values:
// If the function call is successful, TRUE is returned from this API call.
// If the function call is not successful, FALSE is returned from this API
// call and the last error is set to:
// a) ERROR_INVALID_PARAMETER: any of the input arguments are invalid
// b) ERROR_NOT_SUPPORTED: given ioctl is not supported
// c) any other ioctl set by OAL code
//
// Abstract:
// This is called by kernel whenever a user mode thread makes a call to
// KernelIoControl or KernelLibIoControl with io control code being an OAL
// io control code. OEMs can override what ioctls a user mode thread can call
// by enabling or disabling ioctl codes in this function.
//
//------------------------------------------------------------------------------
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_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_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;
}
在 case里面的IOCTL是运行被AP调用的,比如上面的 IOCTL_HAL_REBOOT。
里面还有一段英文注释,意思大概是,AP调用的kerneliocontrol都会先到这里来集合,通过这里的switch case决定是否允许调用到正真的function.只要把你的IOCTL的code加到case里面,它才能被上层AP访问。
kernel模式的驱动要call kerneliocontrol的话应该是直接调用到真正的ioctl,不需要跑到这个鬼地方来.