表4 Device 对象的外部可见域
其中,DeviceExtension域是一个重要的数据结构。它是由I/O管理器创建并自动挂接到Device对象的非分页池,是保存驱动程序任意全局变量的最好办法。因为DeviceExtension是驱动程序特定的,要自定义它的数据结构。
下面是一个驱动程序服务例程利用Device对象和IRP的片段:
NTSTATUS XxSelfDispatch(IN PDEVICE_OBJECT pDO IN PIRP pIrp);
{
PLOCAL_DEVICE_INFO pLDI;
PIO_STACK_LOCATION pIrpStack;
PULONG pIOBuffer;
//得到全局信息
pLDI = (PSELF_DEVICE_INFO)pDO->DeviceExtension;
pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
//得到由用户应用程序发来的用户数据,并在需要时,将结果通过此变量返回给用户
pIOBuffer=PULONGpIrp->AssociatedIrp.System
Buffer;
// 由IRP携带的信息决定驱动程序的执行
switch (pIrpStack->MajorFunction)
{
case IRP_MJ_CREATE:
case IRP_MJ_CLOSE:
Status = STATUS_SUCCESS;
break;
case IRP_MJ_DEVICE_CONTROL:
//由Parameters进一步解释控制代码含义
switch (pIrpStack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_Function1:
//执行功能代码
FiELD1 = pLDI->SelfField1;
...
break;
case IOCTL_Function2:
//执行功能代码
...
break;
}
break
}
// 返回I/O操作的状态
pIrp->IoStatus.Status = Status;
IoCompleteRequest(pIrp IO_NO_INCREMENT);
return Status;
}
5 驱动程序终止例程
Unload例程负责取消由DriverEntry例程所做的任何事情,包括解除属于该驱动程序的任何硬件资源的分配,以及删除属于驱动程序的任何内核对象。通常这仅在系统关闭时需要。
VOID XxUnload(PDRIVER_OBJECT DriverObject)
{
PLOCAL_DEVICE_INFO pLDI;
UNICODE_STRING Win32DeviceName;
// 得到全局数据,根据全局数据进行清理工作
pLDI=PLOCAL_DEVICE_INFODriverObject->Device
Object->DeviceExtension
if (pLDI->Field2 == TRUE)
{
...
// 删除分配的设备名及设备
RtlInitUnicodeString(&Win32DeviceName, SelfWin32 Name);
IoDeleteSymbolicLink(&Win32DeviceName);
IoDeleteDevice(pLDI->DeviceObject);
}
6 用户层应用程序与驱动程序间的接口
驱动程序完成后,将在系统重新引导时装入并初始化(由DriverEntry例程完成)。此时,驱动程序处于可用状态,等待用户层应用程序使用。用户层应用程序可以:
·打开该设备文件(由IRP_MJ_CREATE功能代码完成)
·读出数据(由IRP_MJ_READ功能代码完成)
·写入数据(由IRP_MJ_WRITE功能代码完成)
·执行用户自定义的功能代码(由IRP_MJ_DEVICE_CONTROL功能代码完成)
·关闭该设备文件(由IRP_MJ_CLOSE功能代码完成)
以下是部分实现代码:
void main()
{
HANDLE hndFile; // 由CreateFile得到
union {
ULONG LongData;
USHORT ShortData;
UCHAR CharData;
}DataBuffer; //从设备驱动程序中得到的数据
LONG IoctlCode; //功能代码
ULONG DataLength;
LONG Parameter1;
//调用IRP中的IRP _MJ_CREATE功能
hndFile = CreateFile(
″\\\\.\\SelfWin32Name″, // 打开设备文件″ SelfWin32Name″
>
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL
if (hndFile == INVALID_HANDLE_VALUE)
{
printf(″Unable to open the device.\n″);
exit(1);
}
IoctlCode = IOCTL_Function1; //自定义功能代码
Parameter1 = 1;
DataLength = sizeof(DataBuffer.CharData);
IoctlResult = DeviceIoControl(
hndFile //设备文件句柄
IoctlCode//功能代码,对应IRP中的Parameter.
//DeviceIoControl.IoControlCode域
&Parameter1,//传递到驱动程序的参数缓冲区,对应
//IRP中的AssociatedIrp.SystemBuffer
sizeof(Parameter1) //参数缓冲区长度
&DataBuffer, //从驱动程序传出的数据缓冲区
DataLength, //缓冲区长度
&ReturnedLength, //返回的实际缓冲区长度
NULL //等待,直到操作完成
);
if(!CloseHandlehndFile)) //关闭设备
{
printf(″FaiLED to close device.\n″);
}
}
以上介绍了Windows NT4.0设备驱动程序开发中的一般性过程。用户可利用NT SDK 及DDK开发工具包,并根据自身需要,对以上核心代码进行扩充完成所需任务。
上一篇:笔记本触摸板失灵怎么办?