分类: WINDOWS
2010-11-04 21:23:37
事记:
20101104改写一款PCI卡驱动,因为要有outbuf,因此需要利用驱动传进来的outbuf。
在分析后,认为
KMemory Mem(I.Mdl());
PUCHAR pBuffer = (PUCHAR) Mem.MapToSystemSpace();
即可以让输出地址的应用程序空间映射到内存地址空间,从而就能操作。
谁知:当我利用 outbuf= (PUCHAR) Mem.MapToSystemSpace();
驱动程序运行到此处就死机了。
原因如下:
windows I/O读写分为缓冲的,直接的,不同的读写方式对I.Mdl的定义使用是不同的。
注意:在使用Mem.MapToSystemSpace()之前要先判断其是否为空,
标准解释:from MSDN
定义IO control code时,已经确定此种调用传点进来的是否是buffered 或者Direct的, 因此进入函数后在决定使用outbuf参数。
When defining new IOCTLs, it is important to remember the following rules:
An I/O control code is a 32-bit value that consists of several fields. The following figure illustrates the layout of I/O control codes.
I/O Control Code Layout
Use the system-supplied CTL_CODE macro, which is defined in wdm.h and ntddk.h, to define new I/O control codes. The definition of a new IOCTL code, whether intended for use with IRP_MJ_DEVICE_CONTROL or IRP_MJ_INTERNAL_DEVICE_CONTROL requests, uses the following format:
Choose a descriptive constant name for the IOCTL, of the form IOCTL_Device_Function, where Device indicates the type of device and Function indicates the operation. An example constant name is IOCTL_VIDEO_ENABLE_CURSOR.
Supply the following parameters to the CTL_CODE macro:
Use one of the following system-defined constants:
For information about how the system specifies data buffers for METHOD_BUFFERED I/O control codes, see .
For more information about buffered I/O, see .
Specify METHOD_IN_DIRECT if the caller of DeviceIoControl or IoBuildDeviceIoControlRequest will pass data to the driver.
Specify METHOD_OUT_DIRECT if the caller of DeviceIoControl or IoBuildDeviceIoControlRequest will receive data from the driver.
For information about how the system specifies data buffers for METHOD_IN_DIRECT and METHOD_OUT_DIRECT I/O control codes, see .
For more information about direct I/O, see .
For information about how the system specifies data buffers for METHOD_NEITHER I/O control codes, see .
This method can be used only if the driver can be guaranteed to be running in the context of the thread that originated the I/O control request. Only a highest-level kernel-mode driver is guaranteed to meet this condition, so METHOD_NEITHER is seldom used for the I/O control codes that are passed to low-level device drivers.
With this method, the highest-level driver must determine whether to set up buffered or direct access to user data on receipt of the request, possibly must lock down the user buffer, and must wrap its access to the user buffer in a structured exception handler (see ). Otherwise, the originating user-mode caller might change the buffered data before the driver can use it, or the caller could be swapped out just as the driver is accessing the user buffer.
For more information, see .
FILE_READ_DATA and FILE_WRITE_DATA can be ORed together if the caller must have both read and write access rights.
Some system-defined I/O control codes have a RequiredAccess value of FILE_ANY_ACCESS, which allows unrestricted access to the target device. Examples include I/O control codes that are sent to drivers of
Other system-defined I/O control codes require the caller to have read access rights, write access rights, or both. For example, the following definition of the public I/O control code IOCTL_DISK_SET_PARTITION_INFO shows that this I/O request can be sent to a driver only if the caller has both read and write access rights:
CTL_CODE(IOCTL_DISK_BASE, 0x008, METHOD_BUFFERED,\
FILE_READ_DATA | FILE_WRITE_DATA)
Note: Before specifying FILE_ANY_ACCESS for a new IOCTL code, you must be absolutely certain that allowing unrestricted access to your device does not create a possible path for malicious users to compromise the system.
Drivers can use
NTSTATUS IoDemoDevice::DeviceControl(KIrp I)
{
DbgPrint(__FUNCTION__":IRP 0x%08X\n",I);
switch(I.IoctlCode())
{
case IOCTL_DO_BUFFERED_IO:
{
DbgPrint(__FUNCTION__":IOCTL_DO_BUFFERED_IO\n",I);
ULONG inputSize = I.IoctlInputBufferSize();
ULONG outputSize = I.IoctlOutputBufferSize();
PVOID inputBuffer = I.IoctlBuffer();
PVOID outputBuffer = I.IoctlBuffer();
//显示出传进来的字符串
if(inputSize)
DbgPrint("inputBuffer:%s",(char*)inputBuffer);
//返回一个字符串
char chDoBufferedIO[]="DO_BUFFERED_IO";
strncpy((char*)outputBuffer,chDoBufferedIO,outputSize);
I.Information()=strlen(chDoBufferedIO);
}
break;
case IOCTL_DO_DIRECT_IN:
{
DbgPrint(__FUNCTION__":IOCTL_DO_DIRECT_IN\n",I);
KMemory Mem(I.Mdl());
PUCHAR pBuffer = (PUCHAR) Mem.MapToSystemSpace();
ULONG writeSize = I.WriteSize();
ULONG bytesSent = 0;
if(writeSize)
DbgPrint("pBuffer:%s",(char*)pBuffer);
I.Information()=0;
}
break;
case IOCTL_DO_DIRECT_OUT:
{
DbgPrint(__FUNCTION__":IOCTL_DO_DIRECT_OUT\n",I);
KMemory Mem(I.Mdl());
PUCHAR pBuffer = (PUCHAR) Mem.MapToSystemSpace();
ULONG readSize = I.ReadSize();
ULONG bytesRead = 0;
if(readSize)
{
char chDirectOut[]="DO_DIRECT_OUT";
strncpy((char*)pBuffer,chDirectOut,readSize);
I.Information()=strlen(chDirectOut);
}
}
break;
case IOCTL_DO_NEITHER_IO:
{
DbgPrint(__FUNCTION__":IOCTL_DO_NEITHER_IO\n",I);
ULONG inputSize = I.IoctlInputBufferSize();
ULONG outputSize = I.IoctlOutputBufferSize();
PVOID inputBuffer = I.IoctlType3InputBuffer();
PVOID outputBuffer = I.UserBuffer();
//显示出传进来的字符串
if(inputSize)
DbgPrint("inputBuffer:%s",(char*)inputBuffer);
//返回一个字符串
char chDoNeitherIo[]="DO_NEITHER_IO";
strncpy((char*)outputBuffer,chDoNeitherIo,outputSize);
I.Information()=strlen(chDoNeitherIo);
}
break;
default:
I.Information()=0;
I.Complete(STATUS_INVALID_DEVICE_REQUEST);
return STATUS_INVALID_DEVICE_REQUEST;
}
I.Complete(STATUS_SUCCESS);
return STATUS_SUCCESS;
}