Chinaunix首页 | 论坛 | 博客
  • 博客访问: 942242
  • 博文数量: 173
  • 博客积分: 3436
  • 博客等级: 中校
  • 技术积分: 1886
  • 用 户 组: 普通用户
  • 注册时间: 2009-01-07 09:29
文章分类

全部博文(173)

文章存档

2016年(6)

2015年(10)

2014年(14)

2013年(8)

2012年(36)

2011年(63)

2010年(19)

2009年(17)

分类: 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参数。

 

Defining I/O Control Codes

When defining new IOCTLs, it is important to remember the following rules:

  • If a new IOCTL will be available to user-mode software components, the IOCTL must be used with IRP_MJ_DEVICE_CONTROL requests. User-mode components send IRP_MJ_DEVICE_CONTROL requests by calling the DeviceIoControl, which is a Win32 function.
  • If a new IOCTL will be available only to kernel-mode driver components, the IOCTL must be used with IRP_MJ_INTERNAL_DEVICE_CONTROL requests. Kernel-mode components create IRP_MJ_INTERNAL_DEVICE_CONTROL requests by calling IoBuildDeviceIoControlRequest. For more information, see .

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:

#define IOCTL_Device_Function CTL_CODE(DeviceTypeFunctionMethodAccess)

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:

DeviceType
Identifies the device type. This value must match the value that is set in the DeviceType member of the driver's DEVICE_OBJECT structure. (See ). Values of less than 0x8000 are reserved for Microsoft. Values of 0x8000 and higher can be used by vendors. Note that the vendor-assigned values set the Common bit.
FunctionCode
Identifies the function to be performed by the driver. Values of less than 0x800 are reserved for Microsoft. Values of 0x800 and higher can be used by vendors. Note that the vendor-assigned values set the Custom bit.
TransferType
Indicates how the system will pass data between the caller of DeviceIoControl (or IoBuildDeviceIoControlRequest) and the driver that handles the IRP.

Use one of the following system-defined constants:

METHOD_BUFFERED
Specifies the method, which is typically used for transferring small amounts of data per request. Most I/O control codes for device and intermediate drivers use this TransferType value.

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 .

METHOD_IN_DIRECT or METHOD_OUT_DIRECT
Specifies the method, which is typically used for reading or writing large amounts of data, using DMA or PIO, that must be transferred quickly.

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 .

METHOD_NEITHER
Specifies . The I/O manager does not provide any system buffers or MDLs. The IRP supplies the user-mode virtual addresses of the input and output buffers that were specified to DeviceIoControl or IoBuildDeviceIoControlRequest, without validating or mapping them.

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 .

RequiredAccess
Indicates the type of access that a caller must request when opening the file object that represents the device (see IRP_MJ_CREATE). The I/O manager will create IRPs and call the driver with a particular I/O control code only if the caller has requested the specified access rights. RequiredAccess is specified by using the following system-defined constants:
FILE_ANY_ACCESS
The I/O manager sends the IRP for any caller that has a handle to the file object that represents the target device object.
FILE_READ_DATA
The I/O manager sends the IRP only for a caller with read access rights, allowing the underlying device driver to transfer data from the device to system memory.
FILE_WRITE_DATA
The I/O manager sends the IRP only for a caller with write access rights, allowing the underlying device driver to transfer data from system memory to its device.

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 exclusive devices, and for those that specify buffered I/O.

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:

#define IOCTL_DISK_SET_PARTITION_INFO\
   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 IoValidateDeviceIoControlAccess to perform stricter access checking than that provided by an IOCTL's RequiredAccess bits.

 

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;
}

阅读(2863) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~