128 if (handle != INVALID_HANDLE_VALUE) 129 CloseHandle(handle); 130 } 131 132 JNIEXPORT jlong JNICALL 133 Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored, 134 jstring cmd, 135 jstring envBlock, 136 jstring dir, 137 jlongArray stdHandles, 138 jboolean redirectErrorStream) 139 { 140 HANDLE inRead = INVALID_HANDLE_VALUE; 141 HANDLE inWrite = INVALID_HANDLE_VALUE; 142 HANDLE outRead = INVALID_HANDLE_VALUE; 143 HANDLE outWrite = INVALID_HANDLE_VALUE; 144 HANDLE errRead = INVALID_HANDLE_VALUE; 145 HANDLE errWrite = INVALID_HANDLE_VALUE; 146 SECURITY_ATTRIBUTES sa; 147 PROCESS_INFORMATION pi; 148 STARTUPINFO si; 149 LPTSTR pcmd = NULL; 150 LPCTSTR pdir = NULL; 151 LPVOID penvBlock = NULL; 152 jlong *handles = NULL; 153 jlong ret = 0; 154 OSVERSIONINFO ver; 155 jboolean onNT = JNI_FALSE; 156 DWORD processFlag; 157 158 ver.dwOSVersionInfoSize = sizeof(ver); 159 GetVersionEx(&ver); 160 if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) 161 onNT = JNI_TRUE; 162 163 assert(cmd != NULL); 164 pcmd = (LPTSTR) JNU_GetStringPlatformChars(env, cmd, NULL); 165 if (pcmd == NULL) goto Catch; 166 167 if (dir != 0) { 168 pdir = (LPCTSTR) JNU_GetStringPlatformChars(env, dir, NULL); 169 if (pdir == NULL) goto Catch; 170 pdir = (LPCTSTR) JVM_NativePath((char *)pdir); 171 } 172 173 if (envBlock != NULL) { 174 penvBlock = onNT 175 ? (LPVOID) ((*env)->GetStringChars(env, envBlock, NULL)) 176 : (LPVOID) JNU_GetStringPlatformChars(env, envBlock, NULL); 177 if (penvBlock == NULL) goto Catch; 178 } 179 180 assert(stdHandles != NULL); 181 handles = (*env)->GetLongArrayElements(env, stdHandles, NULL); 182 if (handles == NULL) goto Catch; 183 184 memset(&si, 0, sizeof(si)); 185 si.cb = sizeof(si); 186 si.dwFlags = STARTF_USESTDHANDLES; 187 188 sa.nLength = sizeof(sa); 189 sa.lpSecurityDescriptor = 0; 190 sa.bInheritHandle = TRUE; 191 192 if (handles[0] != (jlong) -1) { 193 si.hStdInput = (HANDLE) handles[0]; 194 handles[0] = (jlong) -1; 195 } else { 196 if (! CreatePipe(&inRead, &inWrite, &sa, PIPE_SIZE)) { 197 win32Error(env, "CreatePipe"); 198 goto Catch; 199 } 222 handles[2] = (jlong) -1; 223 } else if (handles[2] != (jlong) -1) { 224 si.hStdError = (HANDLE) handles[2]; 225 handles[2] = (jlong) -1; 226 } else { 227 if (! CreatePipe(&errRead, &errWrite, &sa, PIPE_SIZE)) { 228 win32Error(env, "CreatePipe"); 229 goto Catch; 230 } 231 si.hStdError = errWrite; 232 SetHandleInformation(errRead, HANDLE_FLAG_INHERIT, FALSE); 233 handles[2] = (jlong) errRead; 234 } 235 SetHandleInformation(si.hStdError, HANDLE_FLAG_INHERIT, TRUE); 236 237 if (onNT) 238 processFlag = CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT; 239 else 240 processFlag = selectProcessFlag(env, cmd); 241 242 /* Java and Windows are both pure Unicode systems at heart. 243 * Windows has both a legacy byte-based API and a 16-bit Unicode 244 * "W" API. The Right Thing here is to call CreateProcessW, since 245 * that will allow all process-related information like command 246 * line arguments to be passed properly to the child. We don't do 247 * that currently, since we would first have to have "W" versions 248 * of JVM_NativePath and perhaps other functions. In the 249 * meantime, we can call CreateProcess with the magic flag 250 * CREATE_UNICODE_ENVIRONMENT, which passes only the environment 251 * in "W" mode. We will fix this later. */ 252 253 ret = CreateProcess(0, /* executable name */ 254 pcmd, /* command line */ 255 0, /* process security attribute */ 256 0, /* thread security attribute */ 257 TRUE, /* inherits system handles */ 258 processFlag, /* selected based on exe type */ 259 penvBlock, /* environment block */ 260 pdir, /* change to the new current directory */ 261 &si, /* (in) startup information */ 262 &pi); /* (out) process information */ 263 264 if (!ret) { 265 win32Error(env, "CreateProcess"); 266 goto Catch; 267 } 268 269 CloseHandle(pi.hThread); 270 ret = (jlong)pi.hProcess; 271 272 Finally: 273 /* Always clean up the child's side of the pipes */ 274 closeSafely(inRead); 275 closeSafely(outWrite); 276 closeSafely(errWrite); 277 278 if (pcmd != NULL) 279 JNU_ReleaseStringPlatformChars(env, cmd, (char *) pcmd); 280 if (pdir != NULL) 281 JNU_ReleaseStringPlatformChars(env, dir, (char *) pdir); 282 if (penvBlock != NULL) { 283 if (onNT) 284 (*env)->ReleaseStringChars(env, envBlock, (jchar *) penvBlock); 285 else 286 JNU_ReleaseStringPlatformChars(env, dir, (char *) penvBlock); 287 } 288 if (handles != NULL) 289 (*env)->ReleaseLongArrayElements(env, stdHandles, handles, 0); 290 291 return ret; 292 293 Catch: 294 /* Clean up the parent's side of the pipes in case of failure only */ 295 closeSafely(inWrite); 296 closeSafely(outRead); 297 closeSafely(errRead); 298 goto Finally; 299 } 300 301 JNIEXPORT jint JNICALL 302 Java_java_lang_ProcessImpl_getExitCodeProcess(JNIEnv *env, jclass ignored, jlong handle) 303 { 304 DWORD exit_code; 305 if (GetExitCodeProcess((HANDLE) handle, &exit_code) == 0) 306 win32Error(env, "GetExitCodeProcess"); 307 return exit_code; 308 } 309 310 JNIEXPORT jint JNICALL | 128 if (handle != INVALID_HANDLE_VALUE) 129 CloseHandle(handle); 130 } 131 132 JNIEXPORT jlong JNICALL 133 Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored, 134 jstring cmd, 135 jstring envBlock, 136 jstring dir, 137 jlongArray stdHandles, 138 jboolean redirectErrorStream) 139 { 140 HANDLE inRead = INVALID_HANDLE_VALUE; 141 HANDLE inWrite = INVALID_HANDLE_VALUE; 142 HANDLE outRead = INVALID_HANDLE_VALUE; 143 HANDLE outWrite = INVALID_HANDLE_VALUE; 144 HANDLE errRead = INVALID_HANDLE_VALUE; 145 HANDLE errWrite = INVALID_HANDLE_VALUE; 146 SECURITY_ATTRIBUTES sa; 147 PROCESS_INFORMATION pi; 148 STARTUPINFOW si; 149 const jchar* pcmd = NULL; 150 const jchar* pdir = NULL; 151 const jchar* penvBlock = NULL; 152 jlong *handles = NULL; 153 jlong ret = 0; 154 OSVERSIONINFO ver; 155 jboolean onNT = JNI_FALSE; 156 DWORD processFlag; 157 158 ver.dwOSVersionInfoSize = sizeof(ver); 159 GetVersionEx(&ver); 160 if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) 161 onNT = JNI_TRUE; 162 163 assert(cmd != NULL); 164 pcmd = (*env)->GetStringChars(env, cmd, NULL); 165 if (pcmd == NULL) goto Catch; 166 167 if (dir != 0) { 168 pdir = (*env)->GetStringChars(env, dir, NULL); 169 if (pdir == NULL) goto Catch; 170 } 171 if (envBlock != NULL) { 172 penvBlock = ((*env)->GetStringChars(env, envBlock, NULL)); 173 if (penvBlock == NULL) goto Catch; 174 } 175 assert(stdHandles != NULL); 176 handles = (*env)->GetLongArrayElements(env, stdHandles, NULL); 177 if (handles == NULL) goto Catch; 178 179 memset(&si, 0, sizeof(si)); 180 si.cb = sizeof(si); 181 si.dwFlags = STARTF_USESTDHANDLES; 182 183 sa.nLength = sizeof(sa); 184 sa.lpSecurityDescriptor = 0; 185 sa.bInheritHandle = TRUE; 186 187 if (handles[0] != (jlong) -1) { 188 si.hStdInput = (HANDLE) handles[0]; 189 handles[0] = (jlong) -1; 190 } else { 191 if (! CreatePipe(&inRead, &inWrite, &sa, PIPE_SIZE)) { 192 win32Error(env, "CreatePipe"); 193 goto Catch; 194 } 217 handles[2] = (jlong) -1; 218 } else if (handles[2] != (jlong) -1) { 219 si.hStdError = (HANDLE) handles[2]; 220 handles[2] = (jlong) -1; 221 } else { 222 if (! CreatePipe(&errRead, &errWrite, &sa, PIPE_SIZE)) { 223 win32Error(env, "CreatePipe"); 224 goto Catch; 225 } 226 si.hStdError = errWrite; 227 SetHandleInformation(errRead, HANDLE_FLAG_INHERIT, FALSE); 228 handles[2] = (jlong) errRead; 229 } 230 SetHandleInformation(si.hStdError, HANDLE_FLAG_INHERIT, TRUE); 231 232 if (onNT) 233 processFlag = CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT; 234 else 235 processFlag = selectProcessFlag(env, cmd); 236 237 ret = CreateProcessW(0, /* executable name */ 238 (LPWSTR)pcmd, /* command line */ 239 0, /* process security attribute */ 240 0, /* thread security attribute */ 241 TRUE, /* inherits system handles */ 242 processFlag, /* selected based on exe type */ 243 (LPVOID)penvBlock,/* environment block */ 244 (LPCWSTR)pdir, /* change to the new current directory */ 245 &si, /* (in) startup information */ 246 &pi); /* (out) process information */ 247 248 if (!ret) { 249 win32Error(env, "CreateProcess"); 250 goto Catch; 251 } 252 253 CloseHandle(pi.hThread); 254 ret = (jlong)pi.hProcess; 255 256 Finally: 257 /* Always clean up the child's side of the pipes */ 258 closeSafely(inRead); 259 closeSafely(outWrite); 260 closeSafely(errWrite); 261 262 if (pcmd != NULL) 263 (*env)->ReleaseStringChars(env, cmd, pcmd); 264 if (pdir != NULL) 265 (*env)->ReleaseStringChars(env, dir, pdir); 266 if (penvBlock != NULL) 267 (*env)->ReleaseStringChars(env, envBlock, penvBlock); 268 if (handles != NULL) 269 (*env)->ReleaseLongArrayElements(env, stdHandles, handles, 0); 270 return ret; 271 272 Catch: 273 /* Clean up the parent's side of the pipes in case of failure only */ 274 closeSafely(inWrite); 275 closeSafely(outRead); 276 closeSafely(errRead); 277 goto Finally; 278 } 279 280 JNIEXPORT jint JNICALL 281 Java_java_lang_ProcessImpl_getExitCodeProcess(JNIEnv *env, jclass ignored, jlong handle) 282 { 283 DWORD exit_code; 284 if (GetExitCodeProcess((HANDLE) handle, &exit_code) == 0) 285 win32Error(env, "GetExitCodeProcess"); 286 return exit_code; 287 } 288 289 JNIEXPORT jint JNICALL |