设备句柄可以用API函数CreateFile获得。它的原型为
HANDLE CreateFile(
LPCTSTR lpFileName, // 文件名/设备路径 设备的名称
DWORD dwDesiredAccess, // 访问方式
DWORD dwShareMode, // 共享方式
LPSECURITY_ATTRIBUTES lpSecurityAttributes, // 安全描述符指针
DWORD dwCreationDisposition, // 创建方式
DWORD dwFlagsAndAttributes, // 文件属性及标志
HANDLE hTemplateFile // 模板文件的句柄
);
打开:createFile
关闭:closehandle
与普通文件名有所不同,设备驱动的“文件名”(常称为“设备路径”)形式固定为“//./DeviceName”(注意在C程序中该字符串写法为“////.//DeviceName”),DeviceName必须与设备驱动程序内定义的设备名称一致。
一般地,调用CreateFile获得设备句柄时,访问方式参数设置为0或GENERIC_READ|GENERIC_WRITE,共享方式参数设置为FILE_SHARE_READ|FILE_SHARE_WRITE,创建方式参数设置为OPEN_EXISTING,其它参数设置为0或NULL。
DeviceIoControl函数向指定的设备驱动发送一个控制码,驱动程序通过这个控制码来完成特定的工作。该函数原型如下:
BOOL DeviceIoControl( |
参数说明
hDevice
要进行操作的设备句柄。获得方法见上面CreateFile。
dwIoControlCode
要进行操作的控制码。驱动程序可以通过CTL_CODE宏来组合定义一个控制码,并在IRP_MJ_DEVICE_CONTROL的实现中进行控制码的操作。在驱动层,irpStack->Parameters.DeviceIoControl.IoControlCode表示了这个控制码。发送不同的控制码,可以调用设备驱动程序的不同类型的功能。在头文件winioctl.h中,预定义的标准设备控制码,都以IOCTL或FSCTL开头。例如,IOCTL_DISK_GET_DRIVE_GEOMETRY是对物理驱动器取结构参数(介质类型、柱面数、每柱面磁道数、每磁道扇区数等)的控制码,FSCTL_LOCK_VOLUME是对逻辑驱动器的卷加锁的控制码。
lpInBuffer
由用户层发送的缓冲区数据。在驱动层,依传输类型的不同,输入缓冲区的位置亦不同,见下表。
传输类型 | 位置 |
METHOD_IN_DIRECT | irp->AssociatedIrp.SystemBuffer |
METHOD_OUT_DIRECT | irp->AssociatedIrp.SystemBuffer |
METHOD_BUFFERED | irp->AssociatedIrp.SystemBuffer |
METHOD_NEITHER | irpStack->Parameters.DeviceIoControl.Type3InputBuffer |
nInBufferSize
由用户层发送的缓冲区大小。在驱动层,这个值是irpStack->Parameters.DeviceIoControl.InputBufferLength。
lpOutBuffer
由用户层指定,用于接收驱动层返回数据的缓冲区。在驱动层,依传输类型的不同,输出缓冲区的位置亦不同,见下表。
传输类型 | 位置 |
METHOD_IN_DIRECT | irp->MdlAddress |
METHOD_OUT_DIRECT | irp->MdlAddress |
METHOD_BUFFERED | irp->AssociatedIrp.SystemBuffer |
METHOD_NEITHER | irp->UserBuffer |
nOutBufferSize
由用户层指定,用于接收驱动层返回数据的缓冲区大小。在驱动层,这个值是irpStack->Parameters.DeviceIoControl.OutputBufferLength。
lpBytesReturned
由用户层指定,用于接收驱动层实际返回数据大小。在驱动层,这个值是irp->IoStatus->Information。
lpOverlapped
用于异步操作。
一个应用程序调用驱动的例子(WINCE下):
一般步骤是这样的,调用CREATEFILE取得设备句柄->判断是否成功->调用DeviceIoControl操作设备->关闭句柄。
BOOL SetBKLPower(BOOL bOn)
{
BOOL bRet = FALSE;
HANDLE hDev = CreateFile(L"GPC1:",GENERIC_WRITE|GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,NULL,NULL);
if (INVALID_HANDLE_VALUE != hDev)
{
if (bOn)
{
bRet = ::DeviceIoControl(hDev,IOCTL_BKL_ON,NULL,NULL,NULL,NULL,NULL,NULL);
}
else
{
bRet = ::DeviceIoControl(hDev,IOCTL_BKL_OFF,NULL,NULL,NULL,NULL,NULL,NULL);
}
CloseHandle(hDev);
}
return bRet;
}