Created attachment 286 [details] Программа, выводящая список USB-устройств В приложении тестовая программа, которая получает список USB-устройств под Windows XP.
В Windows XP информация об USB-устройствах берётся из реестра. Используются как минимум следующие ветки реестра: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\DeviceClasses\GUID_класса, HKEY_LOCAL_MACHINE\System\CurrentControlSet\Enum\USB\ROOT_HUB для хабов и по-видимому похожая ветка для USB-устройств. Если добавить в реестр Wine из Windows XP ветки HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\DeviceClasses\{a5dcbf10-6530-11d2-901f-00c04fb951ed}, HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\DeviceClasses\{f18a0e88-c30c-11d0-8815-00a0c906bed8}, HKEY_LOCAL_MACHINE\System\CurrentControlSet\Enum\USB\ROOT_HUB, то при выполнении тестовой программы наблюдаются следующие проблемы: 1) программа падает; 2) выводятся лишние имена файлов устройств; 3) выводятся сообщения "SetupDiGetDeviceRegistryPropertyA: error 0x103" (0x103 - ошибка ERROR_NO_MORE_ITEMS); 4) в реестре появляется ключ HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\DeviceClasses\{f18a0e88-c30c-11d0-8815-00a0c906bed8}\#
Created attachment 287 [details] HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceClasses\{f18a0e88-c30c-11d0-8815-00a0c906bed8}
Created attachment 288 [details] HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceClasses\{a5dcbf10-6530-11d2-901f-00c04fb951ed}
Created attachment 289 [details] HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\ROOT_HUB
Created attachment 290 [details] Патч частично решает проблему с выводом лишних имён файлов USB-устройств Патч к файлу devinst.c
Created attachment 294 [details] Патч к devinst.c При работе программы происходит повреждение флага phantom в структуре DeviceInfo. В результате его значение меняется с 0 на произвольное, что приводит к изменению поведения при освобождении памяти и падению программы. Данный патч полностью не решает проблему повреждения памяти, а только лишь обходит её, предотвращая падение программы.
Created attachment 305 [details] Патч, решающий проблему падения программы Патч к оригинальному devinst.c
Created attachment 306 [details] Патч, решающий проблему создания ненужного ключа в реестре Патч к оригинальному devinst.c (включает в себя предыдущие патчи) Патч решает проблему создания в реестре ключа HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\DeviceClasses\{f18a0e88-c30c-11d0-8815-00a0c906bed8}\#
Created attachment 307 [details] HKEY_LOCAL_MACHINE\System\CurrentControlSet\Enum\USB\ROOT_HUB20 Ветка реестра, необходимая для отображения информации об одном из хабов
Created attachment 317 [details] HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB
Created attachment 318 [details] Патч к devinst.c (включает предыдущие патчи) Исправлены функции SetupDiGetDeviceRegistryPropertyA и SetupDiGetDeviceRegistryPropertyW. Теперь тестовая программа работает нормально за исключением того, что она выводит все устройства, записи о которых имеются в реестре, а не только те, которые в данный момент установлены в системе.
Не совсем ясно, куда вставить код, отвечающий за создание в реестре списка USB-устройств, чтобы он выполнялся при запуске wine. Можно обновлять список USB-устройств при вызове SetupDiGetClassDevsExW или какой-нибудь другой функции, имеющей отношение к получению списка устройств. В рассылке wine-devel есть патч к programs/explorer/hal.c для получения списка USB-устройств (тема письма "Adding devices to registry with the help of hal"), но он, судя по всему, в данном случае не поможет, так как при запуске тестовой программы explorer не запускается.
При получении списка USB-устройств под Wine почему-то меняются значения параметров HKEY_LOCAL_MACHINE\System\CurrentControlSet\Enum\USB\ROOT_HUB\устройство\ClassGUID
Проблема наблюдается только при использовании сторонней rpcrt4.dll
Реализовано занесение в реестр информации об имеющихся USB-устройствах. Начата реализация функций, отвечающих за удаление записей, соответствующих уже отсутствующим в системе устройствам, информация о которых была записана ранее. В Windows XP в ключе HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\DeviceClasses\{a5dcbf10-6530-11d2-901f-00c04fb951ed} находятся подключи с именами вида ##?#USB#Vid_0529&Pid_0001#what#{a5dcbf10-6530-11d2-901f-00c04fb951ed}, где what может выглядеть, например, так: 5&6d75465&0&2, TQ42Y8VA, 00071212BA8C83C417C3, 359672004624568_0. По-видимому, what используется для того, чтобы различать устройства с одинаковыми Vid и Pid. В Wine вместо what я использовал строку, полученную конкатенацией dev->bus->dirname и dev->filename, где dev - структура usb_device из usb.h.
Не совсем понятно, что делать с хабами, которые не являются корневыми. Сейчас они добавляются в HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\ROOT_HUB. Как делается в Windows, я не знаю, так как у меня нет хаба, чтобы проверить.
Теперь в HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\ROOT_HUB добавляются только хабы, у которых vid и pid равны 0.
Created attachment 332 [details] Патч к Makefile.in для линковки libusb
Created attachment 333 [details] Патч к dlls/setupapi/devinst.c (включает предыдущие патчи) Перечисление USB-устройств с использованием libusb
Для включения патчей в основную ветвь разработки wine необходимо написать тесты, выявляющие проблемы, которые решают патчи. При написании патчей использовалась перечисляющая устройства программа и ветви реестра из WinXP. В тесте надо создать в реестре аналогичные структуры средствами setupapi.dll из wine. Пока это сделать не получилось и даже не ясно, возможно ли это в принципе. Кроме того, оказалось, что многие тесты из setupapi_crosstest.exe (тесты к setupapi/devinst.c) работают под Wine, но не работают на Windows XP Pro SP2, установленной в VMware. А для принятия патчей в оригинальный wine надо написать тесты, работающие под Windows.
> Кроме того, оказалось, что многие тесты из > setupapi_crosstest.exe (тесты к setupapi/devinst.c) работают > под Wine, но не работают на Windows XP Pro SP2, > установленной в VMware. Тесты работают только один раз. Они создают записи в реестре. Если их удалить, то тесты снова смогут работать.
Created attachment 353 [details] Тест, выполняющийся на Windows, но не работающий на Wine
Created attachment 354 [details] Патч к devinst.c Тест testRegisterAndGetDetail не работает, так как в реестре Wine неправильно создаются записи об интерфейсах устройств. Патч решает эту проблему. В результате тест под Wine падает, выявляя ранее обнаруженную ошибку в SETUPDI_AddDeviceToSet.
Created attachment 355 [details] Патч, решающий проблему падения теста под Wine Это часть ранее выложенного патча к devinst.c (devinst.patch_3)
Тест testRegisterAndGetDetail выполняется под Wine с предыдущими 2-мя патчами, но создающиеся при этом записи в реестре отличаются от тех, что создаются в Windows. Основное отличие: под Wine создаются лишние записи об интерфейсах устройств.
Created attachment 356 [details] Патч из приложения 354, из которого удалены ненужные TRACE
Created attachment 357 [details] Тест, выполняющийся на Windows, но не работающий на Wine Удалён ненужный RegCloseKey(key)
Created attachment 358 [details] Улучшение патча из приложения 356 Создаваемые в реестре записи больше похожи на те, что создаются в Windows.
Created attachment 359 [details] Патч к devinst.c, обеспечивающий работу теста testRegisterAndGetDetail Внесены исправления согласно указаниям, данным в wine-devel
Created attachment 360 [details] testRegisterAndGetDetail Тест, исправленный согласно указаниям, данным в wine-devel
Написаны тесты для SetupDiGetDeviceRegistryProperty и SetupDiSetDeviceRegistryProperty. Патч, исправляющий некоторые мешающие ошибки в этих функциях, был написан ранее.
В патче, отвечающем за перечисление USB-устройств, есть ошибка, которая может привести к тому, что одно устройство будет добавлено в реестр несколько раз. Правильно должно быть, например, так: for (bus = usb_busses; bus; bus = bus->next) if (bus->root_dev) print_dev(bus->root_dev); else for (dev = bus->devices; dev; dev = dev->next) print_dev(dev);
Думаю, этот баг не актуален, так как это не нужно никому из клиентов