MWE здесь (требуется Java 22+):
Код: Выделить всё
import java.lang.foreign.*;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.VarHandle;
public final class Drill {
public static void main(String[] args) throws Throwable {
System.loadLibrary("kernel32");
Linker nativeLinker = Linker.nativeLinker();
SymbolLookup stdlibLookup = nativeLinker.defaultLookup();
SymbolLookup loaderLookup = SymbolLookup.loaderLookup();
MemorySegment pfnLoadLibraryW = loaderLookup.find("LoadLibraryW")
.or(() -> stdlibLookup.find("LoadLibraryW"))
.orElse(MemorySegment.NULL);
if (pfnLoadLibraryW.equals(MemorySegment.NULL)) {
throw new RuntimeException("Failed to find LoadLibraryW symbol");
}
MethodHandle hLoadLibraryW = nativeLinker.downcallHandle(
pfnLoadLibraryW,
FunctionDescriptor.of(
ValueLayout.ADDRESS, // returns HMODULE
ValueLayout.ADDRESS.withTargetLayout(ValueLayout.JAVA_SHORT) // LPCWSTR lpLibFileName
),
Linker.Option.captureCallState("GetLastError")
);
try (Arena arena = Arena.ofConfined()) {
char[] libName = "nonexist".toCharArray();
MemorySegment lpLibName = arena.allocate(ValueLayout.JAVA_SHORT, libName.length + 1);
lpLibName.copyFrom(MemorySegment.ofArray(libName));
StructLayout captureStateLayout = Linker.Option.captureStateLayout();
MemorySegment capturedState = arena.allocate(captureStateLayout);
MemorySegment result = (MemorySegment) hLoadLibraryW.invokeExact(lpLibName, capturedState);
if (!result.equals(MemorySegment.NULL)) {
throw new RuntimeException("Why would you even do this?");
}
VarHandle vh = captureStateLayout.varHandle(MemoryLayout.PathElement.groupElement("GetLastError"));
int lastError = (int) vh.get(capturedState, 0L);
System.out.println("GetLastError = " + lastError);
}
}
}
Я проверил это с помощью:
- Windows11 24h2 + Oracle openjdk 24
- windows1019 + oracle /> Windows10 LTSC2019 + Oracle OpenJDK 24
Подробнее здесь: https://stackoverflow.com/questions/796 ... re-getlast