再来看基于WDM的驱动程序,

 

  1. #ifdef __cplusplus  
  2. extern "C" 
  3. {  
  4. #endif  
  5. #include <wdm.h>  
  6. #ifdef __cplusplus  
  7. }  
  8. #endif   
  9.  
  10. typedef struct _DEVICE_EXTENSION  
  11. {  
  12.     PDEVICE_OBJECT fdo;  
  13.     PDEVICE_OBJECT NextStackDevice;  
  14.     UNICODE_STRING ustrDeviceName;    // 设备名  
  15.     UNICODE_STRING ustrSymLinkName;    // 符号链接名  
  16. } DEVICE_EXTENSION, *PDEVICE_EXTENSION;  
  17.  
  18. #define PAGEDCODE code_seg("PAGE")  
  19. #define LOCKEDCODE code_seg()  
  20. #define INITCODE code_seg("INIT")  
  21.  
  22. #define PAGEDDATA data_seg("PAGE")  
  23. #define LOCKEDDATA data_seg()  
  24. #define INITDATA data_seg("INIT")  
  25.  
  26. #define arraysize(p) (sizeof(p)/sizeof((p)[0]))  
  27.  
  28. NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject,  
  29.                            IN PDEVICE_OBJECT PhysicalDeviceObject);  
  30. NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo,  
  31.                         IN PIRP Irp);  
  32. NTSTATUS HelloWDMDispatchRoutine(IN PDEVICE_OBJECT fdo,  
  33.                                  IN PIRP Irp);  
  34. void HelloWDMUnload(IN PDRIVER_OBJECT DriverObject);  
  35.  
  36. extern "C" 
  37. NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,  
  38.                      IN PUNICODE_STRING RegistryPath); 

 

  1. #include "HelloWDM.h"  
  2.  
  3. /************************************************************************  
  4. * 函数名称:DriverEntry  
  5. * 功能描述:初始化驱动程序,定位和申请硬件资源,创建内核对象  
  6. * 参数列表:  
  7.       pDriverObject:从I/O管理器中传进来的驱动对象  
  8.       pRegistryPath:驱动程序在注册表的中的路径  
  9. * 返回 值:返回初始化驱动状态  
  10. *************************************************************************/ 
  11. #pragma INITCODE   
  12. extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,  
  13.                                 IN PUNICODE_STRING pRegistryPath)  
  14. {  
  15.     KdPrint(("Enter DriverEntry\n"));  
  16.  
  17.     pDriverObject->DriverExtension->AddDevice = HelloWDMAddDevice;  
  18.     pDriverObject->MajorFunction[IRP_MJ_PNP] = HelloWDMPnp;  
  19.     pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =   
  20.     pDriverObject->MajorFunction[IRP_MJ_CREATE] =   
  21.     pDriverObject->MajorFunction[IRP_MJ_READ] =   
  22.     pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloWDMDispatchRoutine;  
  23.     pDriverObject->DriverUnload = HelloWDMUnload;  
  24.  
  25.     KdPrint(("Leave DriverEntry\n"));  
  26.     return STATUS_SUCCESS;  
  27. }  
  28.  
  29. /************************************************************************  
  30. * 函数名称:HelloWDMAddDevice  
  31. * 功能描述:添加新设备  
  32. * 参数列表:  
  33.       DriverObject:从I/O管理器中传进来的驱动对象  
  34.       PhysicalDeviceObject:从I/O管理器中传进来的物理设备对象  
  35. * 返回 值:返回添加新设备状态  
  36. *************************************************************************/ 
  37. #pragma PAGEDCODE  
  38. NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject,  
  39.                            IN PDEVICE_OBJECT PhysicalDeviceObject)  
  40. {   
  41.     PAGED_CODE();  
  42.     KdPrint(("Enter HelloWDMAddDevice\n"));  
  43.  
  44.     NTSTATUS status;  
  45.     PDEVICE_OBJECT fdo;  
  46.     UNICODE_STRING devName;  
  47.     RtlInitUnicodeString(&devName,L"\\Device\\MyWDMDevice");  
  48.     status = IoCreateDevice(  
  49.         DriverObject,  
  50.         sizeof(DEVICE_EXTENSION),  
  51.         &(UNICODE_STRING)devName,  
  52.         FILE_DEVICE_UNKNOWN,  
  53.         0,  
  54.         FALSE,  
  55.         &fdo);  
  56.     if( !NT_SUCCESS(status))  
  57.         return status;  
  58.     PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;  
  59.     pdx->fdo = fdo;  
  60.     pdx->NextStackDevice = IoAttachDeviceToDeviceStack(fdo, PhysicalDeviceObject);  
  61.     UNICODE_STRING symLinkName;  
  62.     RtlInitUnicodeString(&symLinkName,L"\\DosDevices\\HelloWDM");  
  63.  
  64.     pdx->ustrDeviceName = devName;  
  65.     pdx->ustrSymLinkName = symLinkName;  
  66.     status = IoCreateSymbolicLink(&(UNICODE_STRING)symLinkName,&(UNICODE_STRING)devName);  
  67.  
  68.     if( !NT_SUCCESS(status))  
  69.     {  
  70.         IoDeleteSymbolicLink(&pdx->ustrSymLinkName);  
  71.         status = IoCreateSymbolicLink(&symLinkName,&devName);  
  72.         if( !NT_SUCCESS(status))  
  73.         {  
  74.             return status;  
  75.         }  
  76.     }  
  77.  
  78.     fdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;  
  79.     fdo->Flags &= ~DO_DEVICE_INITIALIZING;  
  80.  
  81.     KdPrint(("Leave HelloWDMAddDevice\n"));  
  82.     return STATUS_SUCCESS;  
  83. }  
  84.  
  85. /************************************************************************  
  86. * 函数名称:DefaultPnpHandler  
  87. * 功能描述:对PNP IRP进行缺省处理  
  88. * 参数列表:  
  89.       pdx:设备对象的扩展  
  90.       Irp:从IO请求包  
  91. * 返回 值:返回状态  
  92. *************************************************************************/   
  93. #pragma PAGEDCODE  
  94. NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION pdx, PIRP Irp)  
  95. {  
  96.     PAGED_CODE();  
  97.     KdPrint(("Enter DefaultPnpHandler\n"));  
  98.     IoSkipCurrentIrpStackLocation(Irp);  
  99.     KdPrint(("Leave DefaultPnpHandler\n"));  
  100.     return IoCallDriver(pdx->NextStackDevice, Irp);  
  101. }  
  102.  
  103. /************************************************************************  
  104. * 函数名称:HandleRemoveDevice  
  105. * 功能描述:对IRP_MN_REMOVE_DEVICE IRP进行处理  
  106. * 参数列表:  
  107.       fdo:功能设备对象  
  108.       Irp:从IO请求包  
  109. * 返回 值:返回状态  
  110. *************************************************************************/ 
  111. #pragma PAGEDCODE  
  112. NTSTATUS HandleRemoveDevice(PDEVICE_EXTENSION pdx, PIRP Irp)  
  113. {  
  114.     PAGED_CODE();  
  115.     KdPrint(("Enter HandleRemoveDevice\n"));  
  116.  
  117.     Irp->IoStatus.Status = STATUS_SUCCESS;  
  118.     NTSTATUS status = DefaultPnpHandler(pdx, Irp);  
  119.     IoDeleteSymbolicLink(&(UNICODE_STRING)pdx->ustrSymLinkName);  
  120.  
  121.     //调用IoDetachDevice()把fdo从设备栈中脱开:  
  122.     if (pdx->NextStackDevice)  
  123.         IoDetachDevice(pdx->NextStackDevice);  
  124.       
  125.     //删除fdo:  
  126.     IoDeleteDevice(pdx->fdo);  
  127.     KdPrint(("Leave HandleRemoveDevice\n"));  
  128.     return status;  
  129. }  
  130.  
  131. /************************************************************************  
  132. * 函数名称:HelloWDMPnp  
  133. * 功能描述:对即插即用IRP进行处理  
  134. * 参数列表:  
  135.       fdo:功能设备对象  
  136.       Irp:从IO请求包  
  137. * 返回 值:返回状态  
  138. *************************************************************************/ 
  139. #pragma PAGEDCODE  
  140. NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo,  
  141.                         IN PIRP Irp)  
  142. {  
  143.     PAGED_CODE();  
  144.  
  145.     KdPrint(("Enter HelloWDMPnp\n"));  
  146.     NTSTATUS status = STATUS_SUCCESS;  
  147.     PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;  
  148.     PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);  
  149.     static NTSTATUS (*fcntab[])(PDEVICE_EXTENSION pdx, PIRP Irp) =   
  150.     {  
  151.         DefaultPnpHandler,        // IRP_MN_START_DEVICE  
  152.         DefaultPnpHandler,        // IRP_MN_QUERY_REMOVE_DEVICE  
  153.         HandleRemoveDevice,        // IRP_MN_REMOVE_DEVICE  
  154.         DefaultPnpHandler,        // IRP_MN_CANCEL_REMOVE_DEVICE  
  155.         DefaultPnpHandler,        // IRP_MN_STOP_DEVICE  
  156.         DefaultPnpHandler,        // IRP_MN_QUERY_STOP_DEVICE  
  157.         DefaultPnpHandler,        // IRP_MN_CANCEL_STOP_DEVICE  
  158.         DefaultPnpHandler,        // IRP_MN_QUERY_DEVICE_RELATIONS  
  159.         DefaultPnpHandler,        // IRP_MN_QUERY_INTERFACE  
  160.         DefaultPnpHandler,        // IRP_MN_QUERY_CAPABILITIES  
  161.         DefaultPnpHandler,        // IRP_MN_QUERY_RESOURCES  
  162.         DefaultPnpHandler,        // IRP_MN_QUERY_RESOURCE_REQUIREMENTS  
  163.         DefaultPnpHandler,        // IRP_MN_QUERY_DEVICE_TEXT  
  164.         DefaultPnpHandler,        // IRP_MN_FILTER_RESOURCE_REQUIREMENTS  
  165.         DefaultPnpHandler,        //   
  166.         DefaultPnpHandler,        // IRP_MN_READ_CONFIG  
  167.         DefaultPnpHandler,        // IRP_MN_WRITE_CONFIG  
  168.         DefaultPnpHandler,        // IRP_MN_EJECT  
  169.         DefaultPnpHandler,        // IRP_MN_SET_LOCK  
  170.         DefaultPnpHandler,        // IRP_MN_QUERY_ID  
  171.         DefaultPnpHandler,        // IRP_MN_QUERY_PNP_DEVICE_STATE  
  172.         DefaultPnpHandler,        // IRP_MN_QUERY_BUS_INFORMATION  
  173.         DefaultPnpHandler,        // IRP_MN_DEVICE_USAGE_NOTIFICATION  
  174.         DefaultPnpHandler,        // IRP_MN_SURPRISE_REMOVAL  
  175.     };  
  176.  
  177.     ULONG fcn = stack->MinorFunction;  
  178.     if (fcn >= arraysize(fcntab))  
  179.     {                        // 未知的子功能代码  
  180.         status = DefaultPnpHandler(pdx, Irp); // some function we don't know about  
  181.         return status;  
  182.     }                          
  183.  
  184. #if DBG  
  185.     static char* fcnname[] =   
  186.     {  
  187.         "IRP_MN_START_DEVICE",  
  188.         "IRP_MN_QUERY_REMOVE_DEVICE",  
  189.         "IRP_MN_REMOVE_DEVICE",  
  190.         "IRP_MN_CANCEL_REMOVE_DEVICE",  
  191.         "IRP_MN_STOP_DEVICE",  
  192.         "IRP_MN_QUERY_STOP_DEVICE",  
  193.         "IRP_MN_CANCEL_STOP_DEVICE",  
  194.         "IRP_MN_QUERY_DEVICE_RELATIONS",  
  195.         "IRP_MN_QUERY_INTERFACE",  
  196.         "IRP_MN_QUERY_CAPABILITIES",  
  197.         "IRP_MN_QUERY_RESOURCES",  
  198.         "IRP_MN_QUERY_RESOURCE_REQUIREMENTS",  
  199.         "IRP_MN_QUERY_DEVICE_TEXT",  
  200.         "IRP_MN_FILTER_RESOURCE_REQUIREMENTS",  
  201.         "",  
  202.         "IRP_MN_READ_CONFIG",  
  203.         "IRP_MN_WRITE_CONFIG",  
  204.         "IRP_MN_EJECT",  
  205.         "IRP_MN_SET_LOCK",  
  206.         "IRP_MN_QUERY_ID",  
  207.         "IRP_MN_QUERY_PNP_DEVICE_STATE",  
  208.         "IRP_MN_QUERY_BUS_INFORMATION",  
  209.         "IRP_MN_DEVICE_USAGE_NOTIFICATION",  
  210.         "IRP_MN_SURPRISE_REMOVAL",  
  211.     };  
  212.  
  213.     KdPrint(("PNP Request (%s)\n", fcnname[fcn]));  
  214. #endif // DBG  
  215.  
  216.     status = (*fcntab[fcn])(pdx, Irp);  
  217.     KdPrint(("Leave HelloWDMPnp\n"));  
  218.     return status;  
  219. }  
  220.  
  221. /************************************************************************  
  222. * 函数名称:HelloWDMDispatchRoutine  
  223. * 功能描述:对缺省IRP进行处理  
  224. * 参数列表:  
  225.       fdo:功能设备对象  
  226.       Irp:从IO请求包  
  227. * 返回 值:返回状态  
  228. *************************************************************************/ 
  229. #pragma PAGEDCODE  
  230. NTSTATUS HelloWDMDispatchRoutine(IN PDEVICE_OBJECT fdo,  
  231.                                  IN PIRP Irp)  
  232. {  
  233.     PAGED_CODE();  
  234.     KdPrint(("Enter HelloWDMDispatchRoutine\n"));  
  235.     Irp->IoStatus.Status = STATUS_SUCCESS;  
  236.     Irp->IoStatus.Information = 0;    // no bytes xfered  
  237.     IoCompleteRequest( Irp, IO_NO_INCREMENT );  
  238.     KdPrint(("Leave HelloWDMDispatchRoutine\n"));  
  239.     return STATUS_SUCCESS;  
  240. }  
  241.  
  242. /************************************************************************  
  243. * 函数名称:HelloWDMUnload  
  244. * 功能描述:负责驱动程序的卸载操作  
  245. * 参数列表:  
  246.       DriverObject:驱动对象  
  247. * 返回 值:返回状态  
  248. *************************************************************************/ 
  249. #pragma PAGEDCODE  
  250. void HelloWDMUnload(IN PDRIVER_OBJECT DriverObject)  
  251. {  
  252.     PAGED_CODE();  
  253.     KdPrint(("Enter HelloWDMUnload\n"));  
  254.     KdPrint(("Leave HelloWDMUnload\n"));  

      同前面一样,编译也是两种方式,第一种用DDK编译,准备两个脚本文件,makefileSources,其中Sources有所不同,如下所示:

  1. TARGETNAME=HelloWDM  
  2. TARGETTYPE=DRIVER  
  3. DRIVERTYPE=WDM  
  4. TARGETPATH=OBJ  
  5.  
  6. INCLUDES=$(BASEDIR)\inc;\  
  7.          $(BASEDIR)\inc\ddk;\  
  8.  
  9. SOURCES=HelloWDM.cpp\  

        另一种是用VC进行编译,有三点需要注意:

1, 选择c/c++选项卡,将原来的Project Options全删掉,换成下面的:

 

  1. /nologo /Gz /MLd /W3 /WX /Z7 /Od /D WIN32=100 /D _X86_=1 /D WINVER=0x500 /D DBG=1 /Fo"MyDriver_Check/" /Fd"MyDriver_Check/" /FD /c 

2, 选择Link选项卡,将原来的Project Options全删掉,换成下面的:

 

  1. wdm.lib /nologo /base:"0x10000" /stack:0x400000,0x1000 /entry:"DriverEntry" /subsystem:console /incremental:no /pdb:"MyDriver_Check/HelloWDM.pdb" /debug /machine:I386 /nodefaultlib /out:"MyDriver_Check/HelloWDM.sys" /pdbtype:sept /subsystem:native /driver /SECTION:INIT,D /RELEASE /IGNORE:4078 

3, 修改include目录时,加入

 

  1. D:\WINDDK\3790.1830\INC\DDK\WDM\W2K 

 否则会报错如下:

 

  1. fatal error C1083: Cannot open include file: 'wdm.h': No such file or directory 

最后是驱动的安装,WDM驱动的安装需要写一个inf文件,如下所示:

 

  1. ;--------- Version Section ---------------------------------------------------  
  2.  
  3. [Version]  
  4. Signature="$CHICAGO$";  
  5. Provider=Phinecos_Device  
  6. DriverVer=20/2/2000,3.0.0.3  
  7.  
  8. ; If device fits one of the standard classes, use the name and GUID here,  
  9. ; otherwise create your own device class and GUID as this example shows.  
  10.  
  11. Class=PhinecosDevice  
  12. ClassGUID={EF2962F0-0D55-4bff-B8AA-2221EE8A79B0}  
  13.  
  14.  
  15. ;--------- SourceDiskNames and SourceDiskFiles Section -----------------------  
  16.  
  17. ; These sections identify source disks and files for installation. They are  
  18. ; shown here as an example, but commented out.  
  19.  
  20. [SourceDisksNames]  
  21. 1 = "HelloWDM",Disk1,,  
  22.  
  23. [SourceDisksFiles]  
  24. HelloWDM.sys = 1,MyDriver_Check,  
  25.  
  26. ;--------- ClassInstall/ClassInstall32 Section -------------------------------  
  27.  
  28. ; Not necessary if using a standard class 
  29.  
  30. ; 9X Style  
  31. [ClassInstall]  
  32. Addreg=Class_AddReg  
  33.  
  34. ; NT Style  
  35. [ClassInstall32]  
  36. Addreg=Class_AddReg  
  37.  
  38. [Class_AddReg]  
  39. HKR,,,,%DeviceClassName%  
  40. HKR,,Icon,,"-5" 
  41.  
  42. ;--------- DestinationDirs Section -------------------------------------------  
  43.  
  44. [DestinationDirs]  
  45. YouMark_Files_Driver = 10,System32\Drivers  
  46.  
  47. ;--------- Manufacturer and Models Sections ----------------------------------  
  48.  
  49. [Manufacturer]  
  50. %MfgName%=Mfg0  
  51.  
  52. [Mfg0]  
  53.  
  54. ; PCI hardware Ids use the form  
  55. ; PCI\VEN_aaaa&DEV_bbbb&SUBSYS_cccccccc&REV_dd  
  56. ;改成你自己的ID  
  57. %DeviceDesc%=YouMark_DDI, PCI\VEN_9999&DEV_9999  
  58.  
  59. ;---------- DDInstall Sections -----------------------------------------------  
  60. ; --------- Windows 9X -----------------  
  61.  
  62. ; Experimentation has shown that DDInstall root names greater than 19 characters  
  63. ; cause problems in Windows 98  
  64.  
  65. [YouMark_DDI]  
  66. CopyFiles=YouMark_Files_Driver  
  67. AddReg=YouMark_9X_AddReg  
  68.  
  69. [YouMark_9X_AddReg]  
  70. HKR,,DevLoader,,*ntkern  
  71. HKR,,NTMPDriver,,HelloWDM.sys  
  72. HKR, "Parameters""BreakOnEntry", 0x00010001, 0  
  73.  
  74. ; --------- Windows NT -----------------  
  75.  
  76. [YouMark_DDI.NT]  
  77. CopyFiles=YouMark_Files_Driver  
  78. AddReg=YouMark_NT_AddReg  
  79.  
  80. [YouMark_DDI.NT.Services]  
  81. Addservice = HelloWDM, 0x00000002, YouMark_AddService  
  82.  
  83. [YouMark_AddService]  
  84. DisplayName = %SvcDesc%  
  85. ServiceType = 1 ; SERVICE_KERNEL_DRIVER  
  86. StartType = 3 ; SERVICE_DEMAND_START  
  87. ErrorControl = 1 ; SERVICE_ERROR_NORMAL  
  88. ServiceBinary = %10%\System32\Drivers\HelloWDM.sys  
  89.  
  90. [YouMark_NT_AddReg]  
  91. HKLM, "System\CurrentControlSet\Services\HelloWDM\Parameters",\  
  92. "BreakOnEntry", 0x00010001, 0  
  93.  
  94.  
  95. ; --------- Files (common) -------------  
  96.  
  97. [YouMark_Files_Driver]  
  98. HelloWDM.sys  
  99.  
  100. ;--------- Strings Section ---------------------------------------------------  
  101.  
  102. [Strings]  
  103. ProviderName="Phinecos." 
  104. MfgName="Vista Soft" 
  105. DeviceDesc="Hello World WDM!" 
  106. DeviceClassName="Phinecos_Device" 
  107. SvcDesc="Phinecos" 

 这里有两种安装方式,一种是进入控制面板,选择添加硬件,加载进inf文件完成安装,如图所示:

 

 

 

 

     另一种可选的安装测试方式是使用Driver Studio中的EzDriverInstaller工具来进行安装,如图所示: