-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Windows Version Helper functions #1050
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1413,6 +1413,71 @@ boolean CreateProcessW(String lpApplicationName, char[] lpCommandLine, | |
*/ | ||
boolean GetVersionEx(OSVERSIONINFOEX lpVersionInfo); | ||
|
||
/** | ||
* The VerifyVersionInfoW function 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 OSVERSIONINFOEX structure containing the | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
* operating system version requirements to compare. The | ||
* dwTypeMask parameter indicates the members of this structure | ||
* that contain information to compare. | ||
* | ||
* You must set the dwOSVersionInfoSize member of this structure | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you need to add p-tags to get the paragraph formatted (javadoc is HTML). The newlines are removed when rendered to HTML. |
||
* to sizeof(OSVERSIONINFOEX). You must also specify valid data | ||
* for the members indicated by dwTypeMask. The function ignores | ||
* structure members for which the corresponding dwTypeMask bit | ||
* is not set. | ||
* @param dwTypeMask | ||
* A mask that indicates the members of the OSVERSIONINFOEX | ||
* structure to be tested. | ||
* @param dwlConditionMask | ||
* The type of comparison to be used for each lpVersionInfo | ||
* member being compared. To build this value, call the | ||
* VerSetConditionMask function once for each OSVERSIONINFOEX | ||
* member being compared. | ||
* @return If the currently running operating system satisfies the specified | ||
* requirements, the return value is a nonzero value. | ||
* | ||
* If the current system does not satisfy the requirements, the | ||
* return value is zero and GetLastError returns | ||
* ERROR_OLD_WIN_VERSION. | ||
* | ||
* If the function fails, the return value is zero and GetLastError | ||
* returns an error code other than ERROR_OLD_WIN_VERSION. | ||
*/ | ||
boolean VerifyVersionInfoW(OSVERSIONINFOEX lpVersionInformation, int dwTypeMask, long dwlConditionMask); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I tried There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Er, now I see what you mean. This method should properly use I had to go look at There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So I'm thinking about the correct way to handle this. One thought was to copy the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do not see a good option to fix this without breaking API, so at this point in time, I think binding it as |
||
|
||
/** | ||
* The VerSetConditionMask function 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 dwlConditionMask | ||
* parameter of the VerifyVersionInfo function. | ||
* | ||
* @param conditionMask | ||
* A value to be passed as the dwlConditionMask parameter of the | ||
* VerifyVersionInfo function. The function stores the comparison | ||
* information in the bits of this variable. | ||
* | ||
* Before the first call to VerSetCondition, 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 OSVERSIONINFOEX | ||
* structure whose comparison operator is being set. This value | ||
* corresponds to one of the bits specified in the dwTypeMask | ||
* parameter for the VerifyVersionInfo function. | ||
* @param condition | ||
* The operator to be used for the comparison. The | ||
* 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. | ||
* | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,213 @@ | ||
/* 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 { | ||
|
||
/** | ||
* 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, | ||
WinNT.VER_GREATER_EQUAL); | ||
dwlConditionMask = Kernel32.INSTANCE.VerSetConditionMask(dwlConditionMask, WinNT.VER_MINORVERSION, | ||
WinNT.VER_GREATER_EQUAL); | ||
dwlConditionMask = Kernel32.INSTANCE.VerSetConditionMask(dwlConditionMask, WinNT.VER_SERVICEPACKMAJOR, | ||
WinNT.VER_GREATER_EQUAL); | ||
|
||
return Kernel32.INSTANCE.VerifyVersionInfoW(osvi, | ||
WinNT.VER_MAJORVERSION | WinNT.VER_MINORVERSION | WinNT.VER_SERVICEPACKMAJOR, dwlConditionMask); | ||
} | ||
|
||
/** | ||
* @return true if the current OS version matches, or is greater than, the | ||
* Windows XP version. | ||
*/ | ||
public static boolean IsWindowsXPOrGreater() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure whether I like this, but I don't see a saner version, that doesn't look like repeats... What might be worth evaluation is, if pulling There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did try to faithfully reproduce the existing inline header file, in the interest of readability. I think adding variables would be worse than just explicitly doing the math ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry! I did not realize, that I had looked at an older SDK, that did not contain the header. And I just realized, that you linked the header. Your first version was better readable. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So you want me to go back to the HIBYTE and LOBYTE methods (that would be JIT optimized) rather than the current compiler-optimized bit math? I kind of like the current version and think adding a comment would make it just as readable/understandable for future maintainers. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My thinking was, that at this time I understand what you are doing there. But in 6-12 months I might have a WTF moment. I'm ok if you want to keep the bit shifts inline. Independend of this - my original idea was this: private static final byte WIN32_WINNT_WINXP_MAJOR = HIBYTE(WinNT.WIN32_WINNT_WINXP);
private static final byte WIN32_WINNT_WINXP_MINOR = LOBYTE(WinNT.WIN32_WINNT_WINXP);
/**
* @return true if the current OS version matches, or is greater than, the
* Windows XP version.
*/
public static boolean IsWindowsXPOrGreater() {
return IsWindowsVersionOrGreater(WIN32_WINNT_WINXP_MAJOR, WIN32_WINNT_WINXP_MINOR, 0);
} Pulling the calculation into a static final. But as said, if you like it this way, I won't stand in the way. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll add a comment explaining what the bit shifts do, so you and I both can remember what's going on in 6-12 months. |
||
return IsWindowsVersionOrGreater(HIBYTE(WinNT.WIN32_WINNT_WINXP), LOBYTE(WinNT.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(HIBYTE(WinNT.WIN32_WINNT_WINXP), LOBYTE(WinNT.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(HIBYTE(WinNT.WIN32_WINNT_WINXP), LOBYTE(WinNT.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(HIBYTE(WinNT.WIN32_WINNT_WINXP), LOBYTE(WinNT.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(HIBYTE(WinNT.WIN32_WINNT_VISTA), LOBYTE(WinNT.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(HIBYTE(WinNT.WIN32_WINNT_VISTA), LOBYTE(WinNT.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(HIBYTE(WinNT.WIN32_WINNT_VISTA), LOBYTE(WinNT.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(HIBYTE(WinNT.WIN32_WINNT_WIN7), LOBYTE(WinNT.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(HIBYTE(WinNT.WIN32_WINNT_WIN7), LOBYTE(WinNT.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(HIBYTE(WinNT.WIN32_WINNT_WIN8), LOBYTE(WinNT.WIN32_WINNT_WIN8), 0); | ||
} | ||
|
||
/** | ||
* @return true if the current OS version matches, or is greater than, the | ||
* Windows 8.1 version. For Windows 10, 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(HIBYTE(WinNT.WIN32_WINNT_WINBLUE), LOBYTE(WinNT.WIN32_WINNT_WINBLUE), 0); | ||
} | ||
|
||
/** | ||
* @return true if the current OS version matches, or is greater than, the | ||
* Windows 10 version. For Windows 10, IsWindows10OrGreater 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(HIBYTE(WinNT.WIN32_WINNT_WIN10), LOBYTE(WinNT.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() { | ||
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, WinNT.VER_EQUAL); | ||
|
||
return !Kernel32.INSTANCE.VerifyVersionInfoW(osvi, WinNT.VER_PRODUCT_TYPE, dwlConditionMask); | ||
} | ||
|
||
/** | ||
* Get the high byte | ||
* | ||
* @param word | ||
* a two-byte value | ||
* @return The most significant byte | ||
*/ | ||
private static byte HIBYTE(short word) { | ||
return (byte) ((word >> 8) & 0xFF); | ||
} | ||
|
||
/** | ||
* Get the low byte | ||
* | ||
* @param word | ||
* a two-byte value | ||
* @return The least significant byte | ||
*/ | ||
private static byte LOBYTE(short word) { | ||
return (byte) word; | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1988,13 +1988,13 @@ public byte getProductType() { | |
} | ||
} | ||
|
||
int VER_EQUAL = 1; | ||
int VER_GREATER = 2; | ||
int VER_GREATER_EQUAL = 3; | ||
int VER_LESS = 4; | ||
int VER_LESS_EQUAL = 5; | ||
int VER_AND = 6; | ||
int VER_OR = 7; | ||
byte VER_EQUAL = 1; | ||
byte VER_GREATER = 2; | ||
byte VER_GREATER_EQUAL = 3; | ||
byte VER_LESS = 4; | ||
byte VER_LESS_EQUAL = 5; | ||
byte VER_AND = 6; | ||
byte VER_OR = 7; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this a source/binary compatible change (will code compiled against 5.2 still work with 5.3 (or vice-versa)? I see why you do it, but if if is not compatible, please stay with int. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I searched the JNA codebase and don't see anywhere else where these constants are referenced. External code using JNA 5.2 or earlier may use these as Given that byte-to-int happens transparently to the user, but int-to-byte requires an explicit cast, I do not think this breaks compatibility and There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well apparently it's not backwards compatible, which surprises me! But I'll put it back to |
||
|
||
int VER_CONDITION_MASK = 7; | ||
int VER_NUM_BITS_PER_CONDITION_MASK = 3; | ||
|
@@ -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 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please update the version behind "Next release" to "5.3.0", as it will be a feature release with this change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thought so and somewhat expected this comment. :)