2020import org .jackhuang .hmcl .util .KeyValuePairUtils ;
2121import org .jackhuang .hmcl .util .platform .windows .Kernel32 ;
2222import org .jackhuang .hmcl .util .platform .windows .WinTypes ;
23+ import org .jackhuang .hmcl .util .platform .windows .WindowsVersion ;
24+ import org .jetbrains .annotations .Nullable ;
2325
2426import java .io .BufferedReader ;
2527import java .io .IOException ;
@@ -106,6 +108,11 @@ public String getJavaExecutable() {
106108 */
107109 public static final int SYSTEM_BUILD_NUMBER ;
108110
111+ /**
112+ * The version number is non-null if and only if the operating system is {@linkplain #WINDOWS}.
113+ */
114+ public static final @ Nullable WindowsVersion WINDOWS_VERSION ;
115+
109116 /**
110117 * The name of current operating system.
111118 */
@@ -125,8 +132,6 @@ public String getJavaExecutable() {
125132 private static final String [] INVALID_RESOURCE_BASENAMES ;
126133 private static final String [] INVALID_RESOURCE_FULLNAMES ;
127134
128- private static final boolean IS_WINDOWS_7_OR_LATER ;
129-
130135 static {
131136 String nativeEncoding = System .getProperty ("native.encoding" );
132137 String hmclNativeEncoding = System .getProperty ("hmcl.native.encoding" );
@@ -152,61 +157,35 @@ public String getJavaExecutable() {
152157 NATIVE_CHARSET = nativeCharset ;
153158
154159 if (CURRENT_OS == WINDOWS ) {
155- String versionNumber = null ;
156- int buildNumber = -1 ;
157160 int codePage = -1 ;
161+ WindowsVersion windowsVersion = null ;
158162
159163 Kernel32 kernel32 = Kernel32 .INSTANCE ;
160-
161164 // Get Windows version number
162165 if (kernel32 != null ) {
163166 WinTypes .OSVERSIONINFOEXW osVersionInfo = new WinTypes .OSVERSIONINFOEXW ();
164167 if (kernel32 .GetVersionExW (osVersionInfo )) {
165- int majorVersion = osVersionInfo .dwMajorVersion ;
166- int minorVersion = osVersionInfo .dwMinorVersion ;
167-
168- buildNumber = osVersionInfo .dwBuildNumber ;
169- versionNumber = majorVersion + "." + minorVersion + "." + buildNumber ;
168+ windowsVersion = new WindowsVersion (osVersionInfo .dwMajorVersion , osVersionInfo .dwMinorVersion , osVersionInfo .dwBuildNumber );
170169 } else
171170 System .err .println ("Failed to obtain OS version number (" + kernel32 .GetLastError () + ")" );
172171 }
173172
174- if (versionNumber == null ) {
173+ if (windowsVersion == null ) {
175174 try {
176175 Process process = Runtime .getRuntime ().exec (new String []{"cmd" , "ver" });
177176 try (BufferedReader reader = new BufferedReader (new InputStreamReader (process .getInputStream (), NATIVE_CHARSET ))) {
178- Matcher matcher = Pattern .compile ("(?<version>[0-9] +\\ .[0-9] +\\ .(?<build>[0-9]+)( \\ .[0-9]+) ?)]$" )
177+ Matcher matcher = Pattern .compile ("(?<version>\\ d +\\ .\\ d +\\ .\\ d+ \\ .\\ d+ ?)]$" )
179178 .matcher (reader .readLine ().trim ());
180-
181- if (matcher .find ()) {
182- versionNumber = matcher .group ("version" );
183- buildNumber = Integer .parseInt (matcher .group ("build" ));
184- }
179+ if (matcher .find ())
180+ windowsVersion = new WindowsVersion (matcher .group ("version" ));
185181 }
186182 process .destroy ();
187183 } catch (Throwable ignored ) {
188184 }
189185 }
190186
191- if (versionNumber == null )
192- versionNumber = System .getProperty ("os.version" );
193-
194- int major ;
195- int dotIndex = versionNumber .indexOf ('.' );
196- try {
197- if (dotIndex < 0 )
198- major = Integer .parseInt (versionNumber );
199- else
200- major = Integer .parseInt (versionNumber .substring (0 , dotIndex ));
201- } catch (NumberFormatException ignored ) {
202- major = -1 ;
203- }
204-
205- // Windows XP: NT 5.1~5.2
206- // Windows Vista: NT 6.0
207- // Windows 7: NT 6.1
208-
209- IS_WINDOWS_7_OR_LATER = major >= 6 && !versionNumber .startsWith ("6.0" );
187+ if (windowsVersion == null )
188+ windowsVersion = new WindowsVersion (System .getProperty ("os.version" ));
210189
211190 // Get Code Page
212191
@@ -219,9 +198,8 @@ public String getJavaExecutable() {
219198 Matcher matcher = Pattern .compile ("(?<cp>[0-9]+)$" )
220199 .matcher (reader .readLine ().trim ());
221200
222- if (matcher .find ()) {
201+ if (matcher .find ())
223202 codePage = Integer .parseInt (matcher .group ("cp" ));
224- }
225203 }
226204 process .destroy ();
227205 } catch (Throwable ignored ) {
@@ -231,19 +209,20 @@ public String getJavaExecutable() {
231209 String osName = System .getProperty ("os.name" );
232210
233211 // Java 17 or earlier recognizes Windows 11 as Windows 10
234- if (osName .equals ("Windows 10" ) && buildNumber >= 22000 )
212+ if (osName .equals ("Windows 10" ) && windowsVersion . compareTo ( WindowsVersion . WINDOWS_11 ) >= 0 )
235213 osName = "Windows 11" ;
236214
237215 SYSTEM_NAME = osName ;
238- SYSTEM_VERSION = versionNumber ;
239- SYSTEM_BUILD_NUMBER = buildNumber ;
216+ SYSTEM_VERSION = windowsVersion .toString ();
217+ SYSTEM_BUILD_NUMBER = windowsVersion .getBuild ();
218+ WINDOWS_VERSION = windowsVersion ;
240219 CODE_PAGE = codePage ;
241220 } else {
242221 SYSTEM_NAME = System .getProperty ("os.name" );
243222 SYSTEM_VERSION = System .getProperty ("os.version" );
244223 SYSTEM_BUILD_NUMBER = -1 ;
224+ WINDOWS_VERSION = null ;
245225 CODE_PAGE = -1 ;
246- IS_WINDOWS_7_OR_LATER = false ;
247226 }
248227
249228 Map <String , String > osRelease = Collections .emptyMap ();
@@ -299,7 +278,7 @@ else if (name.equals("freebsd"))
299278 }
300279
301280 public static boolean isWindows7OrLater () {
302- return IS_WINDOWS_7_OR_LATER ;
281+ return WINDOWS_VERSION != null && WINDOWS_VERSION . compareTo ( WindowsVersion . WINDOWS_7 ) >= 0 ;
303282 }
304283
305284 public static Path getWorkingDirectory (String folder ) {
0 commit comments