WDM 核心觀念
- 跨平台 (Win98/Win2K)、跨架構 (重新編譯即可運行非 x86)。
- 分層驅動,引入 FDO (功能裝置物件) 與 PDO (物理裝置物件);一個 PDO 對應一個真實硬體,驅動程式操作 FDO/PDO 而非直接操作硬體。
- Ring3 與 Ring0 通訊封裝為 IRP (I/O Request Packet),含 PDO 識別目標裝置。
- 驅動識別靠 128-bit GUID,非檔名或 ID。
DriverEntry 範例
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) {
DriverObject->DriverExtension->AddDevice = AddDevice;
DriverObject->MajorFunction[IRP_MJ_CREATE] = RequestCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = RequestClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = RequestControl;
DriverObject->MajorFunction[IRP_MJ_PNP] = RequestPnp;
return STATUS_SUCCESS;
}
DeviceIoControl 處理範例
NTSTATUS RequestControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
ULONG ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
ULONG InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
ULONG OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
NTSTATUS status;
switch (ControlCode) {
case HELLOWDM_IOCTL_HELLO:
DbgPrint("Hello from WDM.\n");
status = STATUS_SUCCESS;
break;
default:
status = STATUS_INVALID_DEVICE_REQUEST;
}
return CompleteRequest(Irp, status, 0);
}
用戶端開啟裝置介面
HDEVINFO info = SetupDiGetClassDevs((LPGUID)&GUID_HELLOWDM, NULL, NULL, DIGCF_PRESENT|DIGCF_INTERFACEDEVICE);
// 列舉介面 → 取得詳細資訊 (含符號連結名) → CreateFile → DeviceIoControl → CloseHandle
// 最後 SetupDiDestroyDeviceInfoList 釋放資源
注意事項
- 嚴禁使用組合語言 (跨平台需求)。
- 必須正確處理
IRP_MJ_PNP 並轉發其他系統 IRP 至驅動堆疊下層。
- 範例於 Win98 + 98 DDK + VC6.0 + SoftIce 4.0 開發測試。