--- old/src/hotspot/os/windows/os_windows.cpp 2020-03-04 09:15:13.013081500 +0900 +++ new/src/hotspot/os/windows/os_windows.cpp 2020-03-04 09:15:12.720366900 +0900 @@ -4166,85 +4166,106 @@ // additional_space is the number of additionally allocated wchars after the terminating L'\0'. // This is based on pathToNTPath() in io_util_md.cpp, but omits the optimizations for // short paths. -static wchar_t* wide_abs_unc_path(char const* path, errno_t & err, int additional_space = 0) { +static LPWSTR wide_abs_unc_path(char const* path, errno_t & err, int additional_space = 0) { if ((path == NULL) || (path[0] == '\0')) { err = ENOENT; return NULL; } - size_t path_len = strlen(path); // Need to allocate at least room for 3 characters, since os::native_path transforms C: to C:. - char* buf = (char*) os::malloc(1 + MAX2((size_t) 3, path_len), mtInternal); - wchar_t* result = NULL; - + size_t buf_size = 1 + MAX2((size_t)3, strlen(path)); + char* buf = static_cast(os::malloc(buf_size, mtInternal)); if (buf == NULL) { err = ENOMEM; - } else { - memcpy(buf, path, path_len + 1); - os::native_path(buf); - - wchar_t* prefix; - int prefix_off = 0; - bool is_abs = true; - bool needs_fullpath = true; - - if (::isalpha(buf[0]) && !::IsDBCSLeadByte(buf[0]) && buf[1] == ':' && buf[2] == '\\') { - prefix = L"\\\\?\\"; - } else if (buf[0] == '\\' && buf[1] == '\\') { - if (buf[2] == '?' && buf[3] == '\\') { - prefix = L""; - needs_fullpath = false; - } else { - prefix = L"\\\\?\\UNC"; - prefix_off = 1; // Overwrite the first char with the prefix, so \\share\path becomes \\?\UNC\share\path - } - } else { - is_abs = false; - prefix = L"\\\\?\\"; - } + return NULL; + } + memcpy(buf, path, buf_size); + os::native_path(buf); - size_t buf_len = strlen(buf); - size_t prefix_len = wcslen(prefix); - size_t full_path_size = is_abs ? 1 + buf_len : JVM_MAXPATHLEN; - size_t result_size = prefix_len + full_path_size - prefix_off; - result = (wchar_t*) os::malloc(sizeof(wchar_t) * (additional_space + result_size), mtInternal); + // Get required buffer size to convert to Unicode + int unicode_path_len = MultiByteToWideChar(CP_THREAD_ACP, + MB_ERR_INVALID_CHARS, + buf, -1, + NULL, 0); + if (unicode_path_len == 0) { + os::free(buf); + err = EINVAL; + return NULL; + } - if (result == NULL) { - err = ENOMEM; + LPWSTR prefix; + int prefix_off = 0; + bool needs_fullpath = true; + + if (::isalpha(buf[0]) && !::IsDBCSLeadByte(buf[0]) && buf[1] == ':' && buf[2] == '\\') { + prefix = L"\\\\?\\"; + } else if (buf[0] == '\\' && buf[1] == '\\') { + if (buf[2] == '?' && buf[3] == '\\') { + prefix = L""; + needs_fullpath = false; } else { - size_t converted_chars; - wchar_t* path_start = result + prefix_len - prefix_off; - err = ::mbstowcs_s(&converted_chars, path_start, buf_len + 1, buf, buf_len); - - if ((err == ERROR_SUCCESS) && needs_fullpath) { - wchar_t* tmp = (wchar_t*) os::malloc(sizeof(wchar_t) * full_path_size, mtInternal); + prefix = L"\\\\?\\UNC"; + prefix_off = 1; // Overwrite the first char with the prefix, so \\share\path becomes \\?\UNC\share\path + } + } else { + prefix = L"\\\\?\\"; + } + size_t prefix_len = wcslen(prefix); + LPWSTR result = NULL; - if (tmp == NULL) { + LPWSTR unicode_path = static_cast(os::malloc(sizeof(WCHAR) * unicode_path_len, mtInternal)); + if (unicode_path == NULL) { + err = ENOMEM; + } else { + // This call would be success because it is checked in above + err = ERROR_SUCCESS; + MultiByteToWideChar(CP_THREAD_ACP, + MB_ERR_INVALID_CHARS, + buf, -1, + unicode_path, unicode_path_len); + + size_t result_len = prefix_len - prefix_off + additional_space; + if (needs_fullpath) { + // Get required buffer size to convert to full path + DWORD full_path_len = GetFullPathNameW(unicode_path, 0, NULL, NULL); + if (full_path_len == 0) { + err = EINVAL; + } else { + size_t result_size = sizeof(WCHAR) * (result_len + full_path_len); + result = static_cast(os::malloc(result_size, mtInternal)); + if (result == NULL) { err = ENOMEM; } else { - if (!_wfullpath(tmp, path_start, full_path_size)) { - err = ENOENT; - } else { - ::memcpy(path_start, tmp, (1 + wcslen(tmp)) * sizeof(wchar_t)); - } - - os::free(tmp); + // This call would be success because it is checked in above + GetFullPathNameW(unicode_path, full_path_len, result + prefix_len - prefix_off, NULL); + // Copy prefix + memcpy(result, prefix, sizeof(WCHAR) * prefix_len); } } + } else { + size_t result_size = sizeof(WCHAR) * (result_len + unicode_path_len); + result = static_cast(os::malloc(result_size, mtInternal)); + if (result == NULL) { + err = ENOMEM; + } else { + // Copy unicode path + memcpy(result + prefix_len - prefix_off, unicode_path, sizeof(WCHAR) * unicode_path_len); + // Copy prefix + memcpy(result, prefix, sizeof(WCHAR) * prefix_len); + } + } - memcpy(result, prefix, sizeof(wchar_t) * prefix_len); - - // Remove trailing pathsep (not for \\?\:\, since it would make it relative) - size_t result_len = wcslen(result); + // Remove trailing pathsep (not for \\?\:\, since it would make it relative) + result_len = wcslen(result); - if (result[result_len - 1] == L'\\') { - if (!(::iswalpha(result[4]) && result[5] == L':' && result_len == 7)) { - result[result_len - 1] = L'\0'; - } + if (result[result_len - 1] == L'\\') { + if (!(::iswalpha(result[4]) && result[5] == L':' && result_len == 7)) { + result[result_len - 1] = L'\0'; } } } + os::free(unicode_path); os::free(buf); if (err != ERROR_SUCCESS) {