From 6626480358f06be136aef979c2c7201601e1a9bd Mon Sep 17 00:00:00 2001 From: FunkyFr3sh Date: Mon, 6 May 2024 01:23:59 +0200 Subject: [PATCH] extend versionhelpers --- cnc-ddraw.vcxproj | 1 + cnc-ddraw.vcxproj.filters | 3 ++ inc/config.h | 1 - inc/versionhelpers.h | 60 ++++++++++++++++++++------------ src/config.c | 5 ++- src/dd.c | 12 +++---- src/ddsurface.c | 3 +- src/debug.c | 17 +++------ src/dllmain.c | 3 ++ src/fps_limiter.c | 2 +- src/opengl_utils.c | 3 +- src/versionhelpers.c | 72 +++++++++++++++++++++++++++++++++++++++ src/wndproc.c | 11 +++--- 13 files changed, 140 insertions(+), 53 deletions(-) create mode 100644 src/versionhelpers.c diff --git a/cnc-ddraw.vcxproj b/cnc-ddraw.vcxproj index 4980515..edfd7ab 100644 --- a/cnc-ddraw.vcxproj +++ b/cnc-ddraw.vcxproj @@ -67,6 +67,7 @@ + diff --git a/cnc-ddraw.vcxproj.filters b/cnc-ddraw.vcxproj.filters index e9fb994..34b47a6 100644 --- a/cnc-ddraw.vcxproj.filters +++ b/cnc-ddraw.vcxproj.filters @@ -159,6 +159,9 @@ Source Files + + Source Files + diff --git a/inc/config.h b/inc/config.h index fe0f885..badf4fe 100644 --- a/inc/config.h +++ b/inc/config.h @@ -19,7 +19,6 @@ typedef struct CNCDDRAWCONFIG char process_file_ext[MAX_PATH]; char dll_file_ext[MAX_PATH]; INIFILE ini; - BOOL is_wine; BOOL d3d9on12; BOOL opengl_core; diff --git a/inc/versionhelpers.h b/inc/versionhelpers.h index ea574e1..21e3ced 100644 --- a/inc/versionhelpers.h +++ b/inc/versionhelpers.h @@ -6,8 +6,6 @@ #ifndef _INC_VERSIONHELPERS #define _INC_VERSIONHELPERS -#if 1 - #ifdef __cplusplus #define VERSIONHELPERAPI inline bool #else @@ -26,73 +24,91 @@ #ifndef _WIN32_WINNT_WIN10 #define _WIN32_WINNT_WIN10 0x0A00 /* ABRACADABRA_THRESHOLD*/ #endif +#ifndef _WIN32_WINNT_WIN11 +#define _WIN32_WINNT_WIN11 0x0A00 +#endif -VERSIONHELPERAPI IsWindowsVersionOrGreater(WORD major, WORD minor, WORD servpack) + +void verhelp_init(); +BOOL verhelp_verify_version(PRTL_OSVERSIONINFOEXW versionInfo, ULONG typeMask, ULONGLONG conditionMask); +const char* verhelp_wine_get_version(); +void verhelp_wine_get_host_version(const char** sysname, const char** release); +BOOL verhelp_is_wine(); +BOOL verhelp_is_macos(); +BOOL verhelp_is_linux(); + +/* Original MS Functions */ + +VERSIONHELPERAPI IsWindowsVersionOrGreater(DWORD major, DWORD minor, DWORD build, WORD servpack) { - OSVERSIONINFOEXW vi = {sizeof(vi),major,minor,0,0,{0},servpack}; - return VerifyVersionInfoW(&vi, VER_MAJORVERSION|VER_MINORVERSION|VER_SERVICEPACKMAJOR, - VerSetConditionMask(VerSetConditionMask(VerSetConditionMask(0, + RTL_OSVERSIONINFOEXW vi = {sizeof(vi),major,minor,build,0,{0},servpack}; + return verhelp_verify_version(&vi, VER_MAJORVERSION|VER_MINORVERSION|VER_BUILDNUMBER|VER_SERVICEPACKMAJOR, + VerSetConditionMask(VerSetConditionMask(VerSetConditionMask(VerSetConditionMask(0, VER_MAJORVERSION,VER_GREATER_EQUAL), VER_MINORVERSION,VER_GREATER_EQUAL), + VER_BUILDNUMBER,VER_GREATER_EQUAL), VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL)); } VERSIONHELPERAPI IsWindowsXPOrGreater(void) { - return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0); + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0, 0); } VERSIONHELPERAPI IsWindowsXPSP1OrGreater(void) { - return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 1); + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0, 1); } VERSIONHELPERAPI IsWindowsXPSP2OrGreater(void) { - return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 2); + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0, 2); } VERSIONHELPERAPI IsWindowsXPSP3OrGreater(void) { - return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 3); + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0, 3); } VERSIONHELPERAPI IsWindowsVistaOrGreater(void) { - return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0); + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0, 0); } VERSIONHELPERAPI IsWindowsVistaSP1OrGreater(void) { - return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 1); + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0, 1); } VERSIONHELPERAPI IsWindowsVistaSP2OrGreater(void) { - return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 2); + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0, 2); } VERSIONHELPERAPI IsWindows7OrGreater(void) { - return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0); + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0, 0); } VERSIONHELPERAPI IsWindows7SP1OrGreater(void) { - return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 1); + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0, 1); } VERSIONHELPERAPI IsWindows8OrGreater(void) { - return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0); + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0, 0); } -/* Those can't be used without manifest so we comment them out to ensure they're not being used by accident + VERSIONHELPERAPI IsWindows8Point1OrGreater(void) { - return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINBLUE), LOBYTE(_WIN32_WINNT_WINBLUE), 0); + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINBLUE), LOBYTE(_WIN32_WINNT_WINBLUE), 0, 0); } VERSIONHELPERAPI IsWindowsThresholdOrGreater(void) { - return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINTHRESHOLD), LOBYTE(_WIN32_WINNT_WINTHRESHOLD), 0); + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINTHRESHOLD), LOBYTE(_WIN32_WINNT_WINTHRESHOLD), 0, 0); } VERSIONHELPERAPI IsWindows10OrGreater(void) { return IsWindowsThresholdOrGreater(); } -*/ + +VERSIONHELPERAPI IsWindows11OrGreater(void) { + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN11), LOBYTE(_WIN32_WINNT_WIN11), 22000, 0); +} + VERSIONHELPERAPI IsWindowsServer(void) { OSVERSIONINFOEXW vi = {sizeof(vi),0,0,0,0,{0},0,0,0,VER_NT_WORKSTATION}; - return !VerifyVersionInfoW(&vi, VER_PRODUCT_TYPE, VerSetConditionMask(0, VER_PRODUCT_TYPE, VER_EQUAL)); + return !verhelp_verify_version(&vi, VER_PRODUCT_TYPE, VerSetConditionMask(0, VER_PRODUCT_TYPE, VER_EQUAL)); } #endif -#endif diff --git a/src/config.c b/src/config.c index da84184..31cbad5 100644 --- a/src/config.c +++ b/src/config.c @@ -11,6 +11,7 @@ #include "debug.h" #include "dllmain.h" #include "ini.h" +#include "versionhelpers.h" static void cfg_init(); static void cfg_create_ini(); @@ -1075,8 +1076,6 @@ static void cfg_create_ini() static void cfg_init() { - g_config.is_wine = real_GetProcAddress(GetModuleHandleA("ntdll.dll"), "wine_get_version") != 0; - /* get process filename and directory */ if (GetModuleFileNameA(NULL, g_config.game_path, sizeof(g_config.game_path) - 1) > 0) { @@ -1151,7 +1150,7 @@ static DWORD cfg_get_string(LPCSTR key, LPCSTR default_value, LPSTR out_string, { char buf[MAX_PATH] = { 0 }; - if (g_config.is_wine) + if (verhelp_is_wine()) { char section[MAX_PATH] = { 0 }; _snprintf(section, sizeof(section) - 1, "%s/wine", g_config.process_file_name); diff --git a/src/dd.c b/src/dd.c index 68f0810..c2948c6 100644 --- a/src/dd.c +++ b/src/dd.c @@ -875,7 +875,7 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl if (g_config.remove_menu && GetMenu(g_ddraw.hwnd)) SetMenu(g_ddraw.hwnd, NULL); - if (!g_config.is_wine) + if (!verhelp_is_wine()) { MSG msg; /* workaround for "Not Responding" window problem in cnc games */ real_PeekMessageA(&msg, g_ddraw.hwnd, 0, 0, PM_NOREMOVE | PM_QS_INPUT); @@ -905,7 +905,7 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl real_SetWindowLongA(g_ddraw.hwnd, GWL_EXSTYLE, exstyle & ~(WS_EX_TOOLWINDOW)); } - if (g_config.is_wine) + if (verhelp_is_wine()) { real_SetWindowLongA( g_ddraw.hwnd, @@ -1053,7 +1053,7 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl Fix wayland bug: ChangeDisplaySettings fails silently - enable borderless mode in case display resolution was not changed */ - if (g_config.is_wine && + if (verhelp_is_wine() && (g_ddraw.render.mode.dmPelsWidth != real_GetSystemMetrics(SM_CXSCREEN) || g_ddraw.render.mode.dmPelsHeight != real_GetSystemMetrics(SM_CYSCREEN))) { @@ -1066,7 +1066,7 @@ HRESULT dd_SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwFl } } - if (g_config.is_wine) + if (verhelp_is_wine()) { real_SetWindowLongA( g_ddraw.hwnd, @@ -1273,7 +1273,7 @@ HRESULT dd_WaitForVerticalBlank(DWORD dwFlags, HANDLE hEvent) if (g_config.maxgameticks == -2) { /* Workaround for DwmFlush() freeze (e.g. slow alt+tab) issue on windows 7 SP1 */ - if (g_ddraw.renderer == ogl_render_main && !g_config.is_wine && !IsWindows8OrGreater()) + if (g_ddraw.renderer == ogl_render_main && !verhelp_is_wine() && !IsWindows8OrGreater()) { if (fpsl_wait_for_vblank()) return DD_OK; @@ -1556,7 +1556,7 @@ HRESULT dd_CreateEx(GUID* lpGuid, LPVOID* lplpDD, REFIID iid, IUnknown* pUnkOute } else /* auto */ { - if (!g_config.is_wine && d3d9_is_available()) + if (!verhelp_is_wine() && d3d9_is_available()) { g_ddraw.renderer = d3d9_render_main; } diff --git a/src/ddsurface.c b/src/ddsurface.c index ba7a5f1..e188cba 100644 --- a/src/ddsurface.c +++ b/src/ddsurface.c @@ -11,6 +11,7 @@ #include "utils.h" #include "blt.h" #include "config.h" +#include "versionhelpers.h" LONG g_dds_gdi_handles; @@ -957,7 +958,7 @@ HRESULT dds_Lock( dbg_dump_dds_lock_flags(dwFlags); - if (g_ddraw.ref && g_config.fixnotresponding && !g_config.is_wine) + if (g_ddraw.ref && g_config.fixnotresponding && !verhelp_is_wine()) { MSG msg; /* workaround for "Not Responding" window problem */ real_PeekMessageA(&msg, g_ddraw.hwnd, 0, 0, PM_NOREMOVE); diff --git a/src/debug.c b/src/debug.c index 4e81ab5..bc840b8 100644 --- a/src/debug.c +++ b/src/debug.c @@ -8,6 +8,7 @@ #include "debug.h" #include "hook.h" #include "version.h" +#include "versionhelpers.h" double g_dbg_frame_time = 0; @@ -130,23 +131,13 @@ void dbg_init() RegCloseKey(hkey); } - const char* (CDECL * wine_get_version)() = - (void*)real_GetProcAddress(GetModuleHandleA("ntdll.dll"), "wine_get_version"); - - if (wine_get_version) + if (verhelp_is_wine()) { - TRACE("Wine version = %s\n", wine_get_version()); - } + TRACE("Wine version = %s\n", verhelp_wine_get_version()); - void (CDECL* wine_get_host_version)(const char** sysname, const char** release) = - (void*)real_GetProcAddress(GetModuleHandleA("ntdll.dll"), "wine_get_host_version"); - - if (wine_get_host_version) - { const char* sysname = NULL; const char* release = NULL; - - wine_get_host_version(&sysname, &release); + verhelp_wine_get_host_version(&sysname, &release); TRACE("Wine sysname = %s, release = %s\n", sysname, release); } diff --git a/src/dllmain.c b/src/dllmain.c index ee3c2cc..108c9e0 100644 --- a/src/dllmain.c +++ b/src/dllmain.c @@ -9,6 +9,7 @@ #include "debug.h" #include "config.h" #include "hook.h" +#include "versionhelpers.h" /* export for cncnet cnc games */ @@ -28,6 +29,8 @@ BOOL WINAPI DllMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved) { g_ddraw_module = hDll; + verhelp_init(); + if (GetEnvironmentVariableW(L"cnc_ddraw_config_init", NULL, 0)) { cfg_load(); diff --git a/src/fps_limiter.c b/src/fps_limiter.c index 9d74fc5..8ea5992 100644 --- a/src/fps_limiter.c +++ b/src/fps_limiter.c @@ -157,7 +157,7 @@ void fpsl_frame_end() (g_config.vsync && (!g_config.maxfps || g_config.maxfps >= g_ddraw.mode.dmDisplayFrequency))) { /* Workaround for DwmFlush() freeze (e.g. slow alt+tab) issue on windows 7 SP1 */ - if (g_ddraw.renderer == ogl_render_main && !g_config.is_wine && !IsWindows8OrGreater()) + if (g_ddraw.renderer == ogl_render_main && !verhelp_is_wine() && !IsWindows8OrGreater()) { if (fpsl_wait_for_vblank()) return; diff --git a/src/opengl_utils.c b/src/opengl_utils.c index e9497f3..da6e7c7 100644 --- a/src/opengl_utils.c +++ b/src/opengl_utils.c @@ -5,6 +5,7 @@ #include "debug.h" #include "hook.h" #include "config.h" +#include "versionhelpers.h" PFNWGLCREATECONTEXTPROC xwglCreateContext; PFNWGLDELETECONTEXTPROC xwglDeleteContext; @@ -212,7 +213,7 @@ void oglu_init() glEnableVertexAttribArray && glUniform2fv && glUniformMatrix4fv && glGenVertexArrays && glBindVertexArray && glGetUniformLocation; - if (g_config.is_wine && glversion && glversion[0] == '2') // macOS + if (verhelp_is_wine() && glversion && glversion[0] == '2') // macOS { g_oglu_got_version3 = FALSE; wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)xwglGetProcAddress("wglCreateContextAttribsARB"); diff --git a/src/versionhelpers.c b/src/versionhelpers.c new file mode 100644 index 0000000..5752591 --- /dev/null +++ b/src/versionhelpers.c @@ -0,0 +1,72 @@ +#include +#include "versionhelpers.h" + +typedef NTSTATUS(WINAPI* RTLVERIFYVERSIONINFOPROC)(PRTL_OSVERSIONINFOEXW, ULONG, ULONGLONG); +typedef const char* (CDECL* WINE_GET_VERSIONPROC)(); +typedef void (CDECL* WINE_GET_HOST_VERSIONPROC)(const char** sysname, const char** release); + +static RTLVERIFYVERSIONINFOPROC RtlVerifyVersionInfo; +static WINE_GET_VERSIONPROC wine_get_version; +static WINE_GET_HOST_VERSIONPROC wine_get_host_version; + +/* GetProcAddress is rather slow so we use a function to inizialize it once on startup */ +void verhelp_init() +{ + HMODULE mod = GetModuleHandleA("ntdll.dll"); + if (mod) + { + RtlVerifyVersionInfo = (RTLVERIFYVERSIONINFOPROC)GetProcAddress(mod, "RtlVerifyVersionInfo"); + wine_get_version = (WINE_GET_VERSIONPROC)GetProcAddress(mod, "wine_get_version"); + wine_get_host_version = (WINE_GET_HOST_VERSIONPROC)GetProcAddress(mod, "wine_get_host_version"); + } +} + +BOOL verhelp_verify_version(PRTL_OSVERSIONINFOEXW versionInfo, ULONG typeMask, ULONGLONG conditionMask) +{ + return RtlVerifyVersionInfo ? + RtlVerifyVersionInfo(versionInfo, typeMask, conditionMask) == 0 : + VerifyVersionInfoW(versionInfo, typeMask, conditionMask); +} + +const char* verhelp_wine_get_version() +{ + return wine_get_version ? wine_get_version() : NULL; +} + +void verhelp_wine_get_host_version(const char** sysname, const char** release) +{ + if (wine_get_host_version) + { + wine_get_host_version(sysname, release); + return; + } + + if (sysname) + *sysname = NULL; + + if (release) + *release = NULL; +} + +BOOL verhelp_is_wine() +{ + return wine_get_version != NULL; +} + +BOOL verhelp_is_macos() +{ + const char* sysname = NULL; + const char* release = NULL; + verhelp_wine_get_host_version(&sysname, &release); + + return sysname && _strcmpi(sysname, "Darwin") == 0; +} + +BOOL verhelp_is_linux() +{ + const char* sysname = NULL; + const char* release = NULL; + verhelp_wine_get_host_version(&sysname, &release); + + return sysname && _strcmpi(sysname, "Linux") == 0; +} diff --git a/src/wndproc.c b/src/wndproc.c index 8ea8ba5..f983186 100644 --- a/src/wndproc.c +++ b/src/wndproc.c @@ -13,6 +13,7 @@ #include "wndproc.h" #include "utils.h" #include "debug.h" +#include "versionhelpers.h" LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) @@ -228,7 +229,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam pos->hwndInsertAfter, pos->x, pos->y, pos->cx, pos->cy); */ - if (g_config.is_wine && + if (verhelp_is_wine() && !g_config.windowed && (pos->x > 0 || pos->y > 0) && g_ddraw.last_set_window_pos_tick + 500 < timeGetTime()) @@ -462,7 +463,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam util_update_bnet_pos(x, y); } - if (in_size_move || (g_config.is_wine && !g_config.fullscreen && g_ddraw.render.thread)) + if (in_size_move || (verhelp_is_wine() && !g_config.fullscreen && g_ddraw.render.thread)) { if (x != -32000) g_config.window_rect.left = x; /* -32000 = Exit/Minimize */ @@ -479,7 +480,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam } case WM_NCMOUSELEAVE: { - if (!g_config.is_wine) /* hack: disable aero snap */ + if (!verhelp_is_wine()) /* hack: disable aero snap */ { LONG style = real_GetWindowLongA(g_ddraw.hwnd, GWL_STYLE); @@ -492,7 +493,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam } case WM_SYSCOMMAND: { - if ((wParam & ~0x0F) == SC_MOVE && !g_config.is_wine) /* hack: disable aero snap */ + if ((wParam & ~0x0F) == SC_MOVE && !verhelp_is_wine()) /* hack: disable aero snap */ { LONG style = real_GetWindowLongA(g_ddraw.hwnd, GWL_STYLE); @@ -633,7 +634,7 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam mouse_unlock(); - if (g_config.is_wine && g_ddraw.last_set_window_pos_tick + 500 > timeGetTime()) + if (verhelp_is_wine() && g_ddraw.last_set_window_pos_tick + 500 > timeGetTime()) return 0; if (!g_config.windowed)