Windows, JNI, processes: use AutoHandles

Closes #8043.

PiperOrigin-RevId: 243607149
diff --git a/src/main/native/windows/processes-jni.cc b/src/main/native/windows/processes-jni.cc
index 906992c..457d2ee 100644
--- a/src/main/native/windows/processes-jni.cc
+++ b/src/main/native/windows/processes-jni.cc
@@ -155,34 +155,11 @@
 class NativeProcess {
  public:
   NativeProcess()
-      : stdin_(INVALID_HANDLE_VALUE),
-        stdout_(),
-        stderr_(),
-        process_(INVALID_HANDLE_VALUE),
-        job_(INVALID_HANDLE_VALUE),
-        ioport_(INVALID_HANDLE_VALUE),
-        exit_code_(STILL_ACTIVE),
-        error_(L"") {}
+      : stdout_(), stderr_(), exit_code_(STILL_ACTIVE), error_(L"") {}
 
   ~NativeProcess() {
-    if (stdin_ != INVALID_HANDLE_VALUE) {
-      CloseHandle(stdin_);
-    }
-
     stdout_.Close();
     stderr_.Close();
-
-    if (process_ != INVALID_HANDLE_VALUE) {
-      CloseHandle(process_);
-    }
-
-    if (job_ != INVALID_HANDLE_VALUE) {
-      CloseHandle(job_);
-    }
-
-    if (ioport_ != INVALID_HANDLE_VALUE) {
-      CloseHandle(ioport_);
-    }
   }
 
   jboolean Create(JNIEnv* env, jstring java_argv0, jstring java_argv_rest,
@@ -241,8 +218,6 @@
     bazel::windows::AutoHandle stdout_process;
     bazel::windows::AutoHandle stderr_process;
     bazel::windows::AutoHandle thread;
-    PROCESS_INFORMATION process_info = {0};
-    JOBOBJECT_EXTENDED_LIMIT_INFORMATION job_info = {0};
 
     JavaByteArray env_map(env, java_env);
     if (env_map.ptr() != nullptr) {
@@ -368,19 +343,18 @@
 
     // MDSN says that the default for job objects is that breakaway is not
     // allowed. Thus, we don't need to do any more setup here.
-    HANDLE job = CreateJobObject(NULL, NULL);
-    if (job == NULL) {
+    job_ = CreateJobObject(NULL, NULL);
+    if (!job_.IsValid()) {
       DWORD err_code = GetLastError();
       error_ = bazel::windows::MakeErrorMessage(
           WSTR(__FILE__), __LINE__, L"nativeCreateProcess", wpath, err_code);
       return false;
     }
 
-    job_ = job;
-
+    JOBOBJECT_EXTENDED_LIMIT_INFORMATION job_info = {0};
     job_info.BasicLimitInformation.LimitFlags =
         JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
-    if (!SetInformationJobObject(job, JobObjectExtendedLimitInformation,
+    if (!SetInformationJobObject(job_, JobObjectExtendedLimitInformation,
                                  &job_info, sizeof(job_info))) {
       DWORD err_code = GetLastError();
       error_ = bazel::windows::MakeErrorMessage(
@@ -388,18 +362,17 @@
       return false;
     }
 
-    HANDLE ioport = CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 1);
-    if (ioport == nullptr) {
+    ioport_ = CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 1);
+    if (!ioport_.IsValid()) {
       DWORD err_code = GetLastError();
       error_ = bazel::windows::MakeErrorMessage(
           WSTR(__FILE__), __LINE__, L"nativeCreateProcess", wpath, err_code);
       return false;
     }
-    ioport_ = ioport;
     JOBOBJECT_ASSOCIATE_COMPLETION_PORT port;
-    port.CompletionKey = job;
-    port.CompletionPort = ioport;
-    if (!SetInformationJobObject(job,
+    port.CompletionKey = job_;
+    port.CompletionPort = ioport_;
+    if (!SetInformationJobObject(job_,
                                  JobObjectAssociateCompletionPortInformation,
                                  &port, sizeof(port))) {
       DWORD err_code = GetLastError();
@@ -434,6 +407,7 @@
       return false;
     }
 
+    PROCESS_INFORMATION process_info = {0};
     STARTUPINFOEXW info;
     attr_list->InitStartupInfoExW(&info);
     if (!CreateProcessW(
@@ -471,9 +445,7 @@
         // TerminateProcess() and hope for the best. In batch mode, the launcher
         // puts Bazel in a job so that will take care of cleanup once the
         // command finishes.
-        CloseHandle(job_);
         job_ = INVALID_HANDLE_VALUE;
-        CloseHandle(ioport_);
         ioport_ = INVALID_HANDLE_VALUE;
       } else {
         DWORD err_code = GetLastError();
@@ -518,8 +490,7 @@
         return kWaitError;
     }
 
-    if (stdin_ != INVALID_HANDLE_VALUE) {
-      CloseHandle(stdin_);
+    if (stdin_.IsValid()) {
       stdin_ = INVALID_HANDLE_VALUE;
     }
 
@@ -530,7 +501,7 @@
       return kWaitError;
     }
 
-    if (job_ != INVALID_HANDLE_VALUE) {
+    if (job_.IsValid()) {
       // Wait for the job object to complete, signalling that all subprocesses
       // have exited.
       DWORD CompletionCode;
@@ -538,15 +509,12 @@
       LPOVERLAPPED Overlapped;
       while (GetQueuedCompletionStatus(ioport_, &CompletionCode, &CompletionKey,
                                        &Overlapped, INFINITE) &&
-             !((HANDLE)CompletionKey == job_ &&
+             !((HANDLE)CompletionKey == (HANDLE)job_ &&
                CompletionCode == JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO)) {
         // Still waiting...
       }
 
-      CloseHandle(job_);
       job_ = INVALID_HANDLE_VALUE;
-
-      CloseHandle(ioport_);
       ioport_ = INVALID_HANDLE_VALUE;
     }
 
@@ -554,8 +522,7 @@
     // because we cannot do this anymore after we closed the handle.
     GetExitCode();
 
-    if (process_ != INVALID_HANDLE_VALUE) {
-      CloseHandle(process_);
+    if (process_.IsValid()) {
       process_ = INVALID_HANDLE_VALUE;
     }
 
@@ -613,7 +580,7 @@
   jboolean Terminate() {
     static const UINT exit_code = 130;  // 128 + SIGINT, like on Linux
 
-    if (job_ != INVALID_HANDLE_VALUE) {
+    if (job_.IsValid()) {
       if (!TerminateJobObject(job_, exit_code)) {
         DWORD err_code = GetLastError();
         error_ = bazel::windows::MakeErrorMessage(WSTR(__FILE__), __LINE__,
@@ -621,7 +588,7 @@
                                                   ToString(pid_), err_code);
         return JNI_FALSE;
       }
-    } else if (process_ != INVALID_HANDLE_VALUE) {
+    } else if (process_.IsValid()) {
       if (!TerminateProcess(process_, exit_code)) {
         DWORD err_code = GetLastError();
         std::wstring our_error = bazel::windows::MakeErrorMessage(
@@ -664,12 +631,12 @@
   }
 
  private:
-  HANDLE stdin_;
+  bazel::windows::AutoHandle stdin_;
   NativeOutputStream stdout_;
   NativeOutputStream stderr_;
-  HANDLE process_;
-  HANDLE job_;
-  HANDLE ioport_;
+  bazel::windows::AutoHandle process_;
+  bazel::windows::AutoHandle job_;
+  bazel::windows::AutoHandle ioport_;
   DWORD pid_;
   DWORD exit_code_;
   std::wstring error_;