1
+ package mediathek .windows ;
2
+
3
+ import java .lang .foreign .*;
4
+
5
+ public class WindowsVersionHelper {
6
+
7
+ // Constants for VerSetConditionMask dwTypeBitMask parameter
8
+ private static final int VER_MINORVERSION = 0x0000001 ;
9
+ private static final int VER_MAJORVERSION = 0x0000002 ;
10
+ private static final int VER_SERVICEPACKMAJOR = 0x0000020 ;
11
+
12
+ // Constants for VerSetConditionMask dwCondition parameter
13
+ private static final byte VER_GREATER_EQUAL = 3 ;
14
+
15
+ private static final GroupLayout OSVERSIONINFOEXW_LAYOUT = MemoryLayout .structLayout (
16
+ ValueLayout .JAVA_INT .withName ("dwOSVersionInfoSize" ),
17
+ ValueLayout .JAVA_INT .withName ("dwMajorVersion" ),
18
+ ValueLayout .JAVA_INT .withName ("dwMinorVersion" ),
19
+ ValueLayout .JAVA_INT .withName ("dwBuildNumber" ),
20
+ ValueLayout .JAVA_INT .withName ("dwPlatformId" ),
21
+ MemoryLayout .sequenceLayout (128 , ValueLayout .JAVA_CHAR ).withName ("szCSDVersion" ),
22
+ ValueLayout .JAVA_SHORT .withName ("wServicePackMajor" ),
23
+ ValueLayout .JAVA_SHORT .withName ("wServicePackMinor" ),
24
+ ValueLayout .JAVA_SHORT .withName ("wSuiteMask" ),
25
+ ValueLayout .JAVA_BYTE .withName ("wProductType" ),
26
+ ValueLayout .JAVA_BYTE .withName ("wReserved" )
27
+ ).withName ("OSVERSIONINFOEXW" );
28
+
29
+ private static final long OSVERSIONINFOEXW_STRUCT_SIZE = OSVERSIONINFOEXW_LAYOUT .byteSize ();
30
+
31
+
32
+ public static boolean IsWindows10OrGreater () throws Throwable {
33
+ return isWindowsVersionOrGreater (10 ,0 ,0 );
34
+ }
35
+
36
+ public static boolean isWindowsVersionOrGreater (int major , int minor , int servicePackMajor ) throws Throwable {
37
+ try (Arena arena = Arena .ofConfined ()) {
38
+ SymbolLookup kernel32 = SymbolLookup .libraryLookup ("kernel32.dll" , Arena .global ());
39
+
40
+ var NATIVE_LINKER = Linker .nativeLinker ();
41
+ var MH_VerSetConditionMask = NATIVE_LINKER .downcallHandle (
42
+ kernel32 .find ("VerSetConditionMask" ).orElseThrow (() -> new UnsatisfiedLinkError ("VerSetConditionMask not found" )),
43
+ FunctionDescriptor .of (ValueLayout .JAVA_LONG , ValueLayout .JAVA_LONG , ValueLayout .JAVA_INT , ValueLayout .JAVA_BYTE )
44
+ );
45
+
46
+ var MH_VerifyVersionInfoW = NATIVE_LINKER .downcallHandle (
47
+ kernel32 .find ("VerifyVersionInfoW" ).orElseThrow (() -> new UnsatisfiedLinkError ("VerifyVersionInfoW not found" )),
48
+ FunctionDescriptor .of (ValueLayout .JAVA_INT , ValueLayout .ADDRESS , ValueLayout .JAVA_INT , ValueLayout .JAVA_LONG )
49
+ );
50
+ MemorySegment osvi = arena .allocate (OSVERSIONINFOEXW_LAYOUT );
51
+
52
+ var VH_dwOSVersionInfoSize = OSVERSIONINFOEXW_LAYOUT .varHandle (MemoryLayout .PathElement .groupElement ("dwOSVersionInfoSize" ));
53
+ var VH_dwMajorVersion = OSVERSIONINFOEXW_LAYOUT .varHandle (MemoryLayout .PathElement .groupElement ("dwMajorVersion" ));
54
+ var VH_dwMinorVersion = OSVERSIONINFOEXW_LAYOUT .varHandle (MemoryLayout .PathElement .groupElement ("dwMinorVersion" ));
55
+ var VH_wServicePackMajor = OSVERSIONINFOEXW_LAYOUT .varHandle (MemoryLayout .PathElement .groupElement ("wServicePackMajor" ));
56
+
57
+ VH_dwOSVersionInfoSize .set (osvi , 0L , (int ) OSVERSIONINFOEXW_STRUCT_SIZE );
58
+ VH_dwMajorVersion .set (osvi , 0L , major );
59
+ VH_dwMinorVersion .set (osvi , 0L , minor );
60
+ VH_wServicePackMajor .set (osvi , 0L , (short ) servicePackMajor );
61
+
62
+ long conditionMask = 0L ;
63
+ conditionMask = (long ) MH_VerSetConditionMask .invokeExact (conditionMask , VER_MAJORVERSION , VER_GREATER_EQUAL );
64
+ conditionMask = (long ) MH_VerSetConditionMask .invokeExact (conditionMask , VER_MINORVERSION , VER_GREATER_EQUAL );
65
+ conditionMask = (long ) MH_VerSetConditionMask .invokeExact (conditionMask , VER_SERVICEPACKMAJOR , VER_GREATER_EQUAL );
66
+
67
+ int typeMask = VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR ;
68
+
69
+ int result = (int ) MH_VerifyVersionInfoW .invokeExact (osvi , typeMask , conditionMask );
70
+
71
+ return result != 0 ;
72
+ }
73
+ }
74
+
75
+ public static void main (String [] args ) {
76
+ if (!System .getProperty ("os.name" ).toLowerCase ().contains ("win" )) {
77
+ System .out .println ("This version check is designed for Windows OS." );
78
+ return ;
79
+ }
80
+
81
+ try {
82
+ var v = new WindowsVersionHelper ();
83
+ boolean isWin10OrGreater = v .isWindowsVersionOrGreater (10 , 0 , 0 );
84
+ System .out .println ("Is current OS Windows 10.0 SP0 or greater? " + isWin10OrGreater );
85
+
86
+ boolean isWin7OrGreater = v .isWindowsVersionOrGreater (6 , 1 , 0 );
87
+ System .out .println ("Is current OS Windows 7 (6.1 SP0) or greater? " + isWin7OrGreater );
88
+
89
+ boolean isFutureVersion = v .isWindowsVersionOrGreater (99 , 0 , 0 );
90
+ System .out .println ("Is current OS Windows 99.0 SP0 or greater? " + isFutureVersion );
91
+
92
+ } catch (Throwable t ) {
93
+ System .err .println ("An error occurred during the Windows version check:" );
94
+ t .printStackTrace ();
95
+ }
96
+ }
97
+ }
0 commit comments