1977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly/***************************************************************************
2977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly** The BSD 3-Clause License. http://www.opensource.org/licenses/BSD-3-Clause
3977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly**
4977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly** This file is part of 'mingw-builds' project.
5977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly** Copyright (c) 2011,2012,2013 by niXman (i dotty nixman doggy gmail dotty com)
6977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly** All rights reserved.
7977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly**
8977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly** Project: mingw-builds ( http://sourceforge.net/projects/mingwbuilds/ )
9977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly**
10977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly** Redistribution and use in source and binary forms, with or without
11977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly** modification, are permitted provided that the following conditions are met:
12977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly** - Redistributions of source code must retain the above copyright
13977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly**     notice, this list of conditions and the following disclaimer.
14977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly** - Redistributions in binary form must reproduce the above copyright
15977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly**     notice, this list of conditions and the following disclaimer in
16977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly**     the documentation and/or other materials provided with the distribution.
17977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly** - Neither the name of the 'mingw-builds' nor the names of its contributors may
18977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly**     be used to endorse or promote products derived from this software
19977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly**     without specific prior written permission.
20977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly**
21977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly** A PARTICULAR PURPOSE ARE DISCLAIMED.
25977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly** IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
26977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly** USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly**
33977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly***************************************************************************/
34977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
35977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly#include <windows.h>
36977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
37977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly#include <stdio.h>
38977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly#include <strings.h>
39977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
40977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly#ifdef _DEBUG
41977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly #define dbg_printf(...) printf(__VA_ARGS__)
42977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly#else
43977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly #define dbg_printf(...) do {} while(0)
44977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly#endif
45977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
46977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly// When built for the Android NDK, values are
47977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly// passed in on the GCC commandline, and when
48977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly// built for mingw-builds, these defaults are
49977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly// used.
50977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly#ifndef GDB_TO_PYTHON_REL_DIR
51977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly #define GDB_TO_PYTHON_REL_DIR "..\\opt\\bin"
52977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly#endif
53977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
54977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly#ifndef GDB_EXECUTABLE_ORIG_FILENAME
55977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly #define GDB_EXECUTABLE_ORIG_FILENAME "gdborig.exe"
56977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly#endif
57977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
58977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly#ifndef PYTHONHOME_REL_DIR
59977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly #define PYTHONHOME_REL_DIR "..\\opt"
60977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly#endif
61977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
62977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly#define DIE_IF_FALSE(var) \
63977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	do { \
64977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly		if ( !(var) ) { \
65977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly			fprintf(stderr, "%s(%d)[%d]: expression \"%s\" fail. terminate.\n" \
66977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly				,__FILE__ \
67977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly				,__LINE__ \
68977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly				,GetLastError() \
69977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly				,#var \
70977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly			); \
71977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly			exit(1); \
72977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly		} \
73977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	} while (0)
74977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
75977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnellyint main(int argc, char** argv) {
76977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	enum {
77977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly		 envbufsize = 1024*32
78977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly		,exebufsize = 1024
79977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly		,cmdbufsize = envbufsize
80977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	};
81977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
82977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	char *envbuf, *sep, *resbuf, *cmdbuf;
83977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	DWORD len, exitCode;
84977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	STARTUPINFO si;
85977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	PROCESS_INFORMATION pi;
86977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
87977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	DIE_IF_FALSE(
8885869dfbfb859b7f42948aaa1d46a86b9a9b743aAndrew Hsieh		(envbuf = (char *)malloc(envbufsize))
89977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	);
90977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	DIE_IF_FALSE(
9185869dfbfb859b7f42948aaa1d46a86b9a9b743aAndrew Hsieh		(cmdbuf = (char *)malloc(cmdbufsize))
92977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	);
93977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	*cmdbuf = 0;
94977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
95977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	DIE_IF_FALSE(
96977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly		GetEnvironmentVariable("PATH", envbuf, envbufsize)
97977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	);
98977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	dbg_printf("env: %s\n", envbuf);
99977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
100977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	DIE_IF_FALSE(
101977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly		GetModuleFileName(0, cmdbuf, exebufsize)
102977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	);
103977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	dbg_printf("curdir: %s\n", cmdbuf);
104977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
105977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	DIE_IF_FALSE(
106977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly		(sep = strrchr(cmdbuf, '\\'))
107977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	);
108977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	*(sep+1) = 0;
109977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	strcat(cmdbuf, GDB_TO_PYTHON_REL_DIR);
110977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	dbg_printf("sep: %s\n", cmdbuf);
111977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
112977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	len = strlen(envbuf)+strlen(cmdbuf)
113977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly		+1  /* for envronment separator */
114977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly		+1; /* for zero-terminator */
115977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
116977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	DIE_IF_FALSE(
11785869dfbfb859b7f42948aaa1d46a86b9a9b743aAndrew Hsieh		(resbuf = (char *)malloc(len))
118977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	);
119977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
120977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	DIE_IF_FALSE(
121977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly		(snprintf(resbuf, len, "%s;%s", cmdbuf, envbuf) > 0)
122977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	);
123977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	dbg_printf("PATH: %s\n", resbuf);
124977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
125977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	DIE_IF_FALSE(
126977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly		SetEnvironmentVariable("PATH", resbuf)
127977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	);
128977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
129977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	*(sep+1) = 0;
130977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	strcat(cmdbuf, PYTHONHOME_REL_DIR);
131977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	dbg_printf("PYTHONHOME: %s\n", cmdbuf);
132977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	DIE_IF_FALSE(
133977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly		SetEnvironmentVariable("PYTHONHOME", cmdbuf)
134977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	);
135977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
136977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	*(sep+1) = 0;
137977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	strcat(cmdbuf, GDB_EXECUTABLE_ORIG_FILENAME" ");
138977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
139977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	if ( argc > 1 ) {
140977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly		for ( ++argv; *argv; ++argv ) {
141977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly			len = strlen(cmdbuf);
142977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly			snprintf(cmdbuf+len, cmdbufsize-len, "%s ", *argv);
143977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly		}
144977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	}
145977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	dbg_printf("cmd: %s\n", cmdbuf);
146977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
147977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	HANDLE ghJob = CreateJobObject(NULL, "Gdb-Wrapper\0"/*NULL*/);
148977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	if ( ghJob == NULL ) {
149977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly        fprintf(stderr, "Could not create job object\n");
150977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	}
151977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	else{
152977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly		JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };
153977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly		// Configure all child processes associated with the job to terminate when the last handle to the job is closed
154977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly		jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
155977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly		if ( SetInformationJobObject(ghJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli)) == 0 ) {
156977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly            fprintf(stderr, "Could not SetInformationJobObject\n");
157977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly		}
158977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	}
159977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
160977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	memset(&si, 0, sizeof(si));
161977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	si.cb = sizeof(si);
162977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	si.dwFlags |= STARTF_USESTDHANDLES;
163977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
164977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
165977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
166977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
167977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	memset(&pi, 0, sizeof(pi));
168977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
169977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	DIE_IF_FALSE(
170977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly		CreateProcess(
171977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly			0			// exe name
172977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly			,cmdbuf		// command line
173977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly			,0			// process security attributes
174977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly			,0			// primary thread security attributes
175977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly			,TRUE		// handles are inherited
176977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly			,0			// creation flags
177977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly			,0			// use parent's environment
178977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly			,0			// use parent's current directory
179977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly			,&si		// STARTUPINFO pointer
180977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly			,&pi		// receives PROCESS_INFORMATION
181977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly		)
182977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	);
183977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
184977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	if ( ghJob != NULL )
185977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly		if ( AssignProcessToJobObject(ghJob, pi.hProcess) == 0 ) {
186977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly            fprintf(stderr, "Could not AssignProcessToObject\n");
187977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly		}
188977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
189977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	// Do not handle Ctrl-C in the wrapper
190977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	SetConsoleCtrlHandler(NULL, TRUE);
191977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
192977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	WaitForSingleObject(pi.hProcess, INFINITE);
193977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
194977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	DIE_IF_FALSE(
195977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly		GetExitCodeProcess(pi.hProcess, &exitCode)
196977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	);
197977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
198977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	if ( ghJob != NULL )
199977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly		CloseHandle(ghJob);
200977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	CloseHandle( pi.hProcess );
201977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	CloseHandle( pi.hThread );
202977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
203977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	free(envbuf);
204977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	free(resbuf);
205977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	free(cmdbuf);
206977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
207977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	dbg_printf("exiting with exitCode %d", exitCode);
208977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly
209977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly	return exitCode;
210977eaeb520cf5aa5abf33a320672b5b103c7b228Ray Donnelly}
211