gwin32: Add g_win32_check_windows_version() API
authorChun-wei Fan <fanchunwei@src.gnome.org>
Mon, 26 Jan 2015 03:11:48 +0000 (11:11 +0800)
committerChun-wei Fan <fanchunwei@src.gnome.org>
Tue, 27 Jan 2015 04:17:14 +0000 (12:17 +0800)
This adds a public API where one can use to see whether the running version
of Windows where the code is run is at least the specified version, service
pack level, and the type (non-server, server, any) of the running Windows
OS.

This API is done as:
-GetVersion()/GetVersionEx() changed in the way they work since Windows 8.1
 [1][2], so a newer mechanism to check the version of the running Windows
 operating system is needed.  MSDN also states that GetVersion() might be
 further changed or removed after Windows 8.1.  This provides a wrapper for
 VerfyVersionInfo() as well in GLib for most cases, which was recommended
 in place of g_win32_get_windows_version() for more detailed Windows
 version checking.
-Provides an OS-level functionality check, for those that we don't need to
 venture into GetProcAddress(), and also to determine system API behavior
 changes due to differences in OS versions.

Also added a note for the g_win32_get_windows_version() API that since the
behavior of GetVersion() which it uses, is changed since Windows 8.1, users
of the API should be aware.

[1]:
http://msdn.microsoft.com/zh-tw/library/windows/desktop/ms724451%28v=vs.85%29.aspx
[2]:
http://msdn.microsoft.com/zh-tw/library/windows/desktop/ms724451%28v=vs.85%29.aspx

https://bugzilla.gnome.org/show_bug.cgi?id=741895

glib/gwin32.c
glib/gwin32.h

index ffc5fe2..fc4416b 100644 (file)
@@ -516,9 +516,83 @@ g_win32_get_package_installation_subdirectory (const gchar *package,
 
 #endif
 
+#define gwin32condmask(base,var) VerSetConditionMask (base, var, VER_GREATER_EQUAL)
+
+/**
+ * g_win32_check_windows_version:
+ * @major: major version of Windows
+ * @minor: minor version of Windows
+ * @spver: Windows Service Pack Level, 0 if none
+ * @os_type: Type of Windows OS
+ *
+ * Returns whether the version of the Windows operating system the
+ * code is running on is at least the specified major, minor and
+ * service pack versions.  See MSDN documentation for the Operating
+ * System Version.  Software that needs even more detailed version and
+ * feature information should use the Win32 API VerifyVersionInfo()
+ * directly.
+ *
+ * Successive calls of this function can be used for enabling or
+ * disabling features at run-time for a range of Windows versions,
+ * as per the VerifyVersionInfo() API documentation.
+ *
+ * Returns: %TRUE if the Windows Version is the same or greater than
+ *          the specified major, minor and service pack versions, and
+ *          whether the running Windows is a workstation or server edition
+ *          of Windows, if specifically specified.
+ *
+ * Since: 2.44
+ **/
+gboolean
+g_win32_check_windows_version (const gint major,
+                               const gint minor,
+                               const gint spver,
+                               const GWin32OSType os_type)
+{
+  OSVERSIONINFOEXW osverinfo;
+  gboolean test_os_type;
+  const DWORDLONG conds = gwin32condmask (gwin32condmask (gwin32condmask (0, VER_MAJORVERSION), VER_MINORVERSION), VER_SERVICEPACKMAJOR);
+
+  memset (&osverinfo, 0, sizeof (OSVERSIONINFOEXW));
+  osverinfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW);
+  osverinfo.dwPlatformId = VER_PLATFORM_WIN32_NT;
+  osverinfo.dwMajorVersion = major;
+  osverinfo.dwMinorVersion = minor;
+  osverinfo.wServicePackMajor = spver;
+
+  switch (os_type)
+    {
+      case G_WIN32_OS_WORKSTATION:
+        osverinfo.wProductType = VER_NT_WORKSTATION;
+        test_os_type = TRUE;
+        break;
+      case G_WIN32_OS_SERVER:
+        osverinfo.wProductType = VER_NT_SERVER;
+        test_os_type = TRUE;
+        break;
+      default:
+        test_os_type = FALSE;
+        break;
+    }
+
+  if (test_os_type)
+    return VerifyVersionInfoW (&osverinfo,
+                               VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_PRODUCT_TYPE,
+                               gwin32condmask (conds, VER_PRODUCT_TYPE));
+  else
+    return VerifyVersionInfoW (&osverinfo,
+                               VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR,
+                               conds);
+}
+
+#undef gwin32condmask
+
 /**
  * g_win32_get_windows_version:
  *
+ * This function is deprecated. Use
+ * g_win32_check_windows_version() instead.
+ *
  * Returns version information for the Windows operating system the
  * code is running on. See MSDN documentation for the GetVersion()
  * function. To summarize, the most significant bit is one on Win9x,
@@ -530,8 +604,12 @@ g_win32_get_package_installation_subdirectory (const gchar *package,
  * GetVersionEx() and VerifyVersionInfo().
  *
  * Returns: The version information.
- * 
- * Since: 2.6
+ *
+ * Deprecated: 2.44: Be aware that for Windows 8.1 and Windows Server
+ * 2012 R2 and later, this will return 62 unless the application is
+ * manifested for Windows 8.1/Windows Server 2012 R2, for example.
+ * MSDN stated that GetVersion(), which is used here, is subject to
+ * further change or removal after Windows 8.1.
  **/
 guint
 g_win32_get_windows_version (void)
index c7575c4..f6e457d 100644 (file)
@@ -98,7 +98,7 @@ gchar*          g_win32_get_package_installation_subdirectory (const gchar *pack
 GLIB_AVAILABLE_IN_ALL
 gchar*          g_win32_get_package_installation_directory_of_module (gpointer hmodule);
 
-GLIB_AVAILABLE_IN_ALL
+GLIB_DEPRECATED_IN_2_44_FOR(g_win32_check_windows_version)
 guint          g_win32_get_windows_version (void);
 
 GLIB_AVAILABLE_IN_ALL
@@ -130,6 +130,30 @@ gchar *g_win32_get_package_installation_subdirectory_utf8 (const gchar *package,
                                                            const gchar *dll_name,
                                                            const gchar *subdir);
 
+/**
+ * GWin32OSType:
+ * @G_WIN32_OS_ANY: The running system can be a workstation or a server edition of
+ *  Windows.  The type of the running system is therefore not checked.
+ * @G_WIN32_OS_WORKSTATION: The running system is a workstation edition of Windows,
+ *  such as Windows 7 Professional.
+ * @G_WIN32_OS_SERVER: The running system is a server edition of Windows, such as
+ *  Windows Server 2008 R2.
+ *
+ * Type of Windows edition to check for at run-time.
+ **/
+typedef enum
+{
+  G_WIN32_OS_ANY,
+  G_WIN32_OS_WORKSTATION,
+  G_WIN32_OS_SERVER,
+} GWin32OSType;
+
+GLIB_AVAILABLE_IN_2_44
+gboolean g_win32_check_windows_version (const gint major,
+                                        const gint minor,
+                                        const gint spver,
+                                        const GWin32OSType os_type);
+
 #endif /* G_OS_WIN32 */
 #endif /* __GTK_DOC_IGNORE__ */