1.         2.         WDM的安全,也保证安全地创徏一个惟一的、独立于语言的访问设备的Ҏ(gu)?/span>

来调用设备。在某个Win32 APIs用符号链打开一个设备的句柄

?/span>,
  GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ,
  NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL ,NULL
);

?/span>CreateLink中的W一个参C?/span>Windows 98/2000文g)产生驱动E序Q它通常使用c?/span>KunitizedName。例如:(x)如果链接名称的主q是L”那么?/span>CreateFileQ第六个参数(Flags)?/span>

使用一个输出接口打开句柄

库提供两个助手类来获得对该接口的访问容易一些,q两个类?/span>CDeviceInterface, ?/span>

CdeviceInterfaceClasscȝ一个实例来获得一个或更多?/span>CdeviceInterfacecL一个单一讑֤接口的抽象。它的成员函?/span>DevicePath()中用来打开讑֤?/span>

    << DevInterface.DevicePath()
    << endl;

  HANDLE hDev;
  hDev = CreateFile(
   DevInterface.DevicePath(),
    GENERIC_READ | GENERIC_WRITE,
    FILE_SHARE_READ | FILE_SHARE_WRITE,
    NULL,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    NULL
  );
  if (hDev == INVALID_HANDLE_VALUE)
    *pError = GetLastError();
  return hDev;
}

在设备中执行I/O操作

来生到讑֤对象?/span>IRPs

Win32 API

DRIVER_FUNCTION_xxx
IRP_MJ_xxx

KDevice subclass member function

CreateFile

CREATE

Create

ReadFile

READ

Read

WriteFile

WRITE

Write

DeviceIoControl

DEVICE_CONTROL

DeviceControl

CloseHandle

CLOSE
CLEANUP

Close
CleanUp

?/span>CleanUp使内ؓ(f)讑֤创徏一个新的文件对象。这使得多个句柄可以映射同一个文件对象。当q个文g对象的最后一个用L(fng)句柄被撤销后,I/O。当没有M用户U和核心(j)U的Ҏ(gu)件对象的讉K的时候,I/O?/span>

引起错误(无效功能Q?/span>

~写?/span>VxD属性。在Windows NT/2000I/O?/span>WriteFile参数转换?/span>IRP标志Q?/span>I/O锁住在存储器中,q且创徏?jin)一个存储在IRP域。一个设备可以通过调用Kirp::Mdl?/span>

标志Q设备对象分别通过KIrp::BufferedReadDest或写操作获得buff标志也不讄DO_DIRECT_IO?/span>UserBuffer?/span>WriteFile参数。然而,存储区ƈ没有被锁住而且地址只对调用q程有效。驱动程序可以?/span>KIrp::UserBuffer域?/span>

调用Q?/span>buffer控制代码Q它不在讑֤对象的特性中。宏CTL_CODE中定义)(j)用来构造控制代码。这个宏的其中一个参数指明缓冲方法是METHOD_BUFFERED, METHOD_IN_DIRECT, METHOD_OUT_DIRECT, 。下面的表显CZ(jin)q些Ҏ(gu)和与之对应的能获得输入缓冲与输出~冲?/span>KIrp

Method

Input Buffer Parameter

Output Buffer Parameter

METHOD_BUFFERED

KIrp::IoctlBuffer

KIrp::IoctlBuffer

METHOD_IN_DIRECT

KIrp::IoctlBuffer

KIrp::Mdl

METHOD_OUT_DIRECT

KIrp::IoctlBuffer

KIrp::Mdl

METHOD_NEITHER

KIrp::IoctlType3InputBuffer

KIrp::UserBuffer

Q系l分配一个单一的缓冲来作ؓ(f)输入与输出。驱动程序必d向输出缓冲放数据之前拯输入数据。驱动程序通过调用KIrp::IoctlBuffer理器从pȝ~冲拯数据到提供给Ring 3?/span>Information?/span>METHOD_OUT_DIRECT的参数呈C同的含义。参?/span>InputBuffer。参?/span>OutputBuffer对象Q驱动程序对q个对象的访问通过调用KIrp::MdlQ调用者必L对缓冲的写访问权限?/span>

Q内核只提供虚拟地址Q它不会(x)做映来配置~冲。虚拟地址只对调用q程有效?/span>

的例子:(x)

来定义一?/span>IOCTL#define IOCTL_MYDEV_GET_FIRMWARE_REV "

CTL_CODE (FILE_DEVICE_UNKNOWN,0,METHOD_BUFFERED,FILE_ANY_ACCESS)

调用Q?/span>

BOOLEAN b;
CHAR FirmwareRev[60];
ULONG FirmwareRevSize;
b = DeviceIoControl(hDevice, IOCTL_MYDEV_GET_VERSION_STRING,
  NULL, // no input q里?/span>output如果输出~冲_大,讑֤拯串到里面q将拯的资l束讄?/span>FirmwareRevSize在驱动程序中Q代码看h如下所C:(x)

const char* FIRMWARE_REV = "FW 16.33 v5";
NTSTATUS MyDevice::DeviceControl( KIrp I )
{
  ULONG fwLength=0;
  switch ( I.IoctlCode() )
  {
    case IOCTL_MYDEV_GET_FIRMWARE_REV:
      fwLength = strlen(FIRMWARE_REV)+1;
      if (I.IoctlOutputBufferSize() >= fwLength)
      {
        strcpy((PCHAR)I.IoctlBuffer(),FIRMWARE_REV);
        I.Information() = fwLength;      
        return I.Complete(STATUS_SUCCESS);
      }
      else

      {
        
      }
    case . . .
   }
 }