2010年12月16日 星期四

[ Windows DDP ] 我的第二個 Windows 驅動程式 - HelloWDM

前言 : 
這節的 HelloWDM 是基於 WDM 的驅動程式, 和前面介紹的 HelloDDK 非常相似且多了對隨插即用功能的支持. NT 式驅動程式和 WDM 驅動程式的異同將在後面章節介紹. 

HelloWDM 的標頭檔 : 
HelloWDM 的標頭檔主要是為了匯入驅動程式開發所必需的 WDM.h 標頭檔, 此標頭檔裡包含了對DDK 所有匯出函式的宣告. NT 式的驅動要匯入的是 NTDDK.h, 而 WDM 驅動要匯入的標頭檔為 WDM.h. 另外此標頭檔中定義了幾個標籤, 分別在程式中指名函式和變數分配在分頁記憶體中或非分頁記憶體中, 最後該標頭檔列出了此驅動程式的函式宣告. 

- HelloWDM.h :
  1. /************************************************************************ 
  2. * 檔案名稱:HelloWDM.h                                                  
  3. * 作    者: 
  4. * 完成日期:2007-11-1 
  5. *************************************************************************/  
  6.   
  7. #ifdef __cplusplus  
  8. extern "C"  
  9. {  
  10. #endif  
  11. #include   
  12. #ifdef __cplusplus  
  13. }  
  14. #endif   
  15.   
  16. typedef struct _DEVICE_EXTENSION  
  17. {  
  18.     PDEVICE_OBJECT fdo;  
  19.     PDEVICE_OBJECT NextStackDevice;  
  20.     UNICODE_STRING ustrDeviceName;  // 裝置名  
  21.     UNICODE_STRING ustrSymLinkName; // 符號連結名  
  22. } DEVICE_EXTENSION, *PDEVICE_EXTENSION;  
  23.   
  24. #define PAGEDCODE code_seg("PAGE")  
  25. #define LOCKEDCODE code_seg()  
  26. #define INITCODE code_seg("INIT")  
  27.   
  28. #define PAGEDDATA data_seg("PAGE")  
  29. #define LOCKEDDATA data_seg()  
  30. #define INITDATA data_seg("INIT")  
  31.   
  32. #define arraysize(p) (sizeof(p)/sizeof((p)[0]))  
  33.   
  34. NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject,  
  35.                            IN PDEVICE_OBJECT PhysicalDeviceObject);  
  36. NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo,  
  37.                         IN PIRP Irp);  
  38. NTSTATUS HelloWDMDispatchRoutine(IN PDEVICE_OBJECT fdo,  
  39.                                  IN PIRP Irp);  
  40. void HelloWDMUnload(IN PDRIVER_OBJECT DriverObject);  
  41.   
  42. extern "C"  
  43. NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,  
  44.                      IN PUNICODE_STRING RegistryPath);  

HelloWDM 的入口函式 : 
和 NT 式驅動程式一樣, WDM 的入口函式位址同樣是 DriverEntry, 且在 C++ 編譯的同時需要用 extern "C" 修飾. 

- HelloWDM.cpp (DriverEntry 函式) :
  1. /************************************************************************ 
  2. * 函式名稱:DriverEntry 
  3. * 功能描述:初始化驅動程式,定位和申請硬體資源,新建內核物件 
  4. * 參數列表: 
  5.       pDriverObject:從I/O管理器中傳進來的驅動物件 
  6.       pRegistryPath:驅動程式在登錄表的中的路徑 
  7. * 返回 值:返回初始化驅動狀態 
  8. *************************************************************************/  
  9. #pragma INITCODE   
  10. extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,  
  11.                                 IN PUNICODE_STRING pRegistryPath)  
  12. {  
  13.     KdPrint(("Enter DriverEntry\n"));  
  14.   
  15.     pDriverObject->DriverExtension->AddDevice = HelloWDMAddDevice;  
  16.     pDriverObject->MajorFunction[IRP_MJ_PNP] = HelloWDMPnp;  
  17.     pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =   
  18.     pDriverObject->MajorFunction[IRP_MJ_CREATE] =   
  19.     pDriverObject->MajorFunction[IRP_MJ_READ] =   
  20.     pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloWDMDispatchRoutine;  
  21.     pDriverObject->DriverUnload = HelloWDMUnload;  
  22.   
  23.     KdPrint(("Leave DriverEntry\n"));  
  24.     return STATUS_SUCCESS;  
  25. }  

程式碼第 9 行, 將此函式放在 INIT 段中, 當驅動載入結束後, 此函式就可以從記憶體中卸掉. 
程式碼第 10-11 行, 定義驅動入口函式, 用 extern "C" 修飾. 其中傳進兩個參數, 第一個參數 pDriverObject 為驅動元件, 第二個參數 pRegistryPath 為此驅動的登錄表路徑. 
程式碼第 15 行, 設置 AddDevice 的 Callback 函式, 此函式出現在 WDM 驅動程式中, 而在 NT 式驅動中沒有此 Callback 函式. 此 Callback 函式的作用是新建裝置並由 PNP (隨插即用) 管理器呼叫. 
程式碼第 16 行, 設置對 IRP_MJ_PNP 的 Callback 函式. 對 PNP 的 IRP 處理, 是 NT 式驅動和 WDM 驅動重大區別之一. 
程式碼第 17-20 行, 設置常用的 IRP Callback 函式. 這裡只是簡單指向一個預設函式 HelloWDMDispatchRoutine. 
程式碼第 21 行, 向系統登錄卸載常式. 在 WDM 程式中, 大部分卸載工作以不再此處理, 而是放在對 IRP_MN_REMOVE_DEVICE 的 IRP 的 處理函式中處理. 

HelloWDM 的 AddDevice 常式 : 
在 WDM 的驅動程式中, 新建裝置的任務不再由 DriverEntry 承擔, 而需要驅動程式向系統登錄一個叫做 AddDevice 的常式. 此常式由 PNP 管理器負責呼叫, 其函式主要職責就是新建裝置物件. HelloWDMAddDevice 常式有兩個參數, DriverObject 和 PhysicalDeviceObject. DriverObject 式由 PNP 管理器傳遞而來的驅動物件, 此物件是 DriverEntry 中的驅動物件. PhysicalDeviceObject 是 PNP 管理器傳遞進來的底層驅動裝置物件, 這個概念在 NT 式的驅動中是沒有的. 關於這個概念會在後續章節說明. 

- HelloWDM.cpp (HelloWDMAddDevice 函式) :
  1. /************************************************************************ 
  2. * 函式名稱:HelloWDMAddDevice 
  3. * 功能描述:添加新裝置 
  4. * 參數列表: 
  5.       DriverObject:從I/O管理器中傳進來的驅動物件 
  6.       PhysicalDeviceObject:從I/O管理器中傳進來的物理裝置物件 
  7. * 返回 值:返回添加新裝置狀態 
  8. *************************************************************************/  
  9. #pragma PAGEDCODE  
  10. NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject,  
  11.                            IN PDEVICE_OBJECT PhysicalDeviceObject)  
  12. {   
  13.     PAGED_CODE();  
  14.     KdPrint(("Enter HelloWDMAddDevice\n"));  
  15.   
  16.     NTSTATUS status;  
  17.     PDEVICE_OBJECT fdo;  
  18.     UNICODE_STRING devName;  
  19.     RtlInitUnicodeString(&devName,L"\\Device\\MyWDMDevice");  
  20.     status = IoCreateDevice(  
  21.         DriverObject,  
  22.         sizeof(DEVICE_EXTENSION),  
  23.         &(UNICODE_STRING)devName,  
  24.         FILE_DEVICE_UNKNOWN,  
  25.         0,  
  26.         FALSE,  
  27.         &fdo);  
  28.     if( !NT_SUCCESS(status))  
  29.         return status;  
  30.     PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;  
  31.     pdx->fdo = fdo;  
  32.     pdx->NextStackDevice = IoAttachDeviceToDeviceStack(fdo, PhysicalDeviceObject);  
  33.     UNICODE_STRING symLinkName;  
  34.     RtlInitUnicodeString(&symLinkName,L"\\DosDevices\\HelloWDM");  
  35.   
  36.     pdx->ustrDeviceName = devName;  
  37.     pdx->ustrSymLinkName = symLinkName;  
  38.     status = IoCreateSymbolicLink(&(UNICODE_STRING)symLinkName,&(UNICODE_STRING)devName);  
  39.   
  40.     if( !NT_SUCCESS(status))  
  41.     {  
  42.         IoDeleteSymbolicLink(&pdx->ustrSymLinkName);  
  43.         status = IoCreateSymbolicLink(&symLinkName,&devName);  
  44.         if( !NT_SUCCESS(status))  
  45.         {  
  46.             return status;  
  47.         }  
  48.     }  
  49.   
  50.     fdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;  
  51.     fdo->Flags &= ~DO_DEVICE_INITIALIZING;  
  52.   
  53.     KdPrint(("Leave HelloWDMAddDevice\n"));  
  54.     return STATUS_SUCCESS;  
  55. }  

HelloWDM 處理 PNP 的 Callback 函式 : 
WDM 式驅動程式主要區別在於對 IRP_MJ_PNP 的 IRP 處理. 其中 IRP_MJ_PNP 會細分為若干個子類. 例如 IRP_MN_START_DEVICE, IRP_MN_REMOVE_DEVICE, IRP_MN_STOP_DEVICE 等. 本例中除了對 IRP_MN_REMOVE_DEVICE 做特殊處理, 其他 IRP 則作相同處理. 

- HelloWDM.cpp (HelloWDMPnp 函式) :
  1. /************************************************************************ 
  2. * 函式名稱:HelloWDMPnp 
  3. * 功能描述:對隨插即用IRP進行處理 
  4. * 參數列表: 
  5.       fdo:功能裝置物件 
  6.       Irp:從IO請求包 
  7. * 返回 值:返回狀態 
  8. *************************************************************************/  
  9. #pragma PAGEDCODE  
  10. NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo,  
  11.                         IN PIRP Irp)  
  12. {  
  13.     PAGED_CODE();  
  14.   
  15.     KdPrint(("Enter HelloWDMPnp\n"));  
  16.     NTSTATUS status = STATUS_SUCCESS;  
  17.     PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;  
  18.     PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);  
  19.     static NTSTATUS (*fcntab[])(PDEVICE_EXTENSION pdx, PIRP Irp) =   
  20.     {  
  21.         DefaultPnpHandler,      // IRP_MN_START_DEVICE  
  22.         DefaultPnpHandler,      // IRP_MN_QUERY_REMOVE_DEVICE  
  23.         HandleRemoveDevice,     // IRP_MN_REMOVE_DEVICE  
  24.         DefaultPnpHandler,      // IRP_MN_CANCEL_REMOVE_DEVICE  
  25.         DefaultPnpHandler,      // IRP_MN_STOP_DEVICE  
  26.         DefaultPnpHandler,      // IRP_MN_QUERY_STOP_DEVICE  
  27.         DefaultPnpHandler,      // IRP_MN_CANCEL_STOP_DEVICE  
  28.         DefaultPnpHandler,      // IRP_MN_QUERY_DEVICE_RELATIONS  
  29.         DefaultPnpHandler,      // IRP_MN_QUERY_INTERFACE  
  30.         DefaultPnpHandler,      // IRP_MN_QUERY_CAPABILITIES  
  31.         DefaultPnpHandler,      // IRP_MN_QUERY_RESOURCES  
  32.         DefaultPnpHandler,      // IRP_MN_QUERY_RESOURCE_REQUIREMENTS  
  33.         DefaultPnpHandler,      // IRP_MN_QUERY_DEVICE_TEXT  
  34.         DefaultPnpHandler,      // IRP_MN_FILTER_RESOURCE_REQUIREMENTS  
  35.         DefaultPnpHandler,      //   
  36.         DefaultPnpHandler,      // IRP_MN_READ_CONFIG  
  37.         DefaultPnpHandler,      // IRP_MN_WRITE_CONFIG  
  38.         DefaultPnpHandler,      // IRP_MN_EJECT  
  39.         DefaultPnpHandler,      // IRP_MN_SET_LOCK  
  40.         DefaultPnpHandler,      // IRP_MN_QUERY_ID  
  41.         DefaultPnpHandler,      // IRP_MN_QUERY_PNP_DEVICE_STATE  
  42.         DefaultPnpHandler,      // IRP_MN_QUERY_BUS_INFORMATION  
  43.         DefaultPnpHandler,      // IRP_MN_DEVICE_USAGE_NOTIFICATION  
  44.         DefaultPnpHandler,      // IRP_MN_SURPRISE_REMOVAL  
  45.     };  
  46.   
  47.     ULONG fcn = stack->MinorFunction;  
  48.     if (fcn >= arraysize(fcntab))  
  49.     {                       // unknown function  
  50.         status = DefaultPnpHandler(pdx, Irp); // some function we don't know about  
  51.         return status;  
  52.     }                       // unknown function  
  53.   
  54. #if DBG  
  55.     static char* fcnname[] =   
  56.     {  
  57.         "IRP_MN_START_DEVICE",  
  58.         "IRP_MN_QUERY_REMOVE_DEVICE",  
  59.         "IRP_MN_REMOVE_DEVICE",  
  60.         "IRP_MN_CANCEL_REMOVE_DEVICE",  
  61.         "IRP_MN_STOP_DEVICE",  
  62.         "IRP_MN_QUERY_STOP_DEVICE",  
  63.         "IRP_MN_CANCEL_STOP_DEVICE",  
  64.         "IRP_MN_QUERY_DEVICE_RELATIONS",  
  65.         "IRP_MN_QUERY_INTERFACE",  
  66.         "IRP_MN_QUERY_CAPABILITIES",  
  67.         "IRP_MN_QUERY_RESOURCES",  
  68.         "IRP_MN_QUERY_RESOURCE_REQUIREMENTS",  
  69.         "IRP_MN_QUERY_DEVICE_TEXT",  
  70.         "IRP_MN_FILTER_RESOURCE_REQUIREMENTS",  
  71.         "",  
  72.         "IRP_MN_READ_CONFIG",  
  73.         "IRP_MN_WRITE_CONFIG",  
  74.         "IRP_MN_EJECT",  
  75.         "IRP_MN_SET_LOCK",  
  76.         "IRP_MN_QUERY_ID",  
  77.         "IRP_MN_QUERY_PNP_DEVICE_STATE",  
  78.         "IRP_MN_QUERY_BUS_INFORMATION",  
  79.         "IRP_MN_DEVICE_USAGE_NOTIFICATION",  
  80.         "IRP_MN_SURPRISE_REMOVAL",  
  81.     };  
  82.   
  83.     KdPrint(("PNP Request (%s)\n", fcnname[fcn]));  
  84. #endif // DBG  
  85.   
  86.     status = (*fcntab[fcn])(pdx, Irp);  
  87.     KdPrint(("Leave HelloWDMPnp\n"));  
  88.     return status;  
  89. }  

HelloWDM 對 PNP 的預設處理 : 
除了 IRP_MN_STOP_DEVICE 以外, HelloWDM 對其他 PNP 的 IRP 做同樣的處理, 即直接傳遞到底層驅動, 並將底層驅動結果返回. 

- HelloWDM.cpp (DefaultPnpHandler 函式) :
  1. /************************************************************************ 
  2. * 函式名稱:DefaultPnpHandler 
  3. * 功能描述:對PNP IRP進行預設處理 
  4. * 參數列表: 
  5.       pdx:裝置物件的擴充 
  6.       Irp:從IO請求包 
  7. * 返回 值:返回狀態 
  8. *************************************************************************/  
  9. #pragma PAGEDCODE  
  10. NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION pdx, PIRP Irp)  
  11. {  
  12.     PAGED_CODE();  
  13.     KdPrint(("Enter DefaultPnpHandler\n"));  
  14.     IoSkipCurrentIrpStackLocation(Irp);  
  15.     KdPrint(("Leave DefaultPnpHandler\n"));  
  16.     return IoCallDriver(pdx->NextStackDevice, Irp);  
  17. }  

HelloWDM 對 IRP_MN_REMOVE_DEVICE 的處理 : 
對 IRP_MN_REMOVE_DEVICE 的處理類似於 NT 式驅動中的卸載常式, 而在 WDM 式的驅動中, 卸載常式幾乎不用做處理. 

- HelloWDM.cpp (HandleRemoveDevice 函式) :
  1. /************************************************************************ 
  2. * 函式名稱:HandleRemoveDevice 
  3. * 功能描述:對IRP_MN_REMOVE_DEVICE IRP進行處理 
  4. * 參數列表: 
  5.       fdo:功能裝置物件 
  6.       Irp:從IO請求包 
  7. * 返回 值:返回狀態 
  8. *************************************************************************/  
  9. #pragma PAGEDCODE  
  10. NTSTATUS HandleRemoveDevice(PDEVICE_EXTENSION pdx, PIRP Irp)  
  11. {  
  12.     PAGED_CODE();  
  13.     KdPrint(("Enter HandleRemoveDevice\n"));  
  14.   
  15.     Irp->IoStatus.Status = STATUS_SUCCESS;  
  16.     NTSTATUS status = DefaultPnpHandler(pdx, Irp);  
  17.     IoDeleteSymbolicLink(&(UNICODE_STRING)pdx->ustrSymLinkName);  
  18.   
  19.     //呼叫IoDetachDevice()把fdo從裝置堆疊中脫開:  
  20.     if (pdx->NextStackDevice)  
  21.         IoDetachDevice(pdx->NextStackDevice);  
  22.       
  23.     //刪除fdo:  
  24.     IoDeleteDevice(pdx->fdo);  
  25.     KdPrint(("Leave HandleRemoveDevice\n"));  
  26.     return status;  
  27. }  

HelloWDM 對其他 IRP 的 Callback 函式 : 
此處對新建, 關閉, 讀寫裝置的預設處理同 HelloDDK : 

- HelloWDM.cpp (HelloWDMDispatchRoutine 函式) :
  1. /************************************************************************ 
  2. * 函式名稱:HelloWDMDispatchRoutine 
  3. * 功能描述:對預設IRP進行處理 
  4. * 參數列表: 
  5.       fdo:功能裝置物件 
  6.       Irp:從IO請求包 
  7. * 返回 值:返回狀態 
  8. *************************************************************************/  
  9. #pragma PAGEDCODE  
  10. NTSTATUS HelloWDMDispatchRoutine(IN PDEVICE_OBJECT fdo,  
  11.                                  IN PIRP Irp)  
  12. {  
  13.     PAGED_CODE();  
  14.     KdPrint(("Enter HelloWDMDispatchRoutine\n"));  
  15.     Irp->IoStatus.Status = STATUS_SUCCESS;  
  16.     Irp->IoStatus.Information = 0;   // no bytes xfered  
  17.     IoCompleteRequest( Irp, IO_NO_INCREMENT );  
  18.     KdPrint(("Leave HelloWDMDispatchRoutine\n"));  
  19.     return STATUS_SUCCESS;  
  20. }  

HelloWDM 卸載常式 : 
由於 WDM 式驅動程式將主要的卸載任務放在了對 IRP_MN_REMOVE_DEVICE 的處理函式中, 在標準的卸載常式幾乎沒有什麼需要作的. 在這裡只是列印除錯訊息. 

- HelloWDM.cpp (HelloWDMUnload 函式) :
  1. /************************************************************************ 
  2. * 函式名稱:HelloWDMUnload 
  3. * 功能描述:負責驅動程式的卸載操作 
  4. * 參數列表: 
  5.       DriverObject:驅動物件 
  6. * 返回 值:返回狀態 
  7. *************************************************************************/  
  8. #pragma PAGEDCODE  
  9. void HelloWDMUnload(IN PDRIVER_OBJECT DriverObject)  
  10. {  
  11.     PAGED_CODE();  
  12.     KdPrint(("Enter HelloWDMUnload\n"));  
  13.     KdPrint(("Leave HelloWDMUnload\n"));  
  14. }  

HelloWDK 的編譯與安裝 : 
HelloWDK 的編譯與安裝與 HelloDDK 過程中有一些不同, 尤其是安裝過程. 這是因為 HelloWDM 是隨插即用的驅動程式, 並且需要藉助 INF 檔安裝. 
- 編譯 HelloWDM 
編譯 HelloWDM 需要兩個指令檔 makefile 和 Sources. makefile 同 HelloDDK 中一樣, 這裡不再列出, Sources 稍有不同 : 

- 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\  

將兩個檔與原始檔案放在同一目錄下, 進入 "Windows XP Checked Build Environment" 編譯環境下. 用 cd 進入對應目錄後執行 build 會編譯出來對應的 HelloWDM.sys 檔案. 執行結果如下 : 
 
- 安裝 HelloWDM 
WDM 驅動程式和 NT 式驅動程式的安裝有很大出入, 首先為了安裝 HelloWDM 驅動程式, 需要為驅動程式編寫一個 inf 檔. inf 檔描述了 WDM 驅動程式的操作硬體裝置的資訊和驅動程式的一些資訊. 下面是這個 inf 檔的程式碼, 請將這個檔案和其他原始檔放在同一個目錄裡 : 

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

HelloWDM 是個虛擬裝置, 安裝需要如下步驟 : 
1. 首先在第一次安裝 HelloWDM 驅動程式時, 進入控制台, 選擇新增硬體. 系統會自動搜尋是否有新裝置插入, 並彈出對話框詢問是否將硬體連到電腦, 選擇是 如下圖 : 
 

2. 在彈出下一個對話框中選擇 "新增硬體裝置", 並按一下 "下一步" 按鈕如下圖 : 
 

3. 再彈出下一個對話框選擇 "安裝我從清單中手動選取的硬體(進接選項)", 並按下 "下一步" 按鈕 : 
 

4. 再談出下一個對話框中選擇顯示所有裝置, 並按"下一步" 按鈕 
 

5. 在彈出的對話框按下 "從磁片安裝" 紐並選擇之前目錄中的 inf 檔. 
 

6. 最後系統提示安裝成功 : 
 

和 HelloDDK 一樣, 你也可以在裝置管理員中找到這個虛擬裝置, 如下圖 : 
 

這種安裝 WDM 驅動程式作法過於繁雜. 使用一個叫做 ExDriverInstaller 的工具, 可以進行快速安裝. 這個工具也是 DriverStudio 內附的一個工具軟體. 打開 EzDriverInstaller 選擇 "File" | "Open" 在彈出對話框中選擇需要安裝的 inf 檔, 按一下 "Add New Device" 按鈕就可以完成安裝. EzDriverInstaller 還提供刪除驅動程式功能, 開啟/關閉驅動功能, 遮罩驅動功能, 重啟驅動功能等.

沒有留言:

張貼留言

[Git 常見問題] error: The following untracked working tree files would be overwritten by merge

  Source From  Here 方案1: // x -----删除忽略文件已经对 git 来说不识别的文件 // d -----删除未被添加到 git 的路径中的文件 // f -----强制运行 #   git clean -d -fx 方案2: 今天在服务器上  gi...