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 char *
  44 extractExecutablePath(JNIEnv *env, char *source)
  45 {
  46     char *p, *r;
  47 
  48     /* If no spaces, then use entire thing */
  49     if ((p = strchr(source, ' ')) == NULL)
  50         return source;
  51 
  52     /* If no quotes, or quotes after space, return up to space */
  53     if (((r = strchr(source, '"')) == NULL) || (r > p)) {
  54         *p = 0;
  55         return source;
  56     }
  57 
  58     /* Quotes before space, return up to space after next quotes */
  59     p = strchr(r, '"');
  60     if ((p = strchr(p, ' ')) == NULL)
  61         return source;
  62     *p = 0;
  63     return source;
  64 }
  65 
  66 static const char EXE_EXT[] = ".exe";
  67 
  68 DWORD
  69 selectProcessFlag(JNIEnv *env, jstring cmd0)
  70 {
  71     DWORD newFlag = 0;
  72     char *exe = (char *)JNU_GetStringPlatformChars(env, cmd0, 0);
  73     if (exe != NULL) {
  74         char buf[MAX_PATH];
  75         char *name;
  76         DWORD len;
  77         exe = extractExecutablePath(env, exe);
  78         if (exe != NULL) {
  79             /* We are here for Win9x/Me, so the [/] is not the path sep */
  80             char *p = strrchr(exe, '\\');
  81             if (p == NULL) {
  82                 len = SearchPath(NULL, exe, EXE_EXT, MAX_PATH, buf, &name);
  83             } else {
  84                 *p = 0;
  85                 len = SearchPath(exe, p + 1, EXE_EXT, MAX_PATH, buf, &name);
  86             }
  87         }
  88 
  89         if (len > 0 && len < MAX_PATH) {
  90             /* Here the [buf] path is valid and null terminated */
  91             int fd = _open(buf, _O_RDONLY);
  92             if (fd != -1) {
  93                 unsigned char buffer[2];
  94                 if (_read(fd, buffer, 2) == 2
  95                     && buffer[0] == 'M' && buffer[1] == 'Z'
  96                     && _lseek(fd, 60L, SEEK_SET) == 60L
  97                     && _read(fd, buffer, 2) == 2)
  98                 {
  99                     long headerLoc = (long)buffer[1] << 8 | (long)buffer[0];
 100                     if (_lseek(fd, headerLoc, SEEK_SET) == headerLoc
 101                         && _read(fd, buffer, 2) == 2
 102                         && buffer[0] == 'P' && buffer[1] == 'E')
 103                     {
 104                         newFlag = DETACHED_PROCESS;
 105                     }
 106                 }
 107                 _close(fd);
 108             }
 109         }
 110         JNU_ReleaseStringPlatformChars(env, cmd0, exe);
 111     }
 112     return newFlag;
 113 }
 114 
 115 static void
 116 win32Error(JNIEnv *env, const char *functionName)
 117 {
 118     static const char * const format = "%s error=%d, %s";
 119     static const char * const fallbackFormat = "%s failed, error=%d";
 120     char buf[256];
 121     char errmsg[sizeof(buf) + 100];
 122     const int errnum = GetLastError();
 123     const int n = JVM_GetLastErrorString(buf, sizeof(buf));
 124     if (n > 0)
 125         sprintf(errmsg, format, functionName, errnum, buf);
 126     else
 127         sprintf(errmsg, fallbackFormat, functionName, errnum);
 128     JNU_ThrowIOException(env, errmsg);
 129 }
 130 
 131 static void
 132 closeSafely(HANDLE handle)
 133 {
 134     if (handle != INVALID_HANDLE_VALUE)
 135         CloseHandle(handle);
 136 }
 137 
 138 static BOOL hasInheritFlag(HANDLE handle)
 139 {
 140     DWORD mask;
 141     if (GetHandleInformation(handle, &mask)) {
 142         return mask & HANDLE_FLAG_INHERIT;
 143     }
 144     return FALSE;
 145 }
 146 
 147 #define HANDLE_STORAGE_SIZE 6
 148 #define OFFSET_READ  0
 149 #define OFFSET_WRITE 1
 150 //long signed version of INVALID_HANDLE_VALUE
 151 #define JAVA_INVALID_HANDLE_VALUE ((jlong) -1)
 152 #define OPPOSITE_END(offset) (offset==OFFSET_READ ? OFFSET_WRITE : OFFSET_READ)
 153 
 154 /* Pipe holder structure */
 155 typedef struct _STDHOLDER {
 156     HANDLE  pipe[2];
 157     int     offset;
 158 } STDHOLDER;
 159 
 160 /* Responsible for correct initialization of the [pHolder] structure
 161    (that is used for handles recycling) if needs,
 162    and appropriate setup of IOE handle [phStd] for child process based
 163    on created pipe or Java handle. */
 164 static BOOL initHolder(
 165     JNIEnv *env,
 166     jlong *pjhandles,   /* IN OUT - the handle form Java,
 167                                     that can be a file, console or undefined */
 168     STDHOLDER *pHolder, /* OUT    - initialized structure that holds pipe
 169                                     handles */
 170     HANDLE *phStd       /* OUT    - initialized handle for child process */
 171 ) {
 172     /* Here we test the value from Java against invalid
 173        handle value. We are not using INVALID_HANDLE_VALUE macro
 174        due to double signed/unsigned and 32/64bit ambiguity.
 175        Otherwise it will be easy to get the wrong
 176        value   0x00000000FFFFFFFF
 177        instead 0xFFFFFFFFFFFFFFFF. */
 178     if (*pjhandles != JAVA_INVALID_HANDLE_VALUE) {
 179         /* Java file or console redirection */
 180         *phStd = (HANDLE) *pjhandles;
 181         /* Here we set the related Java stream (Process.getXXXXStream())
 182            to [ProcessBuilder.NullXXXXStream.INSTANCE] value.
 183            The initial Java handle [*pjhandles] will be closed in
 184            ANY case. It is not a handle leak. */
 185         *pjhandles = JAVA_INVALID_HANDLE_VALUE;
 186     } else {
 187         /* Creation of parent-child pipe */
 188         if (!CreatePipe(
 189             &pHolder->pipe[OFFSET_READ],
 190             &pHolder->pipe[OFFSET_WRITE],
 191             NULL, /* we would like to inherit
 192                      default process access,
 193                      instead of 'Everybody' access */
 194             PIPE_SIZE))
 195         {
 196             win32Error(env, "CreatePipe");
 197             return FALSE;
 198         } else {
 199             /* [thisProcessEnd] has no the inherit flag because
 200                the [lpPipeAttributes] param of [CreatePipe]
 201                had the NULL value. */
 202             HANDLE thisProcessEnd = pHolder->pipe[OPPOSITE_END(pHolder->offset)];
 203             *phStd = pHolder->pipe[pHolder->offset];
 204             *pjhandles = (jlong) thisProcessEnd;
 205         }
 206     }
 207     /* Pipe handle will be closed in the [releaseHolder] call,
 208        file handle will be closed in Java.
 209        The long-live handle need to restore the inherit flag,
 210        we do it later in the [prepareIOEHandleState] call. */
 211     SetHandleInformation(
 212         *phStd,
 213         HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
 214     return TRUE;
 215 }
 216 
 217 /* Smart recycling of pipe handles in [pHolder]. For the failed
 218    create process attempts, both ends of pipe need to be released.
 219    The [complete] has the [TRUE] value in the failed attempt. */
 220 static void releaseHolder(BOOL complete, STDHOLDER *pHolder) {
 221     closeSafely(pHolder->pipe[pHolder->offset]);
 222     if (complete) {
 223         /* Error occur, close this process pipe end */
 224         closeSafely(pHolder->pipe[OPPOSITE_END(pHolder->offset)]);
 225     }
 226 }
 227 
 228 /* Stores and drops the inherit flag of handles that should not
 229    be shared with the child process by default, but can hold the
 230    inherit flag due to MS process birth specific. */
 231 static void prepareIOEHandleState(
 232     HANDLE *stdIOE,
 233     BOOL *inherit)
 234 {
 235     int i;
 236     for (i = 0; i < HANDLE_STORAGE_SIZE; ++i) {
 237         HANDLE hstd = stdIOE[i];
 238         if (INVALID_HANDLE_VALUE != hstd && hasInheritFlag(hstd)) {
 239             /* FALSE by default */
 240             inherit[i] = TRUE;
 241             /* Java does not need implicit inheritance for IOE handles,
 242                so we drop inherit flag that probably was installed by
 243                previous CreateProcess call that launched current process.
 244                We will return the handle state back after CreateProcess call.
 245                By clearing inherit flag we prevent "greedy grandchild" birth.
 246                The explicit inheritance for child process IOE handles is
 247                implemented in the [initHolder] call. */
 248             SetHandleInformation(hstd, HANDLE_FLAG_INHERIT, 0);
 249         }
 250     }
 251 }
 252 
 253 /* Restores the inheritance flag of handles from stored values. */
 254 static void restoreIOEHandleState(
 255     const HANDLE *stdIOE,
 256     const BOOL *inherit)
 257 {
 258     /* The set of current process standard IOE handles and
 259        the set of child process IOE handles can intersect.
 260        To restore the inherit flag right, we use backward
 261        array iteration. */
 262     int i;
 263     for (i = HANDLE_STORAGE_SIZE - 1; i >= 0; --i)
 264         if (INVALID_HANDLE_VALUE != stdIOE[i]) {
 265            /* Restore inherit flag for any case.
 266               The handle can be changed by explicit inheritance.*/
 267             SetHandleInformation(stdIOE[i],
 268                 HANDLE_FLAG_INHERIT,
 269                 inherit[i] ? HANDLE_FLAG_INHERIT : 0);
 270         }
 271 }
 272 
 273 /* Please, read about the MS inheritance problem
 274    http://support.microsoft.com/kb/315939
 275    and critical section/synchronized block solution. */
 276 static jlong processCreate(
 277     JNIEnv *env,
 278     const jchar *pcmd,
 279     const jchar *penvBlock,
 280     const jchar *pdir,
 281     jlong *handles,
 282     jboolean redirectErrorStream)
 283 {
 284     jlong ret = 0L;
 285     STARTUPINFOW si = {sizeof(si)};
 286 
 287     /* Handles for which the inheritance flag must be restored. */
 288     HANDLE stdIOE[HANDLE_STORAGE_SIZE] = {
 289         /* Current process standard IOE handles: JDK-7147084 */
 290         INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE,
 291         /* Child process IOE handles: JDK-6921885 */
 292         (HANDLE)handles[0], (HANDLE)handles[1], (HANDLE)handles[2]};
 293     BOOL inherit[HANDLE_STORAGE_SIZE] = {
 294         FALSE, FALSE, FALSE,
 295         FALSE, FALSE, FALSE};
 296 
 297     {
 298         /* Extraction of current process standard IOE handles */
 299         DWORD idsIOE[3] = {STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE};
 300         int i;
 301         for (i = 0; i < 3; ++i)
 302             /* Should not be closed by CloseHandle! */
 303             stdIOE[i] = GetStdHandle(idsIOE[i]);
 304     }
 305 
 306     prepareIOEHandleState(stdIOE, inherit);
 307     {
 308         /* Input */
 309         STDHOLDER holderIn = {{INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}, OFFSET_READ};
 310         if (initHolder(env, &handles[0], &holderIn, &si.hStdInput)) {
 311 
 312             /* Output */
 313             STDHOLDER holderOut = {{INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}, OFFSET_WRITE};
 314             if (initHolder(env, &handles[1], &holderOut, &si.hStdOutput)) {
 315 
 316                 /* Error */
 317                 STDHOLDER holderErr = {{INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}, OFFSET_WRITE};
 318                 BOOL success;
 319                 if (redirectErrorStream) {
 320                     si.hStdError = si.hStdOutput;
 321                     /* Here we set the error stream to [ProcessBuilder.NullInputStream.INSTANCE]
 322                        value. That is in accordance with Java Doc for the redirection case.
 323                        The Java file for the [ handles[2] ] will be closed in ANY case. It is not
 324                        a handle leak. */
 325                     handles[2] = JAVA_INVALID_HANDLE_VALUE;
 326                     success = TRUE;
 327                 } else {
 328                     success = initHolder(env, &handles[2], &holderErr, &si.hStdError);
 329                 }
 330 
 331                 if (success) {
 332                     PROCESS_INFORMATION pi;
 333                     DWORD processFlag = CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT;
 334 
 335                     si.dwFlags = STARTF_USESTDHANDLES;
 336                     if (!CreateProcessW(
 337                         NULL,             /* executable name */
 338                         (LPWSTR)pcmd,     /* command line */
 339                         NULL,             /* process security attribute */
 340                         NULL,             /* thread security attribute */
 341                         TRUE,             /* inherits system handles */
 342                         processFlag,      /* selected based on exe type */
 343                         (LPVOID)penvBlock,/* environment block */
 344                         (LPCWSTR)pdir,    /* change to the new current directory */
 345                         &si,              /* (in)  startup information */
 346                         &pi))             /* (out) process information */
 347                     {
 348                         win32Error(env, "CreateProcess");
 349                     } else {
 350                         closeSafely(pi.hThread);
 351                         ret = (jlong)pi.hProcess;
 352                     }
 353                 }
 354                 releaseHolder(ret == 0, &holderErr);
 355                 releaseHolder(ret == 0, &holderOut);
 356             }
 357             releaseHolder(ret == 0, &holderIn);
 358         }
 359     }
 360     restoreIOEHandleState(stdIOE, inherit);
 361 
 362     return ret;
 363 }
 364 
 365 JNIEXPORT jlong JNICALL
 366 Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
 367                                   jstring cmd,
 368                                   jstring envBlock,
 369                                   jstring dir,
 370                                   jlongArray stdHandles,
 371                                   jboolean redirectErrorStream)
 372 {
 373     jlong ret = 0;
 374     if (cmd != NULL && stdHandles != NULL) {
 375         const jchar *pcmd = (*env)->GetStringChars(env, cmd, NULL);
 376         if (pcmd != NULL) {
 377             const jchar *penvBlock = (envBlock != NULL)
 378                 ? (*env)->GetStringChars(env, envBlock, NULL)
 379                 : NULL;
 380             const jchar *pdir = (dir != NULL)
 381                 ? (*env)->GetStringChars(env, dir, NULL)
 382                 : NULL;
 383             jlong *handles = (*env)->GetLongArrayElements(env, stdHandles, NULL);
 384             if (handles != NULL) {
 385                 ret = processCreate(
 386                     env,
 387                     pcmd,
 388                     penvBlock,
 389                     pdir,
 390                     handles,
 391                     redirectErrorStream);
 392                 (*env)->ReleaseLongArrayElements(env, stdHandles, handles, 0);
 393             }
 394             if (pdir != NULL)
 395                 (*env)->ReleaseStringChars(env, dir, pdir);
 396             if (penvBlock != NULL)
 397                 (*env)->ReleaseStringChars(env, envBlock, penvBlock);
 398             (*env)->ReleaseStringChars(env, cmd, pcmd);
 399         }
 400     }
 401     return ret;
 402 }
 403 
 404 JNIEXPORT jint JNICALL
 405 Java_java_lang_ProcessImpl_getExitCodeProcess(JNIEnv *env, jclass ignored, jlong handle)
 406 {
 407     DWORD exit_code;
 408     if (GetExitCodeProcess((HANDLE) handle, &exit_code) == 0)
 409         win32Error(env, "GetExitCodeProcess");
 410     return exit_code;
 411 }
 412 
 413 JNIEXPORT jint JNICALL
 414 Java_java_lang_ProcessImpl_getStillActive(JNIEnv *env, jclass ignored)
 415 {
 416     return STILL_ACTIVE;
 417 }
 418 
 419 JNIEXPORT void JNICALL
 420 Java_java_lang_ProcessImpl_waitForInterruptibly(JNIEnv *env, jclass ignored, jlong handle)
 421 {
 422     HANDLE events[2];
 423     events[0] = (HANDLE) handle;
 424     events[1] = JVM_GetThreadInterruptEvent();
 425 
 426     if (WaitForMultipleObjects(sizeof(events)/sizeof(events[0]), events,
 427                                FALSE,    /* Wait for ANY event */
 428                                INFINITE) /* Wait forever */
 429         == WAIT_FAILED)
 430         win32Error(env, "WaitForMultipleObjects");
 431 }
 432 
 433 JNIEXPORT void JNICALL
 434 Java_java_lang_ProcessImpl_terminateProcess(JNIEnv *env, jclass ignored, jlong handle)
 435 {
 436     TerminateProcess((HANDLE) handle, 1);
 437 }
 438 
 439 JNIEXPORT jboolean JNICALL
 440 Java_java_lang_ProcessImpl_closeHandle(JNIEnv *env, jclass ignored, jlong handle)
 441 {
 442     return CloseHandle((HANDLE) handle);
 443 }
 444 
 445 /**
 446  * Returns a copy of the Unicode characters of a string. Fow now this
 447  * function doesn't handle long path names and other issues.
 448  */
 449 static WCHAR* getPath(JNIEnv *env, jstring ps) {
 450     WCHAR *pathbuf = NULL;
 451     const jchar *chars = (*(env))->GetStringChars(env, ps, NULL);
 452     if (chars != NULL) {
 453         size_t pathlen = wcslen(chars);
 454         pathbuf = (WCHAR*)malloc((pathlen + 6) * sizeof(WCHAR));
 455         if (pathbuf == NULL) {
 456             JNU_ThrowOutOfMemoryError(env, NULL);
 457         } else {
 458             wcscpy(pathbuf, chars);
 459         }
 460         (*env)->ReleaseStringChars(env, ps, chars);
 461     }
 462     return pathbuf;
 463 }
 464 
 465 JNIEXPORT jlong JNICALL
 466 Java_java_lang_ProcessImpl_openForAtomicAppend(JNIEnv *env, jclass ignored, jstring path)
 467 {
 468     const DWORD access = (FILE_GENERIC_WRITE & ~FILE_WRITE_DATA);
 469     const DWORD sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
 470     const DWORD disposition = OPEN_ALWAYS;
 471     const DWORD flagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
 472     HANDLE h;
 473     WCHAR *pathbuf = getPath(env, path);
 474     if (pathbuf == NULL) {
 475         /* Exception already pending */
 476         return -1;
 477     }
 478     h = CreateFileW(
 479         pathbuf,            /* Wide char path name */
 480         access,             /* Read and/or write permission */
 481         sharing,            /* File sharing flags */
 482         NULL,               /* Security attributes */
 483         disposition,        /* creation disposition */
 484         flagsAndAttributes, /* flags and attributes */
 485         NULL);
 486     free(pathbuf);
 487     if (h == INVALID_HANDLE_VALUE) {
 488         JNU_ThrowIOExceptionWithLastError(env, "CreateFileW");
 489     }
 490     return ptr_to_jlong(h);
 491 }