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;
+}