Windows Driver Model (WDM) 為跨平台(Win98/Win2K)驅動架構,支援 USB、IEEE 1394、ACPI 等新標準。本文解析 WDM 分層架構(FDO/PDO)、DriverEntry 註冊、IRP 分派、DeviceIoControl 使用者模式通訊,並提供極簡驅動與用戶端完整代碼。
DriverEntryNTSTATUS DriverEntry(PDRIVER_OBJECT DrvObj, PUNICODE_STRING RegPath) {
DrvObj->DriverExtension->AddDevice = AddDevice;
DrvObj->MajorFunction[IRP_MJ_CREATE] = ReqCreate;
DrvObj->MajorFunction[IRP_MJ_CLOSE] = ReqClose;
DrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ReqControl;
DrvObj->MajorFunction[IRP_MJ_PNP] = ReqPnp; // 必須處理 PnP IRP
DrvObj->DriverUnload = DrvUnload;
return STATUS_SUCCESS;
}
AddDevice 建立 FDO 並附加裝置堆疊NTSTATUS AddDevice(PDRIVER_OBJECT DrvObj, PDEVICE_OBJECT PDO) {
PDEVICE_OBJECT fdo;
IoCreateDevice(DrvObj, sizeof(DEVICE_EXTENSION), NULL, FILE_DEVICE_UNKNOWN, 0, FALSE, &fdo);
fdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
fdo->Flags &= ~DO_DEVICE_INITIALIZING;
IoAttachDeviceToDeviceStack(fdo, PDO); // 附加至堆疊
return STATUS_SUCCESS;
}
IRP_MJ_DEVICE_CONTROL 處理使用者控制碼NTSTATUS ReqControl(PDEVICE_OBJECT DevObj, PIRP Irp) {
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
ULONG code = irpSp->Parameters.DeviceIoControl.IoControlCode;
NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
switch (code) {
case HELLOWDM_IOCTL_HELLO:
DbgPrint("Hello from WDM.\n");
status = STATUS_SUCCESS;
break;
}
return CompleteRequest(Irp, status, 0);
}
SetupDiGetClassDevs(&GUID, NULL, NULL, DIGCF_PRESENT|DIGCF_INTERFACEDEVICE) 取得裝置資訊集。SetupDiEnumDeviceInterfaces 列舉介面。SetupDiGetDeviceInterfaceDetail 兩次呼叫取得符號連結名稱(\\.\xxxx#{GUID})。CreateFile 開啟裝置,DeviceIoControl 發送控制碼。SetupDiDestroyDeviceInfoList 釋放資源。IRP_MJ_PNP(IRP_MN_START_DEVICE、IRP_MN_REMOVE_DEVICE 等)並向下傳遞。