WEB开发网
开发学院软件开发VC Windows 2000驱动程序的设计 阅读

Windows 2000驱动程序的设计

 2006-04-08 11:38:51 来源:WEB开发网   
核心提示: 3.具体实现:同许多应用程序一样,WDM驱动程序是PE格式的,Windows 2000驱动程序的设计(2),但是它却没有WinMain或main这样的入口,取而代之的是DriverEntry:NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObje

3.具体实现:

同许多应用程序一样,WDM驱动程序是PE格式的,但是它却没有WinMain或main这样的入口,取而代之的是DriverEntry:

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
//不同于前面的PDO
IN PUNICODE_STRING RegistryPath)
{
DriverObject- >DriverExtension- >AddDevice =
AddDevice; // DriverExtension 中存放着驱动程序扩展信息,包括设备所需要的硬件资源等。
DriverObject- >MajorFunction[IRP_MJ_CREATE]
= RequestCreate;
DriverObject- >MajorFunction[IRP_MJ_CLOSE]
= RequestClose;
DriverObject- >MajorFunction[IRP_MJ_DEVICE_CONTROL]
= RequestControl;
DriverObject- >MajorFunction[IRP_MJ_PNP]
= RequestPnp;
return STATUS_SUCCESS;
}

在DriverEntry驱动程序要向操作系统登记并注册一些消息处理器,而且还要指明是否对驱动程序输入输出的数据进行缓冲,另外还要我们提供一个AddDevice例程来把驱动程序添加到驱动程序堆栈中。其中,IRP_MJ_XXXXX为驱动程序所收到的系统消息,RequestXXXXX为相应的消息处理函数。在客户端程序中,我们一般要采用DeviceIoControl通过自定义的控制码与驱动程序通信(在VxD中大多也采用这种方式)。看看驱动程序所收到的系统消息,我们不难发现当用户调用DeviceIoControl时操作系统就会向驱动程序发出一条IRP_MJ_DEVICE_CONTROL消息,以触发RequestControl消息处理函数。

NTSTATUS RequestControl(IN PDEVICE_OBJECT
DeviceObject, IN PIRP Irp)
{
PIO_STACK_LOCATION IrpStack;
ULONG ControlCode;
ULONG InputLength,OutputLength;
NTSTATUS status;
IrpStack=IoGetCurrentIrpStackLocation(Irp);
//获取当前IRP所在的I/O堆栈
ControlCode=IrpStack- >Parameters.DeviceIoControl.
IoControlCode; //取得控制码
InputLength=IrpStack- >Parameters.DeviceIoControl.
InputBufferLength; //取输入缓冲区大小
OutputLength=IrpStack- >Parameters.DeviceIoControl.
OutputBufferLength;//取输出缓冲区大小
switch(ControlCode)
{
case HELLOWDM_IOCTL_HELLO: DbgPrint
("Hello from WDM.\n");//向调试器输出字符串
status=STATUS_SUCCESS; //置返回值
break;
default: status=STATUS_INVALID_DEVICE_REQUEST;
//输入的控制码不支持
}
return CompleteRequest(Irp, status, 0);
//调用CompleteRequest通知操作系统完成IRP操作
}

在客户端方面,先调用Setupapi.dll中的 SetupDiGetClassDevs并用上面提到的128位 GUID建立Ring-0与Ring-3接口:

HDEVINFO info=SetupDiGetClassDevs ((LPGUID)&GUID_HELLOWDM,NULL, //GUID_HELLOWDM 是128位GUID NULL,DIGCF_PRESENT|DIGCF_INTERFACEDEVICE); 然后使用SetupDiEnumDeviceInterfaces 对所获得的接口进行枚举以获得接口数据,接着连续两次调用SetupDiGetDeviceInterfaceDetail 获得接口详细信息,其中包括调用CreateFil e所需的一个型为\\.\0000000000000004# {3d93c5c0-0085-11d1-821e-0080c88327ab} 的字符串,最后调用方法和VxD的调用大体相同这里就不赘述了。不过由于使用了 Setupapi.dll中的API所以还需要使用 SetupDiDestroyDeviceInfoList来释放所申请的资源。

4.几点说明:

由于WDM是跨平台和跨操作系统的的驱动程序模型,所以在编写时一定不要使用汇编。另外,在编写时还应注意对IRP_MJ_PNP消息的响应以及其他系统消息的传递,这里的传递是向其它在驱动程序堆栈中的驱动程序而不是向客户端程序,详细的信息请参考本文所提供的例程。最后,由于笔者写此文章时Windows 2000尚未正式发布,一切的编写工作都是在Windows 98上用98DDK与VC6.0完成的,并且用Numega SoftIce 4.0调试通过。

上一页  1 2 

Tags:Windows 驱动程序 设计

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接