Initial commit

This commit is contained in:
Eagle517
2026-01-14 10:27:57 -06:00
commit c1576fee30
11290 changed files with 1552799 additions and 0 deletions

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<fragment
id="org.eclipse.cdt.source.win32.win32.x86"
name="%pluginName"
version="2.0.0"
provider-name="Eclipse.org"
plugin-id="org.eclipse.cdt.source"
plugin-version="2.0.0">
<runtime>
</runtime>
<extension point = "org.eclipse.pde.core.source">
<location path="src" />
</extension>
</fragment>

View File

@@ -0,0 +1,68 @@
/**********************************************************************
* Copyright (c) 2002-2004 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
*
* Spawner.h
*
* This is a part of JNI implementation of spawner
***********************************************************************/
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_eclipse_cdt_utils_spawner_Spawner */
#ifndef _Included_org_eclipse_cdt_utils_spawner_Spawner
#define _Included_org_eclipse_cdt_utils_spawner_Spawner
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: org_eclipse_cdt_utils_spawner_Spawner
* Method: exec0
* Signature: ([Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;[I)I
*/
JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec0
(JNIEnv *, jobject, jobjectArray, jobjectArray, jstring, jintArray);
/*
* Class: org_eclipse_cdt_utils_spawner_Spawner
* Method: exec1
* Signature: ([Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec1
(JNIEnv *, jobject, jobjectArray, jobjectArray, jstring);
/*
* Class: org_eclipse_cdt_utils_spawner_Spawner
* Method: raise
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_raise
(JNIEnv *, jobject, jint, jint);
/*
* Class: org_eclipse_cdt_utils_spawner_Spawner
* Method: waitFor
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_waitFor
(JNIEnv *, jobject, jint);
// #define DEBUG_MONITOR
int interruptProcess(int pid);
#ifdef __cplusplus
}
#endif
// #define DEBUG_MONITOR
#endif

View File

@@ -0,0 +1,47 @@
/**********************************************************************
* Copyright (c) 2002-2004 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
*
* SpawnerInputStream.h
*
* This is a part of JNI implementation of spawner
***********************************************************************/
/* 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,43 @@
/**********************************************************************
* Copyright (c) 2002-2004 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
*
* SpawnerOutputStream.h
*
* This is a part of JNI implementation of spawner
***********************************************************************/
/* 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,22 @@
/**********************************************************************
* Copyright (c) 2002-2004 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
*
* StdAfx.c
*
* This is a part of JNI implementation of spawner
***********************************************************************/
// 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,41 @@
/**********************************************************************
* Copyright (c) 2002-2004 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
*
* StdAfx.h
*
* This is a part of JNI implementation of spawner
***********************************************************************/
// 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,914 @@
/**********************************************************************
* Copyright (c) 2002-2004 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
*
* 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 // Size of pipe buffer
#define MAX_CMD_SIZE 2049 // Maximum size of command line
#define MAX_ENV_SIZE 4096 // Initial size of environment block
#define PIPE_NAME_LENGTH 100 // Size of pipe name buffer
#define PIPE_TIMEOUT 10000 // Default time-out value, in milliseconds.
#define MAX_PROCS (100) // Maximum number of simultaneiously runnig processes
// Process description block. Should be created for each launched process
typedef struct _procInfo {
int pid; // Process ID
int uid; // quasi-unique process ID; we have to create it to avoid duplicated pid
// (actually this impossible from OS point of view but it is still possible
// a clash of new created and already finished process with one and the same PID.
// 3 events connected to this process (see starter)
HANDLE eventBreak;
HANDLE eventWait;
HANDLE eventTerminate;
} procInfo_t, * pProcInfo_t;
static int procCounter = 0; // Number of running processes
// This is a VM helper
JNIEXPORT void JNICALL ThrowByName(JNIEnv *env, const char *name, const char *msg);
// Creates _procInfo block for every launched procss
pProcInfo_t createProcInfo();
// Find process description for this pid
pProcInfo_t findProcInfo(int pid);
// We launch separate thread for each project to trap it termination
unsigned int _stdcall waitProcTermination(void* pv) ;
// This is a helper function to prevent losing of quotatin marks
static int copyTo(_TCHAR * target, const _TCHAR * source, int cpyLenght, int availSpace);
// Use this function to clean project descriptor and return it to the pool of available blocks.
static void cleanUpProcBlock(pProcInfo_t pCurProcInfo);
// Signal codes
typedef enum {
SIG_NOOP,
SIG_HUP,
SIG_INT,
SIG_KILL = 9,
SIG_TERM = 15,
} signals;
extern CRITICAL_SECTION cs;
extern _TCHAR path[MAX_PATH]; // Directory where spawner.dll is located
static HMODULE hVM = NULL; // VM handler
static pProcInfo_t pInfo = NULL;
static int nCounter = 0; // We use it to build unique synchronisation object names
/////////////////////////////////////////////////////////////////////////////////////
// Launcher; launchess process and traps its termination
// Arguments: (see Spawner.java)
// [in] cmdarray - array of command line elements
// [in] envp - array of environment variables
// [in] dir - working directory
// [out] channels - streams handlers
/////////////////////////////////////////////////////////////////////////////////////
JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec0
(JNIEnv * env, jobject process, jobjectArray cmdarray, jobjectArray envp, jstring dir, jintArray channels)
{
HANDLE stdHandles[3];
PROCESS_INFORMATION pi = {0};
STARTUPINFOW si;
DWORD flags = 0;
const _TCHAR * cwd = NULL;
LPVOID envBlk = NULL;
int ret = 0;
_TCHAR szCmdLine[MAX_CMD_SIZE];
int nBlkSize = MAX_ENV_SIZE;
_TCHAR * szEnvBlock = (_TCHAR *)malloc(nBlkSize * sizeof(_TCHAR));
jsize nCmdTokens = 0;
jsize nEnvVars = 0;
int i;
DWORD pid = GetCurrentProcessId();
int nPos;
pProcInfo_t pCurProcInfo;
DWORD dwThreadId;
_TCHAR eventBreakName[20];
_TCHAR eventWaitName[20];
_TCHAR eventTerminateName[20];
#ifdef DEBUG_MONITOR
_TCHAR buffer[1000];
#endif
int nLocalCounter;
_TCHAR inPipeName[PIPE_NAME_LENGTH];
_TCHAR outPipeName[PIPE_NAME_LENGTH];
_TCHAR errPipeName[PIPE_NAME_LENGTH];
if((HIBYTE(LOWORD(GetVersion()))) & 0x80)
{
ThrowByName(env, "java/io/IOException", "Does not support Windows 3.1/95/98/Me");
return 0;
}
if (cmdarray == 0)
{
ThrowByName(env, "java/lang/NullPointerException", "No command line specified");
return 0;
}
ZeroMemory(stdHandles, sizeof(stdHandles));
// Create pipe names
EnterCriticalSection(&cs);
_stprintf(inPipeName, _T("\\\\.\\pipe\\stdin%08i%010i"), pid, nCounter);
_stprintf(outPipeName, _T("\\\\.\\pipe\\stdout%08i%010i"), pid, nCounter);
_stprintf(errPipeName, _T("\\\\.\\pipe\\stderr%08i%010i"), pid, nCounter);
nLocalCounter = nCounter;
++nCounter;
LeaveCriticalSection(&cs);
if ((INVALID_HANDLE_VALUE == (stdHandles[0] = CreateNamedPipeW(inPipeName, PIPE_ACCESS_OUTBOUND,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES, PIPE_SIZE, PIPE_SIZE, PIPE_TIMEOUT, NULL))) ||
(INVALID_HANDLE_VALUE == (stdHandles[1] = CreateNamedPipeW(outPipeName, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES, PIPE_SIZE, PIPE_SIZE, PIPE_TIMEOUT, NULL))) ||
(INVALID_HANDLE_VALUE == (stdHandles[2] = CreateNamedPipeW(errPipeName, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES, PIPE_SIZE, PIPE_SIZE, PIPE_TIMEOUT, NULL)))) {
CloseHandle(stdHandles[0]);
CloseHandle(stdHandles[1]);
CloseHandle(stdHandles[2]);
ThrowByName(env, "java/io/IOException", "CreatePipe");
return 0;
}
#ifdef DEBUG_MONITOR
_stprintf(buffer, _T("Opened pipes: %s, %s, %s\n"), inPipeName, outPipeName, errPipeName);
OutputDebugStringW(buffer);
#endif
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;
}
// Construct starter's command line
_stprintf(eventBreakName, _T("SABreak%p"), pCurProcInfo);
_stprintf(eventWaitName, _T("SAWait%p"), pCurProcInfo);
_stprintf(eventTerminateName, _T("SATerm%p"), pCurProcInfo);
pCurProcInfo -> eventBreak = CreateEventW(NULL, TRUE, FALSE, eventBreakName);
ResetEvent(pCurProcInfo -> eventBreak);
pCurProcInfo -> eventWait = CreateEventW(NULL, TRUE, FALSE, eventWaitName);
ResetEvent(pCurProcInfo -> eventWait);
pCurProcInfo -> eventTerminate = CreateEventW(NULL, TRUE, FALSE, eventTerminateName);
ResetEvent(pCurProcInfo -> eventTerminate);
nPos = _stprintf(szCmdLine, _T("%sstarter.exe %i %i %s %s %s "), path, pid, nLocalCounter, eventBreakName, eventWaitName, eventTerminateName);
// Prepare command line
for(i = 0; i < nCmdTokens; ++i)
{
jobject item = (*env) -> GetObjectArrayElement(env, cmdarray, i);
jsize len = (*env) -> GetStringLength(env, item);
int nCpyLen;
const _TCHAR * str = (*env) -> GetStringChars(env, item, 0);
if(NULL != str)
{
if(0 > (nCpyLen = copyTo(szCmdLine + nPos, str, len, MAX_CMD_SIZE - nPos)))
{
ThrowByName(env, "java/io/IOException", "Too long command line");
return 0;
}
nPos += nCpyLen;
szCmdLine[nPos] = _T(' ');
++nPos;
(*env) -> ReleaseStringChars(env, item, str);
}
}
szCmdLine[nPos] = _T('\0');
// Prepare environment block
if (nEnvVars > 0)
{
nPos = 0;
for(i = 0; i < nEnvVars; ++i)
{
jobject item = (*env) -> GetObjectArrayElement(env, envp, i);
jsize len = (*env) -> GetStringLength(env, item);
const _TCHAR * str = (*env) -> GetStringChars(env, item, 0);
if(NULL != str)
{
while((nBlkSize - nPos) <= (len + 2)) // +2 for two '\0'
{
nBlkSize += MAX_ENV_SIZE;
szEnvBlock = (_TCHAR *)realloc(szEnvBlock, nBlkSize * sizeof(_TCHAR));
if(NULL == szEnvBlock)
{
ThrowByName(env, "java/io/IOException", "Not enough memory");
return 0;
}
#ifdef DEBUG_MONITOR
_stprintf(buffer, _T("Realloc environment block; new length is %i \n"), nBlkSize);
OutputDebugStringW(buffer);
#endif
}
#ifdef DEBUG_MONITOR
_stprintf(buffer, _T("%s\n"), str);
OutputDebugStringW(buffer);
#endif
_tcsnccpy(szEnvBlock + nPos, str, len);
nPos += len;
szEnvBlock[nPos] = _T('\0');
++nPos;
(*env) -> ReleaseStringChars(env, item, str);
}
}
}
if (dir != 0)
{
const _TCHAR * str = (*env) -> GetStringChars(env, dir, 0);
if(NULL != str)
{
cwd = _tcsdup(str);
(*env) -> ReleaseStringChars(env, dir, str);
}
}
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
si.dwFlags |= STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE; // Processes in the Process Group are hidden
SetHandleInformation(stdHandles[0], HANDLE_FLAG_INHERIT, FALSE);
SetHandleInformation(stdHandles[1], HANDLE_FLAG_INHERIT, FALSE);
SetHandleInformation(stdHandles[2], HANDLE_FLAG_INHERIT, FALSE);
flags = CREATE_NEW_CONSOLE;
flags |= CREATE_NO_WINDOW;
flags |= CREATE_UNICODE_ENVIRONMENT;
#ifdef DEBUG_MONITOR
OutputDebugStringW(szCmdLine);
#endif
// launches starter; we need it to create another console group to correctly process
// emulation of SYSint signal (Ctrl-C)
ret = CreateProcessW(0, /* executable name */
szCmdLine, /* command line */
0, /* process security attribute */
0, /* thread security attribute */
FALSE, /* inherits system handles */
flags, /* normal attached process */
envBlk, /* environment block */
cwd, /* change to the new current directory */
&si, /* (in) startup information */
&pi); /* (out) process information */
if(NULL != cwd)
free((void *)cwd);
free(szEnvBlock);
if (!ret) // Launching error
{
char * lpMsgBuf;
CloseHandle(stdHandles[0]);
CloseHandle(stdHandles[1]);
CloseHandle(stdHandles[2]);
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(char *)&lpMsgBuf,
0,
NULL
);
ThrowByName(env, "java/io/IOException", lpMsgBuf);
// Free the buffer.
LocalFree( lpMsgBuf );
cleanUpProcBlock(pCurProcInfo);
ret = -1;
}
else
{
int file_handles[3];
HANDLE h[2];
int what;
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
_stprintf(buffer, _T("Process %i failed\n"), pi.dwProcessId);
OutputDebugStringW(buffer);
#endif
cleanUpProcBlock(pCurProcInfo);
ThrowByName(env, "java/io/IOException", "Launching failed");
#ifdef DEBUG_MONITOR
OutputDebugStringW(_T("Process failed\n"));
#endif
}
else
{
ret = (long)(pCurProcInfo -> uid);
// Prepare stream handlers to return to java program
file_handles[0] = (int)stdHandles[0];
file_handles[1] = (int)stdHandles[1];
file_handles[2] = (int)stdHandles[2];
(*env) -> SetIntArrayRegion(env, channels, 0, 3, file_handles);
#ifdef DEBUG_MONITOR
OutputDebugStringW(_T("Process started\n"));
#endif
}
CloseHandle(h[1]);
LeaveCriticalSection(&cs);
}
return ret;
}
/////////////////////////////////////////////////////////////////////////////////////
// Launcher; just launches process and don't care about it any more
// Arguments: (see Spawner.java)
// [in] cmdarray - array of command line elements
// [in] envp - array of environment variables
// [in] dir - working directory
/////////////////////////////////////////////////////////////////////////////////////
JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec1
(JNIEnv * env, jobject process, jobjectArray cmdarray, jobjectArray envp, jstring dir)
{
SECURITY_ATTRIBUTES sa;
PROCESS_INFORMATION pi = {0};
STARTUPINFOW si;
DWORD flags = 0;
_TCHAR * cwd = NULL;
_TCHAR * envBlk = NULL;
int ret = 0;
jsize nCmdTokens = 0;
jsize nEnvVars = 0;
int i;
int nPos;
_TCHAR szCmdLine[MAX_CMD_SIZE];
int nBlkSize = MAX_ENV_SIZE;
_TCHAR * szEnvBlock = (_TCHAR *)malloc(nBlkSize * sizeof(_TCHAR));
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = 0;
sa.bInheritHandle = TRUE;
nCmdTokens = (*env) -> GetArrayLength(env, cmdarray);
nEnvVars = (*env) -> GetArrayLength(env, envp);
nPos = 0;
// Prepare command line
for(i = 0; i < nCmdTokens; ++i)
{
jobject item = (*env) -> GetObjectArrayElement(env, cmdarray, i);
jsize len = (*env) -> GetStringLength(env, item);
int nCpyLen;
const _TCHAR * str = (*env) -> GetStringChars(env, item, 0);
if(NULL != str)
{
if(0 > (nCpyLen = copyTo(szCmdLine + nPos, str, len, MAX_CMD_SIZE - nPos)))
{
ThrowByName(env, "java/io/Exception", "Too long command line");
return 0;
}
nPos += nCpyLen;
szCmdLine[nPos] = _T(' ');
++nPos;
(*env) -> ReleaseStringChars(env, item, str);
}
}
szCmdLine[nPos] = _T('\0');
// Prepare environment block
if (nEnvVars > 0)
{
nPos = 0;
for(i = 0; i < nEnvVars; ++i)
{
jobject item = (*env) -> GetObjectArrayElement(env, envp, i);
jsize len = (*env) -> GetStringLength(env, item);
const _TCHAR * str = (*env) -> GetStringChars(env, item, 0);
if(NULL != str)
{
while((nBlkSize - nPos) <= (len + 2)) // +2 for two '\0'
{
nBlkSize += MAX_ENV_SIZE;
szEnvBlock = (_TCHAR *)realloc(szEnvBlock, nBlkSize * sizeof(_TCHAR));
if(NULL == szEnvBlock)
{
ThrowByName(env, "java/io/Exception", "Not enough memory");
return 0;
}
}
_tcsnccpy(szEnvBlock + nPos, str, len);
nPos += len;
szEnvBlock[nPos] = _T('\0');
++nPos;
(*env) -> ReleaseStringChars(env, item, str);
}
}
szEnvBlock[nPos] = _T('\0');
envBlk = szEnvBlock;
}
if (dir != 0)
{
const _TCHAR * str = (*env) -> GetStringChars(env, dir, 0);
if(NULL != str)
{
cwd = _tcsdup(str);
(*env) -> ReleaseStringChars(env, dir, str);
}
}
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
flags = CREATE_NEW_CONSOLE;
ret = CreateProcessW(0, /* executable name */
szCmdLine, /* command line */
0, /* process security attribute */
0, /* thread security attribute */
TRUE, /* inherits system handles */
flags, /* normal attached process */
envBlk, /* environment block */
cwd, /* change to the new current directory */
&si, /* (in) startup information */
&pi); /* (out) process information */
if(NULL != cwd)
free(cwd);
free(szEnvBlock);
if (!ret) // error
{
char * lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(char *)&lpMsgBuf,
0,
NULL
);
ThrowByName(env, "java/io/IOException", lpMsgBuf);
// Free the buffer.
LocalFree( lpMsgBuf );
ret = -1;
}
else
{
// Clean-up
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
ret = (long)pi.dwProcessId; //hProcess;
}
return ret;
}
/////////////////////////////////////////////////////////////////////////////////////
// Emulation of the signal raising
// Arguments: (see Spawner.java)
// [in] uid - unique process ID
// [in] signal - signal to raise
/////////////////////////////////////////////////////////////////////////////////////
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
_TCHAR buffer[100];
#endif
if(NULL == pCurProcInfo) {
if(SIG_INT == signal) { // Try another way
return interruptProcess(uid) ;
}
return -1;
}
#ifdef DEBUG_MONITOR
_stprintf(buffer, _T("Spawner received signal %i for process %i\n"), signal, pCurProcInfo -> pid);
OutputDebugStringW(buffer);
#endif
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
_stprintf(buffer, _T("Spawner received KILL or TERM signal for process %i\n"),
pCurProcInfo -> pid);
OutputDebugStringW(buffer);
#endif
SetEvent(pCurProcInfo -> eventTerminate);
#ifdef DEBUG_MONITOR
OutputDebugStringW(_T("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;
}
/////////////////////////////////////////////////////////////////////////////////////
// Wait for process termination
// Arguments: (see Spawner.java)
// [in] uid - unique process ID
/////////////////////////////////////////////////////////////////////////////////////
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(hProc, &exit_code);
}
if(hProc)
CloseHandle(hProc);
return exit_code;
}
// Utilities
/////////////////////////////////////////////////////////////////////////////////////
// Throws Java exception (will be trapped by VM).
// Arguments:
// [in] name - name of exception class
// [in] message to assign thi event
/////////////////////////////////////////////////////////////////////////////////////
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);
}
/////////////////////////////////////////////////////////////////////////////////////
// Create process description block.
// Arguments: no
// Return : pointer to the process descriptor
/////////////////////////////////////////////////////////////////////////////////////
pProcInfo_t createProcInfo()
{
int i;
pProcInfo_t p = NULL;
EnterCriticalSection(&cs);
if(NULL == pInfo)
{
pInfo = malloc(sizeof(procInfo_t) * MAX_PROCS);
ZeroMemory(pInfo, 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;
}
/////////////////////////////////////////////////////////////////////////////////////
// Using unique process ID finds process descriptor
// Arguments: no
// Return : pointer to the process descriptor
/////////////////////////////////////////////////////////////////////////////////////
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;
}
/////////////////////////////////////////////////////////////////////////////////////
// Cleans up vacant process descriptor
// Arguments:
// pCurProcInfo - pointer to descriptor to clean up
// Return : no
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;
}
/////////////////////////////////////////////////////////////////////////////////////
// Running in separae thread and waiting for the process termination
// Arguments:
// pv - (int)pv is a pid
// Return : always 0
/////////////////////////////////////////////////////////////////////////////////////
unsigned int _stdcall waitProcTermination(void* pv)
{
int i;
int pid = (int)pv;
#ifdef DEBUG_MONITOR
_TCHAR buffer[1000];
#endif
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
if(NULL == hProc)
{
#ifdef DEBUG_MONITOR
_stprintf(buffer, _T("waitProcTermination: cannot get handler for PID %i (error %i)\n"),
pid,
GetLastError());
OutputDebugStringW(buffer);
#endif
}
else
{
WaitForSingleObject(hProc, INFINITE);
#ifdef DEBUG_MONITOR
_stprintf(buffer, _T("Process PID %i terminated\n"), pid);
OutputDebugStringW(buffer);
#endif
}
for(i = 0; i < MAX_PROCS; ++i)
{
if(pInfo[i].pid == pid)
{
if(WaitForSingleObject(pInfo[i].eventWait, 1) == WAIT_OBJECT_0) // Correct finish
{
#ifdef DEBUG_MONITOR
_stprintf(buffer, _T("waitProcTermination: set PID %i to 0\n"),
pid,
GetLastError());
OutputDebugStringW(buffer);
#endif
cleanUpProcBlock(pInfo + i);
}
break;
} // Otherwise failed because was not started
}
CloseHandle(hProc);
return 0;
}
/////////////////////////////////////////////////////////////////////////////////////
// Use this utility program to process correctly quotation marks in the command line
// Arguments:
// target - string to copy to
// source - string to copy from
// cpyLength - copy length
// availSpace - size of the target buffer
// Return :number of bytes used in target, or -1 in case of error
/////////////////////////////////////////////////////////////////////////////////////
int copyTo(_TCHAR * target, const _TCHAR * source, int cpyLength, int availSpace)
{
BOOL bSlash = FALSE;
int i = 0, j = 0;
int totCpyLength = cpyLength;
#define QUOTATION_DO 0
#define QUOTATION_DONE 1
#define QUOTATION_NONE 2
int nQuotationMode = 0;
if(availSpace <= cpyLength) // = to reserve space for final '\0'
return -1;
if((_T('\"') == *source) && (_T('\"') == *(source + cpyLength - 1)))
{
nQuotationMode = QUOTATION_DONE;
}
else
if(_tcschr(source, _T(' ')) == NULL)
{
// No reason to quotate term becase it doesn't have embedded spaces
nQuotationMode = QUOTATION_NONE;
}
else
{
// Needs to be quotated
nQuotationMode = QUOTATION_DO;
*target = _T('\"');
++j;
}
for(; i < cpyLength; ++i, ++j)
{
if(source[i] == _T('\\'))
bSlash = TRUE;
else
{
// Don't escape embracing quotation marks
if((source[i] == _T('\"')) && !((nQuotationMode == QUOTATION_DONE) && ((i == 0) || (i == (cpyLength - 1))) ) )
{
if(!bSlash) // If still not escaped
{
if(j == availSpace)
return -1;
target[j] = _T('\\');
++j;
}
}
bSlash = FALSE;
}
if(j == availSpace)
return -1;
target[j] = source[i];
}
if(nQuotationMode == QUOTATION_DO)
{
if(j == availSpace)
return -1;
target[j] = _T('\"');
++j;
}
return j;
}

View File

@@ -0,0 +1,233 @@
/**********************************************************************
* Copyright (c) 2002-2004 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
*
* raise.c
*
* This is a part of JNI implementation of spawner
* Includes implementation of JNI methods (see Spawner.java)
***********************************************************************/
#include "stdafx.h"
#include <string.h>
#include <stdlib.h>
#include "spawner.h"
#include "SpawnerInputStream.h"
#include "SpawnerOutputStream.h"
#include "jni.h"
#include "io.h"
//#define READ_REPORT
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;
#ifdef DEBUG_MONITOR
_TCHAR buffer[1000];
#endif
OVERLAPPED overlapped;
overlapped.Offset = 0;
overlapped.OffsetHigh = 0;
overlapped.hEvent = CreateEvent(NULL, // no security attribute
TRUE, // manual-reset event
TRUE, // initial state = signaled
NULL); // unnamed event object
if(NULL == overlapped.hEvent) {
char * lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(char *) &lpMsgBuf,
0,
NULL
);
ThrowByName(env, "java/io/IOException", lpMsgBuf);
// Free the buffer.
LocalFree( lpMsgBuf );
}
#ifdef DEBUG_MONITOR
#ifdef READ_REPORT
_stprintf(buffer, _T("Start read %i\n"), fd);
OutputDebugStringW(buffer);
#endif
#endif
while(len > nBuffOffset)
{
int nNumberOfBytesToRead = min(len - nBuffOffset, BUFF_SIZE);
int nNumberOfBytesRead;
if(0 == ReadFile((HANDLE)fd, tmpBuf, nNumberOfBytesToRead, &nNumberOfBytesRead, &overlapped ))
{
int err = GetLastError();
if(err == ERROR_IO_PENDING)
{
// asynchronous i/o is still in progress
// check on the results of the asynchronous read
if(GetOverlappedResult((HANDLE)fd, &overlapped,
&nNumberOfBytesRead, TRUE))
err = 0;
// if there was a problem ...
else
err = GetLastError();
}
if(err == ERROR_BROKEN_PIPE) // Pipe was closed
break;
if(err != 0)
{
char * lpMsgBuf;
#ifdef DEBUG_MONITOR
_stprintf(buffer, _T("Read failed - %i, error %i\n"), fd, err);
OutputDebugStringW(buffer);
#endif
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
(char *) &lpMsgBuf,
0,
NULL
);
ThrowByName(env, "java/io/IOException", lpMsgBuf);
LocalFree( lpMsgBuf );
nBuffOffset = 0;
break;
}
}
}
if(nNumberOfBytesRead > 0)
(*env) -> SetByteArrayRegion(env, buf, nBuffOffset, nNumberOfBytesRead, tmpBuf);
else
break;
nBuffOffset += nNumberOfBytesRead;
if(nNumberOfBytesRead != nNumberOfBytesToRead)
break;
}
CloseHandle(overlapped.hEvent);
#ifdef DEBUG_MONITOR
#ifdef READ_REPORT
_stprintf(buffer, _T("End read %i\n"), fd);
OutputDebugStringW(buffer);
#endif
#endif
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)
{
int rc;
#ifdef DEBUG_MONITOR
_TCHAR buffer[1000];
_stprintf(buffer, _T("Close %i\n"), fd);
OutputDebugStringW(buffer);
#endif
DisconnectNamedPipe((HANDLE)fd);
rc = (CloseHandle((HANDLE)fd) ? 0 : -1);
#ifdef DEBUG_MONITOR
_stprintf(buffer, _T("Closed %i\n"), fd);
OutputDebugStringW(buffer);
#endif
return (rc ? GetLastError() : 0);
}
/*
* 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))
{
char * lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(char *) &lpMsgBuf,
0,
NULL
);
ThrowByName(env, "java/io/IOException", lpMsgBuf);
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)
{
int rc;
#ifdef DEBUG_MONITOR
_TCHAR buffer[1000];
_stprintf(buffer, _T("Close %i\n"), fd);
OutputDebugStringW(buffer);
#endif
DisconnectNamedPipe((HANDLE)fd);
rc = (CloseHandle((HANDLE)fd) ? 0 : -1);
#ifdef DEBUG_MONITOR
_stprintf(buffer, _T("Closed %i\n"), fd);
OutputDebugStringW(buffer);
#endif
return (rc ? GetLastError() : 0);
}

View File

@@ -0,0 +1,8 @@
// stdafx.cpp : source file that includes just the standard includes
// ProcList.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,29 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v0.5
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v05.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
// 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__CB3B970F_AA1A_4B59_9F98_DDBEA28470AF__INCLUDED_)
#define AFX_STDAFX_H__CB3B970F_AA1A_4B59_9F98_DDBEA28470AF__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// 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__CB3B970F_AA1A_4B59_9F98_DDBEA28470AF__INCLUDED_)

View File

@@ -0,0 +1,323 @@
/**********************************************************************
* Copyright (c) 2002,2003 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v0.5
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v05.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
***********************************************************************/
// ProcList.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "listtasks.h"
#include <tlhelp32.h>
#include <vdmdbg.h>
#include <iostream>
#include <iomanip>
using namespace std;
typedef struct
{
DWORD dwPID ;
PROCENUMPROC lpProc ;
DWORD lParam ;
BOOL bEnd ;
} EnumInfoStruct ;
BOOL WINAPI Enum16( DWORD dwThreadId, WORD hMod16, WORD hTask16,
PSZ pszModName, PSZ pszFileName, LPARAM lpUserDefined ) ;
BOOL CALLBACK OutProcInfo( DWORD pid, WORD, LPSTR procName, LPARAM ) ;
int main(int argc, char* argv[])
{
EnumProcs(OutProcInfo, 0);
return 0;
}
/*********************
EnumProc.cpp
*********************/
// The EnumProcs function takes a pointer to a callback function
// that will be called once per process in the system providing
// process EXE filename and process ID.
// Callback function definition:
// BOOL CALLBACK Proc( DWORD dw, LPCSTR lpstr, LPARAM lParam ) ;
//
// lpProc -- Address of callback routine.
//
// lParam -- A user-defined LPARAM value to be passed to
// the callback routine.
BOOL WINAPI EnumProcs( PROCENUMPROC lpProc, LPARAM lParam )
{
OSVERSIONINFO osver ;
HINSTANCE hInstLib ;
HINSTANCE hInstLib2 ;
HANDLE hSnapShot ;
PROCESSENTRY32 procentry ;
BOOL bFlag ;
LPDWORD lpdwPIDs ;
DWORD dwSize, dwSize2, dwIndex ;
HMODULE hMod ;
HANDLE hProcess ;
char szFileName[ MAX_PATH ] ;
EnumInfoStruct sInfo ;
// ToolHelp Function Pointers.
HANDLE (WINAPI *lpfCreateToolhelp32Snapshot)(DWORD,DWORD) ;
BOOL (WINAPI *lpfProcess32First)(HANDLE,LPPROCESSENTRY32) ;
BOOL (WINAPI *lpfProcess32Next)(HANDLE,LPPROCESSENTRY32) ;
// PSAPI Function Pointers.
BOOL (WINAPI *lpfEnumProcesses)( DWORD *, DWORD cb, DWORD * );
BOOL (WINAPI *lpfEnumProcessModules)( HANDLE, HMODULE *,
DWORD, LPDWORD );
DWORD (WINAPI *lpfGetModuleFileNameEx)( HANDLE, HMODULE,
LPTSTR, DWORD );
// VDMDBG Function Pointers.
INT (WINAPI *lpfVDMEnumTaskWOWEx)( DWORD,
TASKENUMPROCEX fp, LPARAM );
// Check to see if were running under Windows95 or
// Windows NT.
osver.dwOSVersionInfoSize = sizeof( osver ) ;
if( !GetVersionEx( &osver ) )
{
return FALSE ;
}
// If Windows NT:
if( osver.dwPlatformId == VER_PLATFORM_WIN32_NT )
{
// Load library and get the procedures explicitly. We do
// this so that we don't have to worry about modules using
// this code failing to load under Windows 95, because
// it can't resolve references to the PSAPI.DLL.
hInstLib = LoadLibraryA( "PSAPI.DLL" ) ;
if( hInstLib == NULL )
return FALSE ;
hInstLib2 = LoadLibraryA( "VDMDBG.DLL" ) ;
if( hInstLib2 == NULL )
return FALSE ;
// Get procedure addresses.
lpfEnumProcesses = (BOOL(WINAPI *)(DWORD *,DWORD,DWORD*))
GetProcAddress( hInstLib, "EnumProcesses" ) ;
lpfEnumProcessModules = (BOOL(WINAPI *)(HANDLE, HMODULE *,
DWORD, LPDWORD)) GetProcAddress( hInstLib,
"EnumProcessModules" ) ;
lpfGetModuleFileNameEx =(DWORD (WINAPI *)(HANDLE, HMODULE,
LPTSTR, DWORD )) GetProcAddress( hInstLib,
"GetModuleFileNameExA" ) ;
lpfVDMEnumTaskWOWEx =(INT(WINAPI *)( DWORD, TASKENUMPROCEX,
LPARAM))GetProcAddress( hInstLib2, "VDMEnumTaskWOWEx" );
if( lpfEnumProcesses == NULL ||
lpfEnumProcessModules == NULL ||
lpfGetModuleFileNameEx == NULL ||
lpfVDMEnumTaskWOWEx == NULL)
{
FreeLibrary( hInstLib ) ;
FreeLibrary( hInstLib2 ) ;
return FALSE ;
}
// Call the PSAPI function EnumProcesses to get all of the
// ProcID's currently in the system.
// NOTE: In the documentation, the third parameter of
// EnumProcesses is named cbNeeded, which implies that you
// can call the function once to find out how much space to
// allocate for a buffer and again to fill the buffer.
// This is not the case. The cbNeeded parameter returns
// the number of PIDs returned, so if your buffer size is
// zero cbNeeded returns zero.
// NOTE: The "HeapAlloc" loop here ensures that we
// actually allocate a buffer large enough for all the
// PIDs in the system.
dwSize2 = 256 * sizeof( DWORD ) ;
lpdwPIDs = NULL ;
do
{
if( lpdwPIDs )
{
HeapFree( GetProcessHeap(), 0, lpdwPIDs ) ;
dwSize2 *= 2 ;
}
lpdwPIDs = (LPDWORD)HeapAlloc( GetProcessHeap(), 0, dwSize2 );
if( lpdwPIDs == NULL )
{
FreeLibrary( hInstLib ) ;
FreeLibrary( hInstLib2 ) ;
return FALSE ;
}
if( !lpfEnumProcesses( lpdwPIDs, dwSize2, &dwSize ) )
{
HeapFree( GetProcessHeap(), 0, lpdwPIDs ) ;
FreeLibrary( hInstLib ) ;
FreeLibrary( hInstLib2 ) ;
return FALSE ;
}
}while( dwSize == dwSize2 ) ;
// How many ProcID's did we get?
dwSize /= sizeof( DWORD ) ;
// Loop through each ProcID.
for( dwIndex = 0 ; dwIndex < dwSize ; dwIndex++ )
{
szFileName[0] = 0 ;
// Open the process (if we can... security does not
// permit every process in the system).
hProcess = OpenProcess(
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE, lpdwPIDs[ dwIndex ] ) ;
if( hProcess != NULL )
{
// Here we call EnumProcessModules to get only the
// first module in the process this is important,
// because this will be the .EXE module for which we
// will retrieve the full path name in a second.
if( lpfEnumProcessModules( hProcess, &hMod,
sizeof( hMod ), &dwSize2 ) )
{
// Get Full pathname:
if( !lpfGetModuleFileNameEx( hProcess, hMod,
szFileName, sizeof( szFileName ) ) )
{
szFileName[0] = 0 ;
}
}
CloseHandle( hProcess ) ;
}
// Regardless of OpenProcess success or failure, we
// still call the enum func with the ProcID.
if(!lpProc( lpdwPIDs[dwIndex], 0, szFileName, lParam))
break ;
// Did we just bump into an NTVDM?
if( _stricmp( szFileName+(strlen(szFileName)-9),
"NTVDM.EXE")==0)
{
// Fill in some info for the 16-bit enum proc.
sInfo.dwPID = lpdwPIDs[dwIndex] ;
sInfo.lpProc = lpProc ;
sInfo.lParam = lParam ;
sInfo.bEnd = FALSE ;
// Enum the 16-bit stuff.
lpfVDMEnumTaskWOWEx( lpdwPIDs[dwIndex],
(TASKENUMPROCEX) Enum16,
(LPARAM) &sInfo);
// Did our main enum func say quit?
if(sInfo.bEnd)
break ;
}
}
HeapFree( GetProcessHeap(), 0, lpdwPIDs ) ;
FreeLibrary( hInstLib2 ) ;
// If Windows 95:
}else if( osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
{
hInstLib = LoadLibraryA( "Kernel32.DLL" ) ;
if( hInstLib == NULL )
return FALSE ;
// Get procedure addresses.
// We are linking to these functions of Kernel32
// explicitly, because otherwise a module using
// this code would fail to load under Windows NT,
// which does not have the Toolhelp32
// functions in the Kernel 32.
lpfCreateToolhelp32Snapshot=
(HANDLE(WINAPI *)(DWORD,DWORD))
GetProcAddress( hInstLib,
"CreateToolhelp32Snapshot" ) ;
lpfProcess32First=
(BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))
GetProcAddress( hInstLib, "Process32First" ) ;
lpfProcess32Next=
(BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))
GetProcAddress( hInstLib, "Process32Next" ) ;
if( lpfProcess32Next == NULL ||
lpfProcess32First == NULL ||
lpfCreateToolhelp32Snapshot == NULL )
{
FreeLibrary( hInstLib ) ;
return FALSE ;
}
// Get a handle to a Toolhelp snapshot of the systems
// processes.
hSnapShot = lpfCreateToolhelp32Snapshot(
TH32CS_SNAPPROCESS, 0 ) ;
if( hSnapShot == INVALID_HANDLE_VALUE )
{
FreeLibrary( hInstLib ) ;
return FALSE ;
}
// Get the first process' information.
procentry.dwSize = sizeof(PROCESSENTRY32) ;
bFlag = lpfProcess32First( hSnapShot, &procentry ) ;
// While there are processes, keep looping.
while( bFlag )
{
// Call the enum func with the filename and ProcID.
if(lpProc( procentry.th32ProcessID, 0,
procentry.szExeFile, lParam ))
{
procentry.dwSize = sizeof(PROCESSENTRY32) ;
bFlag = lpfProcess32Next( hSnapShot, &procentry );
}else
bFlag = FALSE ;
}
}else
return FALSE ;
// Free the library.
FreeLibrary( hInstLib ) ;
return TRUE ;
}
BOOL WINAPI Enum16( DWORD dwThreadId, WORD hMod16, WORD hTask16,
PSZ pszModName, PSZ pszFileName, LPARAM lpUserDefined )
{
BOOL bRet ;
EnumInfoStruct *psInfo = (EnumInfoStruct *)lpUserDefined ;
bRet = psInfo->lpProc( psInfo->dwPID, hTask16, pszFileName,
psInfo->lParam ) ;
if(!bRet)
{
psInfo->bEnd = TRUE ;
}
return !bRet;
}
BOOL CALLBACK OutProcInfo( DWORD pid, WORD, LPSTR procName, LPARAM )
{
cout << setw(10) << pid << '\t' << procName << '\n';
return TRUE;
}

View File

@@ -0,0 +1,117 @@
# Microsoft Developer Studio Project File - Name="listtasks" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=listtasks - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "listtasks.mak".
!MESSAGE
!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 "listtasks.mak" CFG="listtasks - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "listtasks - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "listtasks - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "listtasks - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib 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 /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib 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 /machine:I386
!ELSEIF "$(CFG)" == "listtasks - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib 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 /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib 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 /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "listtasks - Win32 Release"
# Name "listtasks - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\listtasks.cpp
# End Source File
# Begin Source File
SOURCE=.\StdAfx.cpp
# ADD CPP /Yc"stdafx.h"
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\listtasks.h
# End Source File
# Begin Source File
SOURCE=.\StdAfx.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# Begin Source File
SOURCE=.\ReadMe.txt
# End Source File
# End Target
# End Project

View File

@@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "listtasks"=.\listtasks.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@@ -0,0 +1,12 @@
#include <windows.h>
#ifndef __LISTTASKS_H
#define __LISTTASKS_H
typedef BOOL (CALLBACK *PROCENUMPROC)( DWORD, WORD, LPSTR,
LPARAM ) ;
BOOL WINAPI EnumProcs( PROCENUMPROC lpProc, LPARAM lParam ) ;
#endif

View File

@@ -0,0 +1,157 @@
/**********************************************************************
* Copyright (c) 2002-2004 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
*
* raise.c
*
* This is a part of JNI implementation of spawner
***********************************************************************/
#include "stdafx.h"
#include "Spawner.h"
#include "jni.h"
extern void JNICALL ThrowByName(JNIEnv *env, const char *name, const char *msg);
static HWND consoleHWND;
/////////////////////////////////////////////////////////////////////////////////////
// Check if window is a console of process with pid
// Arguments:
// hwnd - window handler
// arg - process PID
// Return : TRUE if yes
/////////////////////////////////////////////////////////////////////////////////////
static BOOL CALLBACK
find_child_console (HWND hwnd, LPARAM arg)
{
DWORD thread_id;
DWORD process_id;
DWORD pid = arg;
thread_id = GetWindowThreadProcessId (hwnd, &process_id);
if (process_id == pid)
{
char window_class[32];
GetClassName (hwnd, window_class, sizeof (window_class));
if (strcmp (window_class, "ConsoleWindowClass") == 0)
{
consoleHWND = hwnd;
return FALSE;
}
}
/* keep looking */
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////////////
// Function implements interrupt process (Ctrl-C emulation)
// Arguments:
// pid - process' pid
// Return : 0 if OK or error code
/////////////////////////////////////////////////////////////////////////////////////
int interruptProcess(int pid)
{
#ifdef DEBUG_MONITOR
_TCHAR buffer[1000];
#endif
int rc;
// Try another method
rc = 0;
consoleHWND = NULL;
#ifdef DEBUG_MONITOR
_stprintf(buffer, _T("Try to interrupt process %i\n"), pid);
OutputDebugStringW(buffer);
#endif
// Find console
EnumWindows (find_child_console, (LPARAM) pid);
if(NULL != consoleHWND) // Yes, we found out it
{
// We are going to switch focus to console,
// send Ctrl-C and then restore focus
BYTE control_scan_code = (BYTE) MapVirtualKey (VK_CONTROL, 0);
/* Fake Ctrl-C for SIGINT, and Ctrl-Break for SIGQUIT. */
BYTE vk_c_code = 'C';
BYTE vk_break_code = VK_CANCEL;
BYTE c_scan_code = (BYTE) MapVirtualKey (vk_c_code, 0);
BYTE break_scan_code = (BYTE) MapVirtualKey (vk_break_code, 0);
HWND foreground_window;
foreground_window = GetForegroundWindow ();
if (foreground_window)
{
/* NT 5.0, and apparently also Windows 98, will not allow
a Window to be set to foreground directly without the
user's involvement. The workaround is to attach
ourselves to the thread that owns the foreground
window, since that is the only thread that can set the
foreground window. */
DWORD foreground_thread, child_thread;
foreground_thread =
GetWindowThreadProcessId (foreground_window, NULL);
if (foreground_thread == GetCurrentThreadId ()
|| !AttachThreadInput (GetCurrentThreadId (),
foreground_thread, TRUE))
foreground_thread = 0;
child_thread = GetWindowThreadProcessId (consoleHWND, NULL);
if (child_thread == GetCurrentThreadId ()
|| !AttachThreadInput (GetCurrentThreadId (),
child_thread, TRUE))
child_thread = 0;
/* Set the foreground window to the child. */
if (SetForegroundWindow (consoleHWND))
{
if(0 != break_scan_code) {
/* Generate keystrokes as if user had typed Ctrl-Break */
keybd_event (VK_CONTROL, control_scan_code, 0, 0);
keybd_event (vk_break_code, break_scan_code, KEYEVENTF_EXTENDEDKEY, 0);
keybd_event (vk_break_code, break_scan_code,
KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
keybd_event (VK_CONTROL, control_scan_code, KEYEVENTF_KEYUP, 0);
}
/* Sleep for a bit to give time for respond */
Sleep (100);
SetForegroundWindow (foreground_window);
}
/* Detach from the foreground and child threads now that
the foreground switching is over. */
if (foreground_thread)
AttachThreadInput (GetCurrentThreadId (),
foreground_thread, FALSE);
if (child_thread)
AttachThreadInput (GetCurrentThreadId (),
child_thread, FALSE);
#ifdef DEBUG_MONITOR
_stprintf(buffer, _T("Sent Ctrl-C & Ctrl-Break to process %i\n"), pid);
OutputDebugStringW(buffer);
#endif
}
}
#ifdef DEBUG_MONITOR
else {
_stprintf(buffer, _T("Cannot find console for process %i\n"), pid);
OutputDebugStringW(buffer);
}
#endif
return rc;
}

View File

@@ -0,0 +1,54 @@
/**********************************************************************
* Copyright (c) 2002-2004 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
*
* spawner.c
*
* This is a part of JNI implementation of spawner
***********************************************************************/
#include "stdafx.h"
#include "spawner.h"
CRITICAL_SECTION cs;
_TCHAR path[MAX_PATH + 1] = {_T('\0') }; // Directory where spawner.dll is located
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
_TCHAR * p;
InitializeCriticalSection(&cs);
GetModuleFileNameW(hModule, path, MAX_PATH);
p = _tcsrchr(path, _T('\\'));
if(NULL != p)
*(p + 1) = _T('\0');
else
_tcscat(path, _T("\\"));
}
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
DeleteCriticalSection(&cs);
break;
}
return TRUE;
}

View File

@@ -0,0 +1,18 @@
# Microsoft Developer Studio Generated Dependency File, included by spawner.mak
.\iostream.c : \
"$(JAVA_HOME)\include\jni.h"\
"$(JAVA_HOME)\include\win32\jni_md.h"\
".\SpawnerInputStream.h"\
".\SpawnerOutputStream.h"\
.\StdAfx.c : \
".\StdAfx.h"\
.\Win32ProcessEx.c : \
"$(JAVA_HOME)\include\jni.h"\
"$(JAVA_HOME)\include\win32\jni_md.h"\
".\Spawner.h"\

View File

@@ -0,0 +1,181 @@
# Microsoft Developer Studio Project File - Name="spawner" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=spawner - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "spawner.mak".
!MESSAGE
!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
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "spawner - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPAWNER_EXPORTS" /Yu"stdafx.h" /FD /c
# ADD CPP /nologo /Gz /MT /W3 /GX /O2 /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\Win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "_USRDLL" /D "SPAWNER_EXPORTS" /Yu"stdafx.h" /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 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 /machine:I386
# ADD LINK32 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 /machine:I386
!ELSEIF "$(CFG)" == "spawner - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPAWNER_EXPORTS" /Yu"stdafx.h" /FD /GZ /c
# ADD CPP /nologo /Gz /MD /W3 /Gm /GX /ZI /Od /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\Win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "_USRDLL" /D "SPAWNER_EXPORTS" /FR /Yu"stdafx.h" /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 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 /debug /machine:I386 /pdbtype:sept
# ADD LINK32 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 /map /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "spawner - Win32 Release"
# Name "spawner - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\iostream.c
!IF "$(CFG)" == "spawner - Win32 Release"
# ADD CPP /I "E:\Java\jdk1.3.1\include" /I "E:\Java\jdk1.3.1\include\Win32" /FAcs
!ELSEIF "$(CFG)" == "spawner - Win32 Debug"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\raise.c
# End Source File
# Begin Source File
SOURCE=.\spawner.c
!IF "$(CFG)" == "spawner - Win32 Release"
# ADD CPP /I "E:\Java\jdk1.3.1\include" /I "E:\Java\jdk1.3.1\include\Win32"
!ELSEIF "$(CFG)" == "spawner - Win32 Debug"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\StdAfx.c
!IF "$(CFG)" == "spawner - Win32 Release"
# ADD CPP /I "E:\Java\jdk1.3.1\include" /I "E:\Java\jdk1.3.1\include\Win32" /Yc"stdafx.h"
!ELSEIF "$(CFG)" == "spawner - Win32 Debug"
# ADD CPP /Yc"stdafx.h"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\Win32ProcessEx.c
!IF "$(CFG)" == "spawner - Win32 Release"
# ADD CPP /I "E:\Java\jdk1.3.1\include" /I "E:\Java\jdk1.3.1\include\Win32" /FAcs
!ELSEIF "$(CFG)" == "spawner - Win32 Debug"
!ENDIF
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\Spawner.h
# End Source File
# Begin Source File
SOURCE=.\SpawnerInputStream.h
# End Source File
# Begin Source File
SOURCE=.\SpawnerOutputStream.h
# End Source File
# Begin Source File
SOURCE=.\StdAfx.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# Begin Source File
SOURCE=.\ReadMe.txt
# End Source File
# End Target
# End Project

View File

@@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "spawner"=.\spawner.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@@ -0,0 +1,264 @@
# 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
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"
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.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
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,333 @@
/**********************************************************************
* Copyright (c) 2002-2004 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
*
* starter.cpp
*
* This is a small utility for windows spawner
***********************************************************************/
#define STRICT
#include <Windows.h>
#include <process.h>
#include <tchar.h>
#include <stdio.h>
//#define DEBUG_MONITOR
#define MAX_CMD_LINE_LENGTH (2049)
#define PIPE_NAME_LENGTH 100
int copyTo(_TCHAR * target, const _TCHAR * source, int cpyLength, int availSpace);
void DisplayErrorMessage();
///////////////////////////////////////////////////////////////////////////////
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 < 7) {
_tprintf(_T("Usage: %s (Three InheritableEventHandles) (CommandLineToSpawn)\n"),
argv[0]);
return(0);
}
// Construct the full command line
_TCHAR szCmdLine[MAX_CMD_LINE_LENGTH] = { 0 };
int nPos = 0;
for(int i = 6; i < argc; ++i)
{
int nCpyLen;
if(0 > (nCpyLen = copyTo(szCmdLine + nPos, argv[i], _tcslen(argv[i]), MAX_CMD_LINE_LENGTH - nPos)))
{
#ifdef DEBUG_MONITOR
OutputDebugStringW(_T("Not enough space to build command line\n"));
#endif
return 0;
}
nPos += nCpyLen;
szCmdLine[nPos] = _T(' ');
++nPos;
}
szCmdLine[nPos] = _T('\0');
STARTUPINFOW si = { sizeof(si) };
PROCESS_INFORMATION pi = { 0 };
DWORD dwExitCode = 0;
#ifdef DEBUG_MONITOR
int currentPID = GetCurrentProcessId();
_TCHAR buffer[MAX_CMD_LINE_LENGTH];
#endif
BOOL exitProc = FALSE;
HANDLE waitEvent = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[4]);
HANDLE h[3];
h[0] = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[3]);
h[2] = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[5]); // This is a terminate event
SetConsoleCtrlHandler(HandlerRoutine, TRUE);
int parentPid = _tcstol(argv[1], NULL, 10);
int nCounter = _tcstol(argv[2], NULL, 10);
_TCHAR inPipeName[PIPE_NAME_LENGTH];
_TCHAR outPipeName[PIPE_NAME_LENGTH];
_TCHAR errPipeName[PIPE_NAME_LENGTH];
_stprintf(inPipeName, _T("\\\\.\\pipe\\stdin%08i%010i"), parentPid, nCounter);
_stprintf(outPipeName, _T("\\\\.\\pipe\\stdout%08i%010i"), parentPid, nCounter);
_stprintf(errPipeName, _T("\\\\.\\pipe\\stderr%08i%010i"), parentPid, nCounter);
#ifdef DEBUG_MONITOR
_stprintf(buffer, _T("Pipes: %s, %s, %s\n"), inPipeName, outPipeName, errPipeName);
OutputDebugStringW(buffer);
#endif
HANDLE stdHandles[3];
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
if((INVALID_HANDLE_VALUE == (stdHandles[0] = CreateFileW(inPipeName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, &sa))) ||
(INVALID_HANDLE_VALUE == (stdHandles[1] = CreateFileW(outPipeName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, &sa))) ||
(INVALID_HANDLE_VALUE == (stdHandles[2] = CreateFileW(errPipeName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, &sa))))
{
#ifdef DEBUG_MONITOR
_stprintf(buffer, _T("Failed to open pipe %i, %i, %i: %i\n"), stdHandles[0], stdHandles[1], stdHandles[2], GetLastError());
OutputDebugStringW(buffer);
#endif
CloseHandle(stdHandles[0]);
CloseHandle(stdHandles[1]);
CloseHandle(stdHandles[2]);
return -1;;
}
SetHandleInformation(stdHandles[0], HANDLE_FLAG_INHERIT, TRUE);
SetHandleInformation(stdHandles[1], HANDLE_FLAG_INHERIT, TRUE);
SetHandleInformation(stdHandles[2], HANDLE_FLAG_INHERIT, TRUE);
if(!SetStdHandle(STD_INPUT_HANDLE, stdHandles[0]) ||
!SetStdHandle(STD_OUTPUT_HANDLE, stdHandles[1]) ||
!SetStdHandle(STD_ERROR_HANDLE, stdHandles[2])) {
#ifdef DEBUG_MONITOR
_stprintf(buffer, _T("Failed to reassign standard streams: %i\n"), GetLastError());
OutputDebugStringW(buffer);
#endif
CloseHandle(stdHandles[0]);
CloseHandle(stdHandles[1]);
CloseHandle(stdHandles[2]);
return -1;;
}
#ifdef DEBUG_MONITOR
_stprintf(buffer, _T("Starting: %s\n"), szCmdLine);
OutputDebugStringW(buffer);
#endif
// Spawn the other processes as part of this Process Group
BOOL f = CreateProcessW(NULL, szCmdLine, NULL, NULL, TRUE,
0, NULL, NULL, &si, &pi);
// We don't need them any more
CloseHandle(stdHandles[0]);
CloseHandle(stdHandles[1]);
CloseHandle(stdHandles[2]);
if (f) {
#ifdef DEBUG_MONITOR
_stprintf(buffer, _T("Process %i started\n"), pi.dwProcessId);
OutputDebugStringW(buffer);
#endif
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
_stprintf(buffer, _T("starter (PID %i) received CTRL-C event\n"), currentPID);
OutputDebugStringW(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
_stprintf(buffer, _T("starter: launched process has been terminated(PID %i)\n"),
pi.dwProcessId);
OutputDebugStringW(buffer);
#endif
GetExitCodeProcess(pi.hProcess, &dwExitCode);
exitProc = TRUE;
break;
case WAIT_OBJECT_0 + 2: // Kill
#ifdef DEBUG_MONITOR
_stprintf(buffer, _T("starter received KILL event (PID %i)\n"), currentPID);
OutputDebugStringW(buffer);
#endif
GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
TerminateProcess(h[1], 0);
exitProc = TRUE;
break;
default:
// Unexpected code
#ifdef DEBUG_MONITOR
DisplayErrorMessage();
#endif
exitProc = TRUE;
break;
}
}
CloseHandle(pi.hProcess);
} else {
#ifdef DEBUG_MONITOR
_stprintf(buffer, _T("Cannot start: %s\n"), szCmdLine);
OutputDebugStringW(buffer);
DisplayErrorMessage();
#endif
}
CloseHandle(waitEvent);
CloseHandle(h[0]);
CloseHandle(h[1]);
CloseHandle(h[2]);
return(dwExitCode);
}
/////////////////////////////////////////////////////////////////////////////////////
// Use this utility program to process correctly quotation marks in the command line
// Arguments:
// target - string to copy to
// source - string to copy from
// cpyLength - copy length
// availSpace - size of the target buffer
// Return :number of bytes used in target, or -1 in case of error
/////////////////////////////////////////////////////////////////////////////////////
int copyTo(_TCHAR * target, const _TCHAR * source, int cpyLength, int availSpace)
{
BOOL bSlash = FALSE;
int i = 0, j = 0;
int totCpyLength = cpyLength;
#define QUOTATION_DO 0
#define QUOTATION_DONE 1
#define QUOTATION_NONE 2
int nQuotationMode = 0;
if(availSpace <= cpyLength) // = to reserve space for '\0'
return -1;
if((_T('\"') == *source) && (_T('\"') == *(source + cpyLength - 1)))
{
// Already done
nQuotationMode = QUOTATION_DONE;
}
else
if(_tcschr(source, _T(' ')) == NULL)
{
// No reason to quotate term becase it doesn't have embedded spaces
nQuotationMode = QUOTATION_NONE;
}
else
{
// Needs to be quotated
nQuotationMode = QUOTATION_DO;
*target = _T('\"');
++j;
}
for(; i < cpyLength; ++i, ++j)
{
if(source[i] == _T('\\'))
bSlash = TRUE;
else
// Don't escape embracing quotation marks
if((source[i] == _T('\"')) && !((nQuotationMode == QUOTATION_DONE) && ((i == 0) || (i == (cpyLength - 1))) ) )
{
if(!bSlash)
{
if(j == availSpace)
return -1;
target[j] = _T('\\');
++j;
}
bSlash = FALSE;
}
else
bSlash = FALSE;
if(j == availSpace)
return -1;
target[j] = source[i];
}
if(nQuotationMode == QUOTATION_DO)
{
if(j == availSpace)
return -1;
target[j] = _T('\"');
++j;
}
return j;
}
void DisplayErrorMessage() {
char * lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(char *) &lpMsgBuf,
0,
NULL
);
OutputDebugString(lpMsgBuf);
// Free the buffer.
LocalFree( lpMsgBuf );
}
//////////////////////////////// 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,156 @@
# 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"
CLEAN :
-@erase "$(INTDIR)\starter.obj"
-@erase "$(INTDIR)\starter.sbr"
-@erase "$(INTDIR)\vc60.idb"
-@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
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
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 "$(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