< prev index next >

src/hotspot/os/windows/os_windows.cpp

Print this page

        

@@ -4159,10 +4159,30 @@
   } else {
     sbuf->st_mode |= S_IFREG;
   }
 }
 
+#define TO_UNICODE(mbs, wcs, wcs_len, err) \
+  wcs_len = MultiByteToWideChar(CP_THREAD_ACP, MB_ERR_INVALID_CHARS,        \
+                                mbs, -1, NULL, 0);                          \
+  if (wcs_len == 0) {                                                       \
+    err = EINVAL;                                                           \
+    return NULL;                                                            \
+  }                                                                         \
+  wcs = reinterpret_cast<LPWSTR>(alloca(sizeof(WCHAR) * unicode_path_len)); \
+  MultiByteToWideChar(CP_THREAD_ACP, MB_ERR_INVALID_CHARS,                  \
+                      mbs, -1, wcs, wcs_len);
+
+#define TO_FULL_PATH(rp, fp, fp_len, err) \
+  fp_len = GetFullPathNameW(rp, 0, NULL, NULL);                  \
+  if (fp_len == 0) {                                             \
+    err = EINVAL;                                                \
+    return NULL;                                                 \
+  }                                                              \
+  fp = reinterpret_cast<LPWSTR>(alloca(sizeof(WCHAR) * fp_len)); \
+  GetFullPathNameW(rp, fp_len, fp, NULL);
+
 // Returns the given path as an absolute wide path in unc format. The returned path is NULL
 // on error (with err being set accordingly) and should be freed via os::free() otherwise.
 // 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.

@@ -4170,24 +4190,22 @@
   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;
-
-  if (buf == NULL) {
-    err = ENOMEM;
-  } else {
-    memcpy(buf, path, path_len + 1);
+  size_t buf_size = 1 + MAX2((size_t)3, strlen(path));
+  char* buf = reinterpret_cast<char*>(alloca(buf_size));
+  memcpy(buf, path, buf_size);
     os::native_path(buf);
 
-    wchar_t* prefix;
+  LPWSTR unicode_path;
+  DWORD unicode_path_len;
+  TO_UNICODE(buf, unicode_path, unicode_path_len, err)
+
+  LPWSTR 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] == '\\') {

@@ -4197,64 +4215,40 @@
       } 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"\\\\?\\";
     }
 
-    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);
-
-    if (result == NULL) {
-      err = ENOMEM;
-    } 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);
-
-        if (tmp == NULL) {
-          err = ENOMEM;
-        } else {
-          if (!_wfullpath(tmp, path_start, full_path_size)) {
-            err = ENOENT;
+  LPWSTR converted_path;
+  DWORD converted_path_len;
+  if (needs_fullpath) {
+    TO_FULL_PATH(unicode_path, converted_path, converted_path_len, err)
           } else {
-            ::memcpy(path_start, tmp, (1 + wcslen(tmp)) * sizeof(wchar_t));
+    converted_path = unicode_path;
+    converted_path_len = unicode_path_len;
           }
 
-          os::free(tmp);
-        }
+  size_t prefix_len = wcslen(prefix);
+  size_t result_len = prefix_len - prefix_off + converted_path_len + additional_space + 1;
+  LPWSTR result = reinterpret_cast<LPWSTR>(os::malloc(sizeof(WCHAR) * result_len, mtInternal));
+  if (result == NULL) {
+    vm_exit_out_of_memory(buf_size, OOM_MALLOC_ERROR, "wide_abs_unc_path");
       }
-
-      memcpy(result, prefix, sizeof(wchar_t) * prefix_len);
+  _snwprintf(result, result_len, L"%s%s", prefix, &converted_path[prefix_off]);
 
       // Remove trailing pathsep (not for \\?\<DRIVE>:\, since it would make it relative)
-      size_t result_len = wcslen(result);
-
+  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';
         }
       }
-    }
-  }
-
-  os::free(buf);
-
-  if (err != ERROR_SUCCESS) {
-    os::free(result);
-    result = NULL;
-  }
 
-  return result;
+  err = ERROR_SUCCESS;
+  return static_cast<wchar_t*>(result); // LPWSTR and wchat_t* are the same type on Windows.
 }
 
 int os::stat(const char *path, struct stat *sbuf) {
   errno_t err;
   wchar_t* wide_path = wide_abs_unc_path(path, err);
< prev index next >