泉州网站建设制作,个人手机版网站建设,网站空间服务商查询,成都公司做网站1.
Windows驱动程序分为两类#xff0c;一类是不支持即插即用功能的NT式的驱动程序#xff1b;另一类是支持即插即用功能的WDM式的驱动程序。2.
NT式的驱动程序要导入的头文件时NTDDK.H#xff0c;而WDM式的驱动要导入的头文件为WDM.H.3.
DriverEntry需要放在INIT标志的内存…1.
Windows驱动程序分为两类一类是不支持即插即用功能的NT式的驱动程序另一类是支持即插即用功能的WDM式的驱动程序。2.
NT式的驱动程序要导入的头文件时NTDDK.H而WDM式的驱动要导入的头文件为WDM.H.3.
DriverEntry需要放在INIT标志的内存中。INIT标志指明该函数只是在加载的时候需要载入内存而当驱动程序加载成功后该函数可以从内存中卸载掉。4.C编写驱动需要注意 [cpp] view plaincopy #ifdef __cplusplus extern “C” { #endif #include NTDDK.H #ifdef __cplusplus } #endif #pragma INITCODE extern “C” NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING pRegistryPath){} 5.
来看一个简单的NT式驱动Driver.h: [cpp] view plaincopy #pragma once #ifdef __cplusplus extern C { #endif #include NTDDK.h #ifdef __cplusplus } #endif #define PAGEDCODE code_seg(PAGE) #define LOCKEDCODE code_seg() #define INITCODE code_seg(INIT) #define PAGEDDATA data_seg(PAGE) #define LOCKEDDATA data_seg() #define INITDATA data_seg(INIT) #define arraysize(p) (sizeof(p)/sizeof((p)[0])) typedef struct _DEVICE_EXTENSION { PDEVICE_OBJECT pDevice; UNICODE_STRING ustrDeviceName; //设备名称 UNICODE_STRING ustrSymLinkName; //符号链接名 } DEVICE_EXTENSION, *PDEVICE_EXTENSION; // 驱动函数声明 NTSTATUS CreateDevice (IN PDRIVER_OBJECT pDriverObject); VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject); NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp); driver.cpp [cpp] view plaincopy /************************************************************************ * 函数名称:DriverEntry * 功能描述:初始化驱动程序定位和申请硬件资源创建内核对象 * 参数列表: pDriverObject:从I/O管理器中传进来的驱动对象 pRegistryPath:驱动程序在注册表的中的路径 * 返回 值:返回初始化驱动状态 *************************************************************************/ #pragma INITCODE extern C NTSTATUS DriverEntry ( IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath ) { NTSTATUS status; KdPrint((Enter DriverEntry\n)); //注册其他驱动调用函数入口 pDriverObject-DriverUnload HelloDDKUnload; pDriverObject-MajorFunction[IRP_MJ_CREATE] HelloDDKDispatchRoutine; pDriverObject-MajorFunction[IRP_MJ_CLOSE] HelloDDKDispatchRoutine; pDriverObject-MajorFunction[IRP_MJ_WRITE] HelloDDKDispatchRoutine; pDriverObject-MajorFunction[IRP_MJ_READ] HelloDDKDispatchRoutine; //创建驱动设备对象 status CreateDevice(pDriverObject); KdPrint((DriverEntry end\n)); return status; } /************************************************************************ * 函数名称:CreateDevice * 功能描述:初始化设备对象 * 参数列表: pDriverObject:从I/O管理器中传进来的驱动对象 * 返回 值:返回初始化状态 *************************************************************************/ #pragma INITCODE //指明此函数加载到INIT内存区域即只在加载的时候需要载入内存加载成功后可以从内存中卸载掉 NTSTATUS CreateDevice ( IN PDRIVER_OBJECT pDriverObject) { NTSTATUS status; PDEVICE_OBJECT pDevObj; PDEVICE_EXTENSION pDevExt; //创建设备名称 UNICODE_STRING devName; RtlInitUnicodeString(devName,L\\Device\\MyDDKDevice); //创建设备 status IoCreateDevice( pDriverObject, sizeof(DEVICE_EXTENSION), (UNICODE_STRING)devName, FILE_DEVICE_UNKNOWN,//此种设备为独占设备 0, TRUE, pDevObj ); if (!NT_SUCCESS(status)) return status; pDevObj-Flags | DO_BUFFERED_IO; pDevExt (PDEVICE_EXTENSION)pDevObj-DeviceExtension; pDevExt-pDevice pDevObj; pDevExt-ustrDeviceName devName; //创建符号链接 UNICODE_STRING symLinkName; RtlInitUnicodeString(symLinkName,L\\??\\HelloDDK); pDevExt-ustrSymLinkName symLinkName; status IoCreateSymbolicLink( symLinkName,devName ); if (!NT_SUCCESS(status)) { IoDeleteDevice( pDevObj ); return status; } return STATUS_SUCCESS; } /************************************************************************ * 函数名称:HelloDDKUnload * 功能描述:负责驱动程序的卸载操作 * 参数列表: pDriverObject:驱动对象 * 返回 值:返回状态 *************************************************************************/ #pragma PAGEDCODE VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject) {//遍历系统中所有的此类设备对象删除设备对象及其符号链接 PDEVICE_OBJECT pNextObj; KdPrint((Enter DriverUnload\n)); pNextObj pDriverObject-DeviceObject; while (pNextObj ! NULL) { PDEVICE_EXTENSION pDevExt (PDEVICE_EXTENSION) pNextObj-DeviceExtension; //删除符号链接 UNICODE_STRING pLinkName pDevExt-ustrSymLinkName; IoDeleteSymbolicLink(pLinkName); pNextObj pNextObj-NextDevice; IoDeleteDevice( pDevExt-pDevice ); } } /************************************************************************ * 函数名称:HelloDDKDispatchRoutine * 功能描述:对读IRP进行处理 * 参数列表: pDevObj:功能设备对象 pIrp:从IO请求包 * 返回 值:返回状态 *************************************************************************/ #pragma PAGEDCODE NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp) { KdPrint((Enter HelloDDKDispatchRoutine\n)); NTSTATUS status STATUS_SUCCESS; // 完成IRP pIrp-IoStatus.Status status; pIrp-IoStatus.Information 0; // bytes xfered IoCompleteRequest( pIrp, IO_NO_INCREMENT ); KdPrint((Leave HelloDDKDispatchRoutine\n)); return status; } 驱动虽然有了设备名称但是这种设备名只能在内核态可见而对于应用程序时不可见的。因此驱动需要暴露一个符号链接该链接指向真正的设备名称。编译好生成的sys文件我们可以使用
DriverMonitor
加载加载-启动-停止-卸载。6.再来看看WDM式驱动有什么不同。头文件就直接忽略了。 DriverEntry入口函数 [cpp] view plaincopy /************************************************************************ * 函数名称:DriverEntry * 功能描述:初始化驱动程序定位和申请硬件资源创建内核对象 * 参数列表: pDriverObject:从I/O管理器中传进来的驱动对象 pRegistryPath:驱动程序在注册表的中的路径 * 返回 值:返回初始化驱动状态 *************************************************************************/ #pragma INITCODE extern C NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath) { KdPrint((Enter DriverEntry\n)); pDriverObject-DriverExtension-AddDevice HelloWDMAddDevice; pDriverObject-MajorFunction[IRP_MJ_PNP] HelloWDMPnp; pDriverObject-MajorFunction[IRP_MJ_DEVICE_CONTROL] pDriverObject-MajorFunction[IRP_MJ_CREATE] pDriverObject-MajorFunction[IRP_MJ_READ] pDriverObject-MajorFunction[IRP_MJ_WRITE] HelloWDMDispatchRoutine; pDriverObject-DriverUnload HelloWDMUnload; KdPrint((Leave DriverEntry\n)); return STATUS_SUCCESS; } 这里增加了一个设置AddDevice回调函数此回调函数的作用是创建设备对象并由PNP即插即用管理器调用。并设置对IRP_MJ_PNP的IRP的回调函数。这都是NT和WDM驱动最大的不同点。而且在WDM驱动中大部分卸载工作都不是由DriverUnload来处理而是放在对IRP_MN_REMOVE_DEVICE的IRP的处理函数中处理。 下面是AddDevice回调函数的处理。 [cpp] view plaincopy /************************************************************************ * 函数名称:HelloWDMAddDevice * 功能描述:添加新设备 * 参数列表: DriverObject:从I/O管理器中传进来的驱动对象 PhysicalDeviceObject:从I/O管理器中传进来的物理设备对象 * 返回 值:返回添加新设备状态 *************************************************************************/ #pragma PAGEDCODE NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject) { PAGED_CODE(); KdPrint((Enter HelloWDMAddDevice\n)); NTSTATUS status; PDEVICE_OBJECT fdo; UNICODE_STRING devName; RtlInitUnicodeString(devName,L\\Device\\MyWDMDevice); status IoCreateDevice( DriverObject, sizeof(DEVICE_EXTENSION), (UNICODE_STRING)devName, FILE_DEVICE_UNKNOWN, 0, FALSE, fdo); if( !NT_SUCCESS(status)) return status; PDEVICE_EXTENSION pdx (PDEVICE_EXTENSION)fdo-DeviceExtension; pdx-fdo fdo; pdx-NextStackDevice IoAttachDeviceToDeviceStack(fdo, PhysicalDeviceObject); UNICODE_STRING symLinkName; RtlInitUnicodeString(symLinkName,L\\DosDevices\\HelloWDM); pdx-ustrDeviceName devName; pdx-ustrSymLinkName symLinkName; status IoCreateSymbolicLink((UNICODE_STRING)symLinkName,(UNICODE_STRING)devName); if( !NT_SUCCESS(status)) { IoDeleteSymbolicLink(pdx-ustrSymLinkName); status IoCreateSymbolicLink(symLinkName,devName); if( !NT_SUCCESS(status)) { return status; } } fdo-Flags | DO_BUFFERED_IO | DO_POWER_PAGABLE; fdo-Flags ~DO_DEVICE_INITIALIZING; KdPrint((Leave HelloWDMAddDevice\n)); return STATUS_SUCCESS; } 其中PAGED_CODE是一个DDK提供的宏只在check版中有效。当此例程所在的中断请求及超过APC_LEVEL时会产生一个断言。 本例对IRP_MN_REMOVE_DEVICE的处理。 [cpp] view plaincopy /************************************************************************ * 函数名称:HandleRemoveDevice * 功能描述:对IRP_MN_REMOVE_DEVICE IRP进行处理 * 参数列表: fdo:功能设备对象 Irp:从IO请求包 * 返回 值:返回状态 *************************************************************************/ #pragma PAGEDCODE NTSTATUS HandleRemoveDevice(PDEVICE_EXTENSION pdx, PIRP Irp) { PAGED_CODE(); KdPrint((Enter HandleRemoveDevice\n)); Irp-IoStatus.Status STATUS_SUCCESS; NTSTATUS status DefaultPnpHandler(pdx, Irp); IoDeleteSymbolicLink((UNICODE_STRING)pdx-ustrSymLinkName); //调用IoDetachDevice()把fdo从设备栈中脱开 if (pdx-NextStackDevice) IoDetachDevice(pdx-NextStackDevice); //删除fdo IoDeleteDevice(pdx-fdo); KdPrint((Leave HandleRemoveDevice\n)); return status; } 而对卸载例程的处理可以什么都不用做。 其他PNP的IRP如果不需要做处理那么直接传递到底层驱动并将底层驱动的结果返回。 [cpp] view plaincopy /************************************************************************ * 函数名称:DefaultPnpHandler * 功能描述:对PNP IRP进行缺省处理 * 参数列表: pdx:设备对象的扩展 Irp:从IO请求包 * 返回 值:返回状态 *************************************************************************/ #pragma PAGEDCODE NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION pdx, PIRP Irp) { PAGED_CODE(); KdPrint((Enter DefaultPnpHandler\n)); IoSkipCurrentIrpStackLocation(Irp); KdPrint((Leave DefaultPnpHandler\n)); return IoCallDriver(pdx-NextStackDevice, Irp); } 安装WDM式驱动需要一个inf文件。inf文件描述了WDM驱动程序的操作硬件设备的信息和驱动程序的一些信息。可以直接右击这个inf文件进行安装即可。