从一个接口开始,扫描硬件设备:
#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
- #if __cplusplus
- extern "C"
- {
- #endif
- #include <wdm.h>
- #ifdef __cplusplus
- }
- #endif
-
- typedef struct _DEVICE_EXTERSION
- {
- PDEVICE_OBJECT fdo;
- PDEVICE_OBJECT NextStatckDevice;
- UNICODE_STRING ustrDeviceName;
- UNICODE_STRING ustrSymLinkName;
- }DEVICE_EXTENSION, *PDEVICE_EXTENSION;
-
- #define PAGEDCODE code_seg("PAGE")
- #define LOCKEDCODE code_seg()
- #define INITCODE code_set("INIT")
-
- #define PAGEDDATA data_set("PAGE")
- #define LOCKEDDATA data_set()
- #define INITDATA data_set("INIT")
-
- #define arraysize(p) (sizeof(p)/sizeof((p)[0]))
-
- NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject);
- NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo, IN PIRP Irp);
- NTSTATUS HelloWDMDispatchRoutine(IN PDEVICE_OBJECT fdo, IN PIRP Irp);
- void HelloWDMUnload(IN PDRIVER_OBJECT DriverObject);
- NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION pdx, PIRP Irp);
- NTSTATUS HandleRemoveDevice(PDEVICE_EXTENSION pdx, PIRP Irp);
-
- extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);
HelloWDM.cpp
- #include "HelloWDM.h"
-
- #pragma INITCODE
- extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath)
- {
- KdPrint(("Entry 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;
- }
-
- #pragma PAGECODE
- 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->NextStatckDevice = 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;
- }
-
- #pragma PAGEDCODE
- NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
- {
- PAGED_CODE();
-
- KdPrint(("Enter HelloWDMPnp\n"));
-
- NTSTATUS status = STATUS_SUCCESS;
- PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
- PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
- static NTSTATUS (*fcntab[])(PDEVICE_EXTENSION pdx, PIRP Irp)=
- {
- DefaultPnpHandler,
- DefaultPnpHandler,
- HandleRemoveDevice,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- };
-
- ULONG fcn = stack->MinorFunction;
- if(fcn >= arraysize(fcntab))
- {
- status = DefaultPnpHandler(pdx, Irp);
- return status;
- }
-
- status = (*fcntab[fcn])(pdx, Irp);
- KdPrint(("Leave HelloWDMPnp\n"));
-
- return status;
- }
-
- #pragma PAGEDCODE
- NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION pdx, PIRP Irp)
- {
- PAGED_CODE();
- KdPrint(("Enter DefaultPnpHandler\n"));
- IoSkipCurrentIrpStackLocation(Irp);
- KdPrint(("Leave DefaultPnpHandler\n"));
- return IoCallDriver(pdx->NextStatckDevice, Irp);
- }
-
- #pragma PAGEDCODE
- NTSTATUS HandleRemoveDevice(PDEVICE_EXTENSION pdx, PIRP Irp)
- {
- PAGED_CODE();
- KdPrint(("Enter HandlerRemoveDevice\n"));
-
- Irp->IoStatus.Status = STATUS_SUCCESS;
- NTSTATUS status = DefaultPnpHandler(pdx, Irp);
- IoDeleteSymbolicLink(&(UNICODE_STRING)pdx->ustrSymLinkName);
-
- if(pdx->NextStatckDevice)
- IoDetachDevice(pdx->NextStatckDevice);
-
- IoDeleteDevice(pdx->fdo);
- KdPrint(("Leave HandlerRemoveDevice\n"));
-
- return status;
- }
-
- #pragma PAGEDCODE
- NTSTATUS HelloWDMDispatchRoutine(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
- {
- PAGED_CODE();
- KdPrint(("Enter HelloWDMDispatchRoutine\n"));
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- KdPrint(("Leave HelloWdmDispatchRoutine\n"));
-
- return STATUS_SUCCESS;
- }
-
- #pragma PAGEDCODE
- void HelloWDMUnload(IN PDRIVER_OBJECT DriverObject)
- {
- PAGED_CODE();
- KdPrint(("Enter HelloWDMUnload\n"));
- KdPrint(("Leave HelloWDMUnload\n"));
- }
代码放置后工程目录如图:

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

然后build工程 出现错误:

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

设置后编译通过 生成了MyDriver1.sys文件 MyDriver1.inf文件 这个时候修改inf文件为:如果没有产生INF文件则自己新建一个
- ;--------- Version Section ---------------------------------------------------
-
- [Version]
- Signature="$CHICAGO$";
- Provider=Zhangfan_Device
- DriverVer=07/19/2013,15.16.19.288
-
- ; If device fits one of the standard classes, use the name and GUID here,
- ; otherwise create your own device class and GUID as this example shows.
-
- Class=ZhangfanDevice
- ClassGUID={EF2962F0-0D55-4bff-B8AA-2221EE8A79B0}
-
-
- ;--------- SourceDiskNames and SourceDiskFiles Section -----------------------
-
- ; These sections identify source disks and files for installation. They are
- ; shown here as an example, but commented out.
-
- [SourceDisksNames]
- 1 = "HelloWDM",Disk1,,
-
- [SourceDisksFiles]
- MyDriver1.sys = 1,,
-
- ;--------- ClassInstall/ClassInstall32 Section -------------------------------
-
- ; Not necessary if using a standard class
-
- ; 9X Style
- [ClassInstall]
- Addreg=Class_AddReg
-
- ; NT Style
- [ClassInstall32]
- Addreg=Class_AddReg
-
- [Class_AddReg]
- HKR,,,,%DeviceClassName%
- HKR,,Icon,,"-5"
-
- ;--------- DestinationDirs Section -------------------------------------------
-
- [DestinationDirs]
- YouMark_Files_Driver = 10,System32\Drivers
-
- ;--------- Manufacturer and Models Sections ----------------------------------
-
- [Manufacturer]
- %MfgName%=Mfg0
-
- [Mfg0]
-
- ; PCI hardware Ids use the form
- ; PCI\VEN_aaaa&DEV_bbbb&SUBSYS_cccccccc&REV_dd
- ;改成你自己的ID
- %DeviceDesc%=YouMark_DDI, PCI\VEN_9999&DEV_9999
-
- ;---------- DDInstall Sections -----------------------------------------------
- ; --------- Windows 9X -----------------
-
- ; Experimentation has shown that DDInstall root names greater than 19 characters
- ; cause problems in Windows 98
-
- [YouMark_DDI]
- CopyFiles=YouMark_Files_Driver
- AddReg=YouMark_9X_AddReg
-
- [YouMark_9X_AddReg]
- HKR,,DevLoader,,*ntkern
- HKR,,NTMPDriver,,MyDriver1.sys
- HKR, "Parameters", "BreakOnEntry", 0x00010001, 0
-
- ; --------- Windows NT -----------------
-
- [YouMark_DDI.NT]
- CopyFiles=YouMark_Files_Driver
- AddReg=YouMark_NT_AddReg
-
- [YouMark_DDI.NT.Services]
- Addservice = HelloWDM, 0x00000002, YouMark_AddService
-
- [YouMark_AddService]
- DisplayName = %SvcDesc%
- ServiceType = 1 ; SERVICE_KERNEL_DRIVER
- StartType = 3 ; SERVICE_DEMAND_START
- ErrorControl = 1 ; SERVICE_ERROR_NORMAL
- ServiceBinary = %10%\System32\Drivers\MyDriver1.sys
-
- [YouMark_NT_AddReg]
- HKLM, "System\CurrentControlSet\Services\HelloWDM\Parameters",\
- "BreakOnEntry", 0x00010001, 0
-
-
- ; --------- Files (common) -------------
-
- [YouMark_Files_Driver]
- MyDriver1.sys
-
- ;--------- Strings Section ---------------------------------------------------
-
- [Strings]
- ProviderName="Zhangfan."
- MfgName="Zhangfan Soft"
- DeviceDesc="Hello World WDM!"
- DeviceClassName="Zhangfan_Device"
- 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文件,写入如下内容:
- Windows Registry Editor Version 5.00
-
- [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Debug Print Filter]
-
- "DEFAULT"=dword:00000008
导入重启之后,OK。键值00000008不行 可以改为0000000f尝试 我这边测试08是成功的。
重启后再次开启 EzDriverInstaller 和 DbgView 再次点击 Add New Device 这时发现已经有调试信息了

接下来就是调试WDM驱动,便于测试在驱动中添加一个 读取制定函数SSDT地址的功能 修改后的代码如下:
HelloWDM.h:
- #include "HelloWDM.h"
-
- #pragma INITCODE
- extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath)
- {
- KdPrint(("Entry 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"));
-
- DbgBreakPoint();
-
- ULONG SSDT_NtOpenProcess_Cur_Addr;
- ULONG dwAddr = (ULONG)KeServiceDescriptorTable->pSSDTBase;
- KdPrint(("当前SSDT的基地址是:0x%x\n", dwAddr));
- SSDT_NtOpenProcess_Cur_Addr = *(PULONG)(dwAddr + 4*190);
- KdPrint(("当前NtOpenProcess的地址是0x%x\n", SSDT_NtOpenProcess_Cur_Addr));
-
- return STATUS_SUCCESS;
- }
-
- #pragma PAGECODE
- 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->NextStatckDevice = 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;
- }
-
- #pragma PAGEDCODE
- NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
- {
- PAGED_CODE();
-
- KdPrint(("Enter HelloWDMPnp\n"));
-
- NTSTATUS status = STATUS_SUCCESS;
- PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
- PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
- static NTSTATUS (*fcntab[])(PDEVICE_EXTENSION pdx, PIRP Irp)=
- {
- DefaultPnpHandler,
- DefaultPnpHandler,
- HandleRemoveDevice,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- DefaultPnpHandler,
- };
-
- ULONG fcn = stack->MinorFunction;
- if(fcn >= arraysize(fcntab))
- {
- status = DefaultPnpHandler(pdx, Irp);
- return status;
- }
-
- status = (*fcntab[fcn])(pdx, Irp);
- KdPrint(("Leave HelloWDMPnp\n"));
-
- return status;
- }
-
- #pragma PAGEDCODE
- NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION pdx, PIRP Irp)
- {
- PAGED_CODE();
- KdPrint(("Enter DefaultPnpHandler\n"));
- IoSkipCurrentIrpStackLocation(Irp);
- KdPrint(("Leave DefaultPnpHandler\n"));
- return IoCallDriver(pdx->NextStatckDevice, Irp);
- }
-
- #pragma PAGEDCODE
- NTSTATUS HandleRemoveDevice(PDEVICE_EXTENSION pdx, PIRP Irp)
- {
- PAGED_CODE();
- KdPrint(("Enter HandlerRemoveDevice\n"));
-
- Irp->IoStatus.Status = STATUS_SUCCESS;
- NTSTATUS status = DefaultPnpHandler(pdx, Irp);
- IoDeleteSymbolicLink(&(UNICODE_STRING)pdx->ustrSymLinkName);
-
- if(pdx->NextStatckDevice)
- IoDetachDevice(pdx->NextStatckDevice);
-
- IoDeleteDevice(pdx->fdo);
- KdPrint(("Leave HandlerRemoveDevice\n"));
-
- return status;
- }
-
- #pragma PAGEDCODE
- NTSTATUS HelloWDMDispatchRoutine(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
- {
- PAGED_CODE();
- KdPrint(("Enter HelloWDMDispatchRoutine\n"));
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- KdPrint(("Leave HelloWdmDispatchRoutine\n"));
-
- return STATUS_SUCCESS;
- }
-
- #pragma PAGEDCODE
- void HelloWDMUnload(IN PDRIVER_OBJECT DriverObject)
- {
- PAGED_CODE();
- KdPrint(("Enter HelloWDMUnload\n"));
- KdPrint(("Leave HelloWDMUnload\n"));
- }
由于添加了断点代码所以需要打开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驱动加载器,发现和下面代码逻辑基本一致,所以最终记录以下代码,以便日后使用。
代码如下:
-
-
-
- #include "stdafx.h"
-
- #include <windows.h>
- #include <newdev.h>
- #include <setupapi.h>
- #include <locale.h>
-
- #pragma comment(lib, "newdev.lib")
- #pragma comment(lib, "setupapi.lib")
-
- #ifndef MAX_DEVICE_ID_LEN
- #define MAX_DEVICE_ID_LEN 200
- #define MAX_DEVNODE_ID_LEN MAX_DEVICE_ID_LEN
- #define MAX_GUID_STRING_LEN 39 // 38 chars + terminator null
- #define MAX_CLASS_NAME_LEN 32
- #endif
-
-
- WORD g_wVender = 0;
- WORD g_wHardware = 0;
- TCHAR g_strVender[20][64] = {0};
- TCHAR g_strHardware[20][64] = {0};
- TCHAR g_strHID[MAX_PATH+1] = {0};
-
-
- VOID ShowErrorMsg(DWORD Count,LPCWSTR szData)
- {
- printf("%d\n%s",&Count,&szData);
- }
-
-
- VOID FindComma(LPSTR szData)
- {
- WORD wLen = (WORD)strlen(szData);
- WORD wIdx;
- WORD wLoop;
- CHAR szTmp[128] = {0};
-
- for (wIdx = 0, wLoop = 0; wLoop < wLen; wLoop++)
- {
- if (szData[wLoop] == ',')
- szData[wLoop] = '.';
- else if (szData[wLoop] == ' ')
- continue;
- szTmp[wIdx++] = szData[wLoop];
- }
- memcpy(szData, szTmp, wIdx*sizeof(char));
- szData[wIdx] = 0;
- }
-
-
- VOID StrLTrim(LPSTR szData)
- {
- LPSTR ptr = szData;
-
- while (isspace(*ptr))
- ptr++;
-
- if (strcmp(ptr, szData))
- {
- WORD wLen = (WORD)(strlen(szData) - (ptr - szData));
- memmove(szData, ptr, (wLen+1)*sizeof(char));
- }
- }
-
-
- VOID StrRTrim(LPSTR szData)
- {
- LPSTR ptr = szData;
- LPSTR pTmp = NULL;
-
-
- #if defined(WIN32) && defined(_DEBUG)
- char* locale = setlocale( LC_ALL, ".OCP" );
- #endif
-
- while (*ptr != 0)
- {
-
- if (isspace(*ptr))
- {
- if (!pTmp)
- pTmp = ptr;
- }
- else
- pTmp = NULL;
- ptr++;
- }
-
- if (pTmp)
- {
- *pTmp = 0;
- memmove(szData, szData, strlen(szData) - strlen(pTmp));
- }
- }
-
-
- VOID StrRight(LPSTR szData, WORD wCount)
- {
- WORD wLen = (WORD)strlen(szData) - wCount;
-
- if (wCount > 0x7FFF)
- wCount = 0;
- if (wCount >= (WORD)strlen(szData))
- return;
-
- memmove(szData, szData + wLen, wCount * sizeof(char));
- szData[wCount] = 0;
- }
-
- VOID ConvertGUIDToString(const GUID guid, LPSTR pData)
- {
- CHAR szData[30] = {0};
- CHAR szTmp[3] = {0};
- WORD wLoop;
-
- sprintf_s(pData, _countof(szData), "%04X-%02X-%02X-", guid.Data1, guid.Data2, guid.Data3);
- for (wLoop = 0; wLoop < 8; wLoop++)
- {
- if (wLoop == 2)
- strcat_s(szData, "-");
- sprintf_s(szTmp, _countof(szTmp), "%02X", guid.Data4[wLoop]);
- strcat_s(szData, szTmp);
- }
-
- memcpy(pData + strlen(pData), szData, strlen(szData));
- }
-
- BOOL AnsiToUnicode(LPCSTR Source, const WORD sLen, LPWSTR Destination, const WORD wLen)
- {
- return MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, Source, sLen, Destination, wLen);
- }
-
- BOOL UnicodeToAnsi(LPCWSTR Source, const WORD wLen, LPSTR Destination, const WORD sLen)
- {
- return WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, Source, wLen, Destination, sLen, 0L, 0L);
- }
-
-
- __inline VOID InitialGlobalVar()
- {
- WORD wLoop;
-
- g_wVender = g_wHardware = 0;
- for (wLoop = 0; wLoop < 20; wLoop++)
- {
- RtlZeroMemory(g_strVender[wLoop], sizeof(TCHAR)*64);
- RtlZeroMemory(g_strHardware[wLoop], sizeof(TCHAR)*64);
- }
- }
-
-
- __inline BOOL IsInstalled()
- {
- HDEVINFO hDevInfo = 0L;
- SP_DEVINFO_DATA spDevInfoData = {0L};
- WORD wIdx;
- BOOL bIsFound;
-
-
- hDevInfo = SetupDiGetClassDevs(0L, 0, 0, DIGCF_ALLCLASSES | DIGCF_PRESENT);
- if (hDevInfo == INVALID_HANDLE_VALUE)
- {
- ShowErrorMsg(GetLastError(), _T("SetupDiGetClassDevs"));
- return FALSE;
- }
-
- spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
- wIdx = 0;
- bIsFound = 0;
- while (++wIdx)
- {
-
- if (SetupDiEnumDeviceInfo(hDevInfo, wIdx, &spDevInfoData))
- {
- LPTSTR ptr;
- LPBYTE pBuffer = NULL;
- DWORD dwData = 0L;
- DWORD dwRetVal;
- DWORD dwBufSize = 0L;
-
- while (TRUE)
- {
-
- dwRetVal = SetupDiGetDeviceRegistryProperty(hDevInfo, &spDevInfoData, SPDRP_HARDWAREID,
- &dwData, (PBYTE)pBuffer, dwBufSize, &dwBufSize);
- if (!dwRetVal)
- dwRetVal = GetLastError();
- else
- break;
- if (dwRetVal == ERROR_INVALID_DATA)
- break;
- else if (dwRetVal == ERROR_INSUFFICIENT_BUFFER)
- {
- if (pBuffer)
- LocalFree(pBuffer);
- pBuffer = (LPBYTE)LocalAlloc(LPTR, dwBufSize);
- }
- else
- {
- ShowErrorMsg(dwRetVal, _T("SetupDiGetDeviceRegistryProperty"));
-
- SetupDiDestroyDeviceInfoList(hDevInfo);
- return FALSE;
- }
- }
-
- if (dwRetVal == ERROR_INVALID_DATA)
- continue;
-
- for (ptr = (LPTSTR)pBuffer; *ptr && (ptr < (LPTSTR)&pBuffer[dwBufSize]); ptr += _tcslen(ptr) + sizeof(TCHAR))
- {
- WORD wLoop;
-
- for (wLoop = 0; wLoop < g_wHardware; wLoop++)
- {
- if (!_tcscmp(g_strHardware[wLoop], ptr))
- {
- bIsFound = TRUE;
- break;
- }
- }
- }
- if (pBuffer)
- LocalFree(pBuffer);
- if (bIsFound)
- break;
- }
- }
-
- SetupDiDestroyDeviceInfoList(hDevInfo);
- return bIsFound;
- }
-
-
- BOOL FindSectionName(FILE *pFile, const char *szKey)
- {
- char szData[256] = {0};
-
- if (!pFile)
- return FALSE;
-
-
- rewind(pFile);
-
- while (!feof(pFile))
- {
-
- fgets(szData, 255, pFile);
-
- StrLTrim(szData);
- StrRTrim(szData);
-
- if (strcmp(szKey, szData) == 0)
- return TRUE;
- }
- return FALSE;
- }
-
-
- __inline BOOL GetSectionData(FILE* pFile, const char* szKey, const char bIsVender)
- {
- char szData[128] = {0};
-
- if (bIsVender)
- strcpy_s(szData, szKey);
- else
- sprintf_s(szData, _countof(szData), "[%s]", szKey);
-
- if (FindSectionName(pFile, szData) == FALSE)
- return FALSE;
-
- RtlZeroMemory(szData, sizeof(char)*128);
- while (!feof(pFile))
- {
- char *str = NULL;
- fgets(szData, 127, pFile);
- szData[strlen(szData)-1] = 0;
- StrLTrim(szData);
- StrRTrim(szData);
- if (!*szData)
- continue;
- if (szData[0] == ';')
- continue;
-
- if (strchr(szData, '['))
- {
- StrLTrim(szData);
- if (szData[0] != ';')
- return 1;
- else
- continue;
- }
-
- if (bIsVender)
- str = strchr(szData, '=');
- else
- str = strchr(szData, ',');
-
- if (*str)
- {
- char szTmp[128] = {0};
- WORD pos = (WORD)(str - szData + 1);
-
- StrRight(szData, (short)(strlen(szData)-pos));
- StrLTrim(szData);
- StrRTrim(szData);
- FindComma(szData);
- if (bIsVender)
- {
- AnsiToUnicode(szData, strlen(szData), g_strVender[g_wVender++], 64);
- }
- else
- {
- AnsiToUnicode(szData, strlen(szData), g_strHardware[g_wHardware++], 64);
- }
- }
- }
- return TRUE;
- }
-
-
- BOOL GetINFData(FILE *pFile)
- {
- WORD wLoop;
-
- if (!g_wVender || !g_wHardware)
- InitialGlobalVar();
- if (GetSectionData(pFile, "[Manufacturer]", TRUE) == FALSE)
- return 0;
-
- for (wLoop = 0; wLoop < g_wVender; wLoop++)
- {
- CHAR szVender[64] = {0};
- UnicodeToAnsi(g_strVender[wLoop], _tcslen(g_strVender[wLoop]), szVender, 64);
- GetSectionData(pFile, szVender, FALSE);
- }
- if (g_wHardware != 0)
- {
- if (IsInstalled() == TRUE)
- return FALSE;
- else
- return TRUE;
- }
- return FALSE;
- }
-
-
- __inline BOOL InstallClassDriver(LPCTSTR theINFName)
- {
- GUID guid = {0};
- SP_DEVINFO_DATA spDevData = {0};
- HDEVINFO hDevInfo = 0L;
- TCHAR className[MAX_CLASS_NAME_LEN] = {0};
- LPTSTR pHID = NULL;
- WORD wLoop;
- BOOL bRebootRequired;
-
-
- if (!SetupDiGetINFClass(theINFName, &guid, className, MAX_CLASS_NAME_LEN, 0))
- {
- ShowErrorMsg(GetLastError(), _T("SetupDiGetINFClass"));
- return FALSE;
- }
-
-
- hDevInfo = SetupDiCreateDeviceInfoList(&guid, 0);
- if (hDevInfo == INVALID_HANDLE_VALUE)
- {
- ShowErrorMsg(GetLastError(), _T("SetupDiCreateDeviceInfoList"));
- return FALSE;
- }
-
- spDevData.cbSize = sizeof(SP_DEVINFO_DATA);
-
- if (!SetupDiCreateDeviceInfo(hDevInfo, className, &guid, 0L, 0L, DICD_GENERATE_ID, &spDevData))
- {
- ShowErrorMsg(GetLastError(), _T("SetupDiCreateDeviceInfo"));
-
- SetupDiDestroyDeviceInfoList(hDevInfo);
- return FALSE;
- }
-
- for (wLoop = 0; wLoop < g_wHardware; wLoop++)
- {
- if (pHID)
- LocalFree(pHID);
-
- pHID = (LPTSTR)LocalAlloc(LPTR, _tcslen(g_strHardware[wLoop])*2*sizeof(TCHAR));
- if (!pHID)
- {
- ShowErrorMsg(GetLastError(), _T("LocalAlloc"));
-
- SetupDiDestroyDeviceInfoList(hDevInfo);
- return FALSE;
- }
-
- _tcscpy_s(pHID, _tcslen(g_strHardware[wLoop])*2, g_strHardware[wLoop]);
-
- if (!SetupDiSetDeviceRegistryProperty(hDevInfo, &spDevData, SPDRP_HARDWAREID, (PBYTE)pHID,
- (DWORD)(_tcslen(g_strHardware[wLoop])*2*sizeof(TCHAR))))
- {
- ShowErrorMsg(GetLastError(), _T("SetupDiSetDeviceRegistryProperty"));
-
- SetupDiDestroyDeviceInfoList(hDevInfo);
- LocalFree(pHID);
- return FALSE;
- }
-
- if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, hDevInfo, &spDevData))
- {
- ShowErrorMsg(GetLastError(), _T("SetupDiCallClassInstaller"));
-
- SetupDiDestroyDeviceInfoList(hDevInfo);
- LocalFree(pHID);
- return FALSE;
- }
-
- bRebootRequired = FALSE;
-
- if (!UpdateDriverForPlugAndPlayDevices(0L, g_strHardware[wLoop], theINFName,
- INSTALLFLAG_FORCE, &bRebootRequired))
- {
- DWORD dwErrorCode = GetLastError();
-
- if (!SetupDiCallClassInstaller(DIF_REMOVE, hDevInfo, &spDevData))
- ShowErrorMsg(GetLastError(), _T("SetupDiCallClassInstaller(Remove)"));
- ShowErrorMsg((WORD)dwErrorCode, _T("UpdateDriverForPlugAndPlayDevices"));
-
- SetupDiDestroyDeviceInfoList(hDevInfo);
- LocalFree(pHID);
- return FALSE;
- }
- LocalFree(pHID);
- pHID = NULL;
- }
-
- SetupDiDestroyDeviceInfoList(hDevInfo);
- _tprintf(_T("Install Successed\n"));
- return TRUE;
- }
-
-
- BOOL StartInstallWDMDriver(LPCTSTR theInfName)
- {
- HDEVINFO hDevInfo = 0L;
- GUID guid = {0L};
- SP_DEVINSTALL_PARAMS spDevInst = {0L};
- TCHAR strClass[MAX_CLASS_NAME_LEN] = {0L};
-
-
- if (!SetupDiGetINFClass(theInfName, &guid, strClass, MAX_CLASS_NAME_LEN, 0))
- {
- ShowErrorMsg(GetLastError(), _T("SetupDiGetINFClass"));
- return FALSE;
- }
-
-
- hDevInfo = SetupDiGetClassDevs(&guid, 0L, 0L, DIGCF_PRESENT | DIGCF_ALLCLASSES | DIGCF_PROFILE);
- if (!hDevInfo)
- {
- ShowErrorMsg(GetLastError(), _T("SetupDiGetClassDevs"));
- return FALSE;
- }
-
-
- spDevInst.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
-
- if (!SetupDiGetDeviceInstallParams(hDevInfo, 0L, &spDevInst))
- {
- ShowErrorMsg(GetLastError(), _T("SetupDiGetDeviceInstallParams"));
- return FALSE;
- }
-
- spDevInst.Flags = DI_ENUMSINGLEINF;
- spDevInst.FlagsEx = DI_FLAGSEX_ALLOWEXCLUDEDDRVS;
- _tcscpy_s(spDevInst.DriverPath, _countof(spDevInst.DriverPath), theInfName);
-
-
- if (!SetupDiSetDeviceInstallParams(hDevInfo, 0, &spDevInst))
- {
- ShowErrorMsg(GetLastError(), _T("SetupDiSetDeviceInstallParams"));
- return FALSE;
- }
-
-
- if (!SetupDiBuildDriverInfoList(hDevInfo, 0, SPDIT_CLASSDRIVER))
- {
- ShowErrorMsg(GetLastError(), _T("SetupDiDeviceInstallParams"));
- return FALSE;
- }
-
-
- SetupDiDestroyDeviceInfoList(hDevInfo);
-
-
- return InstallClassDriver(theInfName);
- }
-
-
- VOID UninstallWDMDriver(LPCTSTR theHardware)
- {
- SP_DEVINFO_DATA spDevInfoData = {0};
- HDEVINFO hDevInfo = 0L;
- WORD wIdx, wCount = 0;
-
-
- hDevInfo = SetupDiGetClassDevs(0L, 0L, 0L, DIGCF_ALLCLASSES | DIGCF_PRESENT);
- if (hDevInfo == INVALID_HANDLE_VALUE)
- {
- ShowErrorMsg(GetLastError(), _T("SetupDiGetClassDevs"));
- return;
- }
-
- wIdx = 0;
- while (TRUE)
- {
- spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
-
- if (SetupDiEnumDeviceInfo(hDevInfo, wIdx, &spDevInfoData))
- {
- char Buffer[2048] = {0};
-
-
- if (SetupDiGetDeviceRegistryProperty(hDevInfo, &spDevInfoData, SPDRP_HARDWAREID,
- 0L, (PBYTE)Buffer, 2048, 0L))
- {
- if (!_tcscmp(theHardware, (LPTSTR)Buffer))
- {
-
- if (!SetupDiRemoveDevice(hDevInfo, &spDevInfoData))
- ShowErrorMsg(GetLastError(), _T("SetupDiRemoveDevice"));
- wCount++;
- }
- }
- }
- else
- break;
- wIdx++;
- }
-
- if (wCount != 0)
- _tprintf(_T("UnInstall Successed\n"));
-
-
- SetupDiDestroyDeviceInfoList(hDevInfo);
- InitialGlobalVar();
- return;
- }
-
-
- const LPTSTR g_pInfPath = _T("C:\\Windows\\System32\\DriverStore\\FileRepository\\mydriver1.inf_x86_neutral_15204d1ef3d409a0\\mydriver1.inf");
-
-
- int _tmain(int argc, _TCHAR* argv[])
- {
- CHAR szInfPath[MAX_PATH] = {0};
- UnicodeToAnsi(g_pInfPath, _tcslen(g_pInfPath), szInfPath, MAX_PATH);
- FILE* pInf;
- errno_t err;
-
- if ((err=fopen_s(&pInf, szInfPath, "r"))!=0)
- {
- _tprintf(_T("can not open file %s\n"), g_pInfPath);
- return 0;
- }
-
-
- GetINFData(pInf);
- fclose(pInf);
-
-
- if(_tcscmp(argv[1], TEXT("-Install"))==0)
- {
- if (StartInstallWDMDriver(g_pInfPath) == FALSE)
- {
- _tprintf(_T("Start Install WMD Driver failed\n"));
- return 0;
- }
- }
-
- else if(_tcscmp(argv[1], TEXT("-UnInstall"))==0)
- {
- for (WORD wLoop = 0; wLoop < g_wHardware; wLoop++)
- UninstallWDMDriver(g_strHardware[wLoop]);
- }
-
- return 1;
- }
具体的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驱动的安装卸载就全部结束了。