Initial commit
This commit is contained in:
@@ -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>
|
||||
Binary file not shown.
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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_)
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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_)
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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"\
|
||||
|
||||
@@ -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
|
||||
@@ -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>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 //////////////////////////////////
|
||||
@@ -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"\
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user