From 23f9d8d35d10b1517a303cd79e1300fdc059bb1d Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Thu, 11 Feb 2016 06:11:49 +0100 Subject: [PATCH] Added patch to fix enumeration of display driver properties using setupapi. --- patches/patchinstall.sh | 21 ++ ...registry-keys-for-display-devices-an.patch | 198 ++++++++++++++++++ ...the-case-that-a-full-driver-path-is-.patch | 90 ++++++++ patches/setupapi-Display_Device/definition | 1 + 4 files changed, 310 insertions(+) create mode 100644 patches/setupapi-Display_Device/0001-setupapi-Create-registry-keys-for-display-devices-an.patch create mode 100644 patches/setupapi-Display_Device/0002-setupapi-Handle-the-case-that-a-full-driver-path-is-.patch create mode 100644 patches/setupapi-Display_Device/definition diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 66d3aae7..d892ebd6 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -278,6 +278,7 @@ patch_enable_all () enable_server_Timestamp_Compat="$1" enable_server_Win8_Pseudo_Handles="$1" enable_services_SERVICE_FILE_SYSTEM_DRIVER="$1" + enable_setupapi_Display_Device="$1" enable_setupapi_HSPFILEQ_Check_Type="$1" enable_setupapi_SetupDiSetDeviceInstallParamsW="$1" enable_setupapi_SetupPromptForDisk="$1" @@ -980,6 +981,9 @@ patch_enable () services-SERVICE_FILE_SYSTEM_DRIVER) enable_services_SERVICE_FILE_SYSTEM_DRIVER="$2" ;; + setupapi-Display_Device) + enable_setupapi_Display_Device="$2" + ;; setupapi-HSPFILEQ_Check_Type) enable_setupapi_HSPFILEQ_Check_Type="$2" ;; @@ -5796,6 +5800,23 @@ if test "$enable_services_SERVICE_FILE_SYSTEM_DRIVER" -eq 1; then ) >> "$patchlist" fi +# Patchset setupapi-Display_Device +# | +# | This patchset fixes the following Wine bugs: +# | * [#35345] Fix enumeration of display driver properties using setupapi +# | +# | Modified files: +# | * dlls/setupapi/devinst.c, dlls/setupapi/tests/devinst.c, loader/wine.inf.in +# | +if test "$enable_setupapi_Display_Device" -eq 1; then + patch_apply setupapi-Display_Device/0001-setupapi-Create-registry-keys-for-display-devices-an.patch + patch_apply setupapi-Display_Device/0002-setupapi-Handle-the-case-that-a-full-driver-path-is-.patch + ( + echo '+ { "Michael Müller", "setupapi: Create registry keys for display devices and display drivers.", 1 },'; + echo '+ { "Michael Müller", "setupapi: Handle the case that a full driver path is passed to SetupDiGetClassDevs.", 1 },'; + ) >> "$patchlist" +fi + # Patchset setupapi-HSPFILEQ_Check_Type # | # | This patchset fixes the following Wine bugs: diff --git a/patches/setupapi-Display_Device/0001-setupapi-Create-registry-keys-for-display-devices-an.patch b/patches/setupapi-Display_Device/0001-setupapi-Create-registry-keys-for-display-devices-an.patch new file mode 100644 index 00000000..c42fcc2b --- /dev/null +++ b/patches/setupapi-Display_Device/0001-setupapi-Create-registry-keys-for-display-devices-an.patch @@ -0,0 +1,198 @@ +From 79cc09b9e1b952772d33335518267dcabb927b01 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Thu, 11 Feb 2016 03:17:09 +0100 +Subject: setupapi: Create registry keys for display devices and display + drivers. + +--- + dlls/setupapi/devinst.c | 111 ++++++++++++++++++++++++++++++++++++++++++------ + loader/wine.inf.in | 2 + + 2 files changed, 101 insertions(+), 12 deletions(-) + +diff --git a/dlls/setupapi/devinst.c b/dlls/setupapi/devinst.c +index 318dcdf..fc53c31 100644 +--- a/dlls/setupapi/devinst.c ++++ b/dlls/setupapi/devinst.c +@@ -90,6 +90,15 @@ static const WCHAR LowerFilters[] = {'L','o','w','e','r','F','i','l','t','e','r' + static const WCHAR Phantom[] = {'P','h','a','n','t','o','m',0}; + static const WCHAR SymbolicLink[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0}; + ++/* GUIDs */ ++static const WCHAR displayGUIDW[] = {'{','4','d','3','6','e','9','6','8','-','e','3','2','5','-', ++ '1','1','c','e','-','b','f','c','1','-', ++ '0','8','0','0','2','b','e','1','0','3','1','8','}',0}; ++static const WCHAR ddriverGUIDW[] = {'{','4','d','3','6','e','9','6','8','-','e','3','2','5','-', ++ '1','1','c','e','-','b','f','c','1','-', ++ '0','8','0','0','2','b','e','1','0','3','1','8','}', ++ '\\','0','0','0','0',0}; ++ + /* is used to identify if a DeviceInfoSet pointer is + valid or not */ + #define SETUP_DEVICE_INFO_SET_MAGIC 0xd00ff056 +@@ -140,6 +149,90 @@ struct DeviceInfo + struct list interfaces; + }; + ++static void create_display_keys(HKEY enumKey, int index, DISPLAY_DEVICEW *disp) ++{ ++ static const WCHAR fmtW[] = {'1','3','&','1','2','3','4','5','&','%','d',0}; ++ HKEY devKey, intKey; ++ WCHAR buffer[50]; ++ LONG l; ++ ++ l = RegCreateKeyExW(enumKey, disp->DeviceID, 0, NULL, 0, KEY_ALL_ACCESS, ++ NULL, &devKey, NULL); ++ if (l) return; ++ ++ snprintfW(buffer, sizeof(buffer) / sizeof(WCHAR), fmtW, index); ++ l = RegCreateKeyExW(devKey, buffer, 0, NULL, 0, KEY_ALL_ACCESS, ++ NULL, &intKey, NULL); ++ if (!l) ++ { ++ RegSetValueExW(intKey, ClassGUID, 0, REG_SZ, (BYTE *)displayGUIDW, sizeof(displayGUIDW)); ++ RegSetValueExW(intKey, Driver, 0, REG_SZ, (BYTE *)ddriverGUIDW, sizeof(ddriverGUIDW)); ++ RegCloseKey(intKey); ++ } ++ ++ RegCloseKey(devKey); ++} ++ ++static void create_display_driver_keys(void) ++{ ++ static const WCHAR DriverDateDataW[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0}; ++ HKEY classesKey, driverKey; ++ SYSTEMTIME systime; ++ FILETIME filetime; ++ LONG l; ++ ++ l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, ControlClass, 0, NULL, 0, KEY_ALL_ACCESS, ++ NULL, &classesKey, NULL); ++ if (l) return; ++ ++ l = RegCreateKeyExW(classesKey, ddriverGUIDW, 0, NULL, 0, KEY_ALL_ACCESS, ++ NULL, &driverKey, NULL); ++ if (!l) ++ { ++ /* we are really keeping our drivers up to date */ ++ GetSystemTime(&systime); ++ if (SystemTimeToFileTime(&systime, &filetime)) ++ RegSetValueExW(driverKey, DriverDateDataW, 0, REG_BINARY, (BYTE *)&filetime, sizeof(filetime)); ++ ++ RegCloseKey(driverKey); ++ } ++ ++ RegCloseKey(classesKey); ++} ++ ++static LONG open_enum_key(HKEY *key) ++{ ++ static BOOL initialized = FALSE; ++ DISPLAY_DEVICEW disp; ++ HKEY enumKey; ++ LONG l; ++ ++ l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_ALL_ACCESS, ++ NULL, &enumKey, NULL); ++ if (l) return l; ++ ++ if (!initialized) ++ { ++ /* Wine currently does not properly distinguish between monitors and ++ * display devices yet. On a multi monitor system the enumeration ++ * returns multiple devices although there is only one graphic card. ++ * To work around this, we stop the enumeration after the first device. */ ++ ++ TRACE("creating display keys\n"); ++ ++ disp.cb = sizeof(disp); ++ if (EnumDisplayDevicesW(NULL, 0, &disp, 0)) ++ create_display_keys(enumKey, 0, &disp); ++ ++ create_display_driver_keys(); ++ ++ initialized = TRUE; ++ } ++ ++ *key = enumKey; ++ return ERROR_SUCCESS; ++} ++ + static void SETUPDI_GuidToString(const GUID *guid, LPWSTR guidStr) + { + static const WCHAR fmt[] = {'{','%','0','8','X','-','%','0','4','X','-', +@@ -420,8 +513,7 @@ static HKEY SETUPDI_CreateDevKey(struct DeviceInfo *devInfo) + HKEY enumKey, key = INVALID_HANDLE_VALUE; + LONG l; + +- l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_ALL_ACCESS, +- NULL, &enumKey, NULL); ++ l = open_enum_key(&enumKey); + if (!l) + { + RegCreateKeyExW(enumKey, devInfo->instanceId, 0, NULL, 0, +@@ -509,8 +601,7 @@ static void SETUPDI_FreeDeviceInfo(struct DeviceInfo *devInfo) + HKEY enumKey; + LONG l; + +- l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, +- KEY_ALL_ACCESS, NULL, &enumKey, NULL); ++ l = open_enum_key(&enumKey); + if (!l) + { + RegDeleteTreeW(enumKey, devInfo->instanceId); +@@ -2036,8 +2127,7 @@ static void SETUPDI_EnumerateMatchingInterfaces(HDEVINFO DeviceInfoSet, + + TRACE("%s\n", debugstr_w(enumstr)); + +- l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_READ, NULL, +- &enumKey, NULL); ++ l = open_enum_key(&enumKey); + for (i = 0; !l; i++) + { + len = sizeof(subKeyName) / sizeof(subKeyName[0]); +@@ -2265,8 +2355,7 @@ static void SETUPDI_EnumerateDevices(HDEVINFO DeviceInfoSet, const GUID *class, + TRACE("%p, %s, %s, %08x\n", DeviceInfoSet, debugstr_guid(class), + debugstr_w(enumstr), flags); + +- l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_READ, NULL, +- &enumKey, NULL); ++ l = open_enum_key(&enumKey); + if (enumKey != INVALID_HANDLE_VALUE) + { + if (enumstr) +@@ -3717,8 +3806,7 @@ static HKEY SETUPDI_OpenDevKey(struct DeviceInfo *devInfo, REGSAM samDesired) + HKEY enumKey, key = INVALID_HANDLE_VALUE; + LONG l; + +- l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_ALL_ACCESS, +- NULL, &enumKey, NULL); ++ l = open_enum_key(&enumKey); + if (!l) + { + RegOpenKeyExW(enumKey, devInfo->instanceId, 0, samDesired, &key); +@@ -3834,8 +3922,7 @@ static BOOL SETUPDI_DeleteDevKey(struct DeviceInfo *devInfo) + BOOL ret = FALSE; + LONG l; + +- l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_ALL_ACCESS, +- NULL, &enumKey, NULL); ++ l = open_enum_key(&enumKey); + if (!l) + { + ret = RegDeleteTreeW(enumKey, devInfo->instanceId); +diff --git a/loader/wine.inf.in b/loader/wine.inf.in +index d22b29b..48083b8 100644 +--- a/loader/wine.inf.in ++++ b/loader/wine.inf.in +@@ -443,6 +443,8 @@ HKLM,System\CurrentControlSet\Control\ContentIndex\Language\Neutral,"Locale",0x1 + [ControlClass] + HKLM,System\CurrentControlSet\Control\Class\{4d36e967-e325-11ce-bfc1-08002be10318},,,"Disk drives" + HKLM,System\CurrentControlSet\Control\Class\{4d36e967-e325-11ce-bfc1-08002be10318},"Class",,"DiskDrive" ++HKLM,System\CurrentControlSet\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318},,,"Display drivers" ++HKLM,System\CurrentControlSet\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318},"Class",,"Display" + HKLM,System\CurrentControlSet\Control\Class\{4d36e978-e325-11ce-bfc1-08002be10318},,,"Ports (COM & LPT)" + HKLM,System\CurrentControlSet\Control\Class\{4d36e978-e325-11ce-bfc1-08002be10318},"Class",,"Ports" + HKLM,System\CurrentControlSet\Control\Class\{6bdd1fc6-810f-11d0-bec7-08002be2092f},,,"Imaging devices" +-- +2.7.1 + diff --git a/patches/setupapi-Display_Device/0002-setupapi-Handle-the-case-that-a-full-driver-path-is-.patch b/patches/setupapi-Display_Device/0002-setupapi-Handle-the-case-that-a-full-driver-path-is-.patch new file mode 100644 index 00000000..d003a253 --- /dev/null +++ b/patches/setupapi-Display_Device/0002-setupapi-Handle-the-case-that-a-full-driver-path-is-.patch @@ -0,0 +1,90 @@ +From cb319b87c1753f771771ced81be00fa0c5de06bd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Thu, 11 Feb 2016 03:20:33 +0100 +Subject: setupapi: Handle the case that a full driver path is passed to + SetupDiGetClassDevs. + +--- + dlls/setupapi/devinst.c | 26 ++++++++++++++++++++++++-- + dlls/setupapi/tests/devinst.c | 23 +++++++++++++++++++++++ + 2 files changed, 47 insertions(+), 2 deletions(-) + +diff --git a/dlls/setupapi/devinst.c b/dlls/setupapi/devinst.c +index 744bcd6..3708de7 100644 +--- a/dlls/setupapi/devinst.c ++++ b/dlls/setupapi/devinst.c +@@ -2366,8 +2366,30 @@ static void SETUPDI_EnumerateDevices(HDEVINFO DeviceInfoSet, const GUID *class, + &enumStrKey); + if (!l) + { +- SETUPDI_EnumerateMatchingDevices(DeviceInfoSet, enumstr, +- enumStrKey, class, flags); ++ WCHAR *bus, *device; ++ HKEY devKey; ++ ++ if (!strchrW(enumstr, '\\')) ++ { ++ SETUPDI_EnumerateMatchingDevices(DeviceInfoSet, enumstr, ++ enumStrKey, class, flags); ++ } ++ else if ((bus = strdupW(enumstr))) ++ { ++ device = strchrW(bus, '\\'); ++ *device++ = 0; ++ ++ l = RegOpenKeyExW(enumKey, enumstr, 0, KEY_READ, &devKey); ++ if (!l) ++ { ++ SETUPDI_EnumerateMatchingDeviceInstances(DeviceInfoSet, bus, device, ++ devKey, class, flags); ++ RegCloseKey(devKey); ++ } ++ ++ HeapFree(GetProcessHeap(), 0, bus); ++ } ++ + RegCloseKey(enumStrKey); + } + } +diff --git a/dlls/setupapi/tests/devinst.c b/dlls/setupapi/tests/devinst.c +index 319bb31..a0aa531 100644 +--- a/dlls/setupapi/tests/devinst.c ++++ b/dlls/setupapi/tests/devinst.c +@@ -1542,6 +1542,28 @@ static void testSetupDiGetINFClassA(void) + } + } + ++static void testSetupDiGetClassDevsA(void) ++{ ++ static GUID displayguid = {0x4d36e968, 0xe325, 0x11ce, {0xbf,0xc1,0x08,0x00,0x2b,0xe1,0x03,0x18}}; ++ SP_DEVINFO_DATA devinfo; ++ DISPLAY_DEVICEA disp; ++ HDEVINFO set; ++ BOOL ret; ++ ++ disp.cb = sizeof(disp); ++ ok(EnumDisplayDevicesA(NULL, 0, &disp, 0), "EnumDisplayDevices failed: %08x\n", GetLastError()); ++ ++ SetLastError(0xdeadbeef); ++ set = pSetupDiGetClassDevsA(&displayguid, disp.DeviceID, 0, 0); ++ ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n", GetLastError()); ++ ++ devinfo.cbSize = sizeof(devinfo); ++ ret = SetupDiEnumDeviceInfo(set, 0, &devinfo); ++ ok(ret, "SetupDiEnumDeviceInfo failed: %08x\n", GetLastError()); ++ ++ pSetupDiDestroyDeviceInfoList(set); ++} ++ + START_TEST(devinst) + { + init_function_pointers(); +@@ -1570,4 +1592,5 @@ START_TEST(devinst) + testDeviceRegistryPropertyA(); + testDeviceRegistryPropertyW(); + testSetupDiGetINFClassA(); ++ testSetupDiGetClassDevsA(); + } +-- +2.7.1 + diff --git a/patches/setupapi-Display_Device/definition b/patches/setupapi-Display_Device/definition new file mode 100644 index 00000000..febe71e7 --- /dev/null +++ b/patches/setupapi-Display_Device/definition @@ -0,0 +1 @@ +Fixes: [35345] Fix enumeration of display driver properties using setupapi