简体   繁体   English

在插入或移除时获取 usb 的 dos_name

[英]Get dos_name of usb on inserting or removal

I have designed a program to detect whenever a usb device is connected or removed.我设计了一个程序来检测何时连接或移除 usb 设备。 I want to know the either the dos path of the connected device or a Guid like this \\?\Volume{17ee3574-7082-4881-aeae-07893db4e957}\ But instead dbcc_name gives me \\?\STORAGE#Volume#_??_USBSTOR#Disk&Ven_JetFlash&Prod_Transcend_8GB&Rev_1100#546IYBDAPBE1075Q&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b} Is there anyway to obtain the guid of the connected logical drive or its dos name.我想知道连接设备的dos path或像这样的 Guid \\?\Volume{17ee3574-7082-4881-aeae-07893db4e957}\dbcc_name给了我\\?\STORAGE#Volume#_??_USBSTOR#Disk&Ven_JetFlash&Prod_Transcend_8GB&Rev_1100#546IYBDAPBE1075Q&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}获取连接的逻辑驱动器的名称或无论如何它的名称。 My code is:我的代码是:

#define CLS_NAME L"USB_LISTENER_CLASS"
#define HID_CLASSGUID {0x4d1e55b2, 0xf16f, 0x11cf,{ 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30}}
LRESULT message_handler(HWND__* hwnd, UINT uint, WPARAM wparam, LPARAM lparam)
{
    
    switch (uint)
    {
    case WM_NCCREATE: // before window creation
        return true;
        break;

    case WM_CREATE: // the actual creation of the window
    {
        // you can get your creation params here..like GUID..
        LPCREATESTRUCT params = (LPCREATESTRUCT)lparam;
        GUID InterfaceClassGuid = *((GUID*)params->lpCreateParams);
        DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;

        ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
        NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
        NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
        NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_VOLUME;

        HDEVNOTIFY dev_notify = RegisterDeviceNotification(hwnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
        if (dev_notify == NULL)
        {   
            throw std::runtime_error("Could not register for device Notifications!");
        }

    }
    break;

    case WM_DEVICECHANGE:
    {

        PDEV_BROADCAST_HDR(lpdb) = (PDEV_BROADCAST_HDR)lparam;
        PDEV_BROADCAST_DEVICEINTERFACE_W lpdbv = (PDEV_BROADCAST_DEVICEINTERFACE_W)lpdb;
        switch (wparam)
        {

            case DBT_DEVICEARRIVAL:     //A device or piece of media has been inserted and is now available.

                std::cout << "Device Arrived" << std::endl;
                std::cout << "GUID od inserted device: " << lpdbv->dbcc_name;
                break;

            case DBT_DEVICEREMOVECOMPLETE:
                std::cout << "Device Removed" << std::endl;
                break;
        }
        
    }

    }
    return 0L;
}
void UsbListener::RegisterListener()
{
    HWND hWnd = NULL;
    WNDCLASSEXW wx;
    ZeroMemory(&wx, sizeof(wx));
    wx.cbSize = sizeof(WNDCLASSEX);
    wx.lpfnWndProc = reinterpret_cast<WNDPROC>(message_handler);
    wx.hInstance = reinterpret_cast<HINSTANCE>(GetModuleHandle(0));
    wx.style = CS_HREDRAW | CS_VREDRAW;
    wx.hInstance = GetModuleHandle(0);
    wx.hbrBackground = (HBRUSH)(COLOR_WINDOW);
    wx.lpszClassName = CLS_NAME;
    GUID guid = HID_CLASSGUID;
    if (RegisterClassExW(&wx))
    {
        hWnd = CreateWindowW(
            CLS_NAME, L"DeviceNotificationWindow", WS_ICONIC, 0, 0, CW_USEDEFAULT, 0, HWND_MESSAGE, NULL, GetModuleHandle(0), (void*)&guid
        );
    }
    if (hWnd == NULL)
    {
        throw std::runtime_error("Could not create message window!");
    }
    std::cout <<std::endl<< "Listening..." << std::endl;
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }   
}

I want to know the Dos name of the exact drive that is inserted or removed so that UI can display.我想知道插入或删除的确切驱动器的 Dos 名称,以便 UI 可以显示。 I am new to winapi so please bear with the code,我是 winapi 的新手,所以请耐心等待代码,

at the begin you need open Mount Manager and save it handle in class associated with your window, for not open/close it multiple time, bit only once在开始时,您需要打开安装管理器并将其保存在与您的 window 关联的 class 中,因为不能多次打开/关闭它,仅位一次

#include <mountmgr.h>

HANDLE hMountMgr = CreateFileW(MOUNTMGR_DOS_DEVICE_NAME, 0, 0, 0, OPEN_EXISTING, 0, 0);

for query dos like name (if it exist !) you need first get device name via IOCTL_MOUNTDEV_QUERY_DEVICE_NAME which need send to device, which interface name you have.对于类似名称的查询(如果存在!),您需要首先通过IOCTL_MOUNTDEV_QUERY_DEVICE_NAME获取设备名称,该名称需要发送到设备,您拥有哪个接口名称。 so you need first open it.所以你需要先打开它。

then you can send IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH to Mount Manager and got what you want然后你可以将IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH发送到Mount Manager并得到你想要的

volatile UCHAR guz;

ULONG GetDosVolumePath(HANDLE hMountMgr, PCWSTR InterfaceLink, PWSTR* ppszDosPath)
{
    *ppszDosPath = 0;

    HANDLE hFile = CreateFileW(InterfaceLink, 0, FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING, 0, 0);

    if (hFile == INVALID_HANDLE_VALUE) return GetLastError();

    union {
        PVOID buf;
        PMOUNTDEV_NAME pmdn;
    };

    ULONG dwError;

    PVOID stack = alloca(guz);
    ULONG cb = 0, rcb, InputBufferLength = sizeof(MOUNTDEV_NAME) + 0x40;

    do 
    {
        if (cb < InputBufferLength)
        {
            cb = RtlPointerToOffset(buf = alloca(InputBufferLength - cb), stack);
        }

        dwError = BOOL_TO_ERROR(DeviceIoControl(hFile, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, 0, 0, pmdn, cb, &rcb, 0));

        InputBufferLength = FIELD_OFFSET(MOUNTDEV_NAME, Name) + pmdn->NameLength;

    } while ( dwError == ERROR_MORE_DATA);

    CloseHandle(hFile);

    if (dwError == NOERROR)
    {
        union {
            PVOID pv;
            PMOUNTMGR_VOLUME_PATHS pmvp;
        };

        cb = 0, rcb = sizeof(MOUNTMGR_VOLUME_PATHS) + 8;

        do 
        {
            if (cb < rcb)
            {
                cb = RtlPointerToOffset(pv = alloca(rcb - cb), pmdn);
            }

            dwError = BOOL_TO_ERROR(DeviceIoControl(hMountMgr, 
                IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH, 
                pmdn, InputBufferLength, pmvp, cb, &rcb, 0));

            if (dwError == NOERROR)
            {
                *ppszDosPath = _wcsdup(pmvp->MultiSz);
            }

            rcb = FIELD_OFFSET(MOUNTMGR_VOLUME_PATHS, MultiSz) + pmvp->MultiSzLength;

        } while (dwError == ERROR_MORE_DATA);
    }

    return dwError;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM