Получение dos_name usb при вставке или удалении - PullRequest
1 голос
/ 11 июля 2020

Я разработал программу для обнаружения, когда USB-устройство подключается или отключается. Я хочу знать либо 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} Есть ли способ получить Guid подключенного логического диска или его имя dos. Мой код:

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

Я хочу знать имя Dos того диска, который вставлен или удален, чтобы отображался пользовательский интерфейс. Я новичок в winapi, поэтому, пожалуйста, имейте код

1 Ответ

1 голос
/ 11 июля 2020

в начале вам нужно открыть Mount Manager и сохранить его дескриптор в классе, связанном с вашим окном, чтобы не открывать / закрывать его несколько раз, бит только один раз

#include <mountmgr.h>

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

для запроса типа имени (если оно существует!) Вам сначала нужно получить имя устройства через IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, которое необходимо отправить на устройство, какое имя интерфейса у вас есть. поэтому вам нужно сначала открыть его.

затем вы можете отправить 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...