Skip to content

Commit 143d664

Browse files
committed
Read args via CommandLineToArgvW on Windows
1 parent d3ced12 commit 143d664

1 file changed

Lines changed: 91 additions & 1 deletion

File tree

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/JavaMainWrapper.java

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,15 @@
4343
import org.graalvm.nativeimage.Platforms;
4444
import org.graalvm.nativeimage.StackValue;
4545
import org.graalvm.nativeimage.VMRuntime;
46+
import org.graalvm.nativeimage.c.CContext;
4647
import org.graalvm.nativeimage.c.function.CEntryPoint;
48+
import org.graalvm.nativeimage.c.function.CFunction;
4749
import org.graalvm.nativeimage.c.function.CFunctionPointer;
50+
import org.graalvm.nativeimage.c.struct.CPointerTo;
4851
import org.graalvm.nativeimage.c.struct.SizeOf;
4952
import org.graalvm.nativeimage.c.type.CCharPointer;
5053
import org.graalvm.nativeimage.c.type.CCharPointerPointer;
54+
import org.graalvm.nativeimage.c.type.CIntPointer;
5155
import org.graalvm.nativeimage.c.type.CTypeConversion;
5256
import org.graalvm.nativeimage.c.type.CTypeConversion.CCharPointerHolder;
5357
import org.graalvm.nativeimage.c.type.WordPointer;
@@ -229,7 +233,11 @@ private static int runCore0() {
229233
* exceptions in a InvocationTargetException.
230234
*/
231235
JavaMainSupport mainSupport = ImageSingletons.lookup(JavaMainSupport.class);
232-
invokeMain(mainSupport.mainArgs);
236+
String[] args = mainSupport.mainArgs;
237+
if (Platform.includedIn(Platform.WINDOWS.class)) {
238+
args = WindowsArguments.alterArgs(args);
239+
}
240+
invokeMain(args);
233241

234242
return 0;
235243
} catch (Throwable ex) {
@@ -244,6 +252,88 @@ private static int runCore0() {
244252
}
245253
}
246254

255+
@CContext(WindowsArguments.Directives.class)
256+
final class WindowsArguments {
257+
258+
private WindowsArguments() {
259+
}
260+
261+
public static String[] alterArgs(String[] originalArgs) {
262+
return readCommandLineArgs();
263+
}
264+
265+
private static final int WCHAR_SIZE = 2;
266+
267+
private static String[] readCommandLineArgs() {
268+
var cmd = GetCommandLineW();
269+
270+
CIntPointer numOfArgs = StackValue.get(Long.BYTES);
271+
272+
WCharPointerPointer args = CommandLineToArgvW(cmd, numOfArgs);
273+
try {
274+
var numArgs = numOfArgs.read();
275+
276+
var results = new String[numArgs - 1];
277+
for (var i = 0; i < results.length; i++) {
278+
var arg = args.read(i + 1);
279+
results[i] = toJavaString(arg);
280+
}
281+
282+
return results;
283+
} finally {
284+
LocalFree(args);
285+
}
286+
}
287+
288+
private static String toJavaString(WCharPointer arg) {
289+
return CTypeConversion.asByteBuffer(arg, wcslen(arg) * WCHAR_SIZE)
290+
.order(java.nio.ByteOrder.LITTLE_ENDIAN)
291+
.asCharBuffer()
292+
.toString();
293+
}
294+
295+
@CPointerTo(nameOfCType = "wchar_t")
296+
private interface WCharPointer extends PointerBase {
297+
}
298+
299+
@CPointerTo(WCharPointer.class)
300+
private interface WCharPointerPointer extends PointerBase {
301+
302+
WCharPointer read(int index);
303+
}
304+
305+
@CFunction
306+
private static native WCharPointer GetCommandLineW();
307+
308+
@CFunction
309+
private static native WCharPointerPointer CommandLineToArgvW(
310+
WCharPointer cmdLine, CIntPointer numArgsOut);
311+
312+
@CFunction
313+
private static native int wcslen(WCharPointer str);
314+
315+
@CFunction
316+
private static native void LocalFree(PointerBase p);
317+
318+
static final class Directives implements CContext.Directives {
319+
320+
@Override
321+
public boolean isInConfiguration() {
322+
return Platform.includedIn(Platform.WINDOWS.class);
323+
}
324+
325+
@Override
326+
public List<String> getHeaderFiles() {
327+
return List.of("<windows.h>", "<wchar.h>");
328+
}
329+
330+
@Override
331+
public List<String> getLibraries() {
332+
return List.of("Kernel32", "Shell32");
333+
}
334+
}
335+
}
336+
247337
@Uninterruptible(reason = "The caller initialized the thread state, so the callees do not need to be uninterruptible.", calleeMustBe = false)
248338
private static void runShutdown() {
249339
RecurringCallbackSupport.suspendCallbackTimer("Recurring callbacks can't be executed during shutdown.");

0 commit comments

Comments
 (0)