https://bugs.winehq.org/show_bug.cgi?id=37724
Bug ID: 37724 Summary: Modern applications won't find COM ports nor HID devices Product: Wine Version: unspecified Hardware: x86 OS: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: setupapi Assignee: wine-bugs@winehq.org Reporter: heha@hrz.tu-chemnitz.de Distribution: ---
While old apps search COM ports use CreateFile("COMx"...) attempts to detect the presence of serial interfaces, newer apps use SetupDi functions. As a typical excerpt:
devs=SetupDiGetClassDevs(&GUID_DEVCLASS_PORTS,NULL,0,DIGCF_PRESENT); if (devs!=INVALID_HANDLE_VALUE) { SP_DEVINFO_DATA devInfo; devInfo.cbSize=sizeof devInfo; for (i=0; SetupDiEnumDeviceInfo(devs,i,&devInfo); i++) { HKEY hKey; TCHAR s[16]; DWORD slen=sizeof s; *s=0; if ((hKey=SetupDiOpenDevRegKey(devs,&devInfo, DICS_FLAG_GLOBAL,0,DIREG_DEV,KEY_READ)) ==INVALID_HANDLE_VALUE) continue; RegQueryValueEx(hKey,T("PortName"),NULL,NULL,(LPBYTE)s,&slen); RegCloseKey(hKey); if (*s=='C') { // filter out LPTx int idx=ComboBox_AddString(hCombo,s); int num=StrToInt(s+3)-1; ComboBox_SetItemData(hCombo,idx,num); if (num==Config.SerialNo) ComboBox_SetCurSel(hCombo,idx); } } SetupDiDestroyDeviceInfoList(devs); }
The main advantages for this approach are: * Unlimited COM port numbers * Much faster than looped CreateFile attempts
Therefore, modern apps use this procedure.
Similarly, apps talking with modern USB HID devices (these devices don't need an install procedure), do this procedure to find their device:
GUID hidGuid; HidD_GetHidGuid(&hidGuid); devs=SetupDiGetClassDevs(&hidGuid,0,0,DIGCF_PRESENT|DIGCF_DEVICEINTERFACE); if (devs!=INVALID_HANDLE_VALUE) { SP_DEVICE_INTERFACE_DATA devinterface; devinterface.cbSize=sizeof devinterface; for (i=0; SetupDiEnumDeviceInterfaces(devs,NULL,&hidGuid,i,&devinterface); i++) { THid Hid; union{ // save stack space SP_DEVICE_INTERFACE_DETAIL_DATA detail; TCHAR space[MAX_PATH+4]; WCHAR ps[128]; // Product String HIDD_ATTRIBUTES a; }u; SP_DEVINFO_DATA info; info.cbSize=sizeof info; u.detail.cbSize=sizeof u.detail; if (!SetupDiGetDeviceInterfaceDetail(devs,&devinterface, &u.detail,sizeof u,NULL,&info)) continue; Hid.hDev=CreateFile(u.detail.DevicePath,GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL); if (Hid.hDev!=INVALID_HANDLE_VALUE) { HidD_GetAttributes(Hid.hDev,&u.a); if (*(DWORD*)&u.a.VendorID==0x27D916C0 && HidD_GetProductString(Hid.hDev,u.ps,elemof(u.ps))) { int l=ComboBox_AddStringW(hCombo,u.ps); ComboBox_SetItemData(hCombo,l,i); if (i==Config.iUsbHid) ComboBox_SetCurSel(hCombo,l); } CloseHandle(Hid.hDev); } } SetupDiDestroyDeviceInfoList(devs); }
Nice when at least the COM port detection will work in near future.
I can write a small test application to support the bug-fixing process. Googling for Funkuhr.exe will reveal a source code that contains both routines already.