[PATCH 2/2] user32: Load uxtheme when theming is active.

Zhiyi Zhang zzhang at codeweavers.com
Mon Aug 9 02:00:19 CDT 2021


In comctl32 DllMain(), IsThemeActive() is a delay-loaded function and shouldn't be called in
DllMain(). Instead, tests showed that uxtheme should be loaded by user32.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51540
Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
---
Further tests not included in this patch series show that uxtheme gets unloaded when theming is turned off
and gets loaded when theming is turned on even after application startup. This dynamic loading/unloading
behavior requires at least a window and a message loop (merely calling GetMessage() is enough), which suggests
a WH_GETMESSAGE hook is installed and listens for WM_THEMECHANGED. The WM_THEMECHANGED lparam is a reserved
parameter that is TRUE then theming is active and FALSE otherwise. Due to the WH_GETMESSAGE hook involved,
I decided not to implement the dynamic loading and unloading of uxtheme for user32 to avoid filtering every
messages.

Also a test application that doesn't link to comctl32 and doesn't have a comctl32 v6 manifest still has its
standard scrollbars and dialogs themed when theming is active.

 dlls/comctl32/commctrl.c  |  3 ---
 dlls/user32/class.c       | 16 ++++++++++++++++
 dlls/user32/tests/class.c |  2 +-
 3 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/dlls/comctl32/commctrl.c b/dlls/comctl32/commctrl.c
index 1c7718e2400..b457bdcb8be 100644
--- a/dlls/comctl32/commctrl.c
+++ b/dlls/comctl32/commctrl.c
@@ -208,9 +208,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
             TRACKBAR_Register ();
             TREEVIEW_Register ();
             UPDOWN_Register ();
-
-            /* Call IsThemeActive() so that delay-loaded uxtheme.dll is loaded for hooking user32 */
-            IsThemeActive();
             break;
 
 	case DLL_PROCESS_DETACH:
diff --git a/dlls/user32/class.c b/dlls/user32/class.c
index c17a612c5b9..cef52883988 100644
--- a/dlls/user32/class.c
+++ b/dlls/user32/class.c
@@ -539,6 +539,19 @@ static void register_builtin( const struct builtin_class_descr *descr )
     release_class_ptr( classPtr );
 }
 
+static void load_uxtheme(void)
+{
+    BOOL (WINAPI * pIsThemeActive)(void);
+    HMODULE uxtheme;
+
+    uxtheme = LoadLibraryA("uxtheme.dll");
+    if (uxtheme)
+    {
+        pIsThemeActive = (void *)GetProcAddress(uxtheme, "IsThemeActive");
+        if (!pIsThemeActive || !pIsThemeActive())
+            FreeLibrary(uxtheme);
+    }
+}
 
 /***********************************************************************
  *           register_builtins
@@ -557,6 +570,9 @@ static BOOL WINAPI register_builtins( INIT_ONCE *once, void *param, void **conte
     register_builtin( &SCROLL_builtin_class );
     register_builtin( &STATIC_builtin_class );
     register_builtin( &IME_builtin_class );
+
+    /* Load uxtheme.dll so that standard scrollbars and dialogs are hooked for theming support */
+    load_uxtheme();
     return TRUE;
 }
 
diff --git a/dlls/user32/tests/class.c b/dlls/user32/tests/class.c
index 0f4fd1cf90e..e6762032107 100644
--- a/dlls/user32/tests/class.c
+++ b/dlls/user32/tests/class.c
@@ -1511,6 +1511,7 @@ static void test_uxtheme(void)
     dll_loaded = !!GetModuleHandleA("comctl32.dll");
     ok(!dll_loaded, "Expected comctl32.dll not loaded.\n");
     dll_loaded = !!GetModuleHandleA("uxtheme.dll");
+    todo_wine_if(dll_loaded)
     ok(!dll_loaded, "Expected uxtheme.dll not loaded.\n");
 
     /* Creating a window triggers uxtheme load when theming is active */
@@ -1531,7 +1532,6 @@ static void test_uxtheme(void)
     is_theme_active = pIsThemeActive();
     FreeLibrary(uxtheme);
 
-    todo_wine_if(is_theme_active)
     ok(dll_loaded == is_theme_active, "Expected uxtheme %s when theming is %s.\n",
        is_theme_active ? "loaded" : "not loaded", is_theme_active ? "active" : "inactive");
 
-- 
2.30.2



More information about the wine-devel mailing list