Skip to content

Commit 97eb239

Browse files
committed
convert ffi
1 parent 39c1a12 commit 97eb239

File tree

3 files changed

+109
-8
lines changed

3 files changed

+109
-8
lines changed

src/main/java/mediathek/Main.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import com.formdev.flatlaf.FlatLaf;
44
import com.jidesoft.utils.ThreadCheckingRepaintManager;
5-
import com.sun.jna.platform.win32.VersionHelpers;
65
import javafx.application.Platform;
76
import mediathek.config.*;
87
import mediathek.controller.SenderFilmlistLoadApprover;
@@ -16,6 +15,7 @@
1615
import mediathek.tool.dns.IPvPreferenceMode;
1716
import mediathek.tool.migrator.SettingsMigrator;
1817
import mediathek.windows.MediathekGuiWindows;
18+
import mediathek.windows.WindowsVersionHelper;
1919
import mediathek.x11.MediathekGuiX11;
2020
import org.apache.commons.lang3.SystemUtils;
2121
import org.apache.logging.log4j.Level;
@@ -386,11 +386,16 @@ private static void registerFlatLafCustomization() {
386386
}
387387

388388
private static void checkWindows10OrGreater() {
389-
if (!VersionHelpers.IsWindows10OrGreater()) {
390-
JOptionPane.showMessageDialog(null,
391-
"MediathekView benötigt mindestens Windows 10 zum Start.\nDas Programm wird nun beendet.",
392-
Konstanten.PROGRAMMNAME, JOptionPane.ERROR_MESSAGE);
393-
System.exit(1);
389+
try {
390+
if (!WindowsVersionHelper.IsWindows10OrGreater()) {
391+
JOptionPane.showMessageDialog(null,
392+
"MediathekView benötigt mindestens Windows 10 zum Start.\nDas Programm wird nun beendet.",
393+
Konstanten.PROGRAMMNAME, JOptionPane.ERROR_MESSAGE);
394+
System.exit(1);
395+
}
396+
}
397+
catch (Throwable ex) {
398+
logger.error("Error while checking Windows version", ex);
394399
}
395400
}
396401

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
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+
}

src/main/kotlin/mediathek/windows/TaskbarIndicatorThread.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import javax.swing.JFrame
1111
internal class TaskbarIndicatorThread(parent: MediathekGuiWindows) : IndicatorThread() {
1212
private val parent: JFrame
1313
private val setThreadExecutionState: MethodHandle?
14-
private val arena = Arena.ofAuto()
1514

1615
private fun disableStandby() {
1716
val res = setThreadExecutionState?.invoke(WinFlags.ES_CONTINUOUS or WinFlags.ES_SYSTEM_REQUIRED) ?: 0
@@ -54,7 +53,7 @@ internal class TaskbarIndicatorThread(parent: MediathekGuiWindows) : IndicatorTh
5453
this.parent = parent
5554

5655
val linker = Linker.nativeLinker()
57-
val kernel32 = SymbolLookup.libraryLookup("kernel32.dll", arena)
56+
val kernel32 = SymbolLookup.libraryLookup("kernel32.dll", Arena.global())
5857
setThreadExecutionState = linker.downcallHandle(
5958
kernel32.find("SetThreadExecutionState").orElseThrow(),
6059
FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.JAVA_INT)

0 commit comments

Comments
 (0)