Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學

程式設計:Ring 3 與 Ring 0 層級識別 USB 移動硬碟裝置的 C++ 程式碼實作

編輯:Win7 系統基礎知識

GetDriveType 無法區分移動硬碟與本地硬碟(同回傳 DRIVE_FIXED),透過 DeviceIoControl 查詢總線類型 (BusType) 準確識別 USB 裝置

Ring 3 (用戶模式) 實作

BOOL IsUsbDriver(TCHAR tchDrvName) {
    TCHAR tcsDrvName[8] = TEXT("\\\\.\\X:");
    tcsDrvName[4] = tchDrvName;
    HANDLE hDevice = CreateFile(tcsDrvName, GENERIC_READ,
        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hDevice == INVALID_HANDLE_VALUE) return FALSE;

    STORAGE_PROPERTY_QUERY query = {StorageDeviceProperty, PropertyStandardQuery};
    BYTE buff[1024] = {0};
    PSTORAGE_DEVICE_DESCRIPTOR pDesc = (PSTORAGE_DEVICE_DESCRIPTOR)buff;
    pDesc->Size = sizeof(buff);
    DWORD dwOut;
    BOOL res = DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
        &query, sizeof(query), pDesc, pDesc->Size, &dwOut, NULL);
    CloseHandle(hDevice);
    return res ? (pDesc->BusType == BusTypeUsb) : FALSE;
}

Ring 0 (核心模式) 實作

BOOLEAN IsUsbDriver(IN PDEVICE_OBJECT pDeviceObject) {
    PIRP pIrp; PSTORAGE_DEVICE_DESCRIPTOR pDesc;
    STORAGE_PROPERTY_QUERY query = {StorageDeviceProperty, PropertyStandardQuery};
    CHAR buff[128]; KEVENT evt; NTSTATUS status; IO_STATUS_BLOCK iosb;
    KeInitializeEvent(&evt, NotificationEvent, FALSE);
    pIrp = IoBuildDeviceIoControlRequest(IOCTL_STORAGE_QUERY_PROPERTY,
        pDeviceObject, &query, sizeof(query), buff, sizeof(buff),
        FALSE, &evt, &iosb);
    if (!pIrp) return FALSE;
    status = IoCallDriver(pDeviceObject, pIrp);
    if (status == STATUS_PENDING) {
        status = KeWaitForSingleObject(&evt, Executive, KernelMode, FALSE, NULL);
        status = iosb.Status;
    }
    if (!NT_SUCCESS(status)) return FALSE;
    pDesc = (PSTORAGE_DEVICE_DESCRIPTOR)buff;
    return pDesc->BusType == BusTypeUsb;
}
Ring 0 需配合 DiskDeviceObject 使用,參考部落格說明卷裝置與 DiskDeviceObject 關係。兩種方法皆透過查詢 StorageDeviceProperty 的 BusType 判斷是否為 USB 裝置,比 SetupDiGetDeviceRegistryProperty 簡潔可靠。
Copyright © Windows教程網 All Rights Reserved