blob: 20a24a54a65c29ab1c8adc7e9c662638e1447234 [file] [log] [blame]
/*******************************************************************************
* 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