基于Windows2000开发WDM设备驱动程序的方法
0,
FALSE, // Not exclusive,TRUE为独占
&fdo返回的新设备对象);
if( !NT_SUCCESS(status)
return status;
IoAttachDeviceToDeviceStack(fdo,pdo);与设备栈挂接
2.6 删除设备
NTSTATUS Wdm1Pnp( IN PDEVICE_OBJECT fdo,
IN PIRP Irp)
PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
ULONG MinorFunction = IrpStack->MinorFunction;
if( MinorFunction==IRP_MN_REMOVE_DEVICE)
{
DebugPrint("PnP RemoveDevice"); // disable device interface
IoSetDeviceInterfaceState(&dx->ifSymLinkName, FALSE);
RtlFreeUnicodeString(&dx->ifSymLinkName);
// unattach from stack从设备栈脱离
if (dx->NextStackDevice)
IoDetachDevice(dx->NextStackDevice);
// delete our fdo删除设备
IoDeleteDevice(fdo);
}
CreateFile IRP_MJ_Create WriteFile MJ_WRITE
CloseHandle MJ_CLOSE DeviceIoControl MJ_DEVICEIOCONTROL
ReadFile
MJ_CLOSE所有的分发例程都有相同的函数原型,均需传递一个设备对象的指针和IRP,IRP由IRP首部和一系列的栈单元组成,每个栈单元是一个IO_STACK_LOCATION结构,首部和栈单元指出要作的动作 ,栈中有主要的重要参数如MajorFunction和MinorFunction,每个驱动只认识一个栈单元。
2.7 即插即用
驱动必须有AddDevice例程并处理各种PnP IRP:
IRP_MN_START_DEVICE分配资源并启动一个设备。
IRP_MN_STOP_DEVICE 停止设备进行资源重新分配。
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为相应的消息处理函数。在客户端程序中,我们一般要采用DeviceIoContro l通过自定义的控制码与驱动程序通信(在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操作
立刻注册,免费享受三天的试用收看期,火爆,激情 让您免费欣赏三天
4.结束语
本文是笔者在Windows2000下开发网卡驱动程序的一些经验总结,使用Windows2000 DDK开发包和Windows2000 platform SDK ,在VC++6.0下调试通过。
参考文献
[1] Art Baker Jerry Lozano 著 施 诺 译 Windows 2000设备驱动程序设计指南 机械工业出版社 2001
[2] 武安河 周利莉 著 Windows 设备驱动程序开发实务 电子工业出版社 2002
Tags:
作者:佚名评论内容只代表网友观点,与本站立场无关!
评论摘要(共 0 条,得分 0 分,平均 0 分)
查看完整评论