diff --git a/core/org.eclipse.cdt.core.win32/.classpath b/core/org.eclipse.cdt.core.win32/.classpath new file mode 100644 index 00000000000..782d615590a --- /dev/null +++ b/core/org.eclipse.cdt.core.win32/.classpath @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/core/org.eclipse.cdt.core.win32/.project b/core/org.eclipse.cdt.core.win32/.project new file mode 100644 index 00000000000..2b0ee24a60c --- /dev/null +++ b/core/org.eclipse.cdt.core.win32/.project @@ -0,0 +1,38 @@ + + + org.eclipse.cdt.core.win32 + + + org.apache.xerces + org.eclipse.cdt.core + org.eclipse.compare + org.eclipse.core.boot + org.eclipse.core.resources + org.eclipse.core.runtime + org.eclipse.debug.core + org.eclipse.debug.ui + org.eclipse.search + org.eclipse.ui + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.pde.PluginNature + + diff --git a/core/org.eclipse.cdt.core.win32/build.properties b/core/org.eclipse.cdt.core.win32/build.properties new file mode 100644 index 00000000000..99f473dc81f --- /dev/null +++ b/core/org.eclipse.cdt.core.win32/build.properties @@ -0,0 +1,2 @@ +bin.includes = fragment.xml,\ + os/ diff --git a/core/org.eclipse.cdt.core.win32/fragment.xml b/core/org.eclipse.cdt.core.win32/fragment.xml new file mode 100644 index 00000000000..325be653302 --- /dev/null +++ b/core/org.eclipse.cdt.core.win32/fragment.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + diff --git a/core/org.eclipse.cdt.core.win32/library/Spawner.h b/core/org.eclipse.cdt.core.win32/library/Spawner.h new file mode 100644 index 00000000000..3201467c7ff --- /dev/null +++ b/core/org.eclipse.cdt.core.win32/library/Spawner.h @@ -0,0 +1,45 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class com_qnx_tools_utils_spawner_Spawner */ + +#ifndef _Included_com_qnx_tools_utils_spawner_Spawner +#define _Included_com_qnx_tools_utils_spawner_Spawner +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: com_qnx_tools_utils_spawner_Spawner + * Method: exec0 + * Signature: ([Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;[I)I + */ +JNIEXPORT jint JNICALL Java_com_qnx_tools_utils_spawner_Spawner_exec0 + (JNIEnv *, jobject, jobjectArray, jobjectArray, jstring, jintArray); + +/* + * Class: com_qnx_tools_utils_spawner_Spawner + * Method: exec0 + * Signature: ([Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;[I)I + */ +JNIEXPORT jint JNICALL Java_com_qnx_tools_utils_spawner_Spawner_exec1 + (JNIEnv *, jobject, jobjectArray, jobjectArray, jstring); + +/* + * Class: com_qnx_tools_utils_spawner_Spawner + * Method: raise + * Signature: (II)I + */ +JNIEXPORT jint JNICALL Java_com_qnx_tools_utils_spawner_Spawner_raise + (JNIEnv *, jobject, jint, jint); + +/* + * Class: com_qnx_tools_utils_spawner_Spawner + * Method: waitFor + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_qnx_tools_utils_spawner_Spawner_waitFor + (JNIEnv *, jobject, jint); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/core/org.eclipse.cdt.core.win32/library/SpawnerInputStream.h b/core/org.eclipse.cdt.core.win32/library/SpawnerInputStream.h new file mode 100644 index 00000000000..7ab967353eb --- /dev/null +++ b/core/org.eclipse.cdt.core.win32/library/SpawnerInputStream.h @@ -0,0 +1,32 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class com_qnx_tools_utils_spawner_SpawnerInputStream */ + +#ifndef _Included_com_qnx_tools_utils_spawner_SpawnerInputStream +#define _Included_com_qnx_tools_utils_spawner_SpawnerInputStream +#ifdef __cplusplus +extern "C" { +#endif +#undef com_qnx_tools_utils_spawner_SpawnerInputStream_SKIP_BUFFER_SIZE +#define com_qnx_tools_utils_spawner_SpawnerInputStream_SKIP_BUFFER_SIZE 2048L +/* Inaccessible static: skipBuffer */ +/* + * Class: com_qnx_tools_utils_spawner_SpawnerInputStream + * Method: read0 + * Signature: (I[BI)I + */ +JNIEXPORT jint JNICALL Java_com_qnx_tools_utils_spawner_SpawnerInputStream_read0 + (JNIEnv *, jobject, jint, jbyteArray, jint); + +/* + * Class: com_qnx_tools_utils_spawner_SpawnerInputStream + * Method: close0 + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_qnx_tools_utils_spawner_SpawnerInputStream_close0 + (JNIEnv *, jobject, jint); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/core/org.eclipse.cdt.core.win32/library/SpawnerOutputStream.h b/core/org.eclipse.cdt.core.win32/library/SpawnerOutputStream.h new file mode 100644 index 00000000000..7470e533c9a --- /dev/null +++ b/core/org.eclipse.cdt.core.win32/library/SpawnerOutputStream.h @@ -0,0 +1,29 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class com_qnx_tools_utils_spawner_SpawnerOutputStream */ + +#ifndef _Included_com_qnx_tools_utils_spawner_SpawnerOutputStream +#define _Included_com_qnx_tools_utils_spawner_SpawnerOutputStream +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: com_qnx_tools_utils_spawner_SpawnerOutputStream + * Method: write0 + * Signature: (I[BI)I + */ +JNIEXPORT jint JNICALL Java_com_qnx_tools_utils_spawner_SpawnerOutputStream_write0 + (JNIEnv *, jobject, jint, jbyteArray, jint); + +/* + * Class: com_qnx_tools_utils_spawner_SpawnerOutputStream + * Method: close0 + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_qnx_tools_utils_spawner_SpawnerOutputStream_close0 + (JNIEnv *, jobject, jint); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/core/org.eclipse.cdt.core.win32/library/StdAfx.c b/core/org.eclipse.cdt.core.win32/library/StdAfx.c new file mode 100644 index 00000000000..f932277afe3 --- /dev/null +++ b/core/org.eclipse.cdt.core.win32/library/StdAfx.c @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// spawner.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/core/org.eclipse.cdt.core.win32/library/StdAfx.h b/core/org.eclipse.cdt.core.win32/library/StdAfx.h new file mode 100644 index 00000000000..72d86ebb5b5 --- /dev/null +++ b/core/org.eclipse.cdt.core.win32/library/StdAfx.h @@ -0,0 +1,26 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__9D84F180_36E5_47D6_96AB_22723242789C__INCLUDED_) +#define AFX_STDAFX_H__9D84F180_36E5_47D6_96AB_22723242789C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +// Insert your headers here +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +#include + +#include + +// TODO: reference additional headers your program requires here + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__9D84F180_36E5_47D6_96AB_22723242789C__INCLUDED_) diff --git a/core/org.eclipse.cdt.core.win32/library/Win32ProcessEx.c b/core/org.eclipse.cdt.core.win32/library/Win32ProcessEx.c new file mode 100644 index 00000000000..7c8b1f04203 --- /dev/null +++ b/core/org.eclipse.cdt.core.win32/library/Win32ProcessEx.c @@ -0,0 +1,744 @@ +/* Copyright, 2002, QNX Software Systems Ltd. All Rights Reserved + + * This source code has been published by QNX Software Systems + * Ltd. (QSSL). However, any use, reproduction, modification, distribution + * or transfer of this software, or any software which includes or is based + * upon any of this code, is only permitted if expressly authorized by a + * written license agreement from QSSL. Contact the QNX Developer's Network + * or contact QSSL's legal department for more information. + * + * + * Win32ProcessEx.c + * + * This is a JNI implementation of spawner + */ +#include "stdafx.h" +#include +#include +#include +#include "Spawner.h" + + +#include "jni.h" +#include "io.h" + + +#define PIPE_SIZE 512 +#define MAX_CMD_SIZE 1024 +#define MAX_ENV_SIZE 4096 + +#define MAX_PROCS (100) + +typedef JNIEXPORT void * (JNICALL * JVM_GetThreadInterruptEvent)(); +typedef JNIEXPORT char * (JNICALL * JVM_NativePath)(const char *); + +typedef struct _procInfo { + int pid; // Process ID + int uid; // quasi-unique process ID + HANDLE eventBreak; + HANDLE eventWait; + HANDLE eventTerminate; +} procInfo_t, * pProcInfo_t; + +static int procCounter = 0; + + +JNIEXPORT void * JNICALL GetJVMProc(char * vmlib, char * procName); +JNIEXPORT void JNICALL ThrowByName(JNIEnv *env, const char *name, const char *msg); +pProcInfo_t createProcInfo(); +pProcInfo_t findProcInfo(int pid); +unsigned int _stdcall waitProcTermination(void* pv) ; +static int copyTo(char * target, const char * source, int cpyLenght, int availSpace); +static void cleanUpProcBlock(pProcInfo_t pCurProcInfo); + + + +typedef enum { + SIG_NOOP, + SIG_HUP, + SIG_INT, + SIG_KILL = 9, + SIG_TERM = 15, +} signals; + +extern CRITICAL_SECTION cs; + + +extern TCHAR path[MAX_PATH]; + +static HMODULE hVM = NULL; + + +static pProcInfo_t pInfo = NULL; + + +JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec0 + (JNIEnv * env, jobject process, jobjectArray cmdarray, jobjectArray envp, jstring dir, jintArray channels) +{ + + HANDLE hread[3], hwrite[3]; + SECURITY_ATTRIBUTES sa; + PROCESS_INFORMATION pi = {0}; + STARTUPINFO si; + DWORD flags = 0; + char * cwd = NULL; + LPVOID envBlk = NULL; + int ret = 0; + char szCmdLine[MAX_CMD_SIZE]; + char szEnvBlock[MAX_ENV_SIZE]; + jsize nCmdTokens = 0; + jsize nEnvVars = 0; + int i; + int nPos; + pProcInfo_t pCurProcInfo; + DWORD dwThreadId; + char eventBreakName[20]; + char eventWaitName[20]; + char eventTerminateName[20]; +#ifdef DEBUG_MONITOR + char buffer[100]; +#endif + + + + if (cmdarray == 0) + { + ThrowByName(env, "java/lang/NullPointerException", "No command line specified"); + return 0; + } + + sa.nLength = sizeof(sa); + sa.lpSecurityDescriptor = 0; + sa.bInheritHandle = TRUE; + + memset(hread, 0, sizeof(hread)); + memset(hwrite, 0, sizeof(hwrite)); + if (!(CreatePipe(&hread[0], &hwrite[0], &sa, PIPE_SIZE) && + CreatePipe(&hread[1], &hwrite[1], &sa, PIPE_SIZE) && + CreatePipe(&hread[2], &hwrite[2], &sa, PIPE_SIZE))) + { + CloseHandle(hread[0]); + CloseHandle(hread[1]); + CloseHandle(hread[2]); + CloseHandle(hwrite[0]); + CloseHandle(hwrite[1]); + CloseHandle(hwrite[2]); + ThrowByName(env, "java/io/IOException", "CreatePipe"); + return 0; + } + + nCmdTokens = (*env) -> GetArrayLength(env, cmdarray); + nEnvVars = (*env) -> GetArrayLength(env, envp); + + pCurProcInfo = createProcInfo(); + + if(NULL == pCurProcInfo) + { + ThrowByName(env, "java/io/IOException", "Too many processes"); + return 0; + } + + + sprintf(eventBreakName, "SABreak%p", pCurProcInfo); + sprintf(eventWaitName, "SAWait%p", pCurProcInfo); + sprintf(eventTerminateName, "SATerm%p", pCurProcInfo); + pCurProcInfo -> eventBreak = CreateEvent(NULL, TRUE, FALSE, eventBreakName); + ResetEvent(pCurProcInfo -> eventBreak); + pCurProcInfo -> eventWait = CreateEvent(NULL, TRUE, FALSE, eventWaitName); + pCurProcInfo -> eventTerminate = CreateEvent(NULL, TRUE, FALSE, eventTerminateName); + ResetEvent(pCurProcInfo -> eventTerminate); + + nPos = sprintf(szCmdLine, "%sstarter.exe %s %s %s ", path, eventBreakName, eventWaitName, eventTerminateName); + + for(i = 0; i < nCmdTokens; ++i) + { + jobject item = (*env) -> GetObjectArrayElement(env, cmdarray, i); + jsize len = (*env) -> GetStringUTFLength(env, item); + int nCpyLen; + const char * str = (*env) -> GetStringUTFChars(env, item, 0); + if(0 > (nCpyLen = copyTo(szCmdLine + nPos, str, len, MAX_CMD_SIZE - nPos))) + { + ThrowByName(env, "java/Exception", "Too long command line"); + return 0; + } + nPos += nCpyLen; + szCmdLine[nPos] = ' '; + ++nPos; + (*env) -> ReleaseStringUTFChars(env, item, str); + } + + szCmdLine[nPos] = '\0'; + + if (nEnvVars > 0) + { + nPos = 0; + for(i = 0; i < nEnvVars; ++i) + { + jobject item = (*env) -> GetObjectArrayElement(env, envp, i); + jsize len = (*env) -> GetStringUTFLength(env, item); + int nCpyLen; + const char * str = (*env) -> GetStringUTFChars(env, item, 0); + if(0 > (nCpyLen = copyTo(szEnvBlock + nPos, str, len, MAX_ENV_SIZE - nPos - 1))) + { + ThrowByName(env, "java/Exception", "Too many environment variables"); + return 0; + } + nPos += nCpyLen; + szEnvBlock[nPos] = '\0'; + ++nPos; + (*env) -> ReleaseStringUTFChars(env, item, str); + } + szEnvBlock[nPos] = '\0'; + envBlk = szEnvBlock; + } + + + + if (dir != 0) + { + const char * str = NULL; + JVM_NativePath nativePath = GetJVMProc(NULL, "_JVM_NativePath@4"); + cwd = strdup(nativePath(str = (*env) -> GetStringUTFChars(env, dir, 0))); + (*env) -> ReleaseStringUTFChars(env, dir, str); + } + + + memset(&si, 0, sizeof(si)); + si.cb = sizeof(si); + si.dwFlags |= STARTF_USESTDHANDLES; + si.dwFlags |= STARTF_USESHOWWINDOW; + si.wShowWindow = SW_HIDE; // Processes in the Process Group are hidden + si.hStdInput = hread[0]; + si.hStdOutput = hwrite[1]; + si.hStdError = hwrite[2]; + + + + + SetHandleInformation(hwrite[0], HANDLE_FLAG_INHERIT, FALSE); + SetHandleInformation(hread[1], HANDLE_FLAG_INHERIT, FALSE); + SetHandleInformation(hread[2], HANDLE_FLAG_INHERIT, FALSE); + + flags = CREATE_NEW_CONSOLE; + flags |= CREATE_NO_WINDOW; + +#ifdef DEBUG_MONITOR + OutputDebugString(szCmdLine); +#endif + + ret = CreateProcess(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); + + + CloseHandle(hread[0]); + CloseHandle(hwrite[1]); + CloseHandle(hwrite[2]); + + + if (!ret) + { + LPTSTR lpMsgBuf; + + CloseHandle(hwrite[0]); + CloseHandle(hread[1]); + CloseHandle(hread[2]); + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &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; + + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + + EnterCriticalSection(&cs); + + pCurProcInfo -> pid = pi.dwProcessId; + h[0] = pCurProcInfo -> eventWait; + h[1] = (HANDLE)_beginthreadex(NULL, 0, waitProcTermination, + (void *) &(pi.dwProcessId), 0, (UINT*) &dwThreadId); + + what = WaitForMultipleObjects(2, h, FALSE, INFINITE); + if((what != WAIT_OBJECT_0) && (pCurProcInfo -> pid > 0)) // CreateProcess failed + { +#ifdef DEBUG_MONITOR + sprintf(buffer, "Process %i failed\n", pi.dwProcessId); + OutputDebugString(buffer); +#endif + cleanUpProcBlock(pCurProcInfo); + ThrowByName(env, "java/io/IOException", "Launching failed"); + } + else + { +#ifdef DEBUG_MONITOR + sprintf(buffer, "Process %i created\n", pi.dwProcessId); + OutputDebugString(buffer); +#endif + ret = (long)(pCurProcInfo -> uid); + file_handles[0] = (int)hwrite[0]; + file_handles[1] = (int)hread[1]; + file_handles[2] = (int)hread[2]; + (*env) -> SetIntArrayRegion(env, channels, 0, 3, file_handles); + } + CloseHandle(h[1]); + LeaveCriticalSection(&cs); + + } + + + return ret; + +} + + +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}; + STARTUPINFO si; + DWORD flags = 0; + char * cwd = NULL; + LPVOID envBlk = NULL; + int ret = 0; + jsize nCmdTokens = 0; + jsize nEnvVars = 0; + int i; + int nPos; + char szCmdLine[MAX_CMD_SIZE]; + char szEnvBlock[MAX_ENV_SIZE]; + + + sa.nLength = sizeof(sa); + sa.lpSecurityDescriptor = 0; + sa.bInheritHandle = TRUE; + + + nCmdTokens = (*env) -> GetArrayLength(env, cmdarray); + nEnvVars = (*env) -> GetArrayLength(env, envp); + + nPos = 0; + + for(i = 0; i < nCmdTokens; ++i) + { + jobject item = (*env) -> GetObjectArrayElement(env, cmdarray, i); + jsize len = (*env) -> GetStringUTFLength(env, item); + int nCpyLen; + const char * str = (*env) -> GetStringUTFChars(env, item, 0); + if(0 > (nCpyLen = copyTo(szCmdLine + nPos, str, len, MAX_CMD_SIZE - nPos))) + { + ThrowByName(env, "java/Exception", "Too long command line"); + return 0; + } + nPos += nCpyLen; + szCmdLine[nPos] = ' '; + ++nPos; + (*env) -> ReleaseStringUTFChars(env, item, str); + } + + szCmdLine[nPos] = '\0'; + + if (nEnvVars > 0) + { + nPos = 0; + for(i = 0; i < nEnvVars; ++i) + { + jobject item = (*env) -> GetObjectArrayElement(env, envp, i); + jsize len = (*env) -> GetStringUTFLength(env, item); + int nCpyLen; + const char * str = (*env) -> GetStringUTFChars(env, item, 0); + if(0 > (nCpyLen = copyTo(szEnvBlock + nPos, str, len, MAX_ENV_SIZE - nPos - 1))) + { + ThrowByName(env, "java/Exception", "Too many environment variables"); + return 0; + } + nPos += nCpyLen; + szEnvBlock[nPos] = '\0'; + ++nPos; + (*env) -> ReleaseStringUTFChars(env, item, str); + } + szEnvBlock[nPos] = '\0'; + envBlk = szEnvBlock; + } + + + + if (dir != 0) + { + JVM_NativePath nativePath = GetJVMProc(NULL, "_JVM_NativePath@4"); + cwd = strdup(nativePath((*env) -> GetStringUTFChars(env, dir, 0))); + } + + + memset(&si, 0, sizeof(si)); + si.cb = sizeof(si); + + + + + + flags = CREATE_NEW_CONSOLE; + + ret = CreateProcess(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 (!ret) + { + LPTSTR lpMsgBuf; + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + ThrowByName(env, "java/io/IOException", lpMsgBuf); + // Free the buffer. + LocalFree( lpMsgBuf ); + ret = -1; + } + else + { + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + ret = (long)pi.dwProcessId; //hProcess; + } + + + return ret; + +} + + +JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_raise + (JNIEnv * env, jobject process, jint uid, jint signal) +{ + jint ret = 0; + + HANDLE hProc; + pProcInfo_t pCurProcInfo = findProcInfo(uid); +#ifdef DEBUG_MONITOR + char buffer[100]; +#endif + + if(NULL == pCurProcInfo) + return -1; + + hProc = OpenProcess(PROCESS_ALL_ACCESS, 0, pCurProcInfo -> pid); + + if(NULL == hProc) + return -1; + + switch(signal) + { + case SIG_NOOP: + // Wait 0 msec -just check if the process has been still running + ret = ((WAIT_TIMEOUT == WaitForSingleObject(hProc, 0)) ? 0 : -1); + break; + case SIG_HUP: + // Temporary do nothing + ret = 0; + break; + case SIG_KILL: + case SIG_TERM: +#ifdef DEBUG_MONITOR + sprintf(buffer, "Spawner received KILL or TERM signal for process %i\n", pid); + OutputDebugString(buffer); +#endif + SetEvent(pCurProcInfo -> eventTerminate); +#ifdef DEBUG_MONITOR + OutputDebugString("Spawner signalled KILL event\n"); +#endif + ret = 0; + break; + case SIG_INT: + ResetEvent(pCurProcInfo -> eventWait); + PulseEvent(pCurProcInfo -> eventBreak); + ret = (WaitForSingleObject(pCurProcInfo -> eventWait, 100) == WAIT_OBJECT_0); + break; + default: + break; + } + + CloseHandle(hProc); + return ret; + + +} + + + +JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_waitFor + (JNIEnv * env, jobject process, jint uid) +{ + long exit_code; + int what=0; + HANDLE hProc; + pProcInfo_t pCurProcInfo = findProcInfo(uid); + + if(NULL == pCurProcInfo) + return -1; + + hProc = OpenProcess(PROCESS_ALL_ACCESS, 0, pCurProcInfo -> pid); + + if(NULL == hProc) + return -1; + + what = WaitForSingleObject(hProc, INFINITE); + + + if (what == WAIT_OBJECT_0) + { + GetExitCodeProcess((void *)(pCurProcInfo -> pid), &exit_code); + } + + + if(hProc) + CloseHandle(hProc); + + return exit_code; +} + + + + + +// Utilities + +JNIEXPORT void JNICALL +ThrowByName(JNIEnv *env, const char *name, const char *msg) +{ + jclass cls = (*env)->FindClass(env, name); + + if (cls != 0) /* Otherwise an exception has already been thrown */ + (*env)->ThrowNew(env, cls, msg); + + /* It's a good practice to clean up the local references. */ + (*env)->DeleteLocalRef(env, cls); +} + + + +JNIEXPORT void * JNICALL +GetJVMProc(char * vmlib, char * procName) +{ + if(NULL == vmlib) + vmlib = "jvm.dll"; + if(NULL == hVM) + { + if(NULL == (hVM = GetModuleHandle(vmlib))) + return NULL; + } + return GetProcAddress(hVM, procName); +} + +pProcInfo_t createProcInfo() +{ + int i; + pProcInfo_t p = NULL; + + EnterCriticalSection(&cs); + + if(NULL == pInfo) + { + pInfo = malloc(sizeof(procInfo_t) * MAX_PROCS); + memset(pInfo, 0, sizeof(procInfo_t) * MAX_PROCS); + } + + for(i = 0; i < MAX_PROCS; ++i) + { + if(pInfo[i].pid == 0) + { + pInfo[i].pid = -1; + pInfo[i].uid = ++procCounter; + p = pInfo + i; + break; + } + } + + LeaveCriticalSection(&cs); + + return p; +} + +pProcInfo_t findProcInfo(int uid) +{ + int i; + pProcInfo_t p = NULL; + if(NULL == pInfo) + return NULL; + + for(i = 0; i < MAX_PROCS; ++i) + { + if(pInfo[i].uid == uid) + { + p = pInfo + i; + break; + } + } + + return p; +} + +void cleanUpProcBlock(pProcInfo_t pCurProcInfo) +{ + if(0 != pCurProcInfo -> eventBreak) + { + CloseHandle(pCurProcInfo -> eventBreak); + pCurProcInfo -> eventBreak = 0; + } + if(0 != pCurProcInfo -> eventWait) + { + CloseHandle(pCurProcInfo -> eventWait); + pCurProcInfo -> eventWait = 0; + } + if(0 != pCurProcInfo -> eventTerminate) + { + CloseHandle(pCurProcInfo -> eventTerminate); + pCurProcInfo -> eventTerminate = 0; + } + + pCurProcInfo -> pid = 0; +} + +unsigned int _stdcall waitProcTermination(void* pv) +{ + int i; + int pid = *(int *)pv; + DWORD rc = 0; +#ifdef DEBUG_MONITOR + char buffer[100]; +#endif + + HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, 0, pid); + + if(NULL == hProc) + { +#ifdef DEBUG_MONITOR + sprintf(buffer, "waitProcTermination: cannot get handler for PID %i (error %i)\n", pid, GetLastError()); + OutputDebugString(buffer); +#endif + } + else + { + WaitForSingleObject(hProc, INFINITE); +#ifdef DEBUG_MONITOR + sprintf(buffer, "Process PID %i terminated\n", pid); + OutputDebugString(buffer); +#endif + } + + + for(i = 0; i < MAX_PROCS; ++i) + { + if(pInfo[i].pid == pid) + { +#ifdef DEBUG_MONITOR + sprintf(buffer, "waitProcTermination: set PID %i to 0\n", pid, GetLastError()); + OutputDebugString(buffer); +#endif + cleanUpProcBlock(pInfo + i); + break; + } + } + + CloseHandle(hProc); + + + return 0; +} + +// Return number of bytes in target or -1 in case of error +int copyTo(char * target, const char * source, int cpyLength, int availSpace) +{ + BOOL bSlash = FALSE; + int i, j; + int totCpyLength = cpyLength; + + if(availSpace < cpyLength) + return -1; + strncpy(target, source, cpyLength); + return cpyLength; + + // Don't open this feature for a while + + for(i = 0, j = 0; i < cpyLength; ++i, ++j) + { + if(source[i] == '\\') + bSlash = TRUE; + else + if(source[i] == '"') + { + if(bSlash) + { + if(j == availSpace) + return -1; + target[j] = '\\'; + ++j; + bSlash = FALSE; + } + if(j == availSpace) + return -1; + target[j] = '\\'; + ++j; + } + else + bSlash = FALSE; + + if(j == availSpace) + return -1; + target[j] = source[i]; + } + + return j; +} + diff --git a/core/org.eclipse.cdt.core.win32/library/iostream.c b/core/org.eclipse.cdt.core.win32/library/iostream.c new file mode 100644 index 00000000000..f92d9b18ab6 --- /dev/null +++ b/core/org.eclipse.cdt.core.win32/library/iostream.c @@ -0,0 +1,144 @@ +/* Copyright, 2002, QNX Software Systems Ltd. All Rights Reserved + + * This source code has been published by QNX Software Systems + * Ltd. (QSSL). However, any use, reproduction, modification, distribution + * or transfer of this software, or any software which includes or is based + * upon any of this code, is only permitted if expressly authorized by a + * written license agreement from QSSL. Contact the QNX Developer's Network + * or contact QSSL's legal department for more information. + * + * + * Win32ProcessEx.c + * + * This is a JNI implementation of access to standard i/o streams + */ +#include "stdafx.h" +#include +#include +#include "SpawnerInputStream.h" +#include "SpawnerOutputStream.h" + + +#include "jni.h" +#include "io.h" + + +JNIEXPORT void JNICALL ThrowByName(JNIEnv *env, const char *name, const char *msg); + +#define BUFF_SIZE (1024) + +/* Inaccessible static: skipBuffer */ +/* + * Class: SpawnerInputStream + * Method: read0 + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_SpawnerInputStream_read0 + (JNIEnv * env, jobject proc, jint fd, jbyteArray buf, jint len) +{ + BYTE tmpBuf[BUFF_SIZE]; + int nBuffOffset = 0; + + while(len > nBuffOffset) + { + int nNumberOfBytesToRead = min(len - nBuffOffset, BUFF_SIZE); + int nNumberOfBytesRead; + if(0 == ReadFile((HANDLE)fd, tmpBuf, nNumberOfBytesToRead, &nNumberOfBytesRead, NULL )) + { + LPTSTR lpMsgBuf; + int err = GetLastError(); + + if(err == ERROR_BROKEN_PIPE) // Pipe was closed + return 0; + if(err != ERROR_MORE_DATA) // Otherwise error means just that there are more data + { // than buffer can accept + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + err, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + + ThrowByName(env, "java/io/IOException", lpMsgBuf); + LocalFree( lpMsgBuf ); + return 0; + } + } + if(nNumberOfBytesRead > 0) + (*env) -> SetByteArrayRegion(env, buf, nBuffOffset, nNumberOfBytesRead, tmpBuf); + else + break; + nBuffOffset += nNumberOfBytesRead; + if(nNumberOfBytesRead != nNumberOfBytesToRead) + break; + } + return nBuffOffset; // This is a real full readed length + +} + +/* + * Class: SpawnerInputStream + * Method: close0 + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_SpawnerInputStream_close0 + (JNIEnv * env, jobject proc, jint fd) +{ + return (CloseHandle((HANDLE)fd) ? 0 : -1); +} + +/* + * Class: SpawnerOutputStream + * Method: write0 + * Signature: (I[BI)I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_SpawnerOutputStream_write0 + (JNIEnv * env, jobject proc, jint fd, jbyteArray buf, jint len) +{ + BYTE tmpBuf[BUFF_SIZE]; + int nBuffOffset = 0; + + while(len > nBuffOffset) + { + int nNumberOfBytesToWrite = min(len - nBuffOffset, BUFF_SIZE); + int nNumberOfBytesWritten; + (*env) -> GetByteArrayRegion(env, buf, nBuffOffset, nNumberOfBytesToWrite, tmpBuf); + if(0 == WriteFile((HANDLE)fd, tmpBuf, nNumberOfBytesToWrite, &nNumberOfBytesWritten, NULL)) + { + LPTSTR lpMsgBuf; + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + + ThrowByName(env, "java/io/IOException", lpMsgBuf); + LocalFree( lpMsgBuf ); + return 0; + } + nBuffOffset += nNumberOfBytesWritten; + } + return 0; +} + +/* + * Class: SpawnerOutputStream + * Method: close0 + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_SpawnerOutputStream_close0 + (JNIEnv * env, jobject proc, jint fd) +{ + return (CloseHandle((HANDLE)fd) ? 0 : -1); +} diff --git a/core/org.eclipse.cdt.core.win32/library/spawner.c b/core/org.eclipse.cdt.core.win32/library/spawner.c new file mode 100644 index 00000000000..49537cf5825 --- /dev/null +++ b/core/org.eclipse.cdt.core.win32/library/spawner.c @@ -0,0 +1,41 @@ +// spawner.cpp : Defines the entry point for the DLL application. +// + +#include "stdafx.h" + + +CRITICAL_SECTION cs; + +TCHAR path[MAX_PATH + 1] = {_T('\0') }; + + +BOOL APIENTRY DllMain( HANDLE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + { + LPTSTR p; + InitializeCriticalSection(&cs); + GetModuleFileName(hModule, path, MAX_PATH); + p = _tcsrchr(path, _T('\\')); + if(NULL != p) + *(p + 1) = _T('\0'); + else + _tcscat(path, "\\"); + } + break; + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + break; + case DLL_PROCESS_DETACH: + DeleteCriticalSection(&cs); + break; + } + return TRUE; +} + + diff --git a/core/org.eclipse.cdt.core.win32/library/spawner.dep b/core/org.eclipse.cdt.core.win32/library/spawner.dep new file mode 100644 index 00000000000..52d55921b4a --- /dev/null +++ b/core/org.eclipse.cdt.core.win32/library/spawner.dep @@ -0,0 +1,19 @@ +# Microsoft Developer Studio Generated Dependency File, included by spawner.mak + +.\iostream.c : \ + "..\..\java\jdk1.3.1\include\jni.h"\ + "..\..\java\jdk1.3.1\include\win32\jni_md.h"\ + ".\SpawnerInputStream.h"\ + ".\SpawnerOutputStream.h"\ + + +.\StdAfx.c : \ + "..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ + ".\StdAfx.h"\ + + +.\Win32ProcessEx.c : \ + "..\..\java\jdk1.3.1\include\jni.h"\ + "..\..\java\jdk1.3.1\include\win32\jni_md.h"\ + ".\Spawner.h"\ + diff --git a/core/org.eclipse.cdt.core.win32/library/spawner.mak b/core/org.eclipse.cdt.core.win32/library/spawner.mak new file mode 100644 index 00000000000..1006bb01d11 --- /dev/null +++ b/core/org.eclipse.cdt.core.win32/library/spawner.mak @@ -0,0 +1,279 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on spawner.dsp +!IF "$(CFG)" == "" +CFG=spawner - Win32 Release +!MESSAGE No configuration specified. Defaulting to spawner - Win32 Release. +!ENDIF + +!IF "$(CFG)" != "spawner - Win32 Release" && "$(CFG)" != "spawner - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "spawner.mak" CFG="spawner - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "spawner - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "spawner - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "spawner - Win32 Release" + +OUTDIR=..\os\win32\x86 +INTDIR=.\ +# Begin Custom Macros +OutDir=..\os\win32\x86 +# End Custom Macros + +ALL : "$(OUTDIR)\spawner.dll" + + +CLEAN : + -@erase "$(INTDIR)\iostream.obj" + -@erase "$(INTDIR)\spawner.obj" + -@erase "$(INTDIR)\spawner.pch" + -@erase "$(INTDIR)\StdAfx.obj" + -@erase "$(INTDIR)\vc60.idb" + -@erase "$(INTDIR)\Win32ProcessEx.obj" + -@erase "$(OUTDIR)\spawner.dll" + -@erase "$(OUTDIR)\spawner.exp" + -@erase "$(OUTDIR)\spawner.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /Gz /MT /W3 /GX /O2 /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\Win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPAWNER_EXPORTS" /Fp"$(INTDIR)\spawner.pch" /Yu"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\spawner.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\spawner.pdb" /machine:I386 /out:"$(OUTDIR)\spawner.dll" /implib:"$(OUTDIR)\spawner.lib" +LINK32_OBJS= \ + "$(INTDIR)\iostream.obj" \ + "$(INTDIR)\spawner.obj" \ + "$(INTDIR)\StdAfx.obj" \ + "$(INTDIR)\Win32ProcessEx.obj" + +"$(OUTDIR)\spawner.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "spawner - Win32 Debug" + +OUTDIR=..\os\win32\x86 +INTDIR=.\ +# Begin Custom Macros +OutDir=..\os\win32\x86 +# End Custom Macros + +ALL : "$(OUTDIR)\spawner.dll" "$(OUTDIR)\spawner.bsc" + + +CLEAN : + -@erase "$(INTDIR)\iostream.obj" + -@erase "$(INTDIR)\iostream.sbr" + -@erase "$(INTDIR)\spawner.obj" + -@erase "$(INTDIR)\spawner.pch" + -@erase "$(INTDIR)\spawner.sbr" + -@erase "$(INTDIR)\StdAfx.obj" + -@erase "$(INTDIR)\StdAfx.sbr" + -@erase "$(INTDIR)\vc60.idb" + -@erase "$(INTDIR)\vc60.pdb" + -@erase "$(INTDIR)\Win32ProcessEx.obj" + -@erase "$(INTDIR)\Win32ProcessEx.sbr" + -@erase "$(OUTDIR)\spawner.bsc" + -@erase "$(OUTDIR)\spawner.dll" + -@erase "$(OUTDIR)\spawner.exp" + -@erase "$(OUTDIR)\spawner.ilk" + -@erase "$(OUTDIR)\spawner.lib" + -@erase "$(OUTDIR)\spawner.map" + -@erase "$(OUTDIR)\spawner.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /Gz /MD /W3 /Gm /GX /ZI /Od /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\Win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPAWNER_EXPORTS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\spawner.pch" /Yu"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\spawner.bsc" +BSC32_SBRS= \ + "$(INTDIR)\iostream.sbr" \ + "$(INTDIR)\spawner.sbr" \ + "$(INTDIR)\StdAfx.sbr" \ + "$(INTDIR)\Win32ProcessEx.sbr" + +"$(OUTDIR)\spawner.bsc" : "$(OUTDIR)" $(BSC32_SBRS) + $(BSC32) @<< + $(BSC32_FLAGS) $(BSC32_SBRS) +<< + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\spawner.pdb" /map:"$(INTDIR)\spawner.map" /debug /machine:I386 /out:"$(OUTDIR)\spawner.dll" /implib:"$(OUTDIR)\spawner.lib" /pdbtype:sept +LINK32_OBJS= \ + "$(INTDIR)\iostream.obj" \ + "$(INTDIR)\spawner.obj" \ + "$(INTDIR)\StdAfx.obj" \ + "$(INTDIR)\Win32ProcessEx.obj" + +"$(OUTDIR)\spawner.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("spawner.dep") +!INCLUDE "spawner.dep" +!ELSE +!MESSAGE Warning: cannot find "spawner.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "spawner - Win32 Release" || "$(CFG)" == "spawner - Win32 Debug" +SOURCE=.\iostream.c + +!IF "$(CFG)" == "spawner - Win32 Release" + +CPP_SWITCHES=/nologo /Gz /MT /W3 /GX /O2 /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\Win32" /I "E:\Java\jdk1.3.1\include" /I "E:\Java\jdk1.3.1\include\Win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPAWNER_EXPORTS" /Fp"$(INTDIR)\spawner.pch" /Yu"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c + +"$(INTDIR)\iostream.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\spawner.pch" + $(CPP) @<< + $(CPP_SWITCHES) $(SOURCE) +<< + + +!ELSEIF "$(CFG)" == "spawner - Win32 Debug" + +CPP_SWITCHES=/nologo /Gz /MD /W3 /Gm /GX /ZI /Od /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\Win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPAWNER_EXPORTS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\spawner.pch" /Yu"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c + +"$(INTDIR)\iostream.obj" "$(INTDIR)\iostream.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\spawner.pch" + $(CPP) @<< + $(CPP_SWITCHES) $(SOURCE) +<< + + +!ENDIF + +SOURCE=.\spawner.c + +!IF "$(CFG)" == "spawner - Win32 Release" + +CPP_SWITCHES=/nologo /Gz /MT /W3 /GX /O2 /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\Win32" /I "E:\Java\jdk1.3.1\include" /I "E:\Java\jdk1.3.1\include\Win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPAWNER_EXPORTS" /Fp"$(INTDIR)\spawner.pch" /Yu"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c + +"$(INTDIR)\spawner.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\spawner.pch" + $(CPP) @<< + $(CPP_SWITCHES) $(SOURCE) +<< + + +!ELSEIF "$(CFG)" == "spawner - Win32 Debug" + +CPP_SWITCHES=/nologo /Gz /MD /W3 /Gm /GX /ZI /Od /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\Win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPAWNER_EXPORTS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\spawner.pch" /Yu"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c + +"$(INTDIR)\spawner.obj" "$(INTDIR)\spawner.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\spawner.pch" + $(CPP) @<< + $(CPP_SWITCHES) $(SOURCE) +<< + + +!ENDIF + +SOURCE=.\StdAfx.c + +!IF "$(CFG)" == "spawner - Win32 Release" + +CPP_SWITCHES=/nologo /Gz /MT /W3 /GX /O2 /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\Win32" /I "E:\Java\jdk1.3.1\include" /I "E:\Java\jdk1.3.1\include\Win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPAWNER_EXPORTS" /Fp"$(INTDIR)\spawner.pch" /Yc"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c + +"$(INTDIR)\StdAfx.obj" "$(INTDIR)\spawner.pch" : $(SOURCE) "$(INTDIR)" + $(CPP) @<< + $(CPP_SWITCHES) $(SOURCE) +<< + + +!ELSEIF "$(CFG)" == "spawner - Win32 Debug" + +CPP_SWITCHES=/nologo /Gz /MD /W3 /Gm /GX /ZI /Od /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\Win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPAWNER_EXPORTS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\spawner.pch" /Yc"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c + +"$(INTDIR)\StdAfx.obj" "$(INTDIR)\StdAfx.sbr" "$(INTDIR)\spawner.pch" : $(SOURCE) "$(INTDIR)" + $(CPP) @<< + $(CPP_SWITCHES) $(SOURCE) +<< + + +!ENDIF + +SOURCE=.\Win32ProcessEx.c + +!IF "$(CFG)" == "spawner - Win32 Release" + +CPP_SWITCHES=/nologo /Gz /MT /W3 /GX /O2 /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\Win32" /I "E:\Java\jdk1.3.1\include" /I "E:\Java\jdk1.3.1\include\Win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPAWNER_EXPORTS" /Fp"$(INTDIR)\spawner.pch" /Yu"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c + +"$(INTDIR)\Win32ProcessEx.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\spawner.pch" + $(CPP) @<< + $(CPP_SWITCHES) $(SOURCE) +<< + + +!ELSEIF "$(CFG)" == "spawner - Win32 Debug" + +CPP_SWITCHES=/nologo /Gz /MD /W3 /Gm /GX /ZI /Od /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\Win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPAWNER_EXPORTS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\spawner.pch" /Yu"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c + +"$(INTDIR)\Win32ProcessEx.obj" "$(INTDIR)\Win32ProcessEx.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\spawner.pch" + $(CPP) @<< + $(CPP_SWITCHES) $(SOURCE) +<< + + +!ENDIF + + +!ENDIF + diff --git a/core/org.eclipse.cdt.core.win32/library/starter/starter.cpp b/core/org.eclipse.cdt.core.win32/library/starter/starter.cpp new file mode 100644 index 00000000000..96cb4a35c7a --- /dev/null +++ b/core/org.eclipse.cdt.core.win32/library/starter/starter.cpp @@ -0,0 +1,177 @@ +/* Copyright, 2002, QNX Software Systems Ltd. All Rights Reserved + + * This source code has been published by QNX Software Systems + * Ltd. (QSSL). However, any use, reproduction, modification, distribution + * or transfer of this software, or any software which includes or is based + * upon any of this code, is only permitted if expressly authorized by a + * written license agreement from QSSL. Contact the QNX Developer's Network + * or contact QSSL's legal department for more information. + * + * + * starter.c + * + * This is a small utility for windows spawner + */ + + +//#define UNICODE +//#define _UNICODE + +#define STRICT +#include +#include +#include +#include + +// #define DEBUG_MONITOR +#define MAX_CMD_LINE_LENGTH (1024) + +/////////////////////////////////////////////////////////////////////////////// +BOOL WINAPI HandlerRoutine( DWORD dwCtrlType) // control signal type +{ + BOOL ret = TRUE; + switch(dwCtrlType) + { + case CTRL_C_EVENT: + break; + case CTRL_BREAK_EVENT: + break; + case CTRL_CLOSE_EVENT: + ret = FALSE; + break; + case CTRL_LOGOFF_EVENT: + ret = FALSE; + break; + case CTRL_SHUTDOWN_EVENT: + ret = FALSE; + break; + default: + break; + } + return ret; +} + + + +extern "C" int _tmain(int argc, TCHAR* argv[]) { + + // Make sure that we've been passed the right number of arguments + if (argc < 5) { + _tprintf(__TEXT("Usage: %s (Three InheritableEventHandles) (CommandLineToSpawn)\n"), + argv[0]); + return(0); + } + + // Construct the full command line + TCHAR szCmdLine[MAX_CMD_LINE_LENGTH] = { 0 }; + for (int i = 4; i < argc; i++) { + if(sizeof(szCmdLine) > (_tcslen(szCmdLine) + _tcslen(argv[i]))) + { + _tcscat(szCmdLine, argv[i]); + _tcscat(szCmdLine, __TEXT(" ")); + } +#ifdef DEBUG_MONITOR + else + OutputDebugString("Command line is too long\n"); +#endif + } + + STARTUPINFO si = { sizeof(si) }; + PROCESS_INFORMATION pi = { 0 }; + DWORD dwExitCode = 0; +#ifdef DEBUG_MONITOR + int currentPID = GetCurrentProcessId(); + char buffer[MAX_CMD_LINE_LENGTH]; +#endif + + BOOL exitProc = FALSE; + HANDLE waitEvent = OpenEvent(EVENT_ALL_ACCESS, TRUE, argv[2]); + HANDLE h[3]; + h[0] = OpenEvent(EVENT_ALL_ACCESS, TRUE, argv[1]); + h[2] = OpenEvent(EVENT_ALL_ACCESS, TRUE, argv[3]); // This is a terminate event + SetConsoleCtrlHandler(HandlerRoutine, TRUE); + +#ifdef DEBUG_MONITOR + sprintf(buffer, "starter start command: %s\n", szCmdLine); + OutputDebugString(buffer); +#endif + +// OutputDebugString(szCmdLine); + // Spawn the other processes as part of this Process Group + BOOL f = CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, + 0, NULL, NULL, &si, &pi); + + if (f) + { + SetEvent(waitEvent); // Means thar process has been spawned + CloseHandle(pi.hThread); + h[1] = pi.hProcess; + + while(!exitProc) + { + // Wait for the spawned-process to die or for the event + // indicating that the processes should be forcibly killed. + switch (WaitForMultipleObjects(3, h, FALSE, INFINITE)) + { + case WAIT_OBJECT_0 + 0: // Send Ctrl-C +#ifdef DEBUG_MONITOR + sprintf(buffer, "starter (PID %i) received CTRL-C event\n", currentPID); + OutputDebugString(buffer); +#endif + GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); + SetEvent(waitEvent); + break; + + case WAIT_OBJECT_0 + 1: // App terminated normally + // Make it's exit code our exit code +#ifdef DEBUG_MONITOR + sprintf(buffer, "starter: launched process has been terminated(PID %i)\n", currentPID); + OutputDebugString(buffer); +#endif + GetExitCodeProcess(pi.hProcess, &dwExitCode); + exitProc = TRUE; + break; + case WAIT_OBJECT_0 + 2: // Kill +#ifdef DEBUG_MONITOR + sprintf(buffer, "starter received KILL event (PID %i)\n", currentPID); + OutputDebugString(buffer); +#endif + GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); + TerminateProcess(h[1], 0); + exitProc = TRUE; + break; + default: + // Unexpected code + LPTSTR lpMsgBuf; + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + OutputDebugString(lpMsgBuf); + // Free the buffer. + LocalFree( lpMsgBuf ); + exitProc = TRUE; + break; + } + + } + CloseHandle(pi.hProcess); + } + + CloseHandle(waitEvent); + CloseHandle(h[0]); + CloseHandle(h[2]); + + return(dwExitCode); +} + + +//////////////////////////////// End of File ////////////////////////////////// diff --git a/core/org.eclipse.cdt.core.win32/library/starter/starter.dep b/core/org.eclipse.cdt.core.win32/library/starter/starter.dep new file mode 100644 index 00000000000..3f69f7967a6 --- /dev/null +++ b/core/org.eclipse.cdt.core.win32/library/starter/starter.dep @@ -0,0 +1,5 @@ +# Microsoft Developer Studio Generated Dependency File, included by starter.mak + +.\starter.cpp : \ + "..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ + diff --git a/core/org.eclipse.cdt.core.win32/library/starter/starter.mak b/core/org.eclipse.cdt.core.win32/library/starter/starter.mak new file mode 100644 index 00000000000..da4557508fe --- /dev/null +++ b/core/org.eclipse.cdt.core.win32/library/starter/starter.mak @@ -0,0 +1,171 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on starter.dsp +!IF "$(CFG)" == "" +CFG=starter - Win32 Release +!MESSAGE No configuration specified. Defaulting to starter - Win32 Release +!ENDIF + +!IF "$(CFG)" != "starter - Win32 Release" && "$(CFG)" != "starter - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "starter.mak" CFG="starter - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "starter - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "starter - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "starter - Win32 Release" + +OUTDIR=..\..\os\win32\x86 +INTDIR=.\ +# Begin Custom Macros +OutDir=..\..\os\win32\x86 +# End Custom Macros + +ALL : "$(OUTDIR)\starter.exe" "$(OUTDIR)\starter.bsc" + + +CLEAN : + -@erase "$(INTDIR)\starter.obj" + -@erase "$(INTDIR)\starter.sbr" + -@erase "$(INTDIR)\vc60.idb" + -@erase "$(OUTDIR)\starter.bsc" + -@erase "$(OUTDIR)\starter.exe" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\starter.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\starter.bsc" +BSC32_SBRS= \ + "$(INTDIR)\starter.sbr" + +"$(OUTDIR)\starter.bsc" : "$(OUTDIR)" $(BSC32_SBRS) + $(BSC32) @<< + $(BSC32_FLAGS) $(BSC32_SBRS) +<< + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\starter.pdb" /machine:I386 /out:"$(OUTDIR)\starter.exe" +LINK32_OBJS= \ + "$(INTDIR)\starter.obj" + +"$(OUTDIR)\starter.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "starter - Win32 Debug" + +OUTDIR=..\..\os\win32\x86 +INTDIR=.\ +# Begin Custom Macros +OutDir=..\..\os\win32\x86 +# End Custom Macros + +ALL : "$(OUTDIR)\starter.exe" + + +CLEAN : + -@erase "$(INTDIR)\starter.obj" + -@erase "$(INTDIR)\vc60.idb" + -@erase "$(INTDIR)\vc60.pdb" + -@erase "$(OUTDIR)\starter.exe" + -@erase "$(OUTDIR)\starter.ilk" + -@erase "$(OUTDIR)\starter.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\starter.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\starter.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\starter.pdb" /debug /machine:I386 /out:"$(OUTDIR)\starter.exe" /pdbtype:sept +LINK32_OBJS= \ + "$(INTDIR)\starter.obj" + +"$(OUTDIR)\starter.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("starter.dep") +!INCLUDE "starter.dep" +!ELSE +!MESSAGE Warning: cannot find "starter.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "starter - Win32 Release" || "$(CFG)" == "starter - Win32 Debug" +SOURCE=.\starter.cpp + +!IF "$(CFG)" == "starter - Win32 Release" + + +"$(INTDIR)\starter.obj" "$(INTDIR)\starter.sbr" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "starter - Win32 Debug" + + +"$(INTDIR)\starter.obj" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + + +!ENDIF + diff --git a/core/org.eclipse.cdt.core.win32/os/win32/x86/spawner.dll b/core/org.eclipse.cdt.core.win32/os/win32/x86/spawner.dll new file mode 100644 index 00000000000..e69de29bb2d diff --git a/core/org.eclipse.cdt.core.win32/os/win32/x86/starter.exe b/core/org.eclipse.cdt.core.win32/os/win32/x86/starter.exe new file mode 100644 index 00000000000..e69de29bb2d