1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-07 01:36:01 +02:00

windows spawner

This commit is contained in:
David Inglis 2002-09-03 16:16:20 +00:00
parent 484862d910
commit 25863f8649
19 changed files with 1794 additions and 0 deletions

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="/org.eclipse.core.resources"/>
<classpathentry kind="src" path="/org.eclipse.ui"/>
<classpathentry kind="src" path="/org.eclipse.cdt.core"/>
<classpathentry kind="src" path="/org.eclipse.core.runtime"/>
<classpathentry kind="src" path="/org.apache.xerces"/>
<classpathentry kind="src" path="/org.eclipse.search"/>
<classpathentry kind="src" path="/org.eclipse.compare"/>
<classpathentry kind="src" path="/org.eclipse.debug.ui"/>
<classpathentry kind="src" path="/org.eclipse.debug.core"/>
<classpathentry kind="src" path="/org.eclipse.core.boot"/>
<classpathentry kind="var" path="JRE_LIB" rootpath="JRE_SRCROOT" sourcepath="JRE_SRC"/>
<classpathentry kind="output" path=""/>
</classpath>

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.eclipse.cdt.core.win32</name>
<comment></comment>
<projects>
<project>org.apache.xerces</project>
<project>org.eclipse.cdt.core</project>
<project>org.eclipse.compare</project>
<project>org.eclipse.core.boot</project>
<project>org.eclipse.core.resources</project>
<project>org.eclipse.core.runtime</project>
<project>org.eclipse.debug.core</project>
<project>org.eclipse.debug.ui</project>
<project>org.eclipse.search</project>
<project>org.eclipse.ui</project>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.pde.PluginNature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,2 @@
bin.includes = fragment.xml,\
os/

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<fragment
id="org.eclipse.cdt.core.win32"
name="Win32 Fragment"
version="1.0.0"
provider-name="Eclipse.org"
plugin-id="org.eclipse.cdt.core"
plugin-version="1.0.0">
<runtime>
</runtime>
<requires>
<import plugin="org.eclipse.core.resources"/>
<import plugin="org.eclipse.ui"/>
</requires>
</fragment>

View file

@ -0,0 +1,45 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* 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

View file

@ -0,0 +1,32 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* 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

View file

@ -0,0 +1,29 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* 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

View file

@ -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

View file

@ -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 <tchar.h>
#include <windows.h>
// 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_)

View file

@ -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 <string.h>
#include <stdlib.h>
#include <process.h>
#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;
}

View file

@ -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 <string.h>
#include <stdlib.h>
#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);
}

View file

@ -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;
}

View file

@ -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"\

View file

@ -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

View file

@ -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 <Windows.h>
#include <process.h>
#include <tchar.h>
#include <stdio.h>
// #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 //////////////////////////////////

View file

@ -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"\

View file

@ -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