[PATCH v5 6/7] explorer: Create display device registry fallback data if necessary.

Zhiyi Zhang zzhang at codeweavers.com
Mon May 20 09:15:10 CDT 2019


If user driver didn't initialize the display device registry data, create
some fallback data to at least make EnumDisplayDevice report a primary
adapter. Otherwise, report back the primary adapter GUID to store in the
desktop HWND atom, instead of creating a new one.

Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
---
 dlls/user32/desktop.c         |  11 +--
 dlls/user32/tests/monitor.c   |   6 +-
 programs/explorer/Makefile.in |   2 +-
 programs/explorer/desktop.c   | 167 ++++++++++++++++++++++++++++------
 4 files changed, 143 insertions(+), 43 deletions(-)

diff --git a/dlls/user32/desktop.c b/dlls/user32/desktop.c
index fe6649446e..3662a68976 100644
--- a/dlls/user32/desktop.c
+++ b/dlls/user32/desktop.c
@@ -101,28 +101,21 @@ LRESULT WINAPI DesktopWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lP
     static const WCHAR display_device_guid_propW[] = {
         '_','_','w','i','n','e','_','d','i','s','p','l','a','y','_',
         'd','e','v','i','c','e','_','g','u','i','d',0 };
-    static const WCHAR guid_formatW[] = {
-        '%','0','8','x','-','%','0','4','x','-','%','0','4','x','-','%','0','2','x','%','0','2','x','-',
-        '%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x',0};
 
     switch (message)
     {
     case WM_NCCREATE:
     {
         CREATESTRUCTW *cs = (CREATESTRUCTW *)lParam;
-        const GUID *guid = cs->lpCreateParams;
+        WCHAR *guid = cs->lpCreateParams;
 
         if (guid)
         {
             ATOM atom;
-            WCHAR buffer[37];
 
             if (GetAncestor( hwnd, GA_PARENT )) return FALSE;  /* refuse to create non-desktop window */
 
-            sprintfW( buffer, guid_formatW, guid->Data1, guid->Data2, guid->Data3,
-                      guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
-                      guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
-            atom = GlobalAddAtomW( buffer );
+            atom = GlobalAddAtomW( guid );
             SetPropW( hwnd, display_device_guid_propW, ULongToHandle( atom ) );
         }
         return TRUE;
diff --git a/dlls/user32/tests/monitor.c b/dlls/user32/tests/monitor.c
index c5e6745322..bee1085a14 100644
--- a/dlls/user32/tests/monitor.c
+++ b/dlls/user32/tests/monitor.c
@@ -81,7 +81,7 @@ static int monitor_count = 0;
 
 static void test_enumdisplaydevices_adapter(int index, const DISPLAY_DEVICEA *device, DWORD flags)
 {
-    char video_name[16];
+    char video_name[32];
     char video_value[128];
     char buffer[128];
     int number;
@@ -107,7 +107,7 @@ static void test_enumdisplaydevices_adapter(int index, const DISPLAY_DEVICEA *de
     {
         sprintf(video_name, "\\Device\\Video%d", index);
         ls = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\VIDEO", 0, KEY_READ, &hkey);
-        todo_wine ok(!ls, "#%d: failed to open registry, error: %#x\n", index, ls);
+        ok(!ls, "#%d: failed to open registry, error: %#x\n", index, ls);
         if (!ls)
         {
             memset(video_value, 0, sizeof(video_value));
@@ -115,7 +115,7 @@ static void test_enumdisplaydevices_adapter(int index, const DISPLAY_DEVICEA *de
             ls = RegQueryValueExA(hkey, video_name, NULL, NULL, (unsigned char *)video_value, &size);
             ok(!ls, "#%d: failed to get registry value, error: %#x\n", index, ls);
             RegCloseKey(hkey);
-            ok(!strcmp(video_value, device->DeviceKey), "#%d: wrong DeviceKey: %s\n", index, device->DeviceKey);
+            todo_wine ok(!strcmp(video_value, device->DeviceKey), "#%d: wrong DeviceKey: %s\n", index, device->DeviceKey);
         }
     }
     else
diff --git a/programs/explorer/Makefile.in b/programs/explorer/Makefile.in
index 374c6aaebe..13b0ed3dfa 100644
--- a/programs/explorer/Makefile.in
+++ b/programs/explorer/Makefile.in
@@ -1,5 +1,5 @@
 MODULE    = explorer.exe
-IMPORTS   = rpcrt4 user32 gdi32 advapi32
+IMPORTS   = rpcrt4 user32 gdi32 advapi32 setupapi
 DELAYIMPORTS = comctl32 shell32 oleaut32 ole32 shlwapi
 
 EXTRADLLFLAGS = -mwindows -municode -mno-cygwin
diff --git a/programs/explorer/desktop.c b/programs/explorer/desktop.c
index 2857fcfca9..da93f1e4ba 100644
--- a/programs/explorer/desktop.c
+++ b/programs/explorer/desktop.c
@@ -27,6 +27,11 @@
 #include <rpc.h>
 #include <shlobj.h>
 #include <shellapi.h>
+#include <wingdi.h>
+#include <initguid.h>
+#include <devguid.h>
+#include <devpkey.h>
+#include <setupapi.h>
 #include "exdisp.h"
 
 #include "wine/debug.h"
@@ -752,24 +757,143 @@ static BOOL get_default_enable_shell( const WCHAR *name )
     return result;
 }
 
-static HMODULE load_graphics_driver( const WCHAR *driver, const GUID *guid )
-{
-    static const WCHAR device_keyW[] = {
+/* Initialize the display device registry if user driver didn't do it,
+ * and report the primary adapter guid in paramter guid_string. */
+static BOOL initialize_fallback_display_devices( const WCHAR *driver_path, WCHAR *guid_string )
+{
+    static const WCHAR video_keyW[] = {
+        'H','A','R','D','W','A','R','E','\\',
+        'D','E','V','I','C','E','M','A','P','\\',
+        'V','I','D','E','O',0};
+    static const WCHAR device_video0W[] = {
+        '\\','D','e','v','i','c','e','\\',
+        'V','i','d','e','o','0',0};
+    static const WCHAR device_video_prefixW[] = {
+        '\\','R','e','g','i','s','t','r','y','\\',
+        'M','a','c','h','i','n','e','\\',0};
+    static const WCHAR gpu_instanceW[] = {
+        'P','C','I','\\',
+        'V','E','N','_','0','0','0','0','&',
+        'D','E','V','_','0','0','0','0','&',
+        'S','U','B','S','Y','S','_','0','0','0','0','0','0','0','0','&',
+        'R','E','V','_','0','0','\\',
+        '0','0','0','0','0','0','0','0',0};
+    static const WCHAR gpu_hardware_idW[] = {
+        'P','C','I','\\',
+        'V','E','N','_','0','0','0','0','&',
+        'D','E','V','_','0','0','0','0','&',
+        'S','U','B','S','Y','S','_','0','0','0','0','0','0','0','0','&',
+        'R','E','V','_','0','0',0,0};
+    static const WCHAR device_key_fmtW[] = {
         'S','y','s','t','e','m','\\',
         'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
         'C','o','n','t','r','o','l','\\',
         'V','i','d','e','o','\\',
-        '{','%','0','8','x','-','%','0','4','x','-','%','0','4','x','-',
-        '%','0','2','x','%','0','2','x','-','%','0','2','x','%','0','2','x','%','0','2','x',
-        '%','0','2','x','%','0','2','x','%','0','2','x','}','\\','0','0','0','0',0};
+        '{','%','s','}','\\',
+        '0','0','0','0',0};
+    static const WCHAR guid_formatW[] = {
+        '%','0','8','x','-','%','0','4','x','-','%','0','4','x','-','%','0','2','x','%','0','2','x','-',
+        '%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x',0};
     static const WCHAR graphics_driverW[] = {'G','r','a','p','h','i','c','s','D','r','i','v','e','r',0};
+    static const WCHAR driver_descW[] = {'D','r','i','v','e','r','D','e','s','c',0};
+    static const WCHAR wine_gpuW[] = {'W','i','n','e',' ','G','P','U',0};
+    static const WCHAR state_flagsW[] = {'S','t','a','t','e','F','l','a','g','s',0};
+    static const DWORD primary_state_flags = DISPLAY_DEVICE_PRIMARY_DEVICE | DISPLAY_DEVICE_ATTACHED_TO_DESKTOP;
+    HDEVINFO devinfo;
+    SP_DEVINFO_DATA device_data = {sizeof(device_data)};
+    WCHAR adapter_keyW[MAX_PATH];
+    WCHAR bufferW[MAX_PATH];
+    DWORD disposition = 0;
+    DWORD size;
+    GUID guid;
+    HKEY hkey = NULL;
+    BOOL ret = FALSE;
+
+    /* Create HKLM\HARDWARE\DEVICEMAP\VIDEO key if user drivers didn't do it */
+    RegCreateKeyExW( HKEY_LOCAL_MACHINE, video_keyW, 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &disposition );
+
+    /* User driver did create it. Report back primary adapter guid */
+    if (disposition != REG_CREATED_NEW_KEY)
+    {
+        size = sizeof(bufferW);
+        if (!RegQueryValueExW( hkey, device_video0W, NULL, NULL, (BYTE *)bufferW, &size ))
+        {
+            /* Skip over \Registry\Machine\System\CurrentControlSet\Control\Video\{ to get guid string */
+            memcpy( guid_string, bufferW + 58, 36 * sizeof(WCHAR) );
+            guid_string[36] = 0;
+            RegCloseKey( hkey );
+            return TRUE;
+        }
+        /* Falling through */
+    }
+
+    /* Create basic display device registry data so that functions like EnumDisplayDevice can at least report
+     * a primary adapter */
+    /* Init GPU */
+    devinfo = SetupDiCreateDeviceInfoList( &GUID_DEVCLASS_DISPLAY, NULL );
+    if (!SetupDiOpenDeviceInfoW( devinfo, gpu_instanceW, NULL, 0, &device_data ))
+    {
+        SetupDiCreateDeviceInfoW( devinfo, gpu_instanceW, &GUID_DEVCLASS_DISPLAY, NULL, NULL, 0, &device_data );
+        if (!SetupDiRegisterDeviceInfo( devinfo, &device_data, 0, NULL, NULL, NULL ))
+            goto fail;
+    }
+
+    /* Write HardwareID */
+    if (!SetupDiSetDeviceRegistryPropertyW( devinfo, &device_data, SPDRP_HARDWAREID, (const BYTE *)(gpu_hardware_idW),
+                                            sizeof(gpu_hardware_idW) ))
+        goto fail;
+
+    /* Init primary adapter */
+    UuidCreate( &guid );
+    swprintf( guid_string, 37, guid_formatW, guid.Data1, guid.Data2, guid.Data3,
+              guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
+              guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7] );
+    swprintf( adapter_keyW, ARRAY_SIZE(adapter_keyW), device_key_fmtW, guid_string );
+    lstrcpyW( bufferW, device_video_prefixW );
+    lstrcatW( bufferW, adapter_keyW );
+
+    /* Write value of \Device\Video0 in HKLM\HARDWARE\DEVICEMAP\VIDEO\ */
+    if (RegSetValueExW( hkey, device_video0W, 0, REG_SZ, (const BYTE *)bufferW, (lstrlenW( bufferW ) + 1) * sizeof(WCHAR) ))
+        goto fail;
+    RegCloseKey( hkey );
+    hkey = NULL;
+
+    /* Write GraphicsDriver */
+    RegCreateKeyExW( HKEY_LOCAL_MACHINE, adapter_keyW, 0, NULL, REG_OPTION_VOLATILE, KEY_WRITE, NULL, &hkey, NULL );
+    if (RegSetValueExW( hkey, graphics_driverW, 0, REG_SZ, (const BYTE *)driver_path, (lstrlenW( driver_path ) + 1) * sizeof(WCHAR) ))
+        goto fail;
+
+    /* Write DriverDesc */
+    if (RegSetValueExW( hkey, driver_descW, 0, REG_SZ, (const BYTE *)wine_gpuW, (lstrlenW( wine_gpuW ) + 1) * sizeof(WCHAR) ))
+        goto fail;
+
+    RegCloseKey( hkey );
+    hkey = NULL;
+
+    RegCreateKeyExW( HKEY_CURRENT_CONFIG, adapter_keyW, 0, NULL, REG_OPTION_VOLATILE, KEY_WRITE, NULL, &hkey, NULL );
+    /* Write StateFlags */
+    if (RegSetValueExW( hkey, state_flagsW, 0, REG_DWORD, (const BYTE *)&primary_state_flags,
+                        sizeof(primary_state_flags) ))
+        goto fail;
+
+    ret = TRUE;
+fail:
+    RegCloseKey( hkey );
+    SetupDiDestroyDeviceInfoList( devinfo );
+    if (!ret)
+        ERR("Failed to initialize fallback display device registry data\n");
+    return ret;
+}
+
+/* Load graphics driver, return its module handle in hmodule and report primary adapter guid in guid */
+static void load_graphics_driver( const WCHAR *driver, HMODULE *hmodule, WCHAR *guid )
+{
     static const WCHAR driversW[] = {'S','o','f','t','w','a','r','e','\\',
                                      'W','i','n','e','\\','D','r','i','v','e','r','s',0};
     static const WCHAR graphicsW[] = {'G','r','a','p','h','i','c','s',0};
     static const WCHAR drv_formatW[] = {'w','i','n','e','%','s','.','d','r','v',0};
 
     WCHAR buffer[MAX_PATH], libname[32], *name, *next;
-    WCHAR key[ARRAY_SIZE( device_keyW ) + 39];
     HMODULE module = 0;
     HKEY hkey;
     char error[80];
@@ -812,27 +936,12 @@ static HMODULE load_graphics_driver( const WCHAR *driver, const GUID *guid )
     }
 
     if (module)
-    {
         GetModuleFileNameW( module, buffer, MAX_PATH );
-        TRACE( "display %s driver %s\n", debugstr_guid(guid), debugstr_w(buffer) );
-    }
 
-    swprintf( key, ARRAY_SIZE(key), device_keyW, guid->Data1, guid->Data2, guid->Data3,
-              guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
-              guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
+    initialize_fallback_display_devices( buffer, guid );
+    TRACE( "display %s driver %s\n", debugstr_w(guid), debugstr_w(buffer) );
 
-    if (!RegCreateKeyExW( HKEY_LOCAL_MACHINE, key, 0, NULL,
-                          REG_OPTION_VOLATILE, KEY_SET_VALUE, NULL, &hkey, NULL  ))
-    {
-        if (module)
-            RegSetValueExW( hkey, graphics_driverW, 0, REG_SZ,
-                            (BYTE *)buffer, (lstrlenW(buffer) + 1) * sizeof(WCHAR) );
-        else
-            RegSetValueExA( hkey, "DriverError", 0, REG_SZ, (BYTE *)error, strlen(error) + 1 );
-        RegCloseKey( hkey );
-    }
-
-    return module;
+    *hmodule = module;
 }
 
 static void initialize_display_settings(void)
@@ -891,7 +1000,7 @@ void manage_desktop( WCHAR *arg )
 {
     static const WCHAR messageW[] = {'M','e','s','s','a','g','e',0};
     HDESK desktop = 0;
-    GUID guid;
+    WCHAR guid[37] = {0};
     MSG msg;
     HWND hwnd;
     HMODULE graphics_driver;
@@ -943,13 +1052,11 @@ void manage_desktop( WCHAR *arg )
         SetThreadDesktop( desktop );
     }
 
-    UuidCreate( &guid );
-    TRACE( "display guid %s\n", debugstr_guid(&guid) );
-    graphics_driver = load_graphics_driver( driver, &guid );
+    load_graphics_driver( driver, &graphics_driver, guid );
 
     /* create the desktop window */
     hwnd = CreateWindowExW( 0, DESKTOP_CLASS_ATOM, NULL,
-                            WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, 0, 0, 0, 0, 0, 0, &guid );
+                            WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, 0, 0, 0, 0, 0, 0, guid );
 
     if (hwnd)
     {
-- 
2.20.1





More information about the wine-devel mailing list