From 8d4a9869072b2a0a30c3eab76367c663b5e9c418 Mon Sep 17 00:00:00 2001
From: Daniel Wendt <daniel.wendt@linux.com>
Date: Wed, 5 Dec 2018 10:24:44 +0100
Subject: [PATCH v2] explorer: unload graphics driver and delete registry keys

Registry keys are no longer used after the driver has been unloaded.

The string constant is divided and set globally so that the created
key and folder can be completely removed from the registry.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46233

Signed-off-by: Daniel Wendt <daniel.wendt@linux.com>
---
Changes from v1:

Unloading of the driver removed, as not necessary.

Keep the function unload_graphics_driver as complementary
to the function load_graphics_driver and harmonize the parameter
list of the functions for a better readability.

Add a function for creating/deleting the registry keys.
---
 programs/explorer/desktop.c | 75 +++++++++++++++++++++++++++----------
 1 file changed, 56 insertions(+), 19 deletions(-)

diff --git a/programs/explorer/desktop.c b/programs/explorer/desktop.c
index 27b9b24901..3af4cbb0ab 100644
--- a/programs/explorer/desktop.c
+++ b/programs/explorer/desktop.c
@@ -773,7 +773,7 @@ static BOOL get_default_enable_shell( const WCHAR *name )
     return result;
 }
 
-static HMODULE load_graphics_driver( const WCHAR *driver, const GUID *guid )
+static void handleRegistry( const GUID *guid, BOOL create, const WCHAR* buffer, const char* error, HMODULE module )
 {
     static const WCHAR device_keyW[] = {
         'S','y','s','t','e','m','\\',
@@ -782,15 +782,60 @@ static HMODULE load_graphics_driver( const WCHAR *driver, const GUID *guid )
         '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};
+        '%','0','2','x','%','0','2','x','%','0','2','x','}',0};
+    static const WCHAR device_subkeyW[] = {'\\','0','0','0','0',0};
     static const WCHAR graphics_driverW[] = {'G','r','a','p','h','i','c','s','D','r','i','v','e','r',0};
+
+    HKEY hkey;
+    LONG reg_ret;
+    WCHAR key[ARRAY_SIZE( device_keyW ) + 39];
+    WCHAR subkey[ARRAY_SIZE( device_keyW ) + ARRAY_SIZE( device_subkeyW ) + 39];
+
+    sprintfW( 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] );
+    strcpyW( subkey, key );
+    strcatW( subkey, device_subkeyW );
+
+    if (create)
+    {
+        if (!RegCreateKeyExW( HKEY_LOCAL_MACHINE, subkey, 0, NULL,
+                              REG_OPTION_VOLATILE, KEY_SET_VALUE, NULL, &hkey, NULL  ))
+        {
+            if (module)
+                RegSetValueExW( hkey, graphics_driverW, 0, REG_SZ,
+                                (BYTE *)buffer, (strlenW(buffer) + 1) * sizeof(WCHAR) );
+            else
+                RegSetValueExA( hkey, "DriverError", 0, REG_SZ, (BYTE *)error, strlen(error) + 1 );
+            RegCloseKey( hkey );
+        }
+    }
+    else
+    {
+        reg_ret = RegOpenKeyW( HKEY_LOCAL_MACHINE, subkey, &hkey );
+        if (reg_ret == ERROR_SUCCESS)
+        {
+            RegDeleteKeyW( HKEY_LOCAL_MACHINE, subkey );
+            RegCloseKey( hkey );
+        }
+
+        reg_ret = RegOpenKeyW( HKEY_LOCAL_MACHINE, key, &hkey );
+        if (reg_ret == ERROR_SUCCESS)
+        {
+            RegDeleteKeyW( HKEY_LOCAL_MACHINE, key );
+            RegCloseKey( hkey );
+        }
+    }
+}
+
+static HMODULE load_graphics_driver( const GUID *guid, const WCHAR *driver )
+{
     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];
@@ -838,24 +883,15 @@ static HMODULE load_graphics_driver( const WCHAR *driver, const GUID *guid )
         TRACE( "display %s driver %s\n", debugstr_guid(guid), debugstr_w(buffer) );
     }
 
-    sprintfW( 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] );
-
-    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, (strlenW(buffer) + 1) * sizeof(WCHAR) );
-        else
-            RegSetValueExA( hkey, "DriverError", 0, REG_SZ, (BYTE *)error, strlen(error) + 1 );
-        RegCloseKey( hkey );
-    }
-
+    handleRegistry( guid, TRUE, buffer, error, module );
     return module;
 }
 
+static void unload_graphics_driver( const GUID *guid )
+{
+    handleRegistry( guid, FALSE, 0, 0, 0 );
+}
+
 static void initialize_display_settings(void)
 {
     DEVMODEW dmW;
@@ -966,7 +1002,7 @@ void manage_desktop( WCHAR *arg )
 
     UuidCreate( &guid );
     TRACE( "display guid %s\n", debugstr_guid(&guid) );
-    graphics_driver = load_graphics_driver( driver, &guid );
+    graphics_driver = load_graphics_driver( &guid, driver );
 
     /* create the desktop window */
     hwnd = CreateWindowExW( 0, DESKTOP_CLASS_ATOM, NULL,
@@ -1036,6 +1072,7 @@ void manage_desktop( WCHAR *arg )
     }
 
     if (pShellDDEInit) pShellDDEInit( FALSE );
+    unload_graphics_driver( &guid );
 
     ExitProcess( 0 );
 }
-- 
2.19.2

