-
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
Add Windows Version Helper functions #1050
Conversation
9849f56
to
54d9c51
Compare
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.
I left a few comments inline. Thank you.
* 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 comment
The reason will be displayed to describe this comment to others. Learn more.
This should be VerifyVersionInfo
-- but that would not work, because OSVERSIONINFOEX is only correctly bound for unicode?! Crap...
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.
I tried VerifyVersionInfo
but got UnsatisfiedLinkError: Error looking up function 'VerifyVersionInfo'
. Both the W and A variants worked individually in this case because we're only using the numeric portions of OSVERSIONINFOEX
. The inline functions in the header file use the W version, so that's the one I implemented. Should I add the A version as well?
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.
Er, now I see what you mean. This method should properly use OSVERSIONINFOEXW
which is not defined (but the OSVERSIONINFOEX
defined is the W
version.)
I had to go look at git blame
to make sure I wasn't at fault there.
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.
So I'm thinking about the correct way to handle this. One thought was to copy the OSVERSIONINFOEX
structure to OSVERSIONINFOEXW
(have one extend the other) and mark the non-W version as deprecated. But there are many other functions which also call it, so we'd have to change all of them as well. Even though per the Windows documentation, all these old functions are also deprecated in favor of the Version Helper functions, which currently still refer to this structure... and around in circles we go.
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.
I do not see a good option to fix this without breaking API, so at this point in time, I think binding it as VerifyVersionInfoW
is a good solution.
* 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 comment
The 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.
* behavior. | ||
* | ||
* @param lpVersionInformation | ||
* A pointer to an OSVERSIONINFOEX structure containing the |
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.
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 comment
The 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 comment
The 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 int
, but a byte
will work anywhere an int
is expected with a widening conversion transparent to the user. The alternative is to require users to explicitly cast these all to byte
to use them with VerSetConditionMask
(and potentially other functions).
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 byte
is preferred here.
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.
Well apparently it's not backwards compatible, which surprises me! But I'll put it back to int
and then cast.
* @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 comment
The 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 HIBYTE(WinNT.WIN32_WINNT_WINXP)
and LOBYTE(WinNT.WIN32_WINNT_WINXP)
into private static final variables might be worth it.
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.
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 ((byte) (word >>>8)
) and (byte) word
inline, which would be pre-calculated and optimized by the compiler. (I expect the JIT optimizer would also eventually optimize the method calls as well if they were called frequently enough.)
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.
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 comment
The 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 comment
The 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 comment
The 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.
@@ -7,6 +7,7 @@ Next release (5.2.1) | |||
|
|||
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). |
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. :)
@@ -0,0 +1,66 @@ | |||
package com.sun.jna.platform.win32; |
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.
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 comment
The 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.
Thank you - merging. |
See reference docs. Code directly adapted from header file here.