From c9b3268ab753c5d00ba39968eba4311fdc6e6100 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Thu, 11 Feb 2016 03:17:09 +0100
Subject: [PATCH] setupapi: Create registry keys for display devices and
 display drivers.

---
 dlls/setupapi/devinst.c | 102 +++++++++++++++++++++++++++++++++++++---
 loader/wine.inf.in      |   2 +
 2 files changed, 98 insertions(+), 6 deletions(-)

diff --git a/dlls/setupapi/devinst.c b/dlls/setupapi/devinst.c
index 9b83c3519be..e666d3bb008 100644
--- a/dlls/setupapi/devinst.c
+++ b/dlls/setupapi/devinst.c
@@ -111,6 +111,15 @@ struct driver
     WCHAR description[LINE_LEN];
 };
 
+/* 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
@@ -210,6 +219,90 @@ static struct device_iface *get_device_iface(HDEVINFO devinfo, const SP_DEVICE_I
     return (struct device_iface *)data->Reserved;
 }
 
+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 inline void copy_device_data(SP_DEVINFO_DATA *data, const struct device *device)
 {
     data->ClassGuid = device->class;
@@ -523,8 +616,7 @@ static HKEY SETUPDI_CreateDevKey(struct device *device)
     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, device->instanceId, 0, NULL, 0,
@@ -2143,8 +2235,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 = ARRAY_SIZE(subKeyName);
@@ -2364,8 +2455,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)
diff --git a/loader/wine.inf.in b/loader/wine.inf.in
index 4d28a93c359..7a44e0fe713 100644
--- a/loader/wine.inf.in
+++ b/loader/wine.inf.in
@@ -465,6 +465,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.20.1

