WDM 驅動採分層架構,過濾驅動透過附加至裝置堆疊攔截 IRP,可檢查、修改、完成或建立新 IRP。本文示範如何使用 DriverStudio(DriverWorks)快速建構一個 USB 鍵盤下層過濾驅動,攔截 IRP_MJ_INTERNAL_DEVICE_CONTROL 中的 Get_Report_Descriptor,將 Usage 從 Keyboard (6) 改為 UserDefined (0),使鍵盤不被系統獨佔,並提供完整 INF 安裝腳本。
IO 管理器建立裝置堆疊時,允許將過濾裝置物件附加至功能驅動(如 hidusb.sys)建立的裝置物件上方。IRP 由上而下傳遞,過濾驅動可在通過前/後介入處理。本例採 Lower Filter,附加於 HID 類別驅動之下、USB 總線驅動之上。
C:\Program Files\NuMega\DriverStudio\DriverWorks\Examples\wdm\usbfilt\usbfilt.dswUsbFilterDriver(驅動入口)與 UsbFilterDevice(裝置實例)。DECLARE_DRIVER_CLASS(UsbFilterDriver, NULL)
NTSTATUS UsbFilterDriver::DriverEntry(PUNICODE_STRING RegistryPath)
{
T << "UsbFilterDriver::DriverEntry\n";
m_Unit = 0;
return STATUS_SUCCESS;
UNREFERENCED_PARAMETER(RegistryPath);
}
NTSTATUS UsbFilterDriver::AddDevice(PDEVICE_OBJECT Pdo)
{
T << "UsbFilterDriver::AddDevice\n";
UsbFilterDevice *pFilterDevice = new (NULL, FILE_DEVICE_UNKNOWN, NULL, 0, DO_DIRECT_IO) UsbFilterDevice(Pdo, m_Unit);
if (pFilterDevice)
{
NTSTATUS status = pFilterDevice->ConstructorStatus();
if (!NT_SUCCESS(status))
{
T << "Failed to construct UsbFilterDevice" << (ULONG)m_Unit << " status = " << status << "\n";
delete pFilterDevice;
}
else { m_Unit++; }
return status;
}
T << "Failed to allocate UsbFilterDevice" << (ULONG)m_Unit << "\n";
return STATUS_INSUFFICIENT_RESOURCES;
}
UsbFilterDevice::UsbFilterDevice(PDEVICE_OBJECT Pdo, ULONG Unit) : KWdmFilterDevice(Pdo, NULL)
{
T << "UsbFilterDevice::UsbFilterDevice\n";
if (!NT_SUCCESS(m_ConstructorStatus)) return;
m_Unit = Unit;
m_Usb.Initialize(this, Pdo); // 初始化下層裝置介面
NTSTATUS status = AttachFilter(&m_Usb); // 關鍵:附加至裝置堆疊
if (!NT_SUCCESS(status)) { m_ConstructorStatus = status; return; }
SetFilterPowerPolicy(); SetFilterPnpPolicy();
}
// 攔截 IRP_MJ_INTERNAL_DEVICE_CONTROL
NTSTATUS UsbFilterDevice::InternalDeviceControl(KIrp I)
{
T << "UsbFilterDevice::InternalDeviceControl\n";
if (I.IoctlCode() != IOCTL_INTERNAL_USB_SUBMIT_URB)
return DefaultPnp(I); // 不感興趣的 IOCTL 直接穿透
PURB p = I.Urb(CURRENT);
if (p->UrbHeader.Function != URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE)
return DefaultPnp(I); // 不感興趣的 URB 直接穿透
// 符合條件:設定完成例程
return PassThrough(I, LinkTo(DeviceControlComplete), this);
}
// 完成例程:修改 Report Descriptor
NTSTATUS UsbFilterDevice::DeviceControlComplete(KIrp I)
{
PURB p = I.Urb(CURRENT);
if (p)
{
char* DescriptorBuffer = (char*)p->UrbControlDescriptorRequest.TransferBuffer;
DescriptorBuffer += 3; // 指向 Usage 欄位 (第 3 位元組)
if ((*DescriptorBuffer & 0xff) == 6) // 6 = Keyboard
*DescriptorBuffer = 0; // 0 = UserDefined
}
return I.Status();
}
關鍵點:
AttachFilter 封裝了 IoAttachDevice,將過濾裝置插入堆疊。IOCTL_INTERNAL_USB_SUBMIT_URB + URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE,其他 IRP 直接 PassThrough。; usbkey.INF
[Version]
Signature="$CHICAGO$"
Class=HID
ClassGUID={745a17a0-74d3-11d0-b6fe-00a0c90f57da}
Provider=%USBDBE%
DriverVer=11/12/2001,4.10.2222.1
[DestinationDirs]
DefaultDestDir = 10,system32\drivers
[ClassInstall]
Addreg=HIDClassReg
[HIDClassReg]
HKR,,,,%HID.ClassName%
HKR,,Icon,,-20
[Manufacturer]
%USBDBE%=USBDBE
[USBDBE]
%HID.DeviceDesc% = Keypad_Inst, USB\VID_05AF&PID_0805&MI_00
[Keypad_Inst]
CopyFiles=Keypad_Inst.CopyFiles
AddReg=Keypad_Inst.AddReg
[Keypad_Inst.CopyFiles]
hidusb.sys
hidparse.sys
hidclass.sys
usbfilt.sys
[Keypad_Inst.AddReg]
HKR,,DevLoader,,*ntkern
HKR,,NTMPDriver,,hidusb.sys
[Keypad_Inst.HW]
AddReg=Keypad_Inst.AddReg.HW
[Keypad_Inst.AddReg.HW]
HKR,,"LowerFilters",0x00010000,"usbfilt.sys" ; ★Lower Filter 關鍵
[USBHIDDevice]
CopyFiles=USBHIDDevice.Copy
AddReg=USBHIDDevice.AddReg
[USBHIDDevice.Copy]
hidclass.sys
hidusb.sys
hidparse.sys
[USBHIDDevice.AddReg]
HKR,,DevLoader,,*ntkern
HKR,,NTMPDriver,,hidusb.sys
[Strings]
USBDBE = "SINO Co., Ltd."
HID.DeviceDesc = "SINO USB MultiKeyboard"
HID.ClassName = "Human Input Devices (HID)"
LowerFilters 登錄值指定下層過濾驅動;若為上層過濾請用 UpperFilters。USB\VID_05AF&PID_0805&MI_00) 需對應目標鍵盤硬體,可用 hidview.exe 或註冊表查詢。CopyFiles 區段確保相依系統驅動與過濾驅動同步複製。URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE)修改裝置描述符。DeviceIoControl 或共享記憶體)實現多媒體鍵、巨集鍵功能。DriverStudio 封裝了繁雜的 WDM 模板代碼,開發者只需專注於核心邏輯(攔截哪個 IRP/URB、完成例程做什麼修改)。配合正確的 INF 安裝腳本,即可快速產出可部署的過濾驅動。建議參考 DriverWorks 範例、Waltz Oney 專書第 9 章及 John Hyde 《USB Design By Example》深化理解。
本文配套原始碼可供下載。