From: Helix Graziani helix.graziani@hotmail.com
--- dlls/uxtheme/system.c | 23 +++++++++++ dlls/uxtheme/tests/system.c | 80 +++++++++++++++++++++++++++++++++++++ dlls/uxtheme/uxtheme.spec | 1 + 3 files changed, 104 insertions(+)
diff --git a/dlls/uxtheme/system.c b/dlls/uxtheme/system.c index 25f495d29f3..5f7e27452b7 100644 --- a/dlls/uxtheme/system.c +++ b/dlls/uxtheme/system.c @@ -1256,3 +1256,26 @@ BOOL WINAPI ThemeHooksRemove(void) UnregisterUserApiHook(); return TRUE; } + +/********************************************************************** + * ShouldSystemUseDarkMode (UXTHEME.138) + * + * RETURNS + * Whether or not the system/app should use dark mode. + */ +BOOL WINAPI ShouldSystemUseDarkMode(void) +{ + DWORD system_uses_light_theme_size = sizeof(DWORD); + /* Persists between calls, in windows it might look up some internal table. */ + static DWORD system_uses_light_theme = TRUE; + + /* We don't necessarily care that this might fail because it doesn't affect + * system_uses_light_theme if it does. + */ + RegGetValueA(HKEY_CURRENT_USER, + "Software\Microsoft\Windows\CurrentVersion\Themes\Personalize", + "AppsUseLightTheme", RRF_RT_REG_DWORD, NULL, &system_uses_light_theme, + &system_uses_light_theme_size); + + return !system_uses_light_theme; +} diff --git a/dlls/uxtheme/tests/system.c b/dlls/uxtheme/tests/system.c index 2e769625dab..f04f10c3539 100644 --- a/dlls/uxtheme/tests/system.c +++ b/dlls/uxtheme/tests/system.c @@ -48,6 +48,7 @@ static HDC (WINAPI *pGetBufferedPaintTargetDC)(HPAINTBUFFER); static HRESULT (WINAPI *pGetBufferedPaintTargetRect)(HPAINTBUFFER, RECT *); static HRESULT (WINAPI *pGetThemeIntList)(HTHEME, int, int, int, INTLIST *); static HRESULT (WINAPI *pGetThemeTransitionDuration)(HTHEME, int, int, int, int, DWORD *); +static BOOL (WINAPI *pShouldSystemUseDarkMode)(void);
static LONG (WINAPI *pDisplayConfigGetDeviceInfo)(DISPLAYCONFIG_DEVICE_INFO_HEADER *); static LONG (WINAPI *pDisplayConfigSetDeviceInfo)(DISPLAYCONFIG_DEVICE_INFO_HEADER *); @@ -2597,6 +2598,84 @@ static void test_theme(void) DestroyWindow(hwnd); }
+static void test_ShouldSystemUseDarkMode(void) +{ + DWORD system_uses_light_theme, system_uses_light_theme_size = sizeof(system_uses_light_theme); + DWORD original_reg_value, reg_key_disposition, last_error; + BOOL function_result, set_value = FALSE; + LSTATUS ls; + HKEY hk; + + pShouldSystemUseDarkMode = (void *)GetProcAddress(GetModuleHandleA("uxtheme.dll"), + MAKEINTRESOURCEA(138)); + if (!pShouldSystemUseDarkMode) + { + win_skip("ShouldSystemUseDarkMode() is unavailable.\n"); + return; + } + + /* Create key if it doesn't exist */ + ls = RegCreateKeyExA(HKEY_CURRENT_USER, + "Software\Microsoft\Windows\CurrentVersion\Themes\Personalize", + 0, NULL, REG_OPTION_VOLATILE, KEY_QUERY_VALUE | KEY_SET_VALUE, NULL, &hk, + ®_key_disposition); + ok(ls == 0, "RegCreateKeyExA failed: %ld.\n", ls); + + ls = RegQueryValueExA(hk, "AppsUseLightTheme", NULL, NULL, (BYTE *)&system_uses_light_theme, + &system_uses_light_theme_size); + + /* Create registry value if it doesn't exist, this should not fail the test */ + if (ls == ERROR_FILE_NOT_FOUND) + { + set_value = TRUE; + system_uses_light_theme = 1; /* Assume we default to TRUE, may change */ + ls = RegSetValueExA(hk, "AppsUseLightTheme", 0, REG_DWORD, (BYTE *)&system_uses_light_theme, + sizeof(system_uses_light_theme)); + ok(ls == 0, "RegSetValueExA failed: %ld.\n", ls); + ls = 0; + } + + ok(ls == 0, "RegQueryValueExA failed: %ld.\n", ls); + + if (reg_key_disposition == REG_OPENED_EXISTING_KEY) original_reg_value = system_uses_light_theme; + + /* Call ShouldSystemUseDarkMode() and check for errors */ + SetLastError(ERROR_SUCCESS); /* Clear error buffer so that we can detect if an error occurred. */ + function_result = pShouldSystemUseDarkMode(); + last_error = GetLastError(); + ok(last_error == ERROR_SUCCESS, "ShouldSystemUseDarkMode failed (?) with error %ld.\n", + last_error); + + /* Expect same value as key */ + ok(function_result == !system_uses_light_theme, "Expected value %d, got %d.\n", + !system_uses_light_theme, function_result); + + ls = RegDeleteValueA(hk, "AppsUseLightTheme"); + ok(ls == 0, "RegDeleteValueA failed: %ld.\n", ls); + + /* Call ShouldSystemUseDarkMode() and check for errors with deleted value */ + SetLastError(ERROR_SUCCESS); /* Clear error buffer so that we can detect if an error occurred. */ + function_result = pShouldSystemUseDarkMode(); + last_error = GetLastError(); + ok(last_error == ERROR_SUCCESS, "ShouldSystemUseDarkMode failed (?) with error %ld.\n", last_error); + + /* Expect same value when the value doesn't exist */ + ok(function_result == !system_uses_light_theme, "Expected value %d, got %d.\n", + !system_uses_light_theme, function_result); + + /* Reset registry value if we didn't create it */ + if (reg_key_disposition == REG_OPENED_EXISTING_KEY && !set_value) + { + ls = RegSetValueExA(hk, "AppsUseLightTheme", 0, REG_DWORD, (BYTE *)&original_reg_value, + sizeof(original_reg_value)); + ok(ls == 0, "RegSetValueExA failed: %ld.\n", ls); + } + + ls = RegCloseKey(hk); + ok(ls == 0, "RegCloseKey failed: %ld.\n", ls); + +} + START_TEST(system) { ULONG_PTR ctx_cookie; @@ -2622,6 +2701,7 @@ START_TEST(system) test_DrawThemeBackgroundEx(); test_GetThemeBackgroundRegion(); test_theme(); + test_ShouldSystemUseDarkMode();
if (load_v6_module(&ctx_cookie, &ctx)) { diff --git a/dlls/uxtheme/uxtheme.spec b/dlls/uxtheme/uxtheme.spec index c60254b677d..a5bfb88c49a 100644 --- a/dlls/uxtheme/uxtheme.spec +++ b/dlls/uxtheme/uxtheme.spec @@ -42,6 +42,7 @@ 61 stdcall OpenThemeDataEx(ptr wstr long) 62 stub -noname ServerClearStockObjects 63 stub -noname MarkSelection +138 stdcall -noname ShouldSystemUseDarkMode()
# Standard functions @ stdcall BeginBufferedAnimation(ptr ptr ptr long ptr ptr ptr ptr)