0x01AA Ответов: 2

W32-registerdevicenotification - dev_broadcast_deviceinterface - ansi против unicode


Уважаемые Эксперты
Я должен добавить небольшое расширение к устаревшему приложению. Расширение просто подключается к приезду USB-устройства.

Поэтому я зарегистрировал свое главное окно для получения уведомлений:

Файл MainWindow конструктор
{
   // Register me to receive device Change notifications
   DEV_BROADCAST_DEVICEINTERFACE xNotificationFilter;
   memset(&xNotificationFilter, 0, sizeof(xNotificationFilter));
   xNotificationFilter.dbcc_size= sizeof(xNotificationFilter);
   xNotificationFilter.dbcc_devicetype= DBT_DEVTYP_DEVICEINTERFACE;
   xNotificationFilter.dbcc_classguid= GUID_DEVINTERFACE_USB_DEVICE;
   mHDEVNOTIFY= RegisterDeviceNotification(Handle,
                                           &xNotificationFilter,
                                           DEVICE_NOTIFY_WINDOW_HANDLE);
}

и сделайте это, чтобы справиться с событием:
{
   if (Message.WParam == DBT_DEVICEARRIVAL)
   {
      PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)Message.LParam;
      if (lpdb -> dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
      {
         PDEV_BROADCAST_DEVICEINTERFACE xDevIntf= (PDEV_BROADCAST_DEVICEINTERFACE)Message.LParam;
         if(xDevIntf->dbcc_classguid == GUID_DEVINTERFACE_USB_DEVICE)
         {
            //
	    // -------- Here my confusion. dbcc_name is TCHAR even my app is "ANSI" --------------
            //
            wchar_t* xNameW= (wchar_t*)xDevIntf->dbcc_name;
            AnsiString xName= WideString(xNameW);
            // \\?\USB#VID_0000&PID_0000#5&1835e82d&0&3#{a5dcbf10-...."
            //
            LogMsg(xName);

         }
      }
    }
}


В принципе все работает нормально но в одном пункте у меня есть сомнения:
По словам госпожи Структура DEV_BROADCAST_DEVICEINTERFACE (Windows)[^] dbcc_name структура DEV_BROADCAST_DEVICEINTERFACE должна быть возвращена как ANSI char* для "ANSI Apps", по крайней мере, она описана таким образом.

Но то, что я вижу, это то, что dbcc_name всегда возвращается в Юникоде.

Я пробовал также явно RegisterDeviceNotificationA но то же самое, dbcc_name возвращается как Unicode.


Кто-нибудь может подтвердить это или указать, где я ошибаюсь, что я упускаю?

Заранее большое вам спасибо.


[Edit]кстати, это определяется dbt. h:
#if(WINVER >= 0x040A)

typedef struct _DEV_BROADCAST_DEVICEINTERFACE_A {
    DWORD       dbcc_size;
    DWORD       dbcc_devicetype;
    DWORD       dbcc_reserved;
    GUID        dbcc_classguid;
    char        dbcc_name[1];
} DEV_BROADCAST_DEVICEINTERFACE_A, *PDEV_BROADCAST_DEVICEINTERFACE_A;

typedef struct _DEV_BROADCAST_DEVICEINTERFACE_W {
    DWORD       dbcc_size;
    DWORD       dbcc_devicetype;
    DWORD       dbcc_reserved;
    GUID        dbcc_classguid;
    wchar_t     dbcc_name[1];
} DEV_BROADCAST_DEVICEINTERFACE_W, *PDEV_BROADCAST_DEVICEINTERFACE_W;


Что я уже пробовал:

Я описал выше то, что я пробовал. "Что вы пробовали" - это ужасная новая функция....

2 Ответов

Рейтинг:
14

Richard MacCutchan

Видеть Структура DEV_BROADCAST_DEVICEINTERFACE (Windows)[^] где он объясняет, почему он всегда является Unicode.


0x01AA

Это именно та ссылка, о которой я упоминал, и где вы найдете в деталях, что она не всегда повторяется как Unicode:

dbcc_name:
Строка с нулевым завершением, указывающая имя устройства.

Когда эта структура возвращается в окно через сообщение WM_DEVICECHANGE, строка dbcc_name преобразуется в ANSI по мере необходимости. Службы всегда получают строку Unicode, независимо от того, вызывают ли они RegisterDeviceNotificationW или RegisterDeviceNotificationA.

Хммм... или это опять мой недостаток в английском?
Делает " строка dbcc_name преобразуется в ANSI как подходящий- значит, я должен сделать это сам?

Richard MacCutchan

В субботу мозг более расслаблен, чем обычно.

Заявление: Службы всегда получают строку Unicode, независимо от того, вызывают ли они RegisterDeviceNotificationW или RegisterDeviceNotificationA. это тот, который следует отметить, в котором четко указано, что вы всегда будете получать имя в виде строки Unicode в сообщении DeviceNotification.

0x01AA

_Services_ да! Но я работаю над простым приложением, а не над сервисом!
Это не связано с субботой или вашим вменением/намеком на то, что я пьян ;P

mHDEVNOTIFY= RegisterDeviceNotification(Handle,
&xNotificationFilter,
DEVICE_NOTIFY_WINDOW_HANDLE); это связано с приложением. Сервис должен использовать DEVICE_NOTIFY_SERVICE_HANDLE

Пожалуйста, объясните мне, где я ошибаюсь. то, что я неправильно интерпретирую документацию в MSDN.
Спасибо.

Richard MacCutchan

Я уже не раз говорил вам, пожалуйста, внимательно прочтите следующее:
Услуги всегда получайте строку Unicode, независимо от того, вызывают ли они RegisterDeviceNotificationW или RegisterDeviceNotificationA.

Я согласен, что вы не являетесь сервисом, но вы используете RegisterDeviceNotification, таким образом, вы получите это поле в Юникоде, как указано.

0x01AA

Нет, извини, ты ошибаешься, я думаю. Даже если я использую RegisterDeviceNotificationОдин Я получу его в Юникоде... который не соответствует MSDN:
.....этот строка dbcc_name преобразуется в ANSI по мере необходимости

Кстати: как ссылка, о которой я упоминал в своем вопросе, может быть решением?

BTW1: признаете ли вы разницу между
RegisterDeviceNotification(.....DEVICE_NOTIFY_ОКНО_СПРАВЛЯТЬСЯ.....)
и
RegisterDeviceNotification(.....DEVICE_NOTIFY_ОБСЛУЖИВАНИЕ_СПРАВЛЯТЬСЯ.....)

В любом случае, спасибо за вашу помощь.

0x01AA

Я не буду голосовать за этот ответ, но и не вижу причин голосовать здесь за 5. Это потому, что это не ответ... до сих пор.

Richard MacCutchan

Что ж, это ваш выбор, но все же это ответ - и правильный.

0x01AA

Нет, извини, ты ошибаешься, я думаю. Даже если я использую RegisterDeviceNotificationОдин Я получу его в Юникоде... который не соответствует MSDN.

Richard MacCutchan

Точно, и это то, что я пытаюсь объяснить.

0x01AA

Что "объяснить"?

Признаете ли вы разницу между
RegisterDeviceNotification(.....DEVICE_NOTIFY_WINDOW_HANDLE.....)
и
RegisterDeviceNotification(.....DEVICE_NOTIFY_SERVICE_HANDLE.....)

AnyW32ApiОдин должен получить Ansi (app whise _not_ service), и это, кажется, не так в моем коде... Вы до сих пор не объяснили, в чем я ошибаюсь. Хорошо, это не ваша вещь, это скорее вещь MS :)

В любом случае, спасибо за вашу помощь.

0x01AA

Здесь я сдаюсь. 5 за вашу помолвку и принято. Даже я не уверен в ответе.

Richard MacCutchan

Если вы действительно считаете, что документация неверна, то вам следует опубликовать этот вопрос на форуме Microsoft.

0x01AA

Я не думаю, что документация ошибочна, я думаю, что это мой английский. У меня нет четкого представления о том, что

"строка dbcc_name преобразуется в ANSI по мере необходимости"

действительно означать. Особенно по мере необходимости Я совершенно не знаю, как это интерпретировать.

Теперь решение для меня простое. Я буду явно использовать" W " - Api, чтобы это было безопасно...Я надеюсь :)

Richard MacCutchan

Я всегда избегаю использовать суффиксы W или A. Просто используйте стандартное имя, как в документации, и позвольте компилятору сгенерировать правильный вызов, в зависимости от того, строится ли код для Unicode или ASCII.

Рейтинг:
11

Uwe_Sieber

Просто для протокола... Я столкнулся с точно такой же проблемой. С 1999 года dbcc_name указывал на строку char, если вызывалась RegisterDeviceNotificationA, и на строку wchar_t, если вызывалась RegisterDeviceNotificationW. Единственное исключение было в сервисе HandlerEx, здесь всегда получалась строка wchar_t.

Теперь я получил сообщение о том, что мое USB-устройство просмотра дерева (UsbTreeView) не выполнить какое-либо обновление по прибытии или удаления USB-устройств с V3.0. Начиная с этой версии обновления было избирательным, более старые версии всего выполняется методом сплошной регистрации по прибытии или удаления каких-либо USB-устройства.

Пользователь, сообщивший о проблеме, прислал мне файл журнала, и он ясно показал, что dbcc_name указывает на путь устройства wchar_t, даже RegisterDeviceNotificationA был использован. Я проверил двоичный файл, там нет ссылки на RegisterDeviceNotificationW, только на RegisterDeviceNotificationA.

Теперь я добавил автоопределение char / wchar_t, и автоматическое обновление работает для пользователя, сообщающего о проблеме. Это было на Windows 10 14393 x64 с выпусками Win32 и x64 UsbTreeView. Кодовая страница ANSI-1252, так что здесь нет ничего особенного.
Он заверил меня, что на этом Windows нет никакого анти-чего-то программного обеспечения, которое могло бы обойти вызов A на W.
На моем Win10 14393 и сервере 2016 проблемы нет, пути к устройствам приходят такими же символами, как и должны.
Так что это остается тайной.


0x01AA

Большое вам спасибо за это и, конечно же, acepted и 5.
Бруно