Windows, JNI: shorten the cwd for CreateProcess

The hard limit for SetCurrentDirectory{A,W} is
MAX_PATH-1, even with UNC prefix, therefore a
process' cwd may also not be longer than that.

See https://github.com/bazelbuild/bazel/issues/2107
See https://github.com/bazelbuild/bazel/issues/2406
See https://github.com/bazelbuild/bazel/issues/2181

--
PiperOrigin-RevId: 149290147
MOS_MIGRATED_REVID=149290147
diff --git a/src/main/native/windows_processes.cc b/src/main/native/windows_processes.cc
index a014a8c..3165b38 100644
--- a/src/main/native/windows_processes.cc
+++ b/src/main/native/windows_processes.cc
@@ -184,7 +184,15 @@
       AddUncPrefixMaybe(GetJavaWstring(env, java_stdout_redirect));
   std::wstring stderr_redirect =
       AddUncPrefixMaybe(GetJavaWstring(env, java_stderr_redirect));
-  std::string cwd = GetJavaUTFString(env, java_cwd);
+  std::string cwd;
+  error_msg = windows_util::AsShortPath(
+      GetJavaUTFString(env, java_cwd),
+      [env, java_cwd]() { return GetJavaWstring(env, java_cwd); },
+      &cwd);
+  if (!error_msg.empty()) {
+    result->error_ = error_msg;
+    return PtrAsJlong(result);
+  }
 
   std::unique_ptr<char[]> mutable_commandline(new char[commandline.size() + 1]);
   strncpy(mutable_commandline.get(), commandline.c_str(),
diff --git a/src/main/native/windows_util.cc b/src/main/native/windows_util.cc
index 4223d33..cc0d029 100644
--- a/src/main/native/windows_util.cc
+++ b/src/main/native/windows_util.cc
@@ -64,9 +64,8 @@
   *result = string("\"") + path + "\"";
 }
 
-string AsExecutablePathForCreateProcess(const string& path,
-                                        function<wstring()> path_as_wstring,
-                                        string* result) {
+string AsShortPath(const string& path, function<wstring()> path_as_wstring,
+                   string* result) {
   if (path.empty()) {
     return string("argv[0] should not be empty");
   }
@@ -93,10 +92,7 @@
 
   // Fast-track: the path is already short.
   if (path.size() < MAX_PATH) {
-    // Quote the path in case it's something like "c:\foo\app name.exe".
-    // Do this unconditionally, there's no harm in quoting. Quotes are not
-    // allowed inside paths so we don't need to escape quotes.
-    QuotePath(path, result);
+    *result = path;
     return "";
   }
   // At this point we know that the path is at least MAX_PATH long and that it's
@@ -139,8 +135,21 @@
   }
   mbs_short[mbs_size] = 0;
 
-  QuotePath(mbs_short, result);
+  *result = mbs_short;
   return "";
 }
 
+string AsExecutablePathForCreateProcess(const string& path,
+                                        function<wstring()> path_as_wstring,
+                                        string* result) {
+  string error = AsShortPath(path, path_as_wstring, result);
+  if (error.empty()) {
+    // Quote the path in case it's something like "c:\foo\app name.exe".
+    // Do this unconditionally, there's no harm in quoting. Quotes are not
+    // allowed inside paths so we don't need to escape quotes.
+    QuotePath(*result, result);
+  }
+  return error;
+}
+
 }  // namespace windows_util
diff --git a/src/main/native/windows_util.h b/src/main/native/windows_util.h
index a79d9dd..ea632e7 100644
--- a/src/main/native/windows_util.h
+++ b/src/main/native/windows_util.h
@@ -48,6 +48,10 @@
 
 string GetLastErrorString(const string& cause);
 
+// Same as `AsExecutablePathForCreateProcess` except it won't quote the result.
+string AsShortPath(const string& path, function<wstring()> path_as_wstring,
+                   string* result);
+
 // Computes a path suitable as the executable part in CreateProcessA's cmdline.
 //
 // The null-terminated executable path for CreateProcessA has to fit into