Skip to content

Commit

Permalink
Merge pull request java-native-access#1050 from dbwiddis/version-helper
Browse files Browse the repository at this point in the history
Add Windows Version Helper functions
  • Loading branch information
matthiasblaesing authored Jan 10, 2019
2 parents 216cb34 + 5611ae6 commit 9a1be16
Show file tree
Hide file tree
Showing 5 changed files with 393 additions and 1 deletion.
3 changes: 2 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ NOTE: as of JNA 4.0, JNA is now dual-licensed under LGPL and AL 2.0 (see LICENSE

NOTE: JNI native support is typically incompatible between minor versions, and almost always incompatible between major versions.

Next release (5.2.1)
Next release (5.3.0)
====================

Features
--------
* [#1050](https://github.com/java-native-access/jna/pull/1050): Add `c.s.j.p.win32.VersionHelpers` and supporting functions - [@dbwiddis](https://github.com/dbwiddis).

Bug Fixes
---------
Expand Down
67 changes: 67 additions & 0 deletions contrib/platform/src/com/sun/jna/platform/win32/Kernel32.java
Original file line number Diff line number Diff line change
Expand Up @@ -1413,6 +1413,73 @@ boolean CreateProcessW(String lpApplicationName, char[] lpCommandLine,
*/
boolean GetVersionEx(OSVERSIONINFOEX lpVersionInfo);

/**
* Compares a set of operating system version requirements to the
* corresponding values for the currently running version of the system.
* This function is subject to manifest-based behavior.
*
* @param lpVersionInformation
* A pointer to an {@link WinNT#OSVERSIONINFOEX} structure
* containing the operating system version requirements to
* compare. The {@code dwTypeMask} parameter indicates the
* members of this structure that contain information to compare.
* <p>
* You must set the {@code dwOSVersionInfoSize} member of this
* structure to {@code sizeof(OSVERSIONINFOEX)}. You must also
* specify valid data for the members indicated by
* {@code dwTypeMask}. The function ignores structure members for
* which the corresponding {@code dwTypeMask} bit is not set.
* @param dwTypeMask
* A mask that indicates the members of the
* {@link WinNT#OSVERSIONINFOEX} structure to be tested.
* @param dwlConditionMask
* The type of comparison to be used for each
* {@code lpVersionInfo} member being compared. To build this
* value, call the {@link #VerSetConditionMask} function once for
* each {@link WinNT#OSVERSIONINFOEX} member being compared.
* @return If the currently running operating system satisfies the specified
* requirements, the return value is a nonzero value.
* <p>
* If the current system does not satisfy the requirements, the
* return value is zero and {@link #GetLastError()} returns
* {@link WinError#ERROR_OLD_WIN_VERSION}.
* <p>
* If the function fails, the return value is zero and
* {@link #GetLastError()} returns an error code other than
* {@link WinError#ERROR_OLD_WIN_VERSION}.
*/
boolean VerifyVersionInfoW(OSVERSIONINFOEX lpVersionInformation, int dwTypeMask, long dwlConditionMask);

/**
* Sets the bits of a 64-bit value to indicate the comparison operator to
* use for a specified operating system version attribute. This function is
* used to build the {@code dwlConditionMask} parameter of the
* {@link #VerifyVersionInfo} function.
*
* @param conditionMask
* A value to be passed as the {@code dwlConditionMask} parameter
* of the {@link #VerifyVersionInfo} function. The function
* stores the comparison information in the bits of this
* variable.
* <p>
* Before the first call to {@link #VerSetConditionMask},
* initialize this variable to zero. For subsequent calls, pass
* in the variable used in the previous call.
* @param typeMask
* A mask that indicates the member of the
* {@link WinNT#OSVERSIONINFOEX} structure whose comparison
* operator is being set. This value corresponds to one of the
* bits specified in the {@code dwTypeMask} parameter for the
* {@link #VerifyVersionInfo} function.
* @param condition
* The operator to be used for the comparison. The
* {@link #VerifyVersionInfo} function uses this operator to
* compare a specified attribute value to the corresponding value
* for the currently running system.
* @return The function returns the condition mask value.
*/
long VerSetConditionMask(long conditionMask, int typeMask, byte condition);

/**
* The GetSystemInfo function returns information about the current system.
*
Expand Down
218 changes: 218 additions & 0 deletions contrib/platform/src/com/sun/jna/platform/win32/VersionHelpers.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
/* Copyright (c) 2019 Daniel Widdis, All Rights Reserved
*
* The contents of this file is dual-licensed under 2
* alternative Open Source/Free licenses: LGPL 2.1 or later and
* Apache License 2.0. (starting with JNA version 4.0.0).
*
* You can freely decide which license you want to apply to
* the project.
*
* You may obtain a copy of the LGPL License at:
*
* http://www.gnu.org/licenses/licenses.html
*
* A copy is also included in the downloadable source code package
* containing JNA, in file "LGPL2.1".
*
* You may obtain a copy of the Apache License at:
*
* http://www.apache.org/licenses/
*
* A copy is also included in the downloadable source code package
* containing JNA, in file "AL2.0".
*/
package com.sun.jna.platform.win32;

import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.platform.win32.WinDef.WORD;
import com.sun.jna.platform.win32.WinNT.OSVERSIONINFOEX;

/**
* The following functions can be used to determine the current operating system
* version or identify whether it is a Windows or Windows Server release. These
* functions provide simple tests that use the VerifyVersionInfo function and
* the recommended greater than or equal to comparisons that are proven as a
* robust means to determine the operating system version.
*/
public class VersionHelpers {
/*
* Code in this class is an attempt to faithfully port the inline macros in
* the versionhelpers.h header file of the Windows 10 SDK.
*/

/**
* This function is useful in confirming a version of Windows Server that
* doesn't share a version number with a client release. You should only use
* this function if the other provided version helper functions do not fit
* your scenario.
*
* @param wMajorVersion
* The major version to test
* @param wMinorVersion
* The minor version to test
* @param wServicePackMajor
* The service pack to test
* @return True if the current OS version matches, or is greater than, the
* provided version information.
*/
public static boolean IsWindowsVersionOrGreater(int wMajorVersion, int wMinorVersion, int wServicePackMajor) {
OSVERSIONINFOEX osvi = new OSVERSIONINFOEX();
osvi.dwOSVersionInfoSize = new DWORD(osvi.size());
osvi.dwMajorVersion = new DWORD(wMajorVersion);
osvi.dwMinorVersion = new DWORD(wMinorVersion);
osvi.wServicePackMajor = new WORD(wServicePackMajor);

long dwlConditionMask = 0;
dwlConditionMask = Kernel32.INSTANCE.VerSetConditionMask(dwlConditionMask, WinNT.VER_MAJORVERSION,
(byte) WinNT.VER_GREATER_EQUAL);
dwlConditionMask = Kernel32.INSTANCE.VerSetConditionMask(dwlConditionMask, WinNT.VER_MINORVERSION,
(byte) WinNT.VER_GREATER_EQUAL);
dwlConditionMask = Kernel32.INSTANCE.VerSetConditionMask(dwlConditionMask, WinNT.VER_SERVICEPACKMAJOR,
(byte) WinNT.VER_GREATER_EQUAL);

return Kernel32.INSTANCE.VerifyVersionInfoW(osvi,
WinNT.VER_MAJORVERSION | WinNT.VER_MINORVERSION | WinNT.VER_SERVICEPACKMAJOR, dwlConditionMask);
}

/*
* The constants Kernel32.WIN32_WINNT_* are 2-byte encodings of windows
* version numbers, for example Windows XP is version 5.1 and is encoded as
* 0x0501. To pass to IsWindowsVersionOrGreater, we pass the HIBYTE (e.g.,
* 0x05) as the first argument and LOBYTE (e.g., 0x01) as the second. To get
* the high byte of a short, we shift right 8 bits and cast to byte, e.g.,
* (byte) (word>>>8); to get the low byte wse simply cast to byte.
*/

/**
* @return true if the current OS version matches, or is greater than, the
* Windows XP version.
*/
public static boolean IsWindowsXPOrGreater() {
return IsWindowsVersionOrGreater((byte) (Kernel32.WIN32_WINNT_WINXP >>> 8), (byte) Kernel32.WIN32_WINNT_WINXP,
0);
}

/**
* @return true if the current OS version matches, or is greater than, the
* Windows XP with Service Pack 1 (SP1) version.
*/
public static boolean IsWindowsXPSP1OrGreater() {
return IsWindowsVersionOrGreater((byte) (Kernel32.WIN32_WINNT_WINXP >>> 8), (byte) Kernel32.WIN32_WINNT_WINXP,
1);
}

/**
* @return true if the current OS version matches, or is greater than, the
* Windows XP with Service Pack 2 (SP2) version.
*/
public static boolean IsWindowsXPSP2OrGreater() {
return IsWindowsVersionOrGreater((byte) (Kernel32.WIN32_WINNT_WINXP >>> 8), (byte) Kernel32.WIN32_WINNT_WINXP,
2);
}

/**
* @return true if the current OS version matches, or is greater than, the
* Windows XP with Service Pack 3 (SP3) version.
*/
public static boolean IsWindowsXPSP3OrGreater() {
return IsWindowsVersionOrGreater((byte) (Kernel32.WIN32_WINNT_WINXP >>> 8), (byte) Kernel32.WIN32_WINNT_WINXP,
3);
}

/**
* @return true if the current OS version matches, or is greater than, the
* Windows Vista version.
*/
public static boolean IsWindowsVistaOrGreater() {
return IsWindowsVersionOrGreater((byte) (Kernel32.WIN32_WINNT_VISTA >>> 8), (byte) Kernel32.WIN32_WINNT_VISTA,
0);
}

/**
* @return true if the current OS version matches, or is greater than, the
* Windows Vista with Service Pack 1 (SP1) version.
*/
public static boolean IsWindowsVistaSP1OrGreater() {
return IsWindowsVersionOrGreater((byte) (Kernel32.WIN32_WINNT_VISTA >>> 8), (byte) Kernel32.WIN32_WINNT_VISTA,
1);
}

/**
* @return true if the current OS version matches, or is greater than, the
* Windows Vista with Service Pack 2 (SP2) version.
*/
public static boolean IsWindowsVistaSP2OrGreater() {
return IsWindowsVersionOrGreater((byte) (Kernel32.WIN32_WINNT_VISTA >>> 8), (byte) Kernel32.WIN32_WINNT_VISTA,
2);
}

/**
* @return true if the current OS version matches, or is greater than, the
* Windows 7 version.
*/
public static boolean IsWindows7OrGreater() {
return IsWindowsVersionOrGreater((byte) (Kernel32.WIN32_WINNT_WIN7 >>> 8), (byte) Kernel32.WIN32_WINNT_WIN7, 0);
}

/**
* @return true if the current OS version matches, or is greater than, the
* Windows 7 with Service Pack 1 (SP1) version.
*/
public static boolean IsWindows7SP1OrGreater() {
return IsWindowsVersionOrGreater((byte) (Kernel32.WIN32_WINNT_WIN7 >>> 8), (byte) Kernel32.WIN32_WINNT_WIN7, 1);
}

/**
* @return true if the current OS version matches, or is greater than, the
* Windows 8 version.
*/
public static boolean IsWindows8OrGreater() {
return IsWindowsVersionOrGreater((byte) (Kernel32.WIN32_WINNT_WIN8 >>> 8), (byte) Kernel32.WIN32_WINNT_WIN8, 0);
}

/**
* @return true if the current OS version matches, or is greater than, the
* Windows 8.1 version. For Windows 8.1 and/or Windows 10,
* {@link #IsWindows8Point1OrGreater} returns false unless the
* application contains a manifest that includes a compatibility
* section that contains the GUIDs that designate Windows 8.1 and/or
* Windows 10.
*/
public static boolean IsWindows8Point1OrGreater() {
return IsWindowsVersionOrGreater((byte) (Kernel32.WIN32_WINNT_WINBLUE >>> 8),
(byte) Kernel32.WIN32_WINNT_WINBLUE, 0);
}

/**
* @return true if the current OS version matches, or is greater than, the
* Windows 10 version. For Windows 10,
* {@link #IsWindows8Point1OrGreater} returns false unless the
* application contains a manifest that includes a compatibility
* section that contains the GUID that designates Windows 10.
*/
public static boolean IsWindows10OrGreater() {
return IsWindowsVersionOrGreater((byte) (Kernel32.WIN32_WINNT_WIN10 >>> 8), (byte) Kernel32.WIN32_WINNT_WIN10,
0);
}

/**
* Applications that need to distinguish between server and client versions
* of Windows should call this function.
*
* @return true if the current OS is a Windows Server release.
*/
public static boolean IsWindowsServer() {
// This should properly be OSVERSIONINFOEXW which is not defined in JNA.
// The OSVERSIONINFOEX structure in JNA is the (W) Unicode-compliant
// version.
OSVERSIONINFOEX osvi = new OSVERSIONINFOEX();
osvi.dwOSVersionInfoSize = new DWORD(osvi.size());
osvi.wProductType = WinNT.VER_NT_WORKSTATION;

long dwlConditionMask = Kernel32.INSTANCE.VerSetConditionMask(0, WinNT.VER_PRODUCT_TYPE,
(byte) WinNT.VER_EQUAL);

return !Kernel32.INSTANCE.VerifyVersionInfoW(osvi, WinNT.VER_PRODUCT_TYPE, dwlConditionMask);
}
}

17 changes: 17 additions & 0 deletions contrib/platform/src/com/sun/jna/platform/win32/WinNT.java
Original file line number Diff line number Diff line change
Expand Up @@ -2016,6 +2016,23 @@ public byte getProductType() {
int VER_PLATFORM_WIN32_WINDOWS = 1;
int VER_PLATFORM_WIN32_NT = 2;

/*
* WIN32_WINNT version constants
*/
short WIN32_WINNT_NT4 = 0x0400; // Windows NT 4.0
short WIN32_WINNT_WIN2K = 0x0500; // Windows 2000
short WIN32_WINNT_WINXP = 0x0501; // Windows XP
short WIN32_WINNT_WS03 = 0x0502; // Windows Server 2003
short WIN32_WINNT_WIN6 = 0x0600; // Windows Vista
short WIN32_WINNT_VISTA = 0x0600; // Windows Vista
short WIN32_WINNT_WS08 = 0x0600; // Windows Server 2008
short WIN32_WINNT_LONGHORN = 0x0600; // Windows Vista
short WIN32_WINNT_WIN7 = 0x0601; // Windows 7
short WIN32_WINNT_WIN8 = 0x0602; // Windows 8
short WIN32_WINNT_WINBLUE = 0x0603; // Windows 8.1
short WIN32_WINNT_WINTHRESHOLD = 0x0A00; // Windows 10
short WIN32_WINNT_WIN10 = 0x0A00; // Windows 10

/**
* Read the records sequentially. If this is the first read operation, the
* EVENTLOG_FORWARDS_READ EVENTLOG_BACKWARDS_READ flags determines which
Expand Down
Loading

0 comments on commit 9a1be16

Please sign in to comment.