diff options
author | Laszlo Csomor <laszlocsomor@google.com> | 2016-12-06 17:24:53 +0000 |
---|---|---|
committer | Damien Martin-Guillerez <dmarting@google.com> | 2016-12-06 18:29:11 +0000 |
commit | 4e33ac6326ce93ab1645b5caccb4582ddb6fe9a4 (patch) | |
tree | 78690858ede8c3b5367cf53191cbb206d8eed982 /src/main/native | |
parent | 12d766df10fbc5eba16ec1e6c20c8cd85f9c616f (diff) |
Windows JNI library: prepare for widechar WinAPI
This change:
- renames windows_error_handling.* to
windows_util.*
- moves most stuff except for the JNI method
implementations into the new windows_util
namespace
- implements a jstring to wchar string converter
- uses GetFileAttributesW in
windows_file_operations.cc
See https://github.com/bazelbuild/bazel/issues/2181
--
PiperOrigin-RevId: 141187291
MOS_MIGRATED_REVID=141187291
Diffstat (limited to 'src/main/native')
-rw-r--r-- | src/main/native/windows_file_operations.cc | 33 | ||||
-rw-r--r-- | src/main/native/windows_processes.cc | 37 | ||||
-rw-r--r-- | src/main/native/windows_util.cc (renamed from src/main/native/windows_error_handling.cc) | 25 | ||||
-rw-r--r-- | src/main/native/windows_util.h (renamed from src/main/native/windows_error_handling.h) | 20 |
4 files changed, 80 insertions, 35 deletions
diff --git a/src/main/native/windows_file_operations.cc b/src/main/native/windows_file_operations.cc index cbec4715c0..9f74293c9f 100644 --- a/src/main/native/windows_file_operations.cc +++ b/src/main/native/windows_file_operations.cc @@ -15,9 +15,12 @@ #include <jni.h> #include <windows.h> +#include <memory> #include <string> -#include "src/main/native/windows_error_handling.h" +#include "src/main/native/windows_util.h" + +namespace windows_util { // Keep in sync with j.c.g.devtools.build.lib.windows.WindowsFileOperations enum { @@ -28,6 +31,9 @@ enum { // Determines whether `path` is a junction point or directory symlink. // +// Uses the `GetFileAttributesW` WinAPI function. +// `path` should be a valid Windows-style or UNC path. +// // To read about differences between junction points and directory symlinks, // see http://superuser.com/a/343079. // @@ -39,8 +45,8 @@ enum { // created using "mklink" instead of "mklink /d", as such symlinks don't // behave the same way as directories (e.g. they can't be listed) // - IS_JUNCTION_ERROR, if `path` doesn't exist or some error occurred -int IsJunctionOrDirectorySymlink(const char* path) { - DWORD attrs = GetFileAttributesA(path); +static int IsJunctionOrDirectorySymlink(const wchar_t* path) { + DWORD attrs = GetFileAttributesW(path); if (attrs == INVALID_FILE_ATTRIBUTES) { return IS_JUNCTION_ERROR; } else { @@ -53,21 +59,26 @@ int IsJunctionOrDirectorySymlink(const char* path) { } } +} // namespace windows_util + extern "C" JNIEXPORT jint JNICALL Java_com_google_devtools_build_lib_windows_WindowsFileOperations_nativeIsJunction( JNIEnv* env, jclass clazz, jstring path, jobjectArray error_msg_holder) { - const char* path_cstr = env->GetStringUTFChars(path, NULL); bool report_error = error_msg_holder != NULL && env->GetArrayLength(error_msg_holder) > 0; - int result = IsJunctionOrDirectorySymlink(path_cstr); - if (result == IS_JUNCTION_ERROR && report_error) { - std::string error_str = - GetLastErrorString(std::string("GetFileAttributesA(") + - std::string(path_cstr) + std::string(")")); + std::unique_ptr<wchar_t[]> long_path( + windows_util::JstringToWstring(env, path)); + int result = windows_util::IsJunctionOrDirectorySymlink(long_path.get()); + if (result == windows_util::IS_JUNCTION_ERROR && report_error) { + // Getting the string's characters again in UTF8 encoding is probably + // easier than converting `long_path` using `wcstombs(3)`. + const char* path_cstr = env->GetStringUTFChars(path, NULL); + std::string error_str = windows_util::GetLastErrorString( + std::string("GetFileAttributes(") + std::string(path_cstr) + + std::string(")")); + env->ReleaseStringUTFChars(path, path_cstr); jstring error_msg = env->NewStringUTF(error_str.c_str()); env->SetObjectArrayElement(error_msg_holder, 0, error_msg); } - - env->ReleaseStringUTFChars(path, path_cstr); return result; } diff --git a/src/main/native/windows_processes.cc b/src/main/native/windows_processes.cc index 9210d259aa..49355430e6 100644 --- a/src/main/native/windows_processes.cc +++ b/src/main/native/windows_processes.cc @@ -22,7 +22,7 @@ #include <atomic> #include <string> -#include "src/main/native/windows_error_handling.h" +#include "src/main/native/windows_util.h" extern "C" JNIEXPORT jint JNICALL Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeGetpid( @@ -138,7 +138,7 @@ Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeCreateProcess( } if (!CreatePipe(&stdin_process, &result->stdin_, &sa, 0)) { - result->error_ = GetLastErrorString("CreatePipe(stdin)"); + result->error_ = windows_util::GetLastErrorString("CreatePipe(stdin)"); goto cleanup; } @@ -155,12 +155,12 @@ Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeCreateProcess( NULL); if (stdout_process == INVALID_HANDLE_VALUE) { - result->error_ = GetLastErrorString("CreateFile(stdout)"); + result->error_ = windows_util::GetLastErrorString("CreateFile(stdout)"); goto cleanup; } } else { if (!CreatePipe(&result->stdout_.handle_, &stdout_process, &sa, 0)) { - result->error_ = GetLastErrorString("CreatePipe(stdout)"); + result->error_ = windows_util::GetLastErrorString("CreatePipe(stdout)"); goto cleanup; } } @@ -180,13 +180,13 @@ Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeCreateProcess( NULL); if (stderr_process == INVALID_HANDLE_VALUE) { - result->error_ = GetLastErrorString("CreateFile(stderr)"); + result->error_ = windows_util::GetLastErrorString("CreateFile(stderr)"); goto cleanup; } } } else { if (!CreatePipe(&result->stderr_.handle_, &stderr_process, &sa, 0)) { - result->error_ = GetLastErrorString("CreatePipe(stderr)"); + result->error_ = windows_util::GetLastErrorString("CreatePipe(stderr)"); goto cleanup; } } @@ -196,7 +196,7 @@ Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeCreateProcess( // allowed. Thus, we don't need to do any more setup here. HANDLE job = CreateJobObject(NULL, NULL); if (job == NULL) { - result->error_ = GetLastErrorString("CreateJobObject()"); + result->error_ = windows_util::GetLastErrorString("CreateJobObject()"); goto cleanup; } @@ -209,8 +209,9 @@ Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeCreateProcess( JobObjectExtendedLimitInformation, &job_info, sizeof(job_info))) { - result->error_ = GetLastErrorString("SetInformationJobObject()"); - goto cleanup; + result->error_ = + windows_util::GetLastErrorString("SetInformationJobObject()"); + goto cleanup; } startup_info.hStdInput = stdin_process; @@ -233,7 +234,7 @@ Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeCreateProcess( &process_info); if (!ok) { - result->error_ = GetLastErrorString("CreateProcess()"); + result->error_ = windows_util::GetLastErrorString("CreateProcess()"); goto cleanup; } @@ -253,14 +254,15 @@ Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeCreateProcess( CloseHandle(result->job_); result->job_ = INVALID_HANDLE_VALUE; } else { - result->error_ = GetLastErrorString("AssignProcessToJobObject()"); + result->error_ = + windows_util::GetLastErrorString("AssignProcessToJobObject()"); goto cleanup; } } // Now that we put the process in a new job object, we can start executing it if (ResumeThread(thread) == -1) { - result->error_ = GetLastErrorString("ResumeThread()"); + result->error_ = windows_util::GetLastErrorString("ResumeThread()"); goto cleanup; } @@ -325,7 +327,7 @@ Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeWriteStdin( if (!::WriteFile(process->stdin_, bytes + offset, length, &bytes_written, NULL)) { - process->error_ = GetLastErrorString("WriteFile()"); + process->error_ = windows_util::GetLastErrorString("WriteFile()"); bytes_written = -1; } @@ -377,7 +379,7 @@ Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeReadStream( stream->error_ = ""; bytes_read = 0; } else { - stream->error_ = GetLastErrorString("ReadFile()"); + stream->error_ = windows_util::GetLastErrorString("ReadFile()"); bytes_read = -1; } } else { @@ -394,7 +396,7 @@ Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeGetExitCode( NativeProcess* process = reinterpret_cast<NativeProcess*>(process_long); DWORD exit_code; if (!GetExitCodeProcess(process->process_, &exit_code)) { - process->error_ = GetLastErrorString("GetExitCodeProcess()"); + process->error_ = windows_util::GetLastErrorString("GetExitCodeProcess()"); return -1; } @@ -471,12 +473,13 @@ Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeTerminate( // In theory, CloseHandle() on process->job_ would work, too, since we set // KILL_OBJECT_LIMIT_KILL_ON_JOB_CLOSE, but this is a little more explicit. if (!TerminateJobObject(process->job_, 0)) { - process->error_ = GetLastErrorString("TerminateJobObject()"); + process->error_ = + windows_util::GetLastErrorString("TerminateJobObject()"); return JNI_FALSE; } } else if (process->process_ != INVALID_HANDLE_VALUE) { if (!TerminateProcess(process->process_, 1)) { - process->error_ = GetLastErrorString("TerminateProcess()"); + process->error_ = windows_util::GetLastErrorString("TerminateProcess()"); return JNI_FALSE; } } diff --git a/src/main/native/windows_error_handling.cc b/src/main/native/windows_util.cc index dc14289729..b25bd2c114 100644 --- a/src/main/native/windows_error_handling.cc +++ b/src/main/native/windows_util.cc @@ -13,13 +13,20 @@ // limitations under the License. #include <stdio.h> +#include <stdlib.h> #include <windows.h> +#include <memory> #include <string> -#include "src/main/native/windows_error_handling.h" +#include "src/main/native/windows_util.h" -std::string GetLastErrorString(const std::string& cause) { +namespace windows_util { + +using std::string; +using std::unique_ptr; + +string GetLastErrorString(const string& cause) { DWORD last_error = GetLastError(); if (last_error == 0) { return ""; @@ -45,7 +52,19 @@ std::string GetLastErrorString(const std::string& cause) { buf[sizeof(buf) - 1] = 0; } - std::string result = std::string(message); + string result = string(message); LocalFree(message); return cause + ": " + result; } + +unique_ptr<wchar_t[]> JstringToWstring(JNIEnv* env, const jstring& jstr) { + const jsize len = env->GetStringLength(jstr); + const char* cstr_ptr = env->GetStringUTFChars(jstr, NULL); + unique_ptr<wchar_t[]> result(new wchar_t[len + 1]); + mbstowcs(result.get(), cstr_ptr, len); + result.get()[len] = L'\0'; + env->ReleaseStringUTFChars(jstr, cstr_ptr); + return std::move(result); +} + +} // namespace windows_util diff --git a/src/main/native/windows_error_handling.h b/src/main/native/windows_util.h index efbe95e7ad..48b88be191 100644 --- a/src/main/native/windows_error_handling.h +++ b/src/main/native/windows_util.h @@ -14,11 +14,23 @@ // // INTERNAL header file for use by C++ code in this package. -#ifndef BAZEL_SRC_MAIN_NATIVE_WINDOWS_ERROR_HANDLING_H__ -#define BAZEL_SRC_MAIN_NATIVE_WINDOWS_ERROR_HANDLING_H__ +#ifndef BAZEL_SRC_MAIN_NATIVE_WINDOWS_UTIL_H__ +#define BAZEL_SRC_MAIN_NATIVE_WINDOWS_UTIL_H__ +#include <jni.h> + +#include <memory> #include <string> -std::string GetLastErrorString(const std::string& cause); +namespace windows_util { + +using std::string; +using std::unique_ptr; + +string GetLastErrorString(const string& cause); + +unique_ptr<wchar_t[]> JstringToWstring(JNIEnv* env, const jstring& jstr); + +} // namespace windows_util -#endif // BAZEL_SRC_MAIN_NATIVE_WINDOWS_ERROR_HANDLING_H__ +#endif // BAZEL_SRC_MAIN_NATIVE_WINDOWS_UTIL_H__ |