Merge branch 'improve-win32-version-2-70' into 'glib-2-70'

gutils.c: Improve g_get_os_info() for Windows 10/Server 2019+

See merge request GNOME/glib!2359
This commit is contained in:
Philip Withnall 2021-11-24 10:29:27 +00:00
commit 485dd16dc1
3 changed files with 90 additions and 29 deletions

View File

@ -39,6 +39,7 @@ void g_console_win32_init (void);
void g_clock_win32_init (void);
void g_crash_handler_win32_init (void);
void g_crash_handler_win32_deinit (void);
gboolean _g_win32_call_rtl_version (OSVERSIONINFOEXW *info);
extern HMODULE glib_dll;
#endif

View File

@ -1298,14 +1298,35 @@ get_windows_version (gboolean with_windows)
if (g_win32_check_windows_version (10, 0, 0, G_WIN32_OS_ANY))
{
gchar *win10_release;
gboolean is_win11 = FALSE;
g_string_append (version, "10");
if (!g_win32_check_windows_version (10, 0, 0, G_WIN32_OS_SERVER))
{
OSVERSIONINFOEXW osinfo;
if (!g_win32_check_windows_version (10, 0, 0, G_WIN32_OS_WORKSTATION))
g_string_append (version, " Server");
/*
* This always succeeds if we get here, since the
* g_win32_check_windows_version() already did this!
* We want the OSVERSIONINFOEXW here for more even
* fine-grained versioning items
*/
_g_win32_call_rtl_version (&osinfo);
/* Windows 10 is identified by its release number, such as
* 1511, 1607, 1703, 1709, 1803, 1809 or 1903.
/*
* Windows 11 is actually Windows 10.0.22000+,
* so look at the build number
*/
is_win11 = (osinfo.dwBuildNumber >= 22000);
}
if (is_win11)
g_string_append (version, "11");
else
g_string_append (version, "10");
/* Windows 10/Server 2016+ is identified by its ReleaseId or
* DisplayVersion (since 20H2), such as
* 1511, 1607, 1703, 1709, 1803, 1809 or 1903 etc.
* The first version of Windows 10 has no release number.
*/
win10_release = get_registry_str (HKEY_LOCAL_MACHINE,
@ -1316,7 +1337,26 @@ get_windows_version (gboolean with_windows)
L"ReleaseId");
if (win10_release != NULL)
g_string_append_printf (version, " %s", win10_release);
{
if (g_strcmp0 (win10_release, "2009") != 0)
g_string_append_printf (version, " %s", win10_release);
else
{
g_free (win10_release);
win10_release = get_registry_str (HKEY_LOCAL_MACHINE,
L"SOFTWARE"
L"\\Microsoft"
L"\\Windows NT"
L"\\CurrentVersion",
L"DisplayVersion");
if (win10_release != NULL)
g_string_append_printf (version, " %s", win10_release);
else
g_string_append_printf (version, " 2009");
}
}
g_free (win10_release);
}

View File

@ -491,6 +491,48 @@ G_GNUC_END_IGNORE_DEPRECATIONS
return dirname;
}
/*
* private API to call Windows's RtlGetVersion(), which may need to be called
* via GetProcAddress()
*/
gboolean
_g_win32_call_rtl_version (OSVERSIONINFOEXW *info)
{
static OSVERSIONINFOEXW result;
static gsize inited = 0;
g_return_val_if_fail (info != NULL, FALSE);
if (g_once_init_enter (&inited))
{
#if WINAPI_FAMILY != MODERN_API_FAMILY
/* For non-modern UI Apps, use the LoadLibraryW()/GetProcAddress() thing */
typedef NTSTATUS (WINAPI fRtlGetVersion) (PRTL_OSVERSIONINFOEXW);
fRtlGetVersion *RtlGetVersion;
HMODULE hmodule = LoadLibraryW (L"ntdll.dll");
g_return_val_if_fail (hmodule != NULL, FALSE);
RtlGetVersion = (fRtlGetVersion *) GetProcAddress (hmodule, "RtlGetVersion");
g_return_val_if_fail (RtlGetVersion != NULL, FALSE);
#endif
memset (&result, 0, sizeof (OSVERSIONINFOEXW));
result.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW);
RtlGetVersion (&result);
#if WINAPI_FAMILY != MODERN_API_FAMILY
FreeLibrary (hmodule);
#endif
g_once_init_leave (&inited, TRUE);
}
*info = result;
return TRUE;
}
/**
* g_win32_check_windows_version:
* @major: major version of Windows
@ -526,31 +568,13 @@ g_win32_check_windows_version (const gint major,
gboolean is_ver_checked = FALSE;
gboolean is_type_checked = FALSE;
#if WINAPI_FAMILY != MODERN_API_FAMILY
/* For non-modern UI Apps, use the LoadLibraryW()/GetProcAddress() thing */
typedef NTSTATUS (WINAPI fRtlGetVersion) (PRTL_OSVERSIONINFOEXW);
fRtlGetVersion *RtlGetVersion;
HMODULE hmodule;
#endif
/* We Only Support Checking for XP or later */
g_return_val_if_fail (major >= 5 && (major <=6 || major == 10), FALSE);
g_return_val_if_fail ((major >= 5 && minor >= 1) || major >= 6, FALSE);
/* Check for Service Pack Version >= 0 */
g_return_val_if_fail (spver >= 0, FALSE);
#if WINAPI_FAMILY != MODERN_API_FAMILY
hmodule = LoadLibraryW (L"ntdll.dll");
g_return_val_if_fail (hmodule != NULL, FALSE);
RtlGetVersion = (fRtlGetVersion *) GetProcAddress (hmodule, "RtlGetVersion");
g_return_val_if_fail (RtlGetVersion != NULL, FALSE);
#endif
memset (&osverinfo, 0, sizeof (OSVERSIONINFOEXW));
osverinfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW);
RtlGetVersion (&osverinfo);
g_return_val_if_fail (_g_win32_call_rtl_version (&osverinfo), FALSE);
/* check the OS and Service Pack Versions */
if (osverinfo.dwMajorVersion > major)
@ -588,10 +612,6 @@ g_win32_check_windows_version (const gint major,
}
}
#if WINAPI_FAMILY != MODERN_API_FAMILY
FreeLibrary (hmodule);
#endif
return is_ver_checked && is_type_checked;
}