Make Windows C++ launcher support long path

Change-Id: I25795c748fa98b9275ae34ead17fce02a57dc8e4
PiperOrigin-RevId: 166816800
diff --git a/src/main/cpp/util/BUILD b/src/main/cpp/util/BUILD
index e097bdb..2efd031 100644
--- a/src/main/cpp/util/BUILD
+++ b/src/main/cpp/util/BUILD
@@ -52,6 +52,7 @@
     visibility = [
         ":ijar",
         "//src/test/cpp/util:__pkg__",
+        "//src/tools/launcher:__subpackages__",
         "//src/tools/singlejar:__pkg__",
         "//third_party/def_parser:__pkg__",
     ],
diff --git a/src/tools/launcher/launcher.cc b/src/tools/launcher/launcher.cc
index b981761..eec963e 100644
--- a/src/tools/launcher/launcher.cc
+++ b/src/tools/launcher/launcher.cc
@@ -76,10 +76,7 @@
 
 void BinaryLauncherBase::ParseManifestFile(ManifestFileMap* manifest_file_map,
                                            const string& manifest_path) {
-  // TODO(laszlocsomor): prefix manifest_path with the longpath prefix.
-  // std::ifstream supports long paths, but only if they are in the correct
-  // format, e.g. "\\\\?\\c:\\imagine\\some\\very\\long\\path.txt".
-  ifstream manifest_file(manifest_path.c_str());
+  ifstream manifest_file(AsAbsoluteWindowsPath(manifest_path.c_str()).c_str());
 
   if (!manifest_file) {
     die("Couldn't open MANIFEST file: %s", manifest_path.c_str());
diff --git a/src/tools/launcher/util/BUILD b/src/tools/launcher/util/BUILD
index 7ecee60..b326e6a 100644
--- a/src/tools/launcher/util/BUILD
+++ b/src/tools/launcher/util/BUILD
@@ -17,6 +17,7 @@
     name = "util",
     srcs = ["launcher_util.cc"],
     hdrs = ["launcher_util.h"],
+    deps = ["//src/main/cpp/util:file"],
 )
 
 cc_test(
diff --git a/src/tools/launcher/util/launcher_util.cc b/src/tools/launcher/util/launcher_util.cc
index bc3eddb..149c5f3 100644
--- a/src/tools/launcher/util/launcher_util.cc
+++ b/src/tools/launcher/util/launcher_util.cc
@@ -20,6 +20,7 @@
 #include <sstream>
 #include <string>
 
+#include "src/main/cpp/util/file_platform.h"
 #include "src/tools/launcher/util/launcher_util.h"
 
 namespace bazel {
@@ -27,6 +28,7 @@
 
 using std::ostringstream;
 using std::string;
+using std::wstring;
 using std::stringstream;
 
 string GetLastErrorString() {
@@ -67,19 +69,23 @@
   fputc('\n', stderr);
 }
 
+wstring AsAbsoluteWindowsPath(const char* path) {
+  wstring wpath;
+  if (!blaze_util::AsAbsoluteWindowsPath(path, &wpath)) {
+    die("Couldn't convert %s to absoulte Windows path.", path);
+  }
+  return wpath;
+}
+
 bool DoesFilePathExist(const char* path) {
-  // TODO(laszlocsomor): convert `path` to (const wchar_t*), add longpath-prefix
-  // and use GetFileAttributesW.
-  DWORD dwAttrib = GetFileAttributesA(path);
+  DWORD dwAttrib = GetFileAttributesW(AsAbsoluteWindowsPath(path).c_str());
 
   return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
           !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
 }
 
 bool DoesDirectoryPathExist(const char* path) {
-  // TODO(laszlocsomor): convert `path` to (const wchar_t*), add longpath-prefix
-  // and use GetFileAttributesW.
-  DWORD dwAttrib = GetFileAttributesA(path);
+  DWORD dwAttrib = GetFileAttributesW(AsAbsoluteWindowsPath(path).c_str());
 
   return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
           (dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
diff --git a/src/tools/launcher/util/launcher_util.h b/src/tools/launcher/util/launcher_util.h
index e558300..6ae5782 100644
--- a/src/tools/launcher/util/launcher_util.h
+++ b/src/tools/launcher/util/launcher_util.h
@@ -47,6 +47,10 @@
 // Escape " to \"
 std::string GetEscapedArgument(const std::string& argument);
 
+// Convert a path to an absolute Windows path with \\?\ prefix.
+// This method will print an error and exit if it cannot convert the path.
+std::wstring AsAbsoluteWindowsPath(const char* path);
+
 // Check if a file exists at a given path.
 bool DoesFilePathExist(const char* path);