| /******************************************************************************* |
| * Copyright (c) 2000, 2008 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| |
| #include "swt.h" |
| #include "os_structs.h" |
| #include "os_stats.h" |
| |
| #define OS_NATIVE(func) Java_org_eclipse_swt_internal_win32_OS_##func |
| |
| __declspec(dllexport) HRESULT DllGetVersion(DLLVERSIONINFO *dvi); |
| HRESULT DllGetVersion(DLLVERSIONINFO *dvi) |
| { |
| dvi->dwMajorVersion = SWT_VERSION / 1000; |
| dvi->dwMinorVersion = SWT_VERSION % 1000; |
| dvi->dwBuildNumber = SWT_REVISION; |
| dvi->dwPlatformID = DLLVER_PLATFORM_WINDOWS; |
| return 1; |
| } |
| |
| HINSTANCE g_hInstance = NULL; |
| BOOL WINAPI DllMain(HANDLE hInstDLL, DWORD dwReason, LPVOID lpvReserved) |
| { |
| if (dwReason == DLL_PROCESS_ATTACH) { |
| if (g_hInstance == NULL) g_hInstance = hInstDLL; |
| } |
| return TRUE; |
| } |
| |
| #ifndef NO_GetLibraryHandle |
| JNIEXPORT jlong JNICALL OS_NATIVE(GetLibraryHandle) |
| (JNIEnv *env, jclass that) |
| { |
| jlong rc; |
| OS_NATIVE_ENTER(env, that, GetLibraryHandle_FUNC) |
| rc = (jlong)g_hInstance; |
| OS_NATIVE_EXIT(env, that, GetLibraryHandle_FUNC) |
| return rc; |
| } |
| #endif |
| |
| BOOL Validate_AllowDarkModeForWindow(const BYTE* functionPtr) |
| { |
| #ifdef _M_X64 |
| /* This function is rather long, but it uses an ATOM value of 0xA91E which is unlikely to change */ |
| return |
| (functionPtr[0x15] == 0xBA) && // mov edx, |
| (*(const DWORD*)(functionPtr + 0x16) == 0xA91E); // 0A91Eh |
| #else |
| #error Unsupported processor type |
| #endif |
| } |
| |
| typedef BOOL(WINAPI* TYPE_AllowDarkModeForWindow)(HWND a_HWND, BOOL a_Allow); |
| TYPE_AllowDarkModeForWindow Locate_AllowDarkModeForWindow() |
| { |
| const HMODULE hUxtheme = GetModuleHandle(L"uxtheme.dll"); |
| if (!hUxtheme) |
| return 0; |
| |
| /* |
| * Function is only exported by ordinal. |
| * Hopefully one day Microsoft will finally export it by name. |
| */ |
| const BYTE* candidate = (const BYTE*)GetProcAddress(hUxtheme, MAKEINTRESOURCEA(133)); |
| if (!candidate) |
| return 0; |
| |
| /* |
| * In next Windows version, some other function can end up having this ordinal. |
| * Compare function's code to known signature to make sure. |
| */ |
| if (!Validate_AllowDarkModeForWindow(candidate)) |
| return 0; |
| |
| return (TYPE_AllowDarkModeForWindow)candidate; |
| } |
| |
| #ifndef NO_AllowDarkModeForWindow |
| JNIEXPORT jboolean JNICALL OS_NATIVE(AllowDarkModeForWindow) |
| (JNIEnv* env, jclass that, jlong arg0, jboolean arg1) |
| { |
| /* Cache the search result for performance reasons */ |
| static TYPE_AllowDarkModeForWindow fn_AllowDarkModeForWindow = 0; |
| static int isInitialized = 0; |
| if (!isInitialized) |
| { |
| fn_AllowDarkModeForWindow = Locate_AllowDarkModeForWindow(); |
| isInitialized = 1; |
| } |
| |
| if (!fn_AllowDarkModeForWindow) |
| return 0; |
| |
| jboolean rc = 0; |
| OS_NATIVE_ENTER(env, that, AllowDarkModeForWindow_FUNC); |
| rc = (jboolean)fn_AllowDarkModeForWindow((HWND)arg0, arg1); |
| OS_NATIVE_EXIT(env, that, AllowDarkModeForWindow_FUNC); |
| return rc; |
| } |
| #endif |
| |
| BOOL Validate_SetPreferredAppMode(const BYTE* functionPtr) |
| { |
| #ifdef _M_X64 |
| /* |
| * This function is very simple, so validate entire body. |
| * The only thing we don't know is the variable address. |
| */ |
| const DWORD varOffset1 = *(const DWORD*)(functionPtr + 0x02); |
| const DWORD varOffset2 = *(const DWORD*)(functionPtr + 0x08); |
| if (varOffset1 != (varOffset2 + 6)) |
| return FALSE; |
| |
| return |
| (functionPtr[0x00] == 0x8B) && (functionPtr[0x01] == 0x05) && // mov eax,dword ptr [uxtheme!g_preferredAppMode] |
| (functionPtr[0x06] == 0x87) && (functionPtr[0x07] == 0x0D) && // xchg ecx,dword ptr [uxtheme!g_preferredAppMode] |
| (functionPtr[0x0C] == 0xC3); // ret |
| #else |
| #error Unsupported processor type |
| #endif |
| } |
| |
| typedef DWORD(WINAPI* TYPE_SetPreferredAppMode)(DWORD value); |
| TYPE_SetPreferredAppMode Locate_SetPreferredAppMode() |
| { |
| const HMODULE hUxtheme = GetModuleHandle(L"uxtheme.dll"); |
| if (!hUxtheme) |
| return 0; |
| |
| /* |
| * Function is only exported by ordinal. |
| * Hopefully one day Microsoft will finally export it by name. |
| */ |
| const BYTE* candidate = (const BYTE*)GetProcAddress(hUxtheme, MAKEINTRESOURCEA(135)); |
| if (!candidate) |
| return 0; |
| |
| /* |
| * In next Windows version, some other function can end up having this ordinal. |
| * Compare function's code to known signature to make sure. |
| */ |
| if (!Validate_SetPreferredAppMode(candidate)) |
| return 0; |
| |
| return (TYPE_SetPreferredAppMode)candidate; |
| } |
| |
| #ifndef NO_SetPreferredAppMode |
| JNIEXPORT jint JNICALL OS_NATIVE(SetPreferredAppMode) |
| (JNIEnv* env, jclass that, jint arg0) |
| { |
| /* Cache the search result for performance reasons */ |
| static TYPE_SetPreferredAppMode fn_SetPreferredAppMode = 0; |
| static int isInitialized = 0; |
| if (!isInitialized) |
| { |
| fn_SetPreferredAppMode = Locate_SetPreferredAppMode(); |
| isInitialized = 1; |
| } |
| |
| if (!fn_SetPreferredAppMode) |
| return 0; |
| |
| jint rc = 0; |
| OS_NATIVE_ENTER(env, that, SetPreferredAppMode_FUNC); |
| rc = (jint)fn_SetPreferredAppMode(arg0); |
| OS_NATIVE_EXIT(env, that, SetPreferredAppMode_FUNC); |
| return rc; |
| } |
| #endif |
| |
| #ifndef NO_IsDarkModeAvailable |
| JNIEXPORT jboolean JNICALL OS_NATIVE(IsDarkModeAvailable) |
| (JNIEnv* env, jclass that) |
| { |
| /* Cache the search result for performance reasons */ |
| static jboolean isAvailable = 0; |
| static int isInitialized = 0; |
| if (!isInitialized) |
| { |
| isAvailable = (Locate_SetPreferredAppMode() && Locate_AllowDarkModeForWindow()); |
| isInitialized = 1; |
| } |
| |
| return isAvailable; |
| } |
| #endif |