mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-15 08:46:18 +01:00
Merge branch 'improve-win32-version' into 'main'
gutils.c: Improve g_get_os_info() for Windows 10/Server 2008 R2+ Closes #2443 See merge request GNOME/glib!2351
This commit is contained in:
commit
d455ece99f
@ -39,6 +39,7 @@ void g_console_win32_init (void);
|
|||||||
void g_clock_win32_init (void);
|
void g_clock_win32_init (void);
|
||||||
void g_crash_handler_win32_init (void);
|
void g_crash_handler_win32_init (void);
|
||||||
void g_crash_handler_win32_deinit (void);
|
void g_crash_handler_win32_deinit (void);
|
||||||
|
gboolean _g_win32_call_rtl_version (OSVERSIONINFOEXW *info);
|
||||||
extern HMODULE glib_dll;
|
extern HMODULE glib_dll;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1294,18 +1294,58 @@ static gchar *
|
|||||||
get_windows_version (gboolean with_windows)
|
get_windows_version (gboolean with_windows)
|
||||||
{
|
{
|
||||||
GString *version = g_string_new (NULL);
|
GString *version = g_string_new (NULL);
|
||||||
|
gboolean is_win_server = FALSE;
|
||||||
|
|
||||||
if (g_win32_check_windows_version (10, 0, 0, G_WIN32_OS_ANY))
|
if (g_win32_check_windows_version (10, 0, 0, G_WIN32_OS_ANY))
|
||||||
{
|
{
|
||||||
gchar *win10_release;
|
gchar *win10_release;
|
||||||
|
gboolean is_win11 = FALSE;
|
||||||
|
OSVERSIONINFOEXW osinfo;
|
||||||
|
|
||||||
|
/* Are we on Windows 2016/2019/2022 Server? */
|
||||||
|
is_win_server = g_win32_check_windows_version (10, 0, 0, G_WIN32_OS_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);
|
||||||
|
|
||||||
|
if (!is_win_server)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Windows 11 is actually Windows 10.0.22000+,
|
||||||
|
* so look at the build number
|
||||||
|
*/
|
||||||
|
is_win11 = (osinfo.dwBuildNumber >= 22000);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Windows 2022 Server is actually Windows 10.0.20348+,
|
||||||
|
* Windows 2019 Server is actually Windows 10.0.17763+,
|
||||||
|
* Windows 2016 Server is actually Windows 10.0.14393+,
|
||||||
|
* so look at the build number
|
||||||
|
*/
|
||||||
|
g_string_append (version, "Server");
|
||||||
|
if (osinfo.dwBuildNumber >= 20348)
|
||||||
|
g_string_append (version, " 2022");
|
||||||
|
else if (osinfo.dwBuildNumber >= 17763)
|
||||||
|
g_string_append (version, " 2019");
|
||||||
|
else
|
||||||
|
g_string_append (version, " 2016");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_win11)
|
||||||
|
g_string_append (version, "11");
|
||||||
|
else if (!is_win_server)
|
||||||
g_string_append (version, "10");
|
g_string_append (version, "10");
|
||||||
|
|
||||||
if (!g_win32_check_windows_version (10, 0, 0, G_WIN32_OS_WORKSTATION))
|
/* Windows 10/Server 2016+ is identified by its ReleaseId or
|
||||||
g_string_append (version, " Server");
|
* DisplayVersion (since 20H2), such as
|
||||||
|
* 1511, 1607, 1703, 1709, 1803, 1809 or 1903 etc.
|
||||||
/* Windows 10 is identified by its release number, such as
|
|
||||||
* 1511, 1607, 1703, 1709, 1803, 1809 or 1903.
|
|
||||||
* The first version of Windows 10 has no release number.
|
* The first version of Windows 10 has no release number.
|
||||||
*/
|
*/
|
||||||
win10_release = get_registry_str (HKEY_LOCAL_MACHINE,
|
win10_release = get_registry_str (HKEY_LOCAL_MACHINE,
|
||||||
@ -1316,7 +1356,26 @@ get_windows_version (gboolean with_windows)
|
|||||||
L"ReleaseId");
|
L"ReleaseId");
|
||||||
|
|
||||||
if (win10_release != NULL)
|
if (win10_release != NULL)
|
||||||
|
{
|
||||||
|
if (g_strcmp0 (win10_release, "2009") != 0)
|
||||||
g_string_append_printf (version, " %s", win10_release);
|
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);
|
g_free (win10_release);
|
||||||
}
|
}
|
||||||
@ -1324,10 +1383,10 @@ get_windows_version (gboolean with_windows)
|
|||||||
{
|
{
|
||||||
gchar *win81_update;
|
gchar *win81_update;
|
||||||
|
|
||||||
|
if (g_win32_check_windows_version (6, 3, 0, G_WIN32_OS_WORKSTATION))
|
||||||
g_string_append (version, "8.1");
|
g_string_append (version, "8.1");
|
||||||
|
else
|
||||||
if (!g_win32_check_windows_version (6, 3, 0, G_WIN32_OS_WORKSTATION))
|
g_string_append (version, "Server 2012 R2");
|
||||||
g_string_append (version, " Server");
|
|
||||||
|
|
||||||
win81_update = get_windows_8_1_update ();
|
win81_update = get_windows_8_1_update ();
|
||||||
|
|
||||||
@ -1347,8 +1406,23 @@ get_windows_version (gboolean with_windows)
|
|||||||
|
|
||||||
g_string_append (version, versions[i].version);
|
g_string_append (version, versions[i].version);
|
||||||
|
|
||||||
if (!g_win32_check_windows_version (versions[i].major, versions[i].minor, versions[i].sp, G_WIN32_OS_WORKSTATION))
|
if (g_win32_check_windows_version (versions[i].major, versions[i].minor, versions[i].sp, G_WIN32_OS_SERVER))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This condition should now always hold, since Windows
|
||||||
|
* 7+/Server 2008 R2+ is now required
|
||||||
|
*/
|
||||||
|
if (versions[i].major == 6)
|
||||||
|
{
|
||||||
g_string_append (version, "Server");
|
g_string_append (version, "Server");
|
||||||
|
if (versions[i].minor == 2)
|
||||||
|
g_string_append (version, " 2012");
|
||||||
|
else if (versions[i].minor == 1)
|
||||||
|
g_string_append (version, " 2008 R2");
|
||||||
|
else
|
||||||
|
g_string_append (version, " 2008");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
g_string_append (version, versions[i].spversion);
|
g_string_append (version, versions[i].spversion);
|
||||||
}
|
}
|
||||||
|
@ -491,6 +491,48 @@ G_GNUC_END_IGNORE_DEPRECATIONS
|
|||||||
return dirname;
|
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:
|
* g_win32_check_windows_version:
|
||||||
* @major: major version of Windows
|
* @major: major version of Windows
|
||||||
@ -526,31 +568,13 @@ g_win32_check_windows_version (const gint major,
|
|||||||
gboolean is_ver_checked = FALSE;
|
gboolean is_ver_checked = FALSE;
|
||||||
gboolean is_type_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 */
|
/* 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 && (major <= 6 || major == 10), FALSE);
|
||||||
g_return_val_if_fail ((major >= 5 && minor >= 1) || major >= 6, FALSE);
|
g_return_val_if_fail ((major >= 5 && minor >= 1) || major >= 6, FALSE);
|
||||||
|
|
||||||
/* Check for Service Pack Version >= 0 */
|
/* Check for Service Pack Version >= 0 */
|
||||||
g_return_val_if_fail (spver >= 0, FALSE);
|
g_return_val_if_fail (spver >= 0, FALSE);
|
||||||
|
g_return_val_if_fail (_g_win32_call_rtl_version (&osverinfo), 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);
|
|
||||||
|
|
||||||
/* check the OS and Service Pack Versions */
|
/* check the OS and Service Pack Versions */
|
||||||
if (osverinfo.dwMajorVersion > (DWORD) major)
|
if (osverinfo.dwMajorVersion > (DWORD) 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;
|
return is_ver_checked && is_type_checked;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user