设备scan和驱动入门安装

从一个接口开始,扫描硬件设备:

#include   <cfgmgr32.h> 
BOOL   ScanForHardwareChange() 

        DEVINST   devInst; 
        CONFIGERT   status; 
        
        //得到设备管理树的根结点 
        status   =   CM_Locate_DevNode(&devInst,NULL,CM_LOCATE_DEVNODE_NARMAL); 
        if   (status!=CR_SUCCESS) 
        { 
                printf( "CM_Locate_DevNode   failed:   %x\n ",status); 
                return   FALSE; 
        } 


        //刷新 
        status   =   CM_Reenumerate_DevNode(devInst,CM_REENUMERATE_ASYNCHRONOUS); //CM_REENUMERATE_ASYNCHRONOUS 异步方式可以立即响应
        if   (status   !=CR_SUCCESS) 
        { 
                printf( "CM_Reenumerate_DevNode   failed:   %x\n ",status); 
                return   FALSE; 
        } 
        return   TRUE; 


一 驱动入门实例

VS2012编译调试WDM驱动(KdPrint无调试信息 debugview win7无调试信息)

对于WDM驱动 VS2012有向导可以新建WDM项目 如图 这点说明不用自己配置 文件目录 C/C++ 选项 LINK 选项 等一系列的参数 比以前方便了不少


新建以后是空项目 放入《windows驱动开发技术详解》中第一章的WDM代码

分别是: HelloWDM.h

[cpp]  view plain  copy
  1. #if __cplusplus  
  2. extern "C"  
  3. {  
  4. #endif  
  5. #include <wdm.h>  
  6. #ifdef __cplusplus  
  7. }  
  8. #endif  
  9.   
  10. typedef struct _DEVICE_EXTERSION  
  11. {  
  12.     PDEVICE_OBJECT fdo;  
  13.     PDEVICE_OBJECT NextStatckDevice;  
  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_set("INIT")  
  21.   
  22. #define PAGEDDATA data_set("PAGE")  
  23. #define LOCKEDDATA data_set()  
  24. #define INITDATA data_set("INIT")  
  25.   
  26. #define arraysize(p) (sizeof(p)/sizeof((p)[0]))  
  27.   
  28. NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject);  
  29. NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo, IN PIRP Irp);  
  30. NTSTATUS HelloWDMDispatchRoutine(IN PDEVICE_OBJECT fdo, IN PIRP Irp);  
  31. void HelloWDMUnload(IN PDRIVER_OBJECT DriverObject);  
  32. NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION pdx, PIRP Irp);  
  33. NTSTATUS HandleRemoveDevice(PDEVICE_EXTENSION pdx, PIRP Irp);  
  34.   
  35. extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);  

HelloWDM.cpp

[cpp]  view plain  copy
  1. #include "HelloWDM.h"  
  2.   
  3. #pragma INITCODE  
  4. extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath)  
  5. {  
  6.     KdPrint(("Entry DriverEntry\n"));  
  7.   
  8.     pDriverObject->DriverExtension->AddDevice = HelloWDMAddDevice;  
  9.     pDriverObject->MajorFunction[IRP_MJ_PNP] = HelloWDMPnp;  
  10.     pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =   
  11.     pDriverObject->MajorFunction[IRP_MJ_CREATE] =   
  12.     pDriverObject->MajorFunction[IRP_MJ_READ] =   
  13.     pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloWDMDispatchRoutine;  
  14.     pDriverObject->DriverUnload = HelloWDMUnload;  
  15.   
  16.     KdPrint(("Leave DriverEntry\n"));  
  17.     return STATUS_SUCCESS;  
  18. }  
  19.   
  20. #pragma PAGECODE  
  21. NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject)  
  22. {  
  23.     PAGED_CODE();  
  24.   
  25.     KdPrint(("Enter HelloWDMAddDevice\n"));  
  26.   
  27.     NTSTATUS status;  
  28.     PDEVICE_OBJECT fdo;  
  29.     UNICODE_STRING devName;  
  30.     RtlInitUnicodeString(&devName, L"\\Device\\MyWDMDevice");  
  31.     status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), &(UNICODE_STRING)devName, FILE_DEVICE_UNKNOWN, 0, FALSE, &fdo);  
  32.     if(!NT_SUCCESS(status))  
  33.         return status;  
  34.     PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;  
  35.     pdx->fdo = fdo;  
  36.     pdx->NextStatckDevice = IoAttachDeviceToDeviceStack(fdo, PhysicalDeviceObject);  
  37.     UNICODE_STRING symLinkName;  
  38.     RtlInitUnicodeString(&symLinkName, L"\\DosDevices\\HelloWDM");  
  39.   
  40.     pdx->ustrDeviceName = devName;  
  41.     pdx->ustrSymLinkName = symLinkName;  
  42.     status = IoCreateSymbolicLink(&(UNICODE_STRING)symLinkName, &(UNICODE_STRING)devName);  
  43.     if(!NT_SUCCESS(status))  
  44.     {  
  45.         IoDeleteSymbolicLink(&pdx->ustrSymLinkName);  
  46.         status = IoCreateSymbolicLink(&symLinkName, &devName);  
  47.         if(!NT_SUCCESS(status))  
  48.         {  
  49.             return status;  
  50.         }  
  51.     }  
  52.   
  53.     fdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;  
  54.     fdo->Flags &= ~DO_DEVICE_INITIALIZING;  
  55.   
  56.     KdPrint(("Leave HelloWDMAddDevice\n"));  
  57.     return STATUS_SUCCESS;  
  58. }  
  59.   
  60. #pragma PAGEDCODE  
  61. NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo, IN PIRP Irp)  
  62. {  
  63.     PAGED_CODE();  
  64.   
  65.     KdPrint(("Enter HelloWDMPnp\n"));  
  66.   
  67.     NTSTATUS status = STATUS_SUCCESS;  
  68.     PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;  
  69.     PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);  
  70.     static NTSTATUS (*fcntab[])(PDEVICE_EXTENSION pdx, PIRP Irp)=  
  71.     {  
  72.         DefaultPnpHandler,  
  73.         DefaultPnpHandler,  
  74.         HandleRemoveDevice,  
  75.         DefaultPnpHandler,  
  76.         DefaultPnpHandler,  
  77.         DefaultPnpHandler,  
  78.         DefaultPnpHandler,  
  79.         DefaultPnpHandler,  
  80.         DefaultPnpHandler,  
  81.         DefaultPnpHandler,  
  82.         DefaultPnpHandler,  
  83.         DefaultPnpHandler,  
  84.         DefaultPnpHandler,  
  85.         DefaultPnpHandler,  
  86.         DefaultPnpHandler,  
  87.         DefaultPnpHandler,  
  88.         DefaultPnpHandler,  
  89.         DefaultPnpHandler,  
  90.         DefaultPnpHandler,  
  91.         DefaultPnpHandler,  
  92.         DefaultPnpHandler,  
  93.         DefaultPnpHandler,  
  94.         DefaultPnpHandler,  
  95.         DefaultPnpHandler,  
  96.     };  
  97.   
  98.     ULONG fcn = stack->MinorFunction;  
  99.     if(fcn >= arraysize(fcntab))  
  100.     {  
  101.         status = DefaultPnpHandler(pdx, Irp);  
  102.         return status;  
  103.     }  
  104.   
  105.     status = (*fcntab[fcn])(pdx, Irp);  
  106.     KdPrint(("Leave HelloWDMPnp\n"));  
  107.   
  108.     return status;  
  109. }  
  110.   
  111. #pragma PAGEDCODE  
  112. NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION pdx, PIRP Irp)  
  113. {  
  114.     PAGED_CODE();  
  115.     KdPrint(("Enter DefaultPnpHandler\n"));  
  116.     IoSkipCurrentIrpStackLocation(Irp);  
  117.     KdPrint(("Leave DefaultPnpHandler\n"));  
  118.     return IoCallDriver(pdx->NextStatckDevice, Irp);  
  119. }  
  120.   
  121. #pragma PAGEDCODE  
  122. NTSTATUS HandleRemoveDevice(PDEVICE_EXTENSION pdx, PIRP Irp)  
  123. {  
  124.     PAGED_CODE();  
  125.     KdPrint(("Enter HandlerRemoveDevice\n"));  
  126.   
  127.     Irp->IoStatus.Status = STATUS_SUCCESS;  
  128.     NTSTATUS status = DefaultPnpHandler(pdx, Irp);  
  129.     IoDeleteSymbolicLink(&(UNICODE_STRING)pdx->ustrSymLinkName);  
  130.   
  131.     if(pdx->NextStatckDevice)  
  132.         IoDetachDevice(pdx->NextStatckDevice);  
  133.   
  134.     IoDeleteDevice(pdx->fdo);  
  135.     KdPrint(("Leave HandlerRemoveDevice\n"));  
  136.   
  137.     return status;  
  138. }  
  139.   
  140. #pragma PAGEDCODE  
  141. NTSTATUS HelloWDMDispatchRoutine(IN PDEVICE_OBJECT fdo, IN PIRP Irp)  
  142. {  
  143.     PAGED_CODE();  
  144.     KdPrint(("Enter HelloWDMDispatchRoutine\n"));  
  145.     Irp->IoStatus.Status = STATUS_SUCCESS;  
  146.     Irp->IoStatus.Information = 0;  
  147.     IoCompleteRequest(Irp, IO_NO_INCREMENT);  
  148.     KdPrint(("Leave HelloWdmDispatchRoutine\n"));  
  149.       
  150.     return STATUS_SUCCESS;  
  151. }  
  152.   
  153. #pragma PAGEDCODE  
  154. void HelloWDMUnload(IN PDRIVER_OBJECT DriverObject)  
  155. {  
  156.     PAGED_CODE();  
  157.     KdPrint(("Enter HelloWDMUnload\n"));  
  158.     KdPrint(("Leave HelloWDMUnload\n"));  
  159. }  

代码放置后工程目录如图:



项目默认是vista的debug版本 修改为 win7 debug



然后build工程 出现错误:



错误原因是因为 警告级别设置过高 将警告级别改为W3等级 如图



设置后编译通过 生成了MyDriver1.sys文件 MyDriver1.inf文件 这个时候修改inf文件为:如果没有产生INF文件则自己新建一个

[cpp]  view plain  copy
  1. ;--------- Version Section ---------------------------------------------------  
  2.   
  3. [Version]  
  4. Signature="$CHICAGO$";  
  5. Provider=Zhangfan_Device  
  6. DriverVer=07/19/2013,15.16.19.288  
  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=ZhangfanDevice  
  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. MyDriver1.sys = 1,,  
  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,,MyDriver1.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\MyDriver1.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. MyDriver1.sys  
  99.   
  100. ;--------- Strings Section ---------------------------------------------------  
  101.   
  102. [Strings]  
  103. ProviderName="Zhangfan."  
  104. MfgName="Zhangfan Soft"  
  105. DeviceDesc="Hello World WDM!"  
  106. DeviceClassName="Zhangfan_Device"  
  107. SvcDesc="Zhangfan"  

接下来是加载驱动 使用EzDriverInstaller工具 下载地址:http://download.csdn.NET/detail/whatday/5782597

把MyDriver1.sys和MyDriver1.inf拷贝到VM的win7下,用EzDriverInstaller打开inf文件 如图



这时打开Dbgview 进行调试信息的监视

点击 Add New Device按钮后 设备添加成功 但是DbgView中没有出现调试信息



原因在于 win7/vista下需要修改调试信息过滤的键值 具体做法是

新建一个1.reg文件,写入如下内容:

[cpp]  view plain  copy
  1. Windows Registry Editor Version 5.00  
  2.   
  3. [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Debug Print Filter]  
  4.   
  5. "DEFAULT"=dword:00000008  

导入重启之后,OK。键值00000008不行 可以改为0000000f尝试 我这边测试08是成功的。

重启后再次开启 EzDriverInstaller 和 DbgView 再次点击 Add New Device 这时发现已经有调试信息了


接下来就是调试WDM驱动,便于测试在驱动中添加一个 读取制定函数SSDT地址的功能  修改后的代码如下:

HelloWDM.h:

[cpp]  view plain  copy
  1. #include "HelloWDM.h"  
  2.   
  3. #pragma INITCODE  
  4. extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath)  
  5. {  
  6.     KdPrint(("Entry DriverEntry\n"));  
  7.   
  8.     pDriverObject->DriverExtension->AddDevice = HelloWDMAddDevice;  
  9.     pDriverObject->MajorFunction[IRP_MJ_PNP] = HelloWDMPnp;  
  10.     pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =   
  11.     pDriverObject->MajorFunction[IRP_MJ_CREATE] =   
  12.     pDriverObject->MajorFunction[IRP_MJ_READ] =   
  13.     pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloWDMDispatchRoutine;  
  14.     pDriverObject->DriverUnload = HelloWDMUnload;  
  15.   
  16.     KdPrint(("Leave DriverEntry\n"));  
  17.   
  18.     DbgBreakPoint();  
  19.   
  20.     ULONG SSDT_NtOpenProcess_Cur_Addr;  
  21.     ULONG dwAddr = (ULONG)KeServiceDescriptorTable->pSSDTBase;  
  22.     KdPrint(("当前SSDT的基地址是:0x%x\n", dwAddr));  
  23.     SSDT_NtOpenProcess_Cur_Addr = *(PULONG)(dwAddr + 4*190);  
  24.     KdPrint(("当前NtOpenProcess的地址是0x%x\n", SSDT_NtOpenProcess_Cur_Addr));  
  25.   
  26.     return STATUS_SUCCESS;  
  27. }  
  28.   
  29. #pragma PAGECODE  
  30. NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject)  
  31. {  
  32.     PAGED_CODE();  
  33.   
  34.     KdPrint(("Enter HelloWDMAddDevice\n"));  
  35.   
  36.     NTSTATUS status;  
  37.     PDEVICE_OBJECT fdo;  
  38.     UNICODE_STRING devName;  
  39.     RtlInitUnicodeString(&devName, L"\\Device\\MyWDMDevice");  
  40.     status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), &(UNICODE_STRING)devName, FILE_DEVICE_UNKNOWN, 0, FALSE, &fdo);  
  41.     if(!NT_SUCCESS(status))  
  42.         return status;  
  43.     PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;  
  44.     pdx->fdo = fdo;  
  45.     pdx->NextStatckDevice = IoAttachDeviceToDeviceStack(fdo, PhysicalDeviceObject);  
  46.     UNICODE_STRING symLinkName;  
  47.     RtlInitUnicodeString(&symLinkName, L"\\DosDevices\\HelloWDM");  
  48.        
  49.     pdx->ustrDeviceName = devName;  
  50.     pdx->ustrSymLinkName = symLinkName;  
  51.     status = IoCreateSymbolicLink(&(UNICODE_STRING)symLinkName, &(UNICODE_STRING)devName);  
  52.     if(!NT_SUCCESS(status))  
  53.     {  
  54.         IoDeleteSymbolicLink(&pdx->ustrSymLinkName);  
  55.         status = IoCreateSymbolicLink(&symLinkName, &devName);  
  56.         if(!NT_SUCCESS(status))  
  57.         {  
  58.             return status;  
  59.         }  
  60.     }  
  61.   
  62.     fdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;  
  63.     fdo->Flags &= ~DO_DEVICE_INITIALIZING;  
  64.   
  65.     KdPrint(("Leave HelloWDMAddDevice\n"));  
  66.     return STATUS_SUCCESS;  
  67. }  
  68.   
  69. #pragma PAGEDCODE  
  70. NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo, IN PIRP Irp)  
  71. {  
  72.     PAGED_CODE();  
  73.   
  74.     KdPrint(("Enter HelloWDMPnp\n"));  
  75.   
  76.     NTSTATUS status = STATUS_SUCCESS;  
  77.     PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;  
  78.     PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);  
  79.     static NTSTATUS (*fcntab[])(PDEVICE_EXTENSION pdx, PIRP Irp)=  
  80.     {  
  81.         DefaultPnpHandler,  
  82.         DefaultPnpHandler,  
  83.         HandleRemoveDevice,  
  84.         DefaultPnpHandler,  
  85.         DefaultPnpHandler,  
  86.         DefaultPnpHandler,  
  87.         DefaultPnpHandler,  
  88.         DefaultPnpHandler,  
  89.         DefaultPnpHandler,  
  90.         DefaultPnpHandler,  
  91.         DefaultPnpHandler,  
  92.         DefaultPnpHandler,  
  93.         DefaultPnpHandler,  
  94.         DefaultPnpHandler,  
  95.         DefaultPnpHandler,  
  96.         DefaultPnpHandler,  
  97.         DefaultPnpHandler,  
  98.         DefaultPnpHandler,  
  99.         DefaultPnpHandler,  
  100.         DefaultPnpHandler,  
  101.         DefaultPnpHandler,  
  102.         DefaultPnpHandler,  
  103.         DefaultPnpHandler,  
  104.         DefaultPnpHandler,  
  105.     };  
  106.   
  107.     ULONG fcn = stack->MinorFunction;  
  108.     if(fcn >= arraysize(fcntab))  
  109.     {  
  110.         status = DefaultPnpHandler(pdx, Irp);  
  111.         return status;  
  112.     }  
  113.   
  114.     status = (*fcntab[fcn])(pdx, Irp);  
  115.     KdPrint(("Leave HelloWDMPnp\n"));  
  116.   
  117.     return status;  
  118. }  
  119.   
  120. #pragma PAGEDCODE  
  121. NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION pdx, PIRP Irp)  
  122. {  
  123.     PAGED_CODE();  
  124.     KdPrint(("Enter DefaultPnpHandler\n"));  
  125.     IoSkipCurrentIrpStackLocation(Irp);  
  126.     KdPrint(("Leave DefaultPnpHandler\n"));  
  127.     return IoCallDriver(pdx->NextStatckDevice, Irp);  
  128. }  
  129.   
  130. #pragma PAGEDCODE  
  131. NTSTATUS HandleRemoveDevice(PDEVICE_EXTENSION pdx, PIRP Irp)  
  132. {  
  133.     PAGED_CODE();  
  134.     KdPrint(("Enter HandlerRemoveDevice\n"));  
  135.   
  136.     Irp->IoStatus.Status = STATUS_SUCCESS;  
  137.     NTSTATUS status = DefaultPnpHandler(pdx, Irp);  
  138.     IoDeleteSymbolicLink(&(UNICODE_STRING)pdx->ustrSymLinkName);  
  139.   
  140.     if(pdx->NextStatckDevice)  
  141.         IoDetachDevice(pdx->NextStatckDevice);  
  142.   
  143.     IoDeleteDevice(pdx->fdo);  
  144.     KdPrint(("Leave HandlerRemoveDevice\n"));  
  145.   
  146.     return status;  
  147. }  
  148.   
  149. #pragma PAGEDCODE  
  150. NTSTATUS HelloWDMDispatchRoutine(IN PDEVICE_OBJECT fdo, IN PIRP Irp)  
  151. {  
  152.     PAGED_CODE();  
  153.     KdPrint(("Enter HelloWDMDispatchRoutine\n"));  
  154.     Irp->IoStatus.Status = STATUS_SUCCESS;  
  155.     Irp->IoStatus.Information = 0;  
  156.     IoCompleteRequest(Irp, IO_NO_INCREMENT);  
  157.     KdPrint(("Leave HelloWdmDispatchRoutine\n"));  
  158.       
  159.     return STATUS_SUCCESS;  
  160. }  
  161.   
  162. #pragma PAGEDCODE  
  163. void HelloWDMUnload(IN PDRIVER_OBJECT DriverObject)  
  164. {  
  165.     PAGED_CODE();  
  166.     KdPrint(("Enter HelloWDMUnload\n"));  
  167.     KdPrint(("Leave HelloWDMUnload\n"));  
  168. }  
由于添加了断点代码所以需要打开windbg双机调试,代码编译后覆盖WIN7中的sys文件 用EzDriverInstaller工具加载INF文件 这里可以点击“Update Driver”  发现和以前一样,


没有打印出SSDT的相关信息 ,初步估计还是加载了上次的SYS文件,WIN7系统肯定有备份存档之类的,在C盘搜索MyDriver1.sys 得到4个路径如图:


其中第一个路径 刚才已经覆盖过 但是驱动显示的结果没有变化所以 这里先pass掉

然后依次测试第二 第三,当测试到第三个路径时出现权限问题:

返回上一级目录 对该目录右键 设置管理员取得所有权:

设置后就可以成功覆盖SYS文件了 用EzDriverInstaller工具加载 发现覆盖驱动后 调试信息发生了变化 如图:


一般来说win7的驱动备份文件夹都是各个优化软件的减肥首选,由此看来win7的驱动备份文件夹也不是完全无用的,至少更新驱动的时候还是需要用到。

至此VS2012编译调试WDM驱动就完毕了,现在可以随意的修改调试我们的WDM程序了。

这里需要注意 “Add New Device”测试完毕后 一定要“Remove Device”因为如果重启WIN7 进入正常模式(非DEBUG模式)它会自动加载我们的WDM驱动 如果驱动中有断点API或错误 就会蓝屏挂掉。当然如果是进入DEBUG模式,然后双机调试就可以看到在windbg中断下来了,断点位置就是我们程序中设置的断点API代码。


最后再附上 win7/ vista下为什么需要修改调试信息过滤键值的原因 原文如下

在OSR查了下资料,摘录如下:

The problem: Your DbgPrint or KdPrint messages don't appear in WinDbg (or KD) when you run your driver on Windows Vista.

The reason?  Vista automatically maps DbgPrint and friends to DbgPrintEx.  Now, you may recall that DbgPrintEx allows you to control the conditions under which messages will be sent to the kernel debugger by filtering messages via a component name and level in the function call and an associated filter mask in either the registry or in memory. 

In Vista, DbgPrint and KdPrint are mapped to component "DPFLTR_DEFAULT_ID" and level "DPFLTR_INFO_LEVEL".  Of course, in Vista, xxx_INFO_LEVEL output is disabled by default.  So, by default, your DbgPrint/KdPrint doesn't get sent to the kernel debugger.

 

How to fix it? Two choices:

  • Enable output of DbgPrint/KdPrint messages by default --Open the key "HKLM/SYSTEM/CCS/Control/Session Manager/Debug Print Filter".  Under this key, create a  value with the name "DEFAULT"  Set the value of this key equal to the DWORD value 8 to enable xxx_INFO_LEVEL output as well as xxx_ERROR_LEVEL output.  Or try setting the mask to 0xF so you get all output.  You must reboot for these changes to take effect.

  • Specifically change the component filter mast for DPFLTR.  In early releases of Vista/LH you changed the default printout mask by specifying a mask value for the DWORD at Kd_DPFLTR_MASK ("ed Kd_DPFLTR_MASK").  In build 5308 (the February CTP of Vista), it seems that the mask variable has changed and you need to set the mask value for the DWORD at Kd_DEFAULT_MASK ("ed Kd_DEFAULT_MASK).  In either case, specify 8 to enable DPFLTR_INFO_LEVEL output in addition to DPFLTR_ERROR_LEVEL output, or 0xF to get all levels of output.

See the WDK documentation for Reading and Filtering Debugging Messages (follow the path: Driver Development Tools/Tools for Debugging Drivers/Using Debugging Code in a Driver/Debugging Code Overview) for the complete details on the use of DbgPrintEx/KdPrintEx.  Or look at the Debugging Tools For Windows documentation (Appendix A) on DbgPrintEx.


2 驱动安装与卸载

编译环境:VS2012 + WIN8 64 

测试环境:VM WIN7

测试对象:WDM驱动 (sys文件 和 inf文件)

项目类型:Win32 Console Application

其它说明:代码来源于网络,经小修改而成,加载驱动方法还有很多(如SetupCopyOEMInf等OEM系列函数),但是逆向EzDriverInstaller驱动加载器,发现和下面代码逻辑基本一致,所以最终记录以下代码,以便日后使用。

代码如下:

[cpp]  view plain  copy
  1. // WinInstallWin.cpp :   
  2. //  
  3.   
  4. #include "stdafx.h"  
  5.   
  6. #include <windows.h>  
  7. #include <newdev.h>  
  8. #include <setupapi.h>  
  9. #include <locale.h>  
  10.   
  11. #pragma comment(lib, "newdev.lib")  
  12. #pragma comment(lib, "setupapi.lib")  
  13.   
  14. #ifndef MAX_DEVICE_ID_LEN  
  15. #define MAX_DEVICE_ID_LEN     200  
  16. #define MAX_DEVNODE_ID_LEN    MAX_DEVICE_ID_LEN  
  17. #define MAX_GUID_STRING_LEN   39          // 38 chars + terminator null  
  18. #define MAX_CLASS_NAME_LEN    32  
  19. #endif  
  20.   
  21.   
  22. WORD g_wVender = 0;  
  23. WORD g_wHardware = 0;  
  24. TCHAR g_strVender[20][64] = {0};  
  25. TCHAR g_strHardware[20][64] = {0};  
  26. TCHAR g_strHID[MAX_PATH+1] = {0};  
  27.   
  28. //打印错误  
  29. VOID ShowErrorMsg(DWORD Count,LPCWSTR szData)  
  30. {  
  31.     printf("%d\n%s",&Count,&szData);  
  32. }  
  33.   
  34. //过滤字符  
  35. VOID FindComma(LPSTR szData)  
  36. {  
  37.     WORD wLen = (WORD)strlen(szData);  
  38.     WORD wIdx;  
  39.     WORD wLoop;   
  40.     CHAR szTmp[128] = {0};  
  41.   
  42.     for (wIdx = 0, wLoop = 0; wLoop < wLen; wLoop++)  
  43.     {  
  44.         if (szData[wLoop] == ',')  
  45.             szData[wLoop] = '.';  
  46.         else if (szData[wLoop] == ' ')  
  47.             continue;  
  48.         szTmp[wIdx++] = szData[wLoop];  
  49.     }  
  50.     memcpy(szData, szTmp, wIdx*sizeof(char));  
  51.     szData[wIdx] = 0;  
  52. }  
  53.   
  54. //去除字符串左边的空格  
  55. VOID StrLTrim(LPSTR szData)  
  56. {  
  57.     LPSTR ptr = szData;  
  58.     //判断是否为空格  
  59.     while (isspace(*ptr))  
  60.             ptr++;  
  61.   
  62.     if (strcmp(ptr, szData))  
  63.     {  
  64.         WORD wLen = (WORD)(strlen(szData) - (ptr - szData));  
  65.         memmove(szData, ptr, (wLen+1)*sizeof(char));  
  66.     }  
  67. }  
  68.   
  69. //去除字符串右边的空格  
  70. VOID StrRTrim(LPSTR szData)  
  71. {  
  72.     LPSTR ptr  = szData;  
  73.     LPSTR pTmp = NULL;  
  74.   
  75.     //debug模式下 使用isspace判断中文 需要设置编码  
  76.     #if defined(WIN32) && defined(_DEBUG)  
  77.     char* locale = setlocale( LC_ALL, ".OCP" );  
  78.     #endif   
  79.   
  80.     while (*ptr != 0)  
  81.     {  
  82.         //判断是否为空格  
  83.         if (isspace(*ptr))  
  84.         {  
  85.             if (!pTmp)  
  86.                 pTmp = ptr;  
  87.         }  
  88.         else  
  89.             pTmp = NULL;  
  90.         ptr++;  
  91.     }  
  92.   
  93.     if (pTmp)  
  94.     {  
  95.         *pTmp = 0;  
  96.         memmove(szData, szData, strlen(szData) - strlen(pTmp));  
  97.     }  
  98. }  
  99.   
  100. //从字符串右边开始截取字符串  
  101. VOID StrRight(LPSTR szData, WORD wCount)  
  102. {  
  103.     WORD wLen = (WORD)strlen(szData) - wCount;  
  104.   
  105.     if (wCount > 0x7FFF)//负数  
  106.         wCount = 0;  
  107.     if (wCount >= (WORD)strlen(szData))  
  108.         return;  
  109.   
  110.     memmove(szData, szData + wLen, wCount * sizeof(char));  
  111.     szData[wCount] = 0;  
  112. }  
  113.   
  114. VOID ConvertGUIDToString(const GUID guid, LPSTR pData)  
  115. {  
  116.     CHAR szData[30] = {0};  
  117.     CHAR szTmp[3]   = {0};  
  118.     WORD wLoop;  
  119.   
  120.     sprintf_s(pData, _countof(szData), "%04X-%02X-%02X-", guid.Data1, guid.Data2, guid.Data3);  
  121.     for (wLoop = 0; wLoop < 8; wLoop++)  
  122.     {  
  123.         if (wLoop == 2)  
  124.             strcat_s(szData, "-");  
  125.         sprintf_s(szTmp, _countof(szTmp), "%02X", guid.Data4[wLoop]);  
  126.         strcat_s(szData, szTmp);  
  127.     }  
  128.   
  129.     memcpy(pData + strlen(pData), szData, strlen(szData));  
  130. }  
  131.   
  132. BOOL AnsiToUnicode(LPCSTR Source, const WORD sLen, LPWSTR Destination, const WORD wLen)  
  133. {  
  134.     return MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, Source, sLen, Destination, wLen);  
  135. }  
  136.   
  137. BOOL UnicodeToAnsi(LPCWSTR Source, const WORD wLen, LPSTR Destination, const WORD sLen)  
  138. {  
  139.     return WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, Source, wLen, Destination, sLen, 0L, 0L);  
  140. }  
  141.   
  142. // 初始化全局变量  
  143. __inline VOID InitialGlobalVar()  
  144. {  
  145.     WORD wLoop;  
  146.   
  147.     g_wVender = g_wHardware = 0;  
  148.     for (wLoop = 0; wLoop < 20; wLoop++)  
  149.     {  
  150.         RtlZeroMemory(g_strVender[wLoop], sizeof(TCHAR)*64);  
  151.         RtlZeroMemory(g_strHardware[wLoop], sizeof(TCHAR)*64);  
  152.     }  
  153. }  
  154.   
  155. //安装驱动功能  
  156. __inline BOOL IsInstalled()  
  157. {  
  158.     HDEVINFO hDevInfo = 0L;  
  159.     SP_DEVINFO_DATA spDevInfoData = {0L};  
  160.     WORD wIdx;  
  161.     BOOL bIsFound;  
  162.   
  163.     //得到设备信息结构的句柄  
  164.     hDevInfo = SetupDiGetClassDevs(0L, 0, 0, DIGCF_ALLCLASSES | DIGCF_PRESENT);  
  165.     if (hDevInfo == INVALID_HANDLE_VALUE)  
  166.     {  
  167.         ShowErrorMsg(GetLastError(), _T("SetupDiGetClassDevs"));  
  168.         return FALSE;  
  169.     }  
  170.   
  171.     spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);  
  172.     wIdx = 0;  
  173.     bIsFound = 0;  
  174.     while (++wIdx)  
  175.     {  
  176.         //找到所有的硬件设备,并且可以得到所有的硬件设备的详细信息  
  177.         if (SetupDiEnumDeviceInfo(hDevInfo, wIdx, &spDevInfoData))  
  178.         {  
  179.             LPTSTR ptr;  
  180.             LPBYTE pBuffer = NULL;  
  181.             DWORD dwData  = 0L;  
  182.             DWORD dwRetVal;  
  183.             DWORD dwBufSize = 0L;  
  184.   
  185.             while (TRUE)  
  186.             {  
  187.                 //可以在前面得到的指向某一个具体设备信息集合的指针中取出某一项信息  
  188.                 dwRetVal = SetupDiGetDeviceRegistryProperty(hDevInfo, &spDevInfoData, SPDRP_HARDWAREID,  
  189.                     &dwData, (PBYTE)pBuffer, dwBufSize, &dwBufSize);  
  190.                 if (!dwRetVal)  
  191.                     dwRetVal = GetLastError();  
  192.                 else  
  193.                     break;  
  194.                 if (dwRetVal == ERROR_INVALID_DATA)  
  195.                     break;  
  196.                 else if (dwRetVal == ERROR_INSUFFICIENT_BUFFER)  
  197.                 {  
  198.                     if (pBuffer)  
  199.                         LocalFree(pBuffer);  
  200.                     pBuffer = (LPBYTE)LocalAlloc(LPTR, dwBufSize);  
  201.                 }  
  202.                 else  
  203.                 {  
  204.                     ShowErrorMsg(dwRetVal, _T("SetupDiGetDeviceRegistryProperty"));  
  205.                     //销毁一个设备信息集合  
  206.                     SetupDiDestroyDeviceInfoList(hDevInfo);  
  207.                     return FALSE;  
  208.                 }  
  209.             }  
  210.   
  211.             if (dwRetVal == ERROR_INVALID_DATA)   
  212.                 continue;  
  213.   
  214.             for (ptr = (LPTSTR)pBuffer; *ptr && (ptr < (LPTSTR)&pBuffer[dwBufSize]); ptr += _tcslen(ptr) + sizeof(TCHAR))  
  215.             {  
  216.                 WORD wLoop;  
  217.   
  218.                 for (wLoop = 0; wLoop < g_wHardware; wLoop++)  
  219.                 {  
  220.                     if (!_tcscmp(g_strHardware[wLoop], ptr))  
  221.                     {  
  222.                         bIsFound = TRUE;  
  223.                         break;  
  224.                     }  
  225.                 }  
  226.             }  
  227.             if (pBuffer)  
  228.                 LocalFree(pBuffer);  
  229.             if (bIsFound)  
  230.                 break;  
  231.         }  
  232.     }  
  233.     //销毁一个设备信息集合  
  234.     SetupDiDestroyDeviceInfoList(hDevInfo);  
  235.     return bIsFound;  
  236. }  
  237.   
  238. //寻找指定的节名 如果找到返回TRUE 反之返回FALSE  
  239. BOOL FindSectionName(FILE *pFile, const char *szKey)  
  240. {  
  241.     char szData[256] = {0};  
  242.   
  243.     if (!pFile)  
  244.         return FALSE;  
  245.   
  246.     //将文件内部的位置指针重新指向一个流(数据流/文件)的开头  
  247.     rewind(pFile);  
  248.     //循环读取文件内容  
  249.     while (!feof(pFile))  
  250.     {  
  251.         //读取一行  
  252.         fgets(szData, 255, pFile);  
  253.         //去除前后空格  
  254.         StrLTrim(szData);  
  255.         StrRTrim(szData);  
  256.   
  257.         if (strcmp(szKey, szData) == 0)  
  258.             return TRUE;          
  259.     }  
  260.     return FALSE;  
  261. }  
  262.   
  263. //得到INF文件中节的数量  
  264. __inline BOOL GetSectionData(FILE* pFile, const char* szKey, const char bIsVender)  
  265. {  
  266.     char szData[128] = {0};  
  267.       
  268.     if (bIsVender)  
  269.         strcpy_s(szData, szKey);  
  270.     else  
  271.         sprintf_s(szData, _countof(szData), "[%s]", szKey);  
  272.   
  273.     if (FindSectionName(pFile, szData) == FALSE)  
  274.         return FALSE;  
  275.   
  276.     RtlZeroMemory(szData, sizeof(char)*128);  
  277.     while (!feof(pFile))  
  278.     {  
  279.         char *str = NULL;  
  280.         fgets(szData, 127, pFile);  
  281.         szData[strlen(szData)-1] = 0;  
  282.         StrLTrim(szData);  
  283.         StrRTrim(szData);  
  284.         if (!*szData)  
  285.             continue;  
  286.         if (szData[0] == ';')  
  287.             continue;  
  288.   
  289.         if (strchr(szData, '['))  
  290.         {  
  291.             StrLTrim(szData);  
  292.             if (szData[0] != ';')  
  293.                 return 1;  
  294.             else  
  295.                 continue;  
  296.         }  
  297.   
  298.         if (bIsVender)  
  299.             str = strchr(szData, '=');  
  300.         else  
  301.             str = strchr(szData, ',');  
  302.   
  303.         if (*str)  
  304.         {  
  305.             char szTmp[128] = {0};  
  306.             WORD pos = (WORD)(str - szData + 1);  
  307.   
  308.             StrRight(szData, (short)(strlen(szData)-pos));  
  309.             StrLTrim(szData);  
  310.             StrRTrim(szData);  
  311.             FindComma(szData);  
  312.             if (bIsVender)  
  313.             {  
  314.                 AnsiToUnicode(szData, strlen(szData), g_strVender[g_wVender++], 64);  
  315.             }  
  316.             else  
  317.             {  
  318.                 AnsiToUnicode(szData, strlen(szData), g_strHardware[g_wHardware++], 64);  
  319.             }  
  320.         }/* end if */  
  321.     }  
  322.     return TRUE;  
  323. }  
  324.   
  325. //得到INF文件相关数据  
  326. BOOL GetINFData(FILE *pFile)  
  327. {  
  328.     WORD wLoop;  
  329.   
  330.     if (!g_wVender || !g_wHardware)  
  331.         InitialGlobalVar();  
  332.     if (GetSectionData(pFile, "[Manufacturer]", TRUE) == FALSE)  
  333.         return 0;  
  334.                                  
  335.     for (wLoop = 0; wLoop < g_wVender; wLoop++)  
  336.     {  
  337.         CHAR szVender[64] = {0};  
  338.         UnicodeToAnsi(g_strVender[wLoop], _tcslen(g_strVender[wLoop]), szVender, 64);  
  339.         GetSectionData(pFile, szVender, FALSE);  
  340.     }  
  341.     if (g_wHardware != 0)  
  342.     {  
  343.         if (IsInstalled() == TRUE)//如果已经安装  
  344.             return FALSE;  
  345.         else  
  346.             return TRUE;  
  347.     }  
  348.     return FALSE;  
  349. }  
  350.   
  351. //实质性的安装驱动  
  352. __inline BOOL InstallClassDriver(LPCTSTR theINFName)  
  353. {  
  354.     GUID guid = {0};  
  355.     SP_DEVINFO_DATA spDevData = {0};  
  356.     HDEVINFO hDevInfo = 0L;  
  357.     TCHAR className[MAX_CLASS_NAME_LEN] = {0};  
  358.     LPTSTR pHID = NULL;  
  359.     WORD wLoop;  
  360.     BOOL bRebootRequired;  
  361.   
  362.     //取得此驱动的GUID值  
  363.     if (!SetupDiGetINFClass(theINFName, &guid, className, MAX_CLASS_NAME_LEN, 0))  
  364.     {  
  365.         ShowErrorMsg(GetLastError(), _T("SetupDiGetINFClass"));  
  366.         return FALSE;  
  367.     }  
  368.   
  369.     //创建设备信息块列表  
  370.     hDevInfo = SetupDiCreateDeviceInfoList(&guid, 0);  
  371.     if (hDevInfo == INVALID_HANDLE_VALUE)  
  372.     {  
  373.         ShowErrorMsg(GetLastError(), _T("SetupDiCreateDeviceInfoList"));  
  374.         return FALSE;  
  375.     }  
  376.   
  377.     spDevData.cbSize = sizeof(SP_DEVINFO_DATA);  
  378.     //创建设备信息块  
  379.     if (!SetupDiCreateDeviceInfo(hDevInfo, className, &guid, 0L, 0L, DICD_GENERATE_ID, &spDevData))  
  380.     {  
  381.         ShowErrorMsg(GetLastError(), _T("SetupDiCreateDeviceInfo"));  
  382.         //销毁一个设备信息集合  
  383.         SetupDiDestroyDeviceInfoList(hDevInfo);  
  384.         return FALSE;  
  385.     }  
  386.   
  387.     for (wLoop = 0; wLoop < g_wHardware; wLoop++)  
  388.     {  
  389.         if (pHID)  
  390.             LocalFree(pHID);  
  391.   
  392.         pHID = (LPTSTR)LocalAlloc(LPTR, _tcslen(g_strHardware[wLoop])*2*sizeof(TCHAR));  
  393.         if (!pHID)  
  394.         {  
  395.             ShowErrorMsg(GetLastError(), _T("LocalAlloc"));  
  396.             //销毁一个设备信息集合  
  397.             SetupDiDestroyDeviceInfoList(hDevInfo);  
  398.             return FALSE;  
  399.         }  
  400.   
  401.         _tcscpy_s(pHID, _tcslen(g_strHardware[wLoop])*2, g_strHardware[wLoop]);  
  402.         //设定硬件ID  
  403.         if (!SetupDiSetDeviceRegistryProperty(hDevInfo, &spDevData, SPDRP_HARDWAREID, (PBYTE)pHID,  
  404.             (DWORD)(_tcslen(g_strHardware[wLoop])*2*sizeof(TCHAR))))  
  405.         {  
  406.             ShowErrorMsg(GetLastError(), _T("SetupDiSetDeviceRegistryProperty"));  
  407.             //销毁一个设备信息集合  
  408.             SetupDiDestroyDeviceInfoList(hDevInfo);  
  409.             LocalFree(pHID);  
  410.             return FALSE;  
  411.         }  
  412.         //调用相应的类程序来注册设备  
  413.         if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, hDevInfo, &spDevData))  
  414.         {  
  415.             ShowErrorMsg(GetLastError(), _T("SetupDiCallClassInstaller"));  
  416.             //销毁一个设备信息集合  
  417.             SetupDiDestroyDeviceInfoList(hDevInfo);  
  418.             LocalFree(pHID);  
  419.             return FALSE;  
  420.         }  
  421.   
  422.         bRebootRequired = FALSE;  
  423.         //安装更新和硬件ID相匹配的驱动程序  
  424.         if (!UpdateDriverForPlugAndPlayDevices(0L, g_strHardware[wLoop], theINFName,   
  425.             INSTALLFLAG_FORCE, &bRebootRequired))  
  426.         {  
  427.             DWORD dwErrorCode = GetLastError();  
  428.             //调用相应的类程序来移除设备  
  429.             if (!SetupDiCallClassInstaller(DIF_REMOVE, hDevInfo, &spDevData))  
  430.                 ShowErrorMsg(GetLastError(), _T("SetupDiCallClassInstaller(Remove)"));  
  431.             ShowErrorMsg((WORD)dwErrorCode, _T("UpdateDriverForPlugAndPlayDevices"));  
  432.             //销毁一个设备信息集合  
  433.             SetupDiDestroyDeviceInfoList(hDevInfo);  
  434.             LocalFree(pHID);  
  435.             return FALSE;  
  436.         }  
  437.         LocalFree(pHID);  
  438.         pHID = NULL;  
  439.     }  
  440.     //销毁一个设备信息集合  
  441.     SetupDiDestroyDeviceInfoList(hDevInfo);  
  442.     _tprintf(_T("Install Successed\n"));  
  443.     return TRUE;  
  444. }  
  445.   
  446. // 安装WDM驱动的测试工作  
  447. BOOL StartInstallWDMDriver(LPCTSTR theInfName)  
  448. {  
  449.     HDEVINFO hDevInfo = 0L;  
  450.     GUID guid = {0L};  
  451.     SP_DEVINSTALL_PARAMS spDevInst = {0L};  
  452.     TCHAR strClass[MAX_CLASS_NAME_LEN] = {0L};  
  453.   
  454.     //取得此驱动的GUID值  
  455.     if (!SetupDiGetINFClass(theInfName, &guid, strClass, MAX_CLASS_NAME_LEN, 0))  
  456.     {  
  457.         ShowErrorMsg(GetLastError(), _T("SetupDiGetINFClass"));  
  458.         return FALSE;  
  459.     }  
  460.   
  461.     //得到设备信息结构的句柄  
  462.     hDevInfo = SetupDiGetClassDevs(&guid, 0L, 0L, DIGCF_PRESENT | DIGCF_ALLCLASSES | DIGCF_PROFILE);  
  463.     if (!hDevInfo)  
  464.     {  
  465.         ShowErrorMsg(GetLastError(), _T("SetupDiGetClassDevs"));  
  466.         return FALSE;  
  467.     }  
  468.   
  469.       
  470.     spDevInst.cbSize = sizeof(SP_DEVINSTALL_PARAMS);  
  471.     //获得指定设备的安装信息  
  472.     if (!SetupDiGetDeviceInstallParams(hDevInfo, 0L, &spDevInst))  
  473.     {  
  474.         ShowErrorMsg(GetLastError(), _T("SetupDiGetDeviceInstallParams"));  
  475.         return FALSE;  
  476.     }  
  477.   
  478.     spDevInst.Flags   = DI_ENUMSINGLEINF;  
  479.     spDevInst.FlagsEx = DI_FLAGSEX_ALLOWEXCLUDEDDRVS;  
  480.     _tcscpy_s(spDevInst.DriverPath, _countof(spDevInst.DriverPath), theInfName);  
  481.   
  482.     //为设备信息集或者是一个实际的设备信息单元设置或清除类安装参数  
  483.     if (!SetupDiSetDeviceInstallParams(hDevInfo, 0, &spDevInst))  
  484.     {  
  485.         ShowErrorMsg(GetLastError(), _T("SetupDiSetDeviceInstallParams"));  
  486.         return FALSE;  
  487.     }  
  488.   
  489.     //获取这个设备的驱动程序信息列表  
  490.     if (!SetupDiBuildDriverInfoList(hDevInfo, 0, SPDIT_CLASSDRIVER))  
  491.     {  
  492.         ShowErrorMsg(GetLastError(), _T("SetupDiDeviceInstallParams"));  
  493.         return FALSE;  
  494.     }  
  495.   
  496.     //销毁一个设备信息集合  
  497.     SetupDiDestroyDeviceInfoList(hDevInfo);  
  498.   
  499.     //进入安装设备驱动函数  
  500.     return InstallClassDriver(theInfName);  
  501. }  
  502.   
  503. // 卸载WDM驱动  
  504. VOID UninstallWDMDriver(LPCTSTR theHardware)  
  505. {  
  506.     SP_DEVINFO_DATA spDevInfoData = {0};  
  507.     HDEVINFO hDevInfo = 0L;  
  508.     WORD wIdx, wCount = 0;  
  509.   
  510.     //得到设备信息结构的句柄  
  511.     hDevInfo = SetupDiGetClassDevs(0L, 0L, 0L, DIGCF_ALLCLASSES | DIGCF_PRESENT);  
  512.     if (hDevInfo == INVALID_HANDLE_VALUE)  
  513.     {  
  514.         ShowErrorMsg(GetLastError(), _T("SetupDiGetClassDevs"));  
  515.         return;  
  516.     }  
  517.   
  518.     wIdx = 0;  
  519.     while (TRUE)  
  520.     {  
  521.         spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);  
  522.         //找到所有的硬件设备,并且可以得到所有的硬件设备的详细信息  
  523.         if (SetupDiEnumDeviceInfo(hDevInfo, wIdx, &spDevInfoData))  
  524.         {  
  525.             char Buffer[2048] = {0};  
  526.   
  527.             //可以在前面得到的指向某一个具体设备信息集合的指针中取出某一项信息  
  528.             if (SetupDiGetDeviceRegistryProperty(hDevInfo, &spDevInfoData, SPDRP_HARDWAREID,  
  529.                 0L, (PBYTE)Buffer, 2048, 0L))  
  530.             {  
  531.                 if (!_tcscmp(theHardware, (LPTSTR)Buffer))  
  532.                 {  
  533.                     //从系统中删除一个注册的设备接口  
  534.                     if (!SetupDiRemoveDevice(hDevInfo, &spDevInfoData))  
  535.                         ShowErrorMsg(GetLastError(), _T("SetupDiRemoveDevice"));            
  536.                     wCount++;  
  537.                 }  
  538.             }  
  539.         }  
  540.         else  
  541.             break;  
  542.         wIdx++;  
  543.     }  
  544.   
  545.     if (wCount != 0)  
  546.         _tprintf(_T("UnInstall Successed\n"));  
  547.   
  548.     //销毁一个设备信息集合  
  549.     SetupDiDestroyDeviceInfoList(hDevInfo);  
  550.     InitialGlobalVar();  
  551.     return;  
  552. }  
  553.   
  554. //INF文件路径  
  555. const LPTSTR g_pInfPath = _T("C:\\Windows\\System32\\DriverStore\\FileRepository\\mydriver1.inf_x86_neutral_15204d1ef3d409a0\\mydriver1.inf");  
  556.   
  557. //入口函数  
  558. int _tmain(int argc, _TCHAR* argv[])  
  559. {  
  560.     CHAR szInfPath[MAX_PATH] = {0};  
  561.     UnicodeToAnsi(g_pInfPath, _tcslen(g_pInfPath), szInfPath, MAX_PATH);  
  562.     FILE* pInf;  
  563.     errno_t err;  
  564.   
  565.     if ((err=fopen_s(&pInf, szInfPath, "r"))!=0)  
  566.     {  
  567.         _tprintf(_T("can not open file %s\n"), g_pInfPath);  
  568.         return 0;  
  569.     }  
  570.   
  571.     // 获取INF文件数据  
  572.     GetINFData(pInf);  
  573.     fclose(pInf);  
  574.   
  575.     // 安装WDM驱动  
  576.     if(_tcscmp(argv[1], TEXT("-Install"))==0)  
  577.     {  
  578.         if (StartInstallWDMDriver(g_pInfPath) == FALSE)  
  579.         {  
  580.             _tprintf(_T("Start Install WMD Driver failed\n"));  
  581.             return 0;  
  582.         }  
  583.     }  
  584.     // 卸载WDM驱动  
  585.     else if(_tcscmp(argv[1], TEXT("-UnInstall"))==0)  
  586.     {  
  587.         for (WORD wLoop = 0; wLoop < g_wHardware; wLoop++)  
  588.             UninstallWDMDriver(g_strHardware[wLoop]);  
  589.     }  
  590.       
  591.     return 1;    
  592. }  
具体的SYS 和 INF文件 可参考:http://blog.csdn.net/whatday/article/details/9384577

测试结果:

把相应EXE及其SYS INF文件拷贝的WIN7虚拟机,打开CMD执行WinInstallWin.exe -Install 显示安装成功如图:


再用DeviceTree查看结果:

可以看到设备已经添加成功

在CMD中执行 WinInstallWin.exe -UnInstall 显示卸载成功 如图:

再次使用DeviceTree查看设备 需要刷新一下DeviceTree 结果如图:

先前的设备已经卸载掉了,到此WDM驱动的安装卸载就全部结束了。



0




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值