package com.oracle.svm.core.windows;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.StackValue;
import org.graalvm.nativeimage.c.function.CEntryPointLiteral;
import org.graalvm.nativeimage.c.type.CCharPointer;
import org.graalvm.nativeimage.c.type.CTypeConversion;
import org.graalvm.nativeimage.hosted.Feature;
import org.graalvm.nativeimage.impl.ProcessPropertiesSupport;
import org.graalvm.word.PointerBase;
import org.graalvm.word.WordFactory;
import com.oracle.svm.core.BaseProcessPropertiesSupport;
import com.oracle.svm.core.annotate.AutomaticFeature;
import com.oracle.svm.core.util.VMError;
import com.oracle.svm.core.windows.headers.Process;
import com.oracle.svm.core.windows.headers.WinBase;
import com.oracle.svm.core.windows.headers.WinBase.HANDLE;
public class WindowsProcessPropertiesSupport extends BaseProcessPropertiesSupport {
@Override
public String getExecutableName() {
CCharPointer path = StackValue.get(WinBase.MAX_PATH, CCharPointer.class);
WinBase.HMODULE hModule = WinBase.GetModuleHandleA(WordFactory.nullPointer());
int result = WinBase.GetModuleFileNameA(hModule, path, WinBase.MAX_PATH);
return result == 0 ? null : CTypeConversion.toJavaString(path);
}
@Override
public void exec(Path executable, String[] args) {
if (!Files.isExecutable(executable)) {
throw new RuntimeException("Path " + executable + " does not point to executable file");
}
List<String> cmd = new ArrayList<>(args.length);
cmd.add(executable.toString());
cmd.addAll(Arrays.asList(args).subList(1, args.length));
java.lang.Process process = null;
try {
process = new ProcessBuilder(cmd).redirectInput(ProcessBuilder.Redirect.INHERIT).redirectOutput(ProcessBuilder.Redirect.INHERIT).redirectError(ProcessBuilder.Redirect.INHERIT).start();
} catch (IOException e) {
throw VMError.shouldNotReachHere();
}
while (process.isAlive()) {
try {
System.exit(process.waitFor());
} catch (InterruptedException e) {
}
}
System.exit(process.exitValue());
}
@Override
public long getProcessID() {
return Process.GetCurrentProcessId();
}
@Override
public long getProcessID(java.lang.Process process) {
return WindowsUtils.getpid(process);
}
@Override
public String getObjectFile(String symbol) {
try (CTypeConversion.CCharPointerHolder symbolHolder = CTypeConversion.toCString(symbol)) {
WinBase.HMODULE builtinHandle = WinBase.GetModuleHandleA(WordFactory.nullPointer());
PointerBase symbolAddress = WinBase.GetProcAddress(builtinHandle, symbolHolder.get());
if (symbolAddress.isNonNull()) {
return getObjectFile(symbolAddress);
}
}
return null;
}
@Override
public String getObjectFile(CEntryPointLiteral<?> symbol) {
PointerBase symbolAddress = symbol.getFunctionPointer();
return getObjectFile(symbolAddress);
}
private static String getObjectFile(PointerBase symbolAddress) {
WinBase.HMODULEPointer module = StackValue.get(WinBase.HMODULEPointer.class);
if (!WinBase.GetModuleHandleExA(WinBase.GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS() | WinBase.GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT(),
symbolAddress, module)) {
return null;
}
CCharPointer path = StackValue.get(WinBase.MAX_PATH, CCharPointer.class);
int result = WinBase.GetModuleFileNameA(module.read(), path, WinBase.MAX_PATH);
return result == 0 ? null : CTypeConversion.toJavaString(path);
}
@Override
public String setLocale(String category, String locale) {
throw VMError.unimplemented();
}
@Override
public boolean destroy(long processID) {
return destroyForcibly(processID);
}
@Override
public boolean destroyForcibly(long processID) {
HANDLE handle = Process.OpenProcess(Process.PROCESS_TERMINATE(), 0, (int) processID);
if (handle.isNull()) {
return false;
}
boolean result = Process.TerminateProcess(handle, 1) != 0;
WinBase.CloseHandle(handle);
return result;
}
@Override
public boolean isAlive(long processID) {
throw VMError.unimplemented();
}
@Override
public int waitForProcessExit(long processID) {
throw VMError.unimplemented();
}
@AutomaticFeature
public static class ImagePropertiesFeature implements Feature {
@Override
public void afterRegistration(AfterRegistrationAccess access) {
ImageSingletons.add(ProcessPropertiesSupport.class, new WindowsProcessPropertiesSupport());
}
}
}