1 /*
   2  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include <assert.h>
  27 #include "java_lang_ProcessImpl.h"
  28 
  29 #include "jni.h"
  30 #include "jvm.h"
  31 #include "jni_util.h"
  32 #include "io_util.h"
  33 #include <windows.h>
  34 #include <io.h>
  35 
  36 /* We try to make sure that we can read and write 4095 bytes (the
  37  * fixed limit on Linux) to the pipe on all operating systems without
  38  * deadlock.  Windows 2000 inexplicably appears to need an extra 24
  39  * bytes of slop to avoid deadlock.
  40  */
  41 #define PIPE_SIZE (4096+24)
  42 
  43 /* We have THREE locales in action:
  44  * 1. Thread default locale - dictates UNICODE-to-8bit conversion
  45  * 2. System locale that defines the message localization
  46  * 3. The file name locale
  47  * Each locale could be an extended locale, that means that text cannot be
  48  * mapped to 8bit sequence without multibyte encoding.
  49  * VM is ready for that, if text is UTF-8.
  50  * Here we make the work right from the beginning.
  51  */
  52 size_t os_error_message(int errnum, WCHAR* utf16_OSErrorMsg, size_t maxMsgLength) {
  53     size_t n = (size_t)FormatMessageW(
  54             FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
  55             NULL,
  56             (DWORD)errnum,
  57             0,
  58             utf16_OSErrorMsg,
  59             (DWORD)maxMsgLength,
  60             NULL);
  61     if (n > 3) {
  62         // Drop final '.', CR, LF
  63         if (utf16_OSErrorMsg[n - 1] == L'\n') --n;
  64         if (utf16_OSErrorMsg[n - 1] == L'\r') --n;
  65         if (utf16_OSErrorMsg[n - 1] == L'.') --n;
  66         utf16_OSErrorMsg[n] = L'\0';
  67     }
  68     return n;
  69 }
  70 
  71 #define MESSAGE_LENGTH (256 + 100)
  72 #define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x))
  73 
  74 static void
  75 win32Error(JNIEnv *env, const WCHAR *functionName)
  76 {
  77     WCHAR utf16_OSErrorMsg[MESSAGE_LENGTH - 100];
  78     WCHAR utf16_javaMessage[MESSAGE_LENGTH];
  79     /*Good suggestion about 2-bytes-per-symbol in localized error reports*/
  80     char  utf8_javaMessage[MESSAGE_LENGTH*2];
  81     const int errnum = (int)GetLastError();
  82     size_t n = os_error_message(errnum, utf16_OSErrorMsg, ARRAY_SIZE(utf16_OSErrorMsg));
  83     n = (n > 0)
  84         ? swprintf(utf16_javaMessage, MESSAGE_LENGTH, L"%s error=%d, %s", functionName, errnum, utf16_OSErrorMsg)
  85         : swprintf(utf16_javaMessage, MESSAGE_LENGTH, L"%s failed, error=%d", functionName, errnum);
  86 
  87     if (n > 0) /*terminate '\0' is not a part of conversion procedure*/
  88         n = WideCharToMultiByte(
  89             CP_UTF8,
  90             0,
  91             utf16_javaMessage,
  92             n, /*by creation n <= MESSAGE_LENGTH*/
  93             utf8_javaMessage,
  94             MESSAGE_LENGTH*2,
  95             NULL,
  96             NULL);
  97 
  98     /*no way to die*/
  99     {
 100         const char *errorMessage = "Secondary error while OS message extraction";
 101         if (n > 0) {
 102             utf8_javaMessage[min(MESSAGE_LENGTH*2 - 1, n)] = '\0';
 103             errorMessage = utf8_javaMessage;
 104         }
 105         JNU_ThrowIOException(env, errorMessage);
 106     }
 107 }
 108 
 109 static void
 110 closeSafely(HANDLE handle)
 111 {
 112     if (handle != INVALID_HANDLE_VALUE)
 113         CloseHandle(handle);
 114 }
 115 
 116 static BOOL hasInheritFlag(HANDLE handle)
 117 {
 118     DWORD mask;
 119     if (GetHandleInformation(handle, &mask)) {
 120         return mask & HANDLE_FLAG_INHERIT;
 121     }
 122     return FALSE;
 123 }
 124 
 125 #define HANDLE_STORAGE_SIZE 6
 126 #define OFFSET_READ  0
 127 #define OFFSET_WRITE 1
 128 //long signed version of INVALID_HANDLE_VALUE
 129 #define JAVA_INVALID_HANDLE_VALUE ((jlong) -1)
 130 #define OPPOSITE_END(offset) (offset==OFFSET_READ ? OFFSET_WRITE : OFFSET_READ)
 131 
 132 /* Pipe holder structure */
 133 typedef struct _STDHOLDER {
 134     HANDLE  pipe[2];
 135     int     offset;
 136 } STDHOLDER;
 137 
 138 /* Responsible for correct initialization of the [pHolder] structure
 139    (that is used for handles recycling) if needs,
 140    and appropriate setup of IOE handle [phStd] for child process based
 141    on created pipe or Java handle. */
 142 static BOOL initHolder(
 143     JNIEnv *env,
 144     jlong *pjhandles,   /* IN OUT - the handle form Java,
 145                                     that can be a file, console or undefined */
 146     STDHOLDER *pHolder, /* OUT    - initialized structure that holds pipe
 147                                     handles */
 148     HANDLE *phStd       /* OUT    - initialized handle for child process */
 149 ) {
 150     /* Here we test the value from Java against invalid
 151        handle value. We are not using INVALID_HANDLE_VALUE macro
 152        due to double signed/unsigned and 32/64bit ambiguity.
 153        Otherwise it will be easy to get the wrong
 154        value   0x00000000FFFFFFFF
 155        instead 0xFFFFFFFFFFFFFFFF. */
 156     if (*pjhandles != JAVA_INVALID_HANDLE_VALUE) {
 157         /* Java file or console redirection */
 158         *phStd = (HANDLE) *pjhandles;
 159         /* Here we set the related Java stream (Process.getXXXXStream())
 160            to [ProcessBuilder.NullXXXXStream.INSTANCE] value.
 161            The initial Java handle [*pjhandles] will be closed in
 162            ANY case. It is not a handle leak. */
 163         *pjhandles = JAVA_INVALID_HANDLE_VALUE;
 164     } else {
 165         /* Creation of parent-child pipe */
 166         if (!CreatePipe(
 167             &pHolder->pipe[OFFSET_READ],
 168             &pHolder->pipe[OFFSET_WRITE],
 169             NULL, /* we would like to inherit
 170                      default process access,
 171                      instead of 'Everybody' access */
 172             PIPE_SIZE))
 173         {
 174             win32Error(env, L"CreatePipe");
 175             return FALSE;
 176         } else {
 177             /* [thisProcessEnd] has no the inherit flag because
 178                the [lpPipeAttributes] param of [CreatePipe]
 179                had the NULL value. */
 180             HANDLE thisProcessEnd = pHolder->pipe[OPPOSITE_END(pHolder->offset)];
 181             *phStd = pHolder->pipe[pHolder->offset];
 182             *pjhandles = (jlong) thisProcessEnd;
 183         }
 184     }
 185     /* Pipe handle will be closed in the [releaseHolder] call,
 186        file handle will be closed in Java.
 187        The long-live handle need to restore the inherit flag,
 188        we do it later in the [prepareIOEHandleState] call. */
 189     SetHandleInformation(
 190         *phStd,
 191         HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
 192     return TRUE;
 193 }
 194 
 195 /* Smart recycling of pipe handles in [pHolder]. For the failed
 196    create process attempts, both ends of pipe need to be released.
 197    The [complete] has the [TRUE] value in the failed attempt. */
 198 static void releaseHolder(BOOL complete, STDHOLDER *pHolder) {
 199     closeSafely(pHolder->pipe[pHolder->offset]);
 200     if (complete) {
 201         /* Error occur, close this process pipe end */
 202         closeSafely(pHolder->pipe[OPPOSITE_END(pHolder->offset)]);
 203     }
 204 }
 205 
 206 /* Stores and drops the inherit flag of handles that should not
 207    be shared with the child process by default, but can hold the
 208    inherit flag due to MS process birth specific. */
 209 static void prepareIOEHandleState(
 210     HANDLE *stdIOE,
 211     BOOL *inherit)
 212 {
 213     int i;
 214     for (i = 0; i < HANDLE_STORAGE_SIZE; ++i) {
 215         HANDLE hstd = stdIOE[i];
 216         if (INVALID_HANDLE_VALUE != hstd && hasInheritFlag(hstd)) {
 217             /* FALSE by default */
 218             inherit[i] = TRUE;
 219             /* Java does not need implicit inheritance for IOE handles,
 220                so we drop inherit flag that probably was installed by
 221                previous CreateProcess call that launched current process.
 222                We will return the handle state back after CreateProcess call.
 223                By clearing inherit flag we prevent "greedy grandchild" birth.
 224                The explicit inheritance for child process IOE handles is
 225                implemented in the [initHolder] call. */
 226             SetHandleInformation(hstd, HANDLE_FLAG_INHERIT, 0);
 227         }
 228     }
 229 }
 230 
 231 /* Restores the inheritance flag of handles from stored values. */
 232 static void restoreIOEHandleState(
 233     const HANDLE *stdIOE,
 234     const BOOL *inherit)
 235 {
 236     /* The set of current process standard IOE handles and
 237        the set of child process IOE handles can intersect.
 238        To restore the inherit flag right, we use backward
 239        array iteration. */
 240     int i;
 241     for (i = HANDLE_STORAGE_SIZE - 1; i >= 0; --i)
 242         if (INVALID_HANDLE_VALUE != stdIOE[i]) {
 243            /* Restore inherit flag for any case.
 244               The handle can be changed by explicit inheritance.*/
 245             SetHandleInformation(stdIOE[i],
 246                 HANDLE_FLAG_INHERIT,
 247                 inherit[i] ? HANDLE_FLAG_INHERIT : 0);
 248         }
 249 }
 250 
 251 /*
 252  * Class:     java_lang_ProcessImpl
 253  * Method:    getProcessId0
 254  * Signature: (J)I
 255  */
 256 JNIEXPORT jint JNICALL Java_java_lang_ProcessImpl_getProcessId0
 257   (JNIEnv *env, jclass clazz, jlong handle) {
 258     DWORD pid = GetProcessId((HANDLE) jlong_to_ptr(handle));
 259     return (jint)pid;
 260 }
 261 
 262 /* Please, read about the MS inheritance problem
 263    http://support.microsoft.com/kb/315939
 264    and critical section/synchronized block solution. */
 265 static jlong processCreate(
 266     JNIEnv *env,
 267     const jchar *pcmd,
 268     const jchar *penvBlock,
 269     const jchar *pdir,
 270     jlong *handles,
 271     jboolean redirectErrorStream)
 272 {
 273     jlong ret = 0L;
 274     STARTUPINFOW si = {sizeof(si)};
 275 
 276     /* Handles for which the inheritance flag must be restored. */
 277     HANDLE stdIOE[HANDLE_STORAGE_SIZE] = {
 278         /* Current process standard IOE handles: JDK-7147084 */
 279         INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE,
 280         /* Child process IOE handles: JDK-6921885 */
 281         (HANDLE)handles[0], (HANDLE)handles[1], (HANDLE)handles[2]};
 282     BOOL inherit[HANDLE_STORAGE_SIZE] = {
 283         FALSE, FALSE, FALSE,
 284         FALSE, FALSE, FALSE};
 285 
 286     /* These three should not be closed by CloseHandle! */
 287     stdIOE[0] = GetStdHandle(STD_INPUT_HANDLE);
 288     stdIOE[1] = GetStdHandle(STD_OUTPUT_HANDLE);
 289     stdIOE[2] = GetStdHandle(STD_ERROR_HANDLE);
 290 
 291     prepareIOEHandleState(stdIOE, inherit);
 292     {
 293         /* Input */
 294         STDHOLDER holderIn = {{INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}, OFFSET_READ};
 295         if (initHolder(env, &handles[0], &holderIn, &si.hStdInput)) {
 296 
 297             /* Output */
 298             STDHOLDER holderOut = {{INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}, OFFSET_WRITE};
 299             if (initHolder(env, &handles[1], &holderOut, &si.hStdOutput)) {
 300 
 301                 /* Error */
 302                 STDHOLDER holderErr = {{INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}, OFFSET_WRITE};
 303                 BOOL success;
 304                 if (redirectErrorStream) {
 305                     si.hStdError = si.hStdOutput;
 306                     /* Here we set the error stream to [ProcessBuilder.NullInputStream.INSTANCE]
 307                        value. That is in accordance with Java Doc for the redirection case.
 308                        The Java file for the [ handles[2] ] will be closed in ANY case. It is not
 309                        a handle leak. */
 310                     handles[2] = JAVA_INVALID_HANDLE_VALUE;
 311                     success = TRUE;
 312                 } else {
 313                     success = initHolder(env, &handles[2], &holderErr, &si.hStdError);
 314                 }
 315 
 316                 if (success) {
 317                     PROCESS_INFORMATION pi;
 318                     DWORD processFlag = CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT;
 319 
 320                     /* If the standard I/O is inherited, CREATE_NO_WINDOW must not be used. */
 321                     if (GetConsoleWindow() != NULL &&
 322                         (si.hStdInput  == stdIOE[0] ||
 323                          si.hStdOutput == stdIOE[1] ||
 324                          si.hStdError  == (redirectErrorStream ? stdIOE[1] : stdIOE[2])))
 325                     {
 326                         processFlag &= ~CREATE_NO_WINDOW;
 327                     }
 328 
 329                     si.dwFlags = STARTF_USESTDHANDLES;
 330                     if (!CreateProcessW(
 331                         NULL,             /* executable name */
 332                         (LPWSTR)pcmd,     /* command line */
 333                         NULL,             /* process security attribute */
 334                         NULL,             /* thread security attribute */
 335                         TRUE,             /* inherits system handles */
 336                         processFlag,      /* selected based on exe type */
 337                         (LPVOID)penvBlock,/* environment block */
 338                         (LPCWSTR)pdir,    /* change to the new current directory */
 339                         &si,              /* (in)  startup information */
 340                         &pi))             /* (out) process information */
 341                     {
 342                         win32Error(env, L"CreateProcess");
 343                     } else {
 344                         closeSafely(pi.hThread);
 345                         ret = (jlong)pi.hProcess;
 346                     }
 347                 }
 348                 releaseHolder(ret == 0, &holderErr);
 349                 releaseHolder(ret == 0, &holderOut);
 350             }
 351             releaseHolder(ret == 0, &holderIn);
 352         }
 353     }
 354     restoreIOEHandleState(stdIOE, inherit);
 355 
 356     return ret;
 357 }
 358 
 359 JNIEXPORT jlong JNICALL
 360 Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
 361                                   jstring cmd,
 362                                   jstring envBlock,
 363                                   jstring dir,
 364                                   jlongArray stdHandles,
 365                                   jboolean redirectErrorStream)
 366 {
 367     jlong ret = 0;
 368     if (cmd != NULL && stdHandles != NULL) {
 369         const jchar *pcmd = (*env)->GetStringChars(env, cmd, NULL);
 370         if (pcmd != NULL) {
 371             const jchar *penvBlock = (envBlock != NULL)
 372                 ? (*env)->GetStringChars(env, envBlock, NULL)
 373                 : NULL;
 374             if (!(*env)->ExceptionCheck(env)) {
 375                 const jchar *pdir = (dir != NULL)
 376                     ? (*env)->GetStringChars(env, dir, NULL)
 377                     : NULL;
 378                 if (!(*env)->ExceptionCheck(env)) {
 379                     jlong *handles = (*env)->GetLongArrayElements(env, stdHandles, NULL);
 380                     if (handles != NULL) {
 381                         ret = processCreate(
 382                             env,
 383                             pcmd,
 384                             penvBlock,
 385                             pdir,
 386                             handles,
 387                             redirectErrorStream);
 388                         (*env)->ReleaseLongArrayElements(env, stdHandles, handles, 0);
 389                     }
 390                     if (pdir != NULL)
 391                         (*env)->ReleaseStringChars(env, dir, pdir);
 392                 }
 393                 if (penvBlock != NULL)
 394                     (*env)->ReleaseStringChars(env, envBlock, penvBlock);
 395             }
 396             (*env)->ReleaseStringChars(env, cmd, pcmd);
 397         }
 398     }
 399     return ret;
 400 }
 401 
 402 JNIEXPORT jint JNICALL
 403 Java_java_lang_ProcessImpl_getExitCodeProcess(JNIEnv *env, jclass ignored, jlong handle)
 404 {
 405     DWORD exit_code;
 406     if (GetExitCodeProcess((HANDLE) handle, &exit_code) == 0)
 407         win32Error(env, L"GetExitCodeProcess");
 408     return exit_code;
 409 }
 410 
 411 JNIEXPORT jint JNICALL
 412 Java_java_lang_ProcessImpl_getStillActive(JNIEnv *env, jclass ignored)
 413 {
 414     return STILL_ACTIVE;
 415 }
 416 
 417 JNIEXPORT void JNICALL
 418 Java_java_lang_ProcessImpl_waitForInterruptibly(JNIEnv *env, jclass ignored, jlong handle)
 419 {
 420     HANDLE events[2];
 421     events[0] = (HANDLE) handle;
 422     events[1] = JVM_GetThreadInterruptEvent();
 423 
 424     if (WaitForMultipleObjects(sizeof(events)/sizeof(events[0]), events,
 425                                FALSE,    /* Wait for ANY event */
 426                                INFINITE)  /* Wait forever */
 427         == WAIT_FAILED)
 428         win32Error(env, L"WaitForMultipleObjects");
 429 }
 430 
 431 JNIEXPORT void JNICALL
 432 Java_java_lang_ProcessImpl_waitForTimeoutInterruptibly(JNIEnv *env,
 433                                                        jclass ignored,
 434                                                        jlong handle,
 435                                                        jlong timeout)
 436 {
 437     HANDLE events[2];
 438     DWORD dwTimeout = (DWORD)timeout;
 439     DWORD result;
 440     events[0] = (HANDLE) handle;
 441     events[1] = JVM_GetThreadInterruptEvent();
 442     result = WaitForMultipleObjects(sizeof(events)/sizeof(events[0]), events,
 443                                     FALSE,    /* Wait for ANY event */
 444                                     dwTimeout);  /* Wait for dwTimeout */
 445 
 446     if (result == WAIT_FAILED)
 447         win32Error(env, L"WaitForMultipleObjects");
 448 }
 449 
 450 JNIEXPORT void JNICALL
 451 Java_java_lang_ProcessImpl_terminateProcess(JNIEnv *env, jclass ignored, jlong handle)
 452 {
 453     TerminateProcess((HANDLE) handle, 1);
 454 }
 455 
 456 JNIEXPORT jboolean JNICALL
 457 Java_java_lang_ProcessImpl_isProcessAlive(JNIEnv *env, jclass ignored, jlong handle)
 458 {
 459     DWORD dwExitStatus;
 460     GetExitCodeProcess((HANDLE) handle, &dwExitStatus);
 461     return dwExitStatus == STILL_ACTIVE;
 462 }
 463 
 464 JNIEXPORT jboolean JNICALL
 465 Java_java_lang_ProcessImpl_closeHandle(JNIEnv *env, jclass ignored, jlong handle)
 466 {
 467     return (jboolean) CloseHandle((HANDLE) handle);
 468 }
 469 
 470 /**
 471  * Returns a copy of the Unicode characters of a string. Fow now this
 472  * function doesn't handle long path names and other issues.
 473  */
 474 static WCHAR* getPath(JNIEnv *env, jstring ps) {
 475     WCHAR *pathbuf = NULL;
 476     const jchar *chars = (*(env))->GetStringChars(env, ps, NULL);
 477     if (chars != NULL) {
 478         size_t pathlen = wcslen(chars);
 479         pathbuf = (WCHAR*)malloc((pathlen + 6) * sizeof(WCHAR));
 480         if (pathbuf == NULL) {
 481             JNU_ThrowOutOfMemoryError(env, NULL);
 482         } else {
 483             wcscpy(pathbuf, chars);
 484         }
 485         (*env)->ReleaseStringChars(env, ps, chars);
 486     }
 487     return pathbuf;
 488 }
 489 
 490 JNIEXPORT jlong JNICALL
 491 Java_java_lang_ProcessImpl_openForAtomicAppend(JNIEnv *env, jclass ignored, jstring path)
 492 {
 493     const DWORD access = (FILE_GENERIC_WRITE & ~FILE_WRITE_DATA);
 494     const DWORD sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
 495     const DWORD disposition = OPEN_ALWAYS;
 496     const DWORD flagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
 497     HANDLE h;
 498     WCHAR *pathbuf = getPath(env, path);
 499     if (pathbuf == NULL) {
 500         /* Exception already pending */
 501         return -1;
 502     }
 503     h = CreateFileW(
 504         pathbuf,            /* Wide char path name */
 505         access,             /* Read and/or write permission */
 506         sharing,            /* File sharing flags */
 507         NULL,               /* Security attributes */
 508         disposition,        /* creation disposition */
 509         flagsAndAttributes, /* flags and attributes */
 510         NULL);
 511     free(pathbuf);
 512     if (h == INVALID_HANDLE_VALUE) {
 513         JNU_ThrowIOExceptionWithLastError(env, "CreateFileW");
 514     }
 515     return ptr_to_jlong(h);
 516 }