-
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 2 commits
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,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); | ||
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 |
||
|
||
/** | ||
* 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. | ||
* | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,202 @@ | ||
/* 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, | ||
(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); | ||
} | ||
|
||
/** | ||
* @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((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() { | ||
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); | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package com.sun.jna.platform.win32; | ||
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 missed this in the first round - could you please also the ALv2+LGPL header here? I'd like to converge on that. 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. Sure, will do! I just copied some other random test file that was missing a header so didn't know if that was standard. |
||
|
||
import static org.junit.Assert.assertFalse; | ||
import static org.junit.Assert.assertTrue; | ||
|
||
import org.junit.Test; | ||
|
||
public class VersionHelpersTest { | ||
@Test | ||
public void testVersionHelpers() { | ||
// All windows versions should be higher than version 0.0! | ||
assertTrue(VersionHelpers.IsWindowsVersionOrGreater(0, 0, 0)); | ||
// All windows versions should be lower than version Short.MAX_VALUE! | ||
assertFalse(VersionHelpers.IsWindowsVersionOrGreater(Short.MAX_VALUE, Short.MAX_VALUE, Short.MAX_VALUE)); | ||
// These tests in order should be true until false; once false never | ||
// true again | ||
boolean lastVersionTest = true; | ||
boolean versionTest = VersionHelpers.IsWindowsXPOrGreater(); | ||
assertTrue((lastVersionTest == versionTest) || !versionTest); | ||
|
||
lastVersionTest = versionTest; | ||
versionTest = VersionHelpers.IsWindowsXPSP1OrGreater(); | ||
assertTrue((lastVersionTest == versionTest) || !versionTest); | ||
|
||
lastVersionTest = versionTest; | ||
versionTest = VersionHelpers.IsWindowsXPSP2OrGreater(); | ||
assertTrue((lastVersionTest == versionTest) || !versionTest); | ||
|
||
lastVersionTest = versionTest; | ||
versionTest = VersionHelpers.IsWindowsXPSP3OrGreater(); | ||
assertTrue((lastVersionTest == versionTest) || !versionTest); | ||
|
||
lastVersionTest = versionTest; | ||
versionTest = VersionHelpers.IsWindowsVistaOrGreater(); | ||
assertTrue((lastVersionTest == versionTest) || !versionTest); | ||
|
||
lastVersionTest = versionTest; | ||
versionTest = VersionHelpers.IsWindowsVistaSP1OrGreater(); | ||
assertTrue((lastVersionTest == versionTest) || !versionTest); | ||
|
||
lastVersionTest = versionTest; | ||
versionTest = VersionHelpers.IsWindowsVistaSP2OrGreater(); | ||
assertTrue((lastVersionTest == versionTest) || !versionTest); | ||
|
||
lastVersionTest = versionTest; | ||
versionTest = VersionHelpers.IsWindows7OrGreater(); | ||
assertTrue((lastVersionTest == versionTest) || !versionTest); | ||
|
||
lastVersionTest = versionTest; | ||
versionTest = VersionHelpers.IsWindows7SP1OrGreater(); | ||
assertTrue((lastVersionTest == versionTest) || !versionTest); | ||
|
||
lastVersionTest = versionTest; | ||
versionTest = VersionHelpers.IsWindows8OrGreater(); | ||
assertTrue((lastVersionTest == versionTest) || !versionTest); | ||
|
||
lastVersionTest = versionTest; | ||
versionTest = VersionHelpers.IsWindows8Point1OrGreater(); | ||
assertTrue((lastVersionTest == versionTest) || !versionTest); | ||
|
||
lastVersionTest = versionTest; | ||
versionTest = VersionHelpers.IsWindows10OrGreater(); | ||
assertTrue((lastVersionTest == versionTest) || !versionTest); | ||
} | ||
} | ||
|
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. :)