src/java.base/windows/native/libjli/java_md.c
Print this page
@@ -1011,5 +1011,116 @@
}
JLI_MemFree(nargv);
JLI_MemFree(filteredargs);
return outArray;
}
+
+/*
+ * Checks the command line arguments to find whether they are on Unicode.
+ */
+static jboolean
+IsArgsUnicodeDecodingRequired(int argc, char **argv) {
+ int i;
+
+ if (argc < 2) {
+ return JNI_FALSE;
+ }
+
+ for (i = 1; i < argc; ++i) {
+ char *arg = argv[i];
+ if (*arg != '-') {
+ break;
+ }
+ if (stricmp(arg, "-Dwindows.UnicodeConsole=true") == 0) {
+ return JNI_TRUE;
+ }
+ }
+ return JNI_FALSE;
+}
+
+/*
+ * Translate Unicode command line arguments to multi byte chars.
+ */
+static jboolean
+DecodeUnicodeArgs(LPWSTR cmd_line_wide, LPSTR* cmd_line_utf8) {
+ int cmd_line_utf8_length;
+
+ // First call to WideCharToMultiByte calculates destination buffer length.
+ cmd_line_utf8_length = WideCharToMultiByte(CP_UTF8,
+ 0,
+ cmd_line_wide,
+ -1,
+ NULL,
+ 0,
+ NULL,
+ NULL);
+ if (!cmd_line_utf8_length) {
+ JLI_ReportErrorMessage(
+ "WideCharToMultiByte failed to calculate destination buffer length "
+ "with error code %d", GetLastError());
+ return JNI_FALSE;
+ }
+
+ // Allocate buffer to receive conversion to UTF-8.
+ *cmd_line_utf8 = JLI_MemAlloc((size_t)cmd_line_utf8_length * sizeof(CHAR));
+
+ // Second call to WideCharToMultiByte does the actual conversion. Note that
+ // we are forcing the encoding to UTF-8. This only works right if
+ // getEncodingInternal in java_props_md.c also returns UTF-8.
+ if (!WideCharToMultiByte(CP_UTF8,
+ 0,
+ cmd_line_wide,
+ -1,
+ *cmd_line_utf8,
+ cmd_line_utf8_length,
+ NULL,
+ NULL)) {
+ JLI_ReportErrorMessage(
+ "WideCharToMultiByte failed to convert to UTF-8 "
+ "with error code %d", GetLastError());
+ JLI_MemFree(*cmd_line_utf8);
+ return JNI_FALSE;
+ }
+ return JNI_TRUE;
+}
+
+/*
+ * Translate command line arguments from Windows format to argc+argv.
+ */
+static void
+ConvertWinArgsToCommonFormat(LPSTR cmd_line, int *pargc, char*** pargv) {
+ JLI_CmdToArgs(cmd_line);
+
+ *pargc = JLI_GetStdArgc();
+ // add one more to mark the end
+ *pargv = (char **)JLI_MemAlloc((*pargc + 1) * (sizeof(char *)));
+ {
+ int i = 0;
+ StdArg *stdargs = JLI_GetStdArgs();
+ for (i = 0 ; i < *pargc ; ++i) {
+ (*pargv)[i] = stdargs[i].arg;
+ }
+ (*pargv)[i] = NULL;
+ }
+}
+
+jboolean
+JLI_DecodeArgs(int *pargc, char*** pargv) {
+ LPSTR cmdLineUtf8;
+
+ // On Windows command line arguments could be encoded as Unicode
+ // if it is declared explicitly.
+ // Try to parse them as Unicode and look for Unicode encoding request
+ if (!DecodeUnicodeArgs(GetCommandLineW(), &cmdLineUtf8)) {
+ return JNI_FALSE;
+ }
+ ConvertWinArgsToCommonFormat(cmdLineUtf8, pargc, pargv);
+ JLI_MemFree(cmdLineUtf8);
+
+ // If arguments are not on Unicode, decode them as chars.
+ if (!IsArgsUnicodeDecodingRequired(*pargc, *pargv)) {
+ JLI_MemFree(*pargv);
+ JLI_ReleaseStdArgs();
+ ConvertWinArgsToCommonFormat(GetCommandLine(), pargc, pargv);
+ }
+ return JNI_TRUE;
+}