--- old/make/lib/CoreLibraries.gmk 2015-09-18 09:02:51.414218500 -0700 +++ new/make/lib/CoreLibraries.gmk 2015-09-18 09:02:50.823916400 -0700 @@ -333,6 +333,7 @@ -export:JLI_CmdToArgs \ -export:JLI_GetStdArgc \ -export:JLI_GetStdArgs \ + -export:JLI_DecodeArgs \ -export:JLI_List_new \ -export:JLI_List_add \ -export:JLI_StringDup \ --- old/src/java.base/share/native/launcher/main.c 2015-09-18 09:02:55.355237400 -0700 +++ new/src/java.base/share/native/launcher/main.c 2015-09-18 09:02:54.807956700 -0700 @@ -110,17 +110,9 @@ } } } - JLI_CmdToArgs(GetCommandLine()); - margc = JLI_GetStdArgc(); - // add one more to mark the end - margv = (char **)JLI_MemAlloc((margc + 1) * (sizeof(char *))); - { - int i = 0; - StdArg *stdargs = JLI_GetStdArgs(); - for (i = 0 ; i < margc ; i++) { - margv[i] = stdargs[i].arg; - } - margv[i] = NULL; + + if (!JLI_DecodeArgs(&margc, &margv)) { + exit(1); } #else /* *NIXES */ { --- old/src/java.base/share/native/libjli/jli_util.h 2015-09-18 09:02:59.019114100 -0700 +++ new/src/java.base/share/native/libjli/jli_util.h 2015-09-18 09:02:58.449823100 -0700 @@ -78,6 +78,7 @@ #define JLI_StrNCaseCmp(p1, p2, p3) strnicmp((p1), (p2), (p3)) int JLI_Snprintf(char *buffer, size_t size, const char *format, ...); void JLI_CmdToArgs(char *cmdline); +jboolean JLI_DecodeArgs(int *pargc, char*** pargv); #define JLI_Lseek _lseeki64 #define JLI_PutEnv _putenv #define JLI_GetPid _getpid --- old/src/java.base/unix/native/libjli/java_md_common.c 2015-09-18 09:03:02.595946400 -0700 +++ new/src/java.base/unix/native/libjli/java_md_common.c 2015-09-18 09:03:02.040662200 -0700 @@ -319,3 +319,8 @@ { return NewPlatformStringArray(env, strv, argc); } + +jboolean +JLI_DecodeArgs(int *pargc, char*** pargv) { + return JLI_TRUE; +} --- old/src/java.base/windows/native/libjava/Console_md.c 2015-09-18 09:03:06.286837700 -0700 +++ new/src/java.base/windows/native/libjava/Console_md.c 2015-09-18 09:03:05.749564500 -0700 @@ -57,6 +57,8 @@ int cp = GetConsoleCP(); if (cp >= 874 && cp <= 950) sprintf(buf, "ms%d", cp); + else if (cp == 65001) + sprintf(buf, "UTF-8"); else sprintf(buf, "cp%d", cp); return JNU_NewStringPlatform(env, buf); --- old/src/java.base/windows/native/libjava/java_props_md.c 2015-09-18 09:03:09.816646200 -0700 +++ new/src/java.base/windows/native/libjava/java_props_md.c 2015-09-18 09:03:09.275369000 -0700 @@ -145,6 +145,8 @@ cp = GetConsoleCP(); if (cp >= 874 && cp <= 950) sprintf(buf, "ms%d", cp); + else if (cp == 65001) + sprintf(buf, "UTF-8"); else sprintf(buf, "cp%d", cp); return buf; @@ -688,17 +690,27 @@ } hStdOutErr = GetStdHandle(STD_OUTPUT_HANDLE); - if (hStdOutErr != INVALID_HANDLE_VALUE && - GetFileType(hStdOutErr) == FILE_TYPE_CHAR) { - sprops.sun_stdout_encoding = getConsoleEncoding(); + if (hStdOutErr != INVALID_HANDLE_VALUE) { + switch(GetFileType(hStdOutErr)) { + case FILE_TYPE_DISK: + case FILE_TYPE_CHAR: + case FILE_TYPE_PIPE: + sprops.sun_stdout_encoding = getConsoleEncoding(); + break; + } } hStdOutErr = GetStdHandle(STD_ERROR_HANDLE); - if (hStdOutErr != INVALID_HANDLE_VALUE && - GetFileType(hStdOutErr) == FILE_TYPE_CHAR) { - if (sprops.sun_stdout_encoding != NULL) - sprops.sun_stderr_encoding = sprops.sun_stdout_encoding; - else - sprops.sun_stderr_encoding = getConsoleEncoding(); + if (hStdOutErr != INVALID_HANDLE_VALUE) { + switch (GetFileType(hStdOutErr)) { + case FILE_TYPE_DISK: + case FILE_TYPE_CHAR: + case FILE_TYPE_PIPE: + if (sprops.sun_stdout_encoding != NULL) + sprops.sun_stderr_encoding = sprops.sun_stdout_encoding; + else + sprops.sun_stderr_encoding = getConsoleEncoding(); + break; + } } } } --- old/src/java.base/windows/native/libjli/java_md.c 2015-09-18 09:03:13.589580500 -0700 +++ new/src/java.base/windows/native/libjli/java_md.c 2015-09-18 09:03:13.007283500 -0700 @@ -1017,3 +1017,81 @@ JLI_MemFree(filteredargs); return outArray; } + +/* + * 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. + 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); + *cmd_line_utf8 = NULL; + 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; + + if (!DecodeUnicodeArgs(GetCommandLineW(), &cmdLineUtf8)) { + return JNI_FALSE; + } + ConvertWinArgsToCommonFormat(cmdLineUtf8, pargc, pargv); + JLI_MemFree(cmdLineUtf8); + + return JNI_TRUE; +}