/* * Class: jcuda_jcufft_JCufft * Method: cufftGetVersionNative * Signature: ([I)I */ JNIEXPORT jint JNICALL Java_jcuda_jcufft_JCufft_cufftGetVersionNative (JNIEnv *env, jclass cls, jintArray version) { if (version == NULL) { ThrowByName(env, "java/lang/NullPointerException", "Parameter 'version' is null for cufftGetVersion"); return JCUFFT_INTERNAL_ERROR; } Logger::log(LOG_TRACE, "Executing cufftGetVersion\n"); int nativeVersion = 0; int result = cufftGetVersion(&nativeVersion); set(env, version, 0, nativeVersion); return result; }
/* * Class: jcuda_jcufft_JCufft * Method: cufftPlan3dNative * Signature: (Ljcuda/jcufft/JCufftHandle;IIII)I */ JNIEXPORT jint JNICALL Java_jcuda_jcufft_JCufft_cufftPlan3dNative (JNIEnv *env, jclass cla, jobject handle, jint nx, jint ny, jint nz, jint type) { if (handle == NULL) { ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cufftPlan3d"); return JCUFFT_INTERNAL_ERROR; } Logger::log(LOG_TRACE, "Creating 3D plan for (%d, %d, %d) elements of type %d\n", nx, ny, nz, type); cufftHandle plan = env->GetIntField(handle, cufftHandle_plan); cufftResult result = cufftPlan3d(&plan, nx, ny, nz, getCufftType(type)); env->SetIntField(handle, cufftHandle_plan, plan); return result; }
bool releaseNative(JNIEnv *env, cl_double2& values_native, jdoubleArray values, bool writeBack) { if (writeBack) { jsize length = env->GetArrayLength(values); if (length < 2) { ThrowByName(env, "java/lang/ArrayIndexOutOfBoundsException", "Array length must be at least 2"); } jdouble localValues[2]; localValues[0] = (jdouble)values_native.x; localValues[1] = (jdouble)values_native.y; env->SetDoubleArrayRegion(values, 0, 2, localValues); } return true; }
bool initNative(JNIEnv *env, jdoubleArray values, cl_double2& values_native, bool fillTarget) { if (fillTarget) { jsize length = env->GetArrayLength(values); if (length < 2) { ThrowByName(env, "java/lang/ArrayIndexOutOfBoundsException", "Array length must be at least 2"); } jdouble localValues[2]; env->GetDoubleArrayRegion(values, 0, 2, localValues); values_native.x = (cl_double)localValues[0]; values_native.y = (cl_double)localValues[1]; } return true; }
/* * Class: jcuda_jcufft_JCufft * Method: cufftEstimate3dNative * Signature: (IIII[J)I */ JNIEXPORT jint JNICALL Java_jcuda_jcufft_JCufft_cufftEstimate3dNative (JNIEnv *env, jclass cls, jint nx, jint ny, jint nz, jint type, jlongArray workSize) { if (workSize == NULL) { ThrowByName(env, "java/lang/NullPointerException", "Parameter 'workSize' is null for cufftEstimate3d"); return JCUFFT_INTERNAL_ERROR; } Logger::log(LOG_TRACE, "Executing cufftEstimate3d\n"); size_t nativeWorkSize = 0; cufftResult result = cufftEstimate3d((int)nx, (int)ny, (int)nz, getCufftType(type), &nativeWorkSize); set(env, workSize, 0, (jlong)nativeWorkSize); return result; }
/* * Class: jcuda_jcufft_JCufft * Method: cufftSetCompatibilityModeNative * Signature: (Ljcuda/jcufft/cufftHandle;I)I */ JNIEXPORT jint JNICALL Java_jcuda_jcufft_JCufft_cufftSetCompatibilityModeNative (JNIEnv *env, jclass cla, jobject plan, jint mode) { if (plan == NULL) { ThrowByName(env, "java/lang/NullPointerException", "Parameter 'plan' is null for cufftSetCompatibilityMode"); return JCUFFT_INTERNAL_ERROR; } Logger::log(LOG_TRACE, "Executing cufftSetCompatibilityMode\n"); cufftHandle nativePlan = env->GetIntField(plan, cufftHandle_plan); cufftCompatibility nativeMode = (cufftCompatibility)mode; cufftResult result = cufftSetCompatibilityMode(nativePlan, nativeMode); return result; }
/* * Class: jcuda_jcufft_JCufft * Method: cufftCreateNative * Signature: (Ljcuda/jcufft/cufftHandle;)I */ JNIEXPORT jint JNICALL Java_jcuda_jcufft_JCufft_cufftCreateNative (JNIEnv *env, jclass cls, jobject handle) { if (handle == NULL) { ThrowByName(env, "java/lang/NullPointerException", "Parameter 'handle' is null for cufftCreate"); return JCUFFT_INTERNAL_ERROR; } Logger::log(LOG_TRACE, "Executing cufftCreate\n"); cufftHandle nativeHandle = env->GetIntField(handle, cufftHandle_plan); cufftResult result = cufftCreate(&nativeHandle); env->SetIntField(handle, cufftHandle_plan, nativeHandle); return result; }
bool init(JNIEnv *env, jobject object) { // Obtain the direct buffer address from the given buffer jobject buffer = env->GetObjectField(object, Pointer_buffer); startPointer = env->GetDirectBufferAddress(buffer); if (startPointer == 0) { ThrowByName(env, "java/lang/IllegalArgumentException", "Failed to obtain direct buffer address"); return false; } // Obtain the byteOffset byteOffset = env->GetLongField(object, Pointer_byteOffset); if (env->ExceptionCheck()) { return false; } Logger::log(LOG_DEBUGTRACE, "Initialized DirectBufferPointerData %p\n", startPointer); return true; }
/** * Converts the given jlongArray into a size_t* and returns it. * To delete the size_t* is left to the caller. Returns * NULL if an error occurs. */ size_t* convertArray(JNIEnv *env, jlongArray array) { jsize arrayLength = env->GetArrayLength(array); size_t *result = new size_t[(size_t)arrayLength]; if (result == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", "Out of memory during array creation"); return NULL; } jlong *jArray = (jlong*)env->GetPrimitiveArrayCritical(array, NULL); if (jArray == NULL) { return NULL; } for (int i=0; i<arrayLength; i++) { result[i] = (size_t)jArray[i]; } env->ReleasePrimitiveArrayCritical(array, jArray, JNI_ABORT); return result; }
bool init(JNIEnv *env, jobject object) { if (object != NULL) { // Create a global reference to the given object nativePointerObject = env->NewGlobalRef(object); if (nativePointerObject == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", "Out of memory while creating global reference for pointer data"); return false; } // Obtain the nativePointer value nativePointer = env->GetLongField(object, NativePointerObject_nativePointer); if (env->ExceptionCheck()) { return false; } } Logger::log(LOG_DEBUGTRACE, "Initialized NativePointerObjectPointerData %p\n", nativePointer); return true; }
bool setNewNativePointerValue(JNIEnv *env, jlong nativePointerValue) { ThrowByName(env, "java/lang/IllegalArgumentException", "Pointer to an array may not be overwritten"); return false; }
bool release(JNIEnv *env, jint mode=0) { Logger::log(LOG_DEBUGTRACE, "Releasing PointersArrayPointerData %p\n", startPointer); jobjectArray pointersArray = (jobjectArray)env->GetObjectField( nativePointerObject, Pointer_pointers); long size = (long)env->GetArrayLength(pointersArray); void **localPointer = (void**)startPointer; if (mode != JNI_ABORT) { // Write back the values from the native pointers array // into the Java objects for (int i=0; i<size; i++) { jobject p = env->GetObjectArrayElement(pointersArray, i); if (env->ExceptionCheck()) { return false; } if (p != NULL) { // Check whether the value inside the pointer array has changed. void *oldLocalPointer = arrayPointerDatas[i]->getPointer(env); Logger::log(LOG_DEBUGTRACE, "About to write back pointer %d in PointersArrayPointerData\n", i); Logger::log(LOG_DEBUGTRACE, "Old local pointer was %p\n", oldLocalPointer); Logger::log(LOG_DEBUGTRACE, "New local pointer is %p\n", localPointer[i]); if (localPointer[i] != oldLocalPointer) { Logger::log(LOG_DEBUGTRACE, "In pointer %d setting value %p\n", i, localPointer[i]); bool pointerUpdated = arrayPointerDatas[i]->setNewNativePointerValue(env, (jlong)localPointer[i]); if (!pointerUpdated) { // If the pointer value could not be updated, // (see setNewNativePointerValue documentation) // then there is a pending IllegalArgumentException return false; } } } else if (localPointer[i] != NULL) { // TODO: In future versions, it might be necessary to instantiate // a pointer object here ThrowByName(env, "java/lang/NullPointerException", "Pointer points to an array containing a 'null' entry"); return false; } } } // Release the PointerDatas for the pointer objects that // the pointer points to if (arrayPointerDatas != NULL) { for (int i=0; i<size; i++) { if (arrayPointerDatas[i] != NULL) { if (!releasePointerData(env, arrayPointerDatas[i], mode)) return false; } } delete[] arrayPointerDatas; } delete[] localPointer; env->DeleteGlobalRef(nativePointerObject); return true; }
bool init(JNIEnv *env, jobject object) { // Create a global reference to the given object nativePointerObject = env->NewGlobalRef(object); if (nativePointerObject == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", "Out of memory while creating global reference for pointer data"); return false; } jobjectArray pointersArray = (jobjectArray)env->GetObjectField( object, Pointer_pointers); long size = (long)env->GetArrayLength(pointersArray); // Prepare the pointer that points to the pointer // values of the NativePointerObjects void **localPointer = new void*[size]; if (localPointer == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", "Out of memory while initializing pointer array"); return false; } startPointer = (void*)localPointer; // Prepare the PointerData objects for the Java NativePointerObjects arrayPointerDatas = new PointerData*[size]; if (arrayPointerDatas == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", "Out of memory while initializing pointer data array"); return false; } // Initialize the PointerDatas and the pointer values // from the NativePointerObjects in the Java Pointer. for (int i=0; i<size; i++) { jobject p = env->GetObjectArrayElement(pointersArray, i); if (env->ExceptionCheck()) { return false; } if (p != NULL) { // Initialize a PointerData for the pointer object that // the pointer points to PointerData *arrayPointerData = initPointerData(env, p); if (arrayPointerData == NULL) { return false; } arrayPointerDatas[i] = arrayPointerData; localPointer[i] = arrayPointerData->getPointer(env); } else { arrayPointerDatas[i] = NULL; localPointer[i] = NULL; } } // Obtain the byteOffset byteOffset = env->GetLongField(object, Pointer_byteOffset); if (env->ExceptionCheck()) { return false; } Logger::log(LOG_DEBUGTRACE, "Initialized PointersArrayPointerData %p\n", startPointer); return true; }
/** * Initializes a PointerData with the data from the given Java NativePointerObject. * * If the given pointerObject is NULL, the method simply sets the startPointer * and pointer of the pointerData to NULL and returns it. * * Otherwise, this method will initialize the startPointer of the PointerData, * and the pointer of the PointerData will be set to * startPointer+byteOffset * where byteOffset is the byteOffset that is obtained from the Java Pointer * object. * * By default, the startPointer of the PointerData will be initialized with * the native pointer value from the given Java Pointer object. If this * startPointer is non-NULL, the method sets memoryType to NATIVE and * returns it. * * If the array of Java Pointers that the Pointer points to is non-NULL, then * the startPointer of the PointerData be set to point to an array of * void* pointers that correspond to the values of the Java Pointers * from the array. If this array can be created, the method sets the * memoryType to POINTERS and returns the PointerData. * * If the Buffer of the Pointer is non-null, then the startPointer will be * obtained from the buffer: * - If the Buffer is direct, this method sets the startPointer to the * direct buffer address, sets memoryType to DIRECT and returns the * PointerData * - If the buffer has an array, the method sets the startPointer to the * array, sets memoryType to ARRAY or ARRAY_COPY, indicating whether * the array was pinned or copied, and returns the PointerData. * * If none of these attempts of obtaining the startPointer was * successful, then the method returns the empty PointerData. * * If an Exception occurs, NULL is returned. */ PointerData* initPointerData(JNIEnv *env, jobject pointerObject) { Logger::log(LOG_DEBUGTRACE, "Initializing pointer data for Java Pointer object %p\n", pointerObject); PointerData *pointerData = new PointerData(); if (pointerData == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", "Out of memory while initializing pointer data"); return NULL; } pointerData->startPointer = (jlong)NULL; pointerData->pointer = (jlong)NULL; pointerData->memoryType = NATIVE; if (pointerObject == NULL) { return pointerData; } else { pointerData->pointerObject = env->NewGlobalRef(pointerObject); if (pointerData->pointerObject == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", "Out of memory while creating reference to pointer object"); return NULL; } } pointerData->startPointer = env->GetLongField(pointerData->pointerObject, NativePointerObject_nativePointer); // Set the actual pointer to be the startPointer + the byte offset long byteOffset = (long)env->GetLongField(pointerObject, NativePointerObject_byteOffset); pointerData->pointer = (jlong)(((char*)pointerData->startPointer)+byteOffset); if (pointerData->startPointer != (jlong)NULL) { Logger::log(LOG_DEBUGTRACE, "Obtaining native pointer %p\n", (void*)pointerData->startPointer); pointerData->memoryType = NATIVE; return pointerData; } // Obtain the array of pointers the pointer points to jobjectArray pointersArray = (jobjectArray)env->GetObjectField(pointerObject, NativePointerObject_pointers); if (pointersArray != NULL) { Logger::log(LOG_DEBUGTRACE, "Obtaining pointers in host memory\n"); // Create an array containing the native representations of the // pointers, and store them as the data of the pointerData jsize size = env->GetArrayLength(pointersArray); void **localPointer = new void*[(size_t)size]; PointerData **localPointerDatas = new PointerData*[(size_t)size]; if (localPointer == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", "Out of memory while obtaining native pointers"); return NULL; } for (int i=0; i<size; i++) { jobject p = env->GetObjectArrayElement(pointersArray, i); if (env->ExceptionCheck()) { return NULL; } if (p != NULL) { // Initialize a PointerData for the pointer object that // the pointer points to PointerData *localPointerData = initPointerData(env, p); if (localPointerData == NULL) { return NULL; } localPointerDatas[i] = localPointerData; localPointer[i] = (void*)localPointerData->startPointer; } else { localPointerDatas[i] = NULL; localPointer[i] = NULL; } } pointerData->pointers = localPointerDatas; pointerData->startPointer = (jlong)localPointer; // Set the actual pointer to be the startPointer + the byte offset long byteOffset = (long)env->GetLongField(pointerObject, NativePointerObject_byteOffset); pointerData->pointer = (jlong)(((char*)pointerData->startPointer)+byteOffset); pointerData->memoryType = POINTERS; return pointerData; } jobject buffer = env->GetObjectField(pointerObject, NativePointerObject_buffer); if (buffer != NULL) { // Check if the buffer is direct jboolean isDirect = env->CallBooleanMethod(buffer, Buffer_isDirect); if (env->ExceptionCheck()) { return NULL; } if (isDirect==JNI_TRUE) { Logger::log(LOG_DEBUGTRACE, "Obtaining host memory from direct java buffer\n"); // Obtain the direct buffer address from the given buffer pointerData->startPointer = (jlong)env->GetDirectBufferAddress(buffer); if (pointerData->startPointer == 0) { ThrowByName(env, "java/lang/IllegalArgumentException", "Failed to obtain direct buffer address"); return NULL; } pointerData->memoryType = DIRECT; // Set the actual pointer to be the startPointer + the byte offset long byteOffset = (long)env->GetLongField(pointerObject, NativePointerObject_byteOffset); pointerData->pointer = (jlong)(((char*)pointerData->startPointer)+byteOffset); return pointerData; } // Check if the buffer has an array jboolean hasArray = env->CallBooleanMethod(buffer, Buffer_hasArray); if (env->ExceptionCheck()) { return NULL; } if (hasArray==JNI_TRUE) { Logger::log(LOG_DEBUGTRACE, "Obtaining host memory from array in java buffer\n"); long byteOffset = (long)env->GetLongField(pointerObject, NativePointerObject_byteOffset); jarray localArray = (jarray)env->CallObjectMethod(buffer, Buffer_array); if (env->ExceptionCheck()) { return NULL; } jarray globalArray = (jarray)env->NewGlobalRef(localArray); if (globalArray == NULL) { return NULL; } pointerData->array = globalArray; jboolean isCopy = JNI_FALSE; pointerData->startPointer = (jlong)env->GetPrimitiveArrayCritical(globalArray, &isCopy); if (pointerData->startPointer == 0) { return NULL; } if (isCopy==JNI_TRUE) { pointerData->memoryType = ARRAY_COPY; } else { pointerData->memoryType = ARRAY; } // Set the actual pointer to be the startPointer + the byte offset pointerData->pointer = (jlong)(((char*)pointerData->startPointer)+byteOffset); return pointerData; } // The buffer is neither direct nor has an array - should have // been checked on Java side Logger::log(LOG_ERROR, "Buffer is neither direct nor has an array\n"); ThrowByName(env, "java/lang/IllegalArgumentException", "Buffer is neither direct nor has an array"); return NULL; } return pointerData; }
JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec1 (JNIEnv * env, jobject process, jobjectArray cmdarray, jobjectArray envp, jstring dir) { SECURITY_ATTRIBUTES sa; PROCESS_INFORMATION pi = {0}; STARTUPINFOW si; DWORD flags = 0; wchar_t * cwd = NULL; wchar_t * envBlk = NULL; int ret = 0; jsize nCmdTokens = 0; jsize nEnvVars = 0; int i; int nPos; int nCmdLineLength= 0; wchar_t * szCmdLine= 0; int nBlkSize = MAX_ENV_SIZE; wchar_t * szEnvBlock = NULL; nCmdLineLength= MAX_CMD_SIZE; szCmdLine= (wchar_t *)malloc(nCmdLineLength * sizeof(wchar_t)); szCmdLine[0]= 0; sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = 0; sa.bInheritHandle = TRUE; nCmdTokens = env->GetArrayLength(cmdarray); nEnvVars = env->GetArrayLength(envp); nPos = 0; // Prepare command line for(i = 0; i < nCmdTokens; ++i) { jstring item = (jstring)env->GetObjectArrayElement(cmdarray, i); jsize len = env->GetStringLength(item); int nCpyLen; const wchar_t * str = (const wchar_t *)env->GetStringChars(item, 0); if(NULL != str) { int requiredSize= nPos+len+2; if (requiredSize > 32*1024) { ThrowByName(env, "java/io/IOException", "Command line too long"); return 0; } ensureSize(&szCmdLine, &nCmdLineLength, requiredSize); if (NULL == szCmdLine) { ThrowByName(env, "java/io/IOException", "Not enough memory"); return 0; } if(0 > (nCpyLen = copyTo(szCmdLine + nPos, str, len, nCmdLineLength - nPos))) { ThrowByName(env, "java/io/Exception", "Command line too long"); return 0; } nPos += nCpyLen; szCmdLine[nPos] = _T(' '); ++nPos; env->ReleaseStringChars(item, (const jchar *)str); } } szCmdLine[nPos] = _T('\0'); // Prepare environment block if (nEnvVars > 0) { szEnvBlock = (wchar_t *)malloc(nBlkSize * sizeof(wchar_t)); nPos = 0; for(i = 0; i < nEnvVars; ++i) { jstring item = (jstring)env->GetObjectArrayElement(envp, i); jsize len = env->GetStringLength(item); const wchar_t * str = (const wchar_t *)env->GetStringChars(item, 0); if(NULL != str) { while((nBlkSize - nPos) <= (len + 2)) // +2 for two '\0' { nBlkSize += MAX_ENV_SIZE; szEnvBlock = (wchar_t *)realloc(szEnvBlock, nBlkSize * sizeof(wchar_t)); if(NULL == szEnvBlock) { ThrowByName(env, "java/io/Exception", "Not enough memory"); return 0; } } wcsncpy(szEnvBlock + nPos, str, len); nPos += len; szEnvBlock[nPos] = _T('\0'); ++nPos; env->ReleaseStringChars(item, (const jchar *)str); } } szEnvBlock[nPos] = _T('\0'); envBlk = szEnvBlock; } if (dir != 0) { const wchar_t * str = (const wchar_t *)env->GetStringChars(dir, 0); if(NULL != str) { cwd = wcsdup(str); env->ReleaseStringChars(dir, (const jchar *)str); } } ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); flags = CREATE_NEW_CONSOLE; flags |= CREATE_UNICODE_ENVIRONMENT; ret = CreateProcessW(0, /* executable name */ szCmdLine, /* command line */ 0, /* process security attribute */ 0, /* thread security attribute */ TRUE, /* inherits system handles */ flags, /* normal attached process */ envBlk, /* environment block */ cwd, /* change to the new current directory */ &si, /* (in) startup information */ &pi); /* (out) process information */ if(NULL != cwd) free(cwd); if(NULL != szEnvBlock) free(szEnvBlock); if(NULL != szCmdLine) free(szCmdLine); if (!ret) // error { char * lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (wchar_t *)&lpMsgBuf, 0, NULL ); ThrowByName(env, "java/io/IOException", lpMsgBuf); // Free the buffer. LocalFree( lpMsgBuf ); ret = -1; } else { // Clean-up CloseHandle(pi.hThread); CloseHandle(pi.hProcess); ret = (long)pi.dwProcessId; //hProcess; } return ret; }
JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec0 (JNIEnv * env, jobject process, jobjectArray cmdarray, jobjectArray envp, jstring dir, jintArray channels) { HANDLE stdHandles[3]; PROCESS_INFORMATION pi = {0}, *piCopy; STARTUPINFOW si; DWORD flags = 0; const wchar_t * cwd = NULL; LPVOID envBlk = NULL; int ret = 0; int nCmdLineLength= 0; wchar_t * szCmdLine= 0; int nBlkSize = MAX_ENV_SIZE; wchar_t * szEnvBlock = NULL; jsize nCmdTokens = 0; jsize nEnvVars = 0; int i; DWORD pid = GetCurrentProcessId(); int nPos; pProcInfo_t pCurProcInfo; // This needs to be big enough to contain the name of the event used when calling CreateEventW bellow. // It is made of a prefix (7 characters max) plus the value of a pointer that gets output in characters. // This will be bigger in the case of 64 bit. static const int MAX_EVENT_NAME_LENGTH = 50; wchar_t eventBreakName[MAX_EVENT_NAME_LENGTH]; wchar_t eventWaitName[MAX_EVENT_NAME_LENGTH]; wchar_t eventTerminateName[MAX_EVENT_NAME_LENGTH]; wchar_t eventKillName[MAX_EVENT_NAME_LENGTH]; wchar_t eventCtrlcName[MAX_EVENT_NAME_LENGTH]; #ifdef DEBUG_MONITOR wchar_t buffer[4000]; #endif int nLocalCounter; wchar_t inPipeName[PIPE_NAME_LENGTH]; wchar_t outPipeName[PIPE_NAME_LENGTH]; wchar_t errPipeName[PIPE_NAME_LENGTH]; nCmdLineLength= MAX_CMD_SIZE; szCmdLine= (wchar_t *)malloc(nCmdLineLength * sizeof(wchar_t)); szCmdLine[0]= _T('\0'); if((HIBYTE(LOWORD(GetVersion()))) & 0x80) { ThrowByName(env, "java/io/IOException", "Does not support Windows 3.1/95/98/Me"); return 0; } if (cmdarray == 0) { ThrowByName(env, "java/lang/NullPointerException", "No command line specified"); return 0; } ZeroMemory(stdHandles, sizeof(stdHandles)); // Create pipe names EnterCriticalSection(&cs); swprintf(inPipeName, L"\\\\.\\pipe\\stdin%08i%010i", pid, nCounter); swprintf(outPipeName, L"\\\\.\\pipe\\stdout%08i%010i", pid, nCounter); swprintf(errPipeName, L"\\\\.\\pipe\\stderr%08i%010i", pid, nCounter); nLocalCounter = nCounter; ++nCounter; LeaveCriticalSection(&cs); if ((INVALID_HANDLE_VALUE == (stdHandles[0] = CreateNamedPipeW(inPipeName, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, PIPE_SIZE, PIPE_SIZE, PIPE_TIMEOUT, NULL))) || (INVALID_HANDLE_VALUE == (stdHandles[1] = CreateNamedPipeW(outPipeName, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, PIPE_SIZE, PIPE_SIZE, PIPE_TIMEOUT, NULL))) || (INVALID_HANDLE_VALUE == (stdHandles[2] = CreateNamedPipeW(errPipeName, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, PIPE_SIZE, PIPE_SIZE, PIPE_TIMEOUT, NULL)))) { CloseHandle(stdHandles[0]); CloseHandle(stdHandles[1]); CloseHandle(stdHandles[2]); ThrowByName(env, "java/io/IOException", "CreatePipe"); return 0; } #ifdef DEBUG_MONITOR swprintf(buffer, _T("Opened pipes: %s, %s, %s\n"), inPipeName, outPipeName, errPipeName); OutputDebugStringW(buffer); #endif nCmdTokens = env->GetArrayLength(cmdarray); nEnvVars = env->GetArrayLength(envp); pCurProcInfo = createProcInfo(); if(NULL == pCurProcInfo) { ThrowByName(env, "java/io/IOException", "Too many processes"); return 0; } // Construct starter's command line swprintf(eventBreakName, L"SABreak%04x%08x", pid, nLocalCounter); swprintf(eventWaitName, L"SAWait%004x%08x", pid, nLocalCounter); swprintf(eventTerminateName, L"SATerm%004x%08x", pid, nLocalCounter); swprintf(eventKillName, L"SAKill%04x%08x", pid, nLocalCounter); swprintf(eventCtrlcName, L"SACtrlc%04x%08x", pid, nLocalCounter); pCurProcInfo->eventBreak = CreateEventW(NULL, FALSE, FALSE, eventBreakName); if(NULL == pCurProcInfo->eventBreak || GetLastError() == ERROR_ALREADY_EXISTS) { ThrowByName(env, "java/io/IOException", "Cannot create event"); return 0; } pCurProcInfo->eventWait = CreateEventW(NULL, TRUE, FALSE, eventWaitName); pCurProcInfo->eventTerminate = CreateEventW(NULL, FALSE, FALSE, eventTerminateName); pCurProcInfo->eventKill = CreateEventW(NULL, FALSE, FALSE, eventKillName); pCurProcInfo->eventCtrlc = CreateEventW(NULL, FALSE, FALSE, eventCtrlcName); swprintf(szCmdLine, L"\"%sstarter.exe\" %i %i %s %s %s %s %s ", path, pid, nLocalCounter, eventBreakName, eventWaitName, eventTerminateName, eventKillName, eventCtrlcName); nPos = wcslen(szCmdLine); // Prepare command line for(i = 0; i < nCmdTokens; ++i) { jstring item = (jstring)env->GetObjectArrayElement(cmdarray, i); jsize len = env->GetStringLength(item); int nCpyLen; const wchar_t * str = (const wchar_t *)env->GetStringChars(item, 0); if(NULL != str) { int requiredSize= nPos+len+2; if (requiredSize > 32*1024) { ThrowByName(env, "java/io/IOException", "Command line too long"); return 0; } ensureSize(&szCmdLine, &nCmdLineLength, requiredSize); if (NULL == szCmdLine) { ThrowByName(env, "java/io/IOException", "Not enough memory"); return 0; } if(0 > (nCpyLen = copyTo(szCmdLine + nPos, str, len, nCmdLineLength - nPos))) { ThrowByName(env, "java/io/IOException", "Command line too long"); return 0; } nPos += nCpyLen; szCmdLine[nPos] = _T(' '); ++nPos; env->ReleaseStringChars(item, (const jchar *)str); } } szCmdLine[nPos] = _T('\0'); #ifdef DEBUG_MONITOR swprintf(buffer, _T("There are %i environment variables \n"), nEnvVars); OutputDebugStringW(buffer); #endif // Prepare environment block if (nEnvVars > 0) { nPos = 0; szEnvBlock = (wchar_t *)malloc(nBlkSize * sizeof(wchar_t)); for(i = 0; i < nEnvVars; ++i) { jstring item = (jstring)env->GetObjectArrayElement(envp, i); jsize len = env->GetStringLength(item); const wchar_t * str = (const wchar_t *)env->GetStringChars(item, 0); if(NULL != str) { while((nBlkSize - nPos) <= (len + 2)) // +2 for two '\0' { nBlkSize += MAX_ENV_SIZE; szEnvBlock = (wchar_t *)realloc(szEnvBlock, nBlkSize * sizeof(wchar_t)); if(NULL == szEnvBlock) { ThrowByName(env, "java/io/IOException", "Not enough memory"); return 0; } #ifdef DEBUG_MONITOR swprintf(buffer, _T("Realloc environment block; new length is %i \n"), nBlkSize); OutputDebugStringW(buffer); #endif } #ifdef DEBUG_MONITOR swprintf(buffer, _T("%s\n"), str); OutputDebugStringW(buffer); #endif wcsncpy(szEnvBlock + nPos, str, len); nPos += len; szEnvBlock[nPos] = _T('\0'); ++nPos; env->ReleaseStringChars(item, (const jchar *)str); } } szEnvBlock[nPos] = _T('\0'); } if (dir != 0) { const wchar_t * str = (const wchar_t *)env->GetStringChars(dir, 0); if(NULL != str) { cwd = wcsdup(str); env->ReleaseStringChars(dir, (const jchar *)str); } } ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.dwFlags |= STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; // Processes in the Process Group are hidden SetHandleInformation(stdHandles[0], HANDLE_FLAG_INHERIT, FALSE); SetHandleInformation(stdHandles[1], HANDLE_FLAG_INHERIT, FALSE); SetHandleInformation(stdHandles[2], HANDLE_FLAG_INHERIT, FALSE); flags = CREATE_NEW_CONSOLE; flags |= CREATE_NO_WINDOW; flags |= CREATE_UNICODE_ENVIRONMENT; #ifdef DEBUG_MONITOR OutputDebugStringW(szCmdLine); #endif // launches starter; we need it to create another console group to correctly process // emulation of SYSint signal (Ctrl-C) ret = CreateProcessW(0, /* executable name */ szCmdLine, /* command line */ 0, /* process security attribute */ 0, /* thread security attribute */ FALSE, /* inherits system handles */ flags, /* normal attached process */ szEnvBlock, /* environment block */ cwd, /* change to the new current directory */ &si, /* (in) startup information */ &pi); /* (out) process information */ if(NULL != cwd) free((void *)cwd); if(NULL != szEnvBlock) free(szEnvBlock); if(NULL != szCmdLine) free(szCmdLine); if (!ret) // Launching error { char * lpMsgBuf; CloseHandle(stdHandles[0]); CloseHandle(stdHandles[1]); CloseHandle(stdHandles[2]); FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (char *)&lpMsgBuf, 0, NULL ); ThrowByName(env, "java/io/IOException", lpMsgBuf); // Free the buffer. LocalFree( lpMsgBuf ); cleanUpProcBlock(pCurProcInfo); ret = -1; } else { int file_handles[3]; HANDLE h[2]; int what; EnterCriticalSection(&cs); pCurProcInfo -> pid = pi.dwProcessId; h[0] = pCurProcInfo -> eventWait; h[1] = pi.hProcess; what = WaitForMultipleObjects(2, h, FALSE, INFINITE); if(what != WAIT_OBJECT_0) // CreateProcess failed { #ifdef DEBUG_MONITOR swprintf(buffer, _T("Process %i failed\n"), pi.dwProcessId); OutputDebugStringW(buffer); #endif cleanUpProcBlock(pCurProcInfo); ThrowByName(env, "java/io/IOException", "Launching failed"); #ifdef DEBUG_MONITOR OutputDebugStringW(_T("Process failed\n")); #endif } else { ret = (long)(pCurProcInfo -> uid); // Prepare stream handlers to return to java program file_handles[0] = (int)stdHandles[0]; file_handles[1] = (int)stdHandles[1]; file_handles[2] = (int)stdHandles[2]; env->SetIntArrayRegion(channels, 0, 3, (jint *)file_handles); // do the cleanup so launch the according thread // create a copy of the PROCESS_INFORMATION as this might get destroyed piCopy = (PROCESS_INFORMATION *)malloc(sizeof(PROCESS_INFORMATION)); memcpy(piCopy, &pi, sizeof(PROCESS_INFORMATION)); _beginthread(waitProcTermination, 0, (void *)piCopy); #ifdef DEBUG_MONITOR OutputDebugStringW(_T("Process started\n")); #endif } LeaveCriticalSection(&cs); } CloseHandle(pi.hThread); return ret; }