首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

使用 DriverStudio 開發 USB HID 過濾驅動:從原理到 INF 安裝完整實作

     編輯:關於VC++

前言

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 總線驅動之上。

DriverStudio 專案建立與修改

  1. 開啟 DriverWorks 範例專案:C:\Program Files\NuMega\DriverStudio\DriverWorks\Examples\wdm\usbfilt\usbfilt.dsw
  2. 專案包含兩個核心類別:UsbFilterDriver(驅動入口)與 UsbFilterDevice(裝置實例)。

驅動類別:入口與 AddDevice

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;
}

裝置類別:附加堆疊與攔截 IRP

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。
  • 完成例程中直接修改傳輸緩衝區的 Usage 值,達到「偽裝」裝置類型的目的。

INF 安裝腳本(Win98 範例)

; 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)"

INF 關鍵說明

  • LowerFilters 登錄值指定下層過濾驅動;若為上層過濾請用 UpperFilters。
  • 裝置 ID (USB\VID_05AF&PID_0805&MI_00) 需對應目標鍵盤硬體,可用 hidview.exe 或註冊表查詢。
  • CopyFiles 區段確保相依系統驅動與過濾驅動同步複製。

擴充應用想像

  • 攔截其他 URB(如 URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE)修改裝置描述符。
  • 攔截特定按鍵 HID Report,配合使用者模式程式(透過 DeviceIoControl 或共享記憶體)實現多媒體鍵、巨集鍵功能。
  • 結合上層過濾驅動,在 HID 類別驅動層處理邏輯。

結語

DriverStudio 封裝了繁雜的 WDM 模板代碼,開發者只需專注於核心邏輯(攔截哪個 IRP/URB、完成例程做什麼修改)。配合正確的 INF 安裝腳本,即可快速產出可部署的過濾驅動。建議參考 DriverWorks 範例、Waltz Oney 專書第 9 章及 John Hyde 《USB Design By Example》深化理解。

本文配套原始碼可供下載。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved