So that we can access the correct device IDs.
---
The EA launcher uses WMI to query system information to tie licenses to particular machines. It expects that a video controller's PNPDeviceID will be valid (i.e. something under CurrentControlSet\Enum), which it no longer is since we stopped using DXGI in d511872a3d0dce5148d23ce5cbf80c989d484b26 / !7450. That information is available from setupapi, which is presumably faster than DXGI (speed was the motivating factor for !7450 - see the original bug https://bugs.winehq.org/show_bug.cgi?id=38879).
I'm all ears if there's a better way to associate the devices under CurrentControlSet\Control\Class{4d36e968-e325-11ce-bfc1-08002be10318} with those that setupapi reads from ...\Enum, or if there's a way to get the stuff that's in ...\Class out of setupapi (e.g. the RAM and DAC type).
From: Tim Clem tclem@codeweavers.com
So that we can access the correct device IDs. --- dlls/wbemprox/Makefile.in | 2 +- dlls/wbemprox/builtin.c | 127 ++++++++++++++++++++++++-------------- 2 files changed, 83 insertions(+), 46 deletions(-)
diff --git a/dlls/wbemprox/Makefile.in b/dlls/wbemprox/Makefile.in index 8c57cf95cdb..3abfac841c9 100644 --- a/dlls/wbemprox/Makefile.in +++ b/dlls/wbemprox/Makefile.in @@ -1,5 +1,5 @@ MODULE = wbemprox.dll -IMPORTS = winspool version iphlpapi oleaut32 ole32 advapi32 user32 gdi32 ws2_32 +IMPORTS = winspool version iphlpapi setupapi oleaut32 ole32 advapi32 user32 gdi32 ws2_32
SOURCES = \ builtin.c \ diff --git a/dlls/wbemprox/builtin.c b/dlls/wbemprox/builtin.c index e306fbbce53..a2e309dd88b 100644 --- a/dlls/wbemprox/builtin.c +++ b/dlls/wbemprox/builtin.c @@ -40,6 +40,8 @@ #include "ntsecapi.h" #include "winspool.h" #include "ntddstor.h" +#include "setupapi.h" +#include "devguid.h"
#include "wine/debug.h" #include "wbemprox_private.h" @@ -4530,58 +4532,105 @@ struct display_adapter WCHAR *driver_date; WCHAR *driver_desc; WCHAR *driver_version; + WCHAR *pnpdevice_id; WCHAR *dac_type; DWORD memory_size; };
-static struct display_adapter *get_display_adapters( UINT *count ) +static WCHAR *get_string_devprop( HDEVINFO set, SP_DEVINFO_DATA *dev_info, const DEVPROPKEY *key ) { - DWORD nb_allocated = 2, i = 0, idx_class = 0; - HKEY key_class, key_instance; - struct display_adapter *ret, *tmp; - WCHAR instance[5]; - - if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, - L"System\CurrentControlSet\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}", - 0, KEY_ENUMERATE_SUB_KEYS, &key_class )) return NULL; + DEVPROPTYPE type; + DWORD size; + WCHAR *str;
- if (!(ret = malloc( nb_allocated * sizeof(*ret) ))) + if (SetupDiGetDevicePropertyW( set, dev_info, key, &type, NULL, 0, &size, 0 ) || GetLastError() != ERROR_INSUFFICIENT_BUFFER) return NULL; + if (type != DEVPROP_TYPE_STRING && type != DEVPROP_TYPE_STRING_LIST) return NULL; + if (!(str = malloc( size ))) return NULL; + if (!SetupDiGetDevicePropertyW( set, dev_info, key, &type, (BYTE *)str, size, NULL, 0 )) { - RegCloseKey( key_class ); + free(str); return NULL; }
- while (RegEnumKeyW( key_class, idx_class++, instance, ARRAY_SIZE(instance) ) != ERROR_NO_MORE_ITEMS) + return str; +} + +static struct display_adapter *get_display_adapters( UINT *count ) +{ + static const WCHAR *class_prefix = L"System\CurrentControlSet\Control\Class\"; + DWORD nb_allocated = 2, i = 0, idx_devinfo = 0; + struct display_adapter *ret, *tmp; + HDEVINFO devs; + SP_DEVINFO_DATA dev_info = { .cbSize = sizeof(SP_DEVINFO_DATA) }; + + if (!(ret = malloc( nb_allocated * sizeof(*ret) ))) return NULL; + + if ((devs = SetupDiGetClassDevsW( &GUID_DEVCLASS_DISPLAY, NULL, NULL, DIGCF_PRESENT )) == INVALID_HANDLE_VALUE) return NULL; + + while(SetupDiEnumDeviceInfo( devs, idx_devinfo++, &dev_info )) { - if (!RegOpenKeyExW( key_class, instance, 0, KEY_READ, &key_instance )) + WCHAR *driver, *hw_ids; + UINT key_len; + WCHAR *key_path; + HKEY key_instance; + + if (!(driver = get_string_devprop( devs, &dev_info, &DEVPKEY_Device_Driver ))) continue; + if (!(hw_ids = get_string_devprop( devs, &dev_info, &DEVPKEY_Device_HardwareIds ))) + { + free( driver ); + continue; + } + + key_len = wcslen( class_prefix ) + wcslen( driver ) + 1; + if (!(key_path = calloc( sizeof(WCHAR), key_len ))) { - ret[i].driver_date = get_reg_value( key_instance, L"DriverDate" ); - ret[i].driver_desc = get_reg_value( key_instance, L"DriverDesc" ); - ret[i].driver_version = get_reg_value( key_instance, L"DriverVersion" ); - ret[i].dac_type = get_reg_value( key_instance, L"HardwareInformation.DacType" ); - ret[i].memory_size = get_reg_value_dword( key_instance, L"HardwareInformation.MemorySize" ); - if (++i >= nb_allocated) + free( driver ); + free( hw_ids ); + continue; + } + + swprintf( key_path, key_len, L"%s%s", class_prefix, driver ); + free( driver ); + + if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, key_path, 0, KEY_QUERY_VALUE, &key_instance )) + { + free( hw_ids ); + free( key_path ); + continue; + } + + free( key_path ); + + ret[i].driver_date = get_reg_value( key_instance, L"DriverDate" ); + ret[i].driver_desc = get_reg_value( key_instance, L"DriverDesc" ); + ret[i].driver_version = get_reg_value( key_instance, L"DriverVersion" ); + /* DEVPKEY_Device_HardwareIds is actually an array of null-terminated + strings, so consumers will only see the first one. */ + ret[i].pnpdevice_id = hw_ids; + ret[i].dac_type = get_reg_value( key_instance, L"HardwareInformation.DacType" ); + ret[i].memory_size = get_reg_value_dword( key_instance, L"HardwareInformation.MemorySize" ); + if (++i >= nb_allocated) + { + nb_allocated *= 2; + if ((tmp = realloc( ret, nb_allocated * sizeof(*ret) ))) ret = tmp; + else { - nb_allocated *= 2; - if ((tmp = realloc( ret, nb_allocated * sizeof(*ret) ))) ret = tmp; - else + while (--i) { - while (--i) - { - free( ret[i].driver_date ); - free( ret[i].driver_desc ); - free( ret[i].driver_version ); - free( ret[i].dac_type ); - } - goto done; + free( ret[i].driver_date ); + free( ret[i].driver_desc ); + free( ret[i].driver_version ); + free( ret[i].pnpdevice_id ); + free( ret[i].dac_type ); } + RegCloseKey( key_instance ); + goto done; } - RegCloseKey( key_instance ); } + RegCloseKey( key_instance ); }
done: - RegCloseKey( key_class ); if (!i) { free( ret ); @@ -4605,18 +4654,6 @@ static DWORD get_adapter_vendor_id( const WCHAR *desc ) return HW_VENDOR_WINE; }
-static WCHAR *get_videocontroller_pnpdeviceid( const WCHAR *desc ) -{ - static const WCHAR fmtW[] = L"PCI\VEN_%04X&DEV_0000&SUBSYS_00000000&REV_00\0&DEADBEEF&0&DEAD"; - DWORD vendor_id = get_adapter_vendor_id( desc ); - UINT len = ARRAY_SIZE(fmtW); - WCHAR *ret; - - if (!(ret = malloc( len * sizeof(WCHAR) ))) return NULL; - swprintf( ret, len, fmtW, vendor_id ); - return ret; -} - static const WCHAR *get_videocontroller_installeddriver( const WCHAR *desc ) { DWORD vendor_id = get_adapter_vendor_id( desc ); @@ -4674,7 +4711,7 @@ static enum fill_status fill_videocontroller( struct table *table, const struct rec->driverversion = adapters[i].driver_version; rec->installeddriver = get_videocontroller_installeddriver( adapters[i].driver_desc ); rec->name = wcsdup( rec->caption ); - rec->pnpdevice_id = get_videocontroller_pnpdeviceid( adapters[i].driver_desc ); + rec->pnpdevice_id = adapters[i].pnpdevice_id; rec->status = L"OK"; rec->videoarchitecture = 2; /* Unknown */ rec->videomemorytype = 2; /* Unknown */