blob: 14e133326e0affaaec95b7222f3ad24eb092c8f9 [file] [log] [blame]
Fredrik Lundh5b3687d2004-10-12 15:26:28 +00001/*
2 * support routines for subprocess module
3 *
4 * Currently, this extension module is only required when using the
5 * subprocess module on Windows, but in the future, stubs for other
Tim Petersf3250b02004-10-12 21:38:22 +00006 * platforms might be added here as well.
Fredrik Lundh5b3687d2004-10-12 15:26:28 +00007 *
8 * Copyright (c) 2004 by Fredrik Lundh <fredrik@pythonware.com>
9 * Copyright (c) 2004 by Secret Labs AB, http://www.pythonware.com
10 * Copyright (c) 2004 by Peter Astrand <astrand@lysator.liu.se>
Tim Petersf3250b02004-10-12 21:38:22 +000011 *
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000012 * By obtaining, using, and/or copying this software and/or its
13 * associated documentation, you agree that you have read, understood,
14 * and will comply with the following terms and conditions:
Tim Petersf3250b02004-10-12 21:38:22 +000015 *
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000016 * Permission to use, copy, modify, and distribute this software and
17 * its associated documentation for any purpose and without fee is
18 * hereby granted, provided that the above copyright notice appears in
19 * all copies, and that both that copyright notice and this permission
20 * notice appear in supporting documentation, and that the name of the
21 * authors not be used in advertising or publicity pertaining to
22 * distribution of the software without specific, written prior
23 * permission.
Tim Petersf3250b02004-10-12 21:38:22 +000024 *
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000025 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
26 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
27 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
28 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
29 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
30 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
31 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Tim Petersf3250b02004-10-12 21:38:22 +000032 *
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000033 */
34
Fredrik Lundh63168a52005-12-14 22:29:34 +000035/* Licensed to PSF under a Contributor Agreement. */
36/* See http://www.python.org/2.4/license for licensing details. */
37
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000038/* TODO: handle unicode command lines? */
39/* TODO: handle unicode environment? */
40
41#include "Python.h"
42
43#define WINDOWS_LEAN_AND_MEAN
44#include "windows.h"
45
46/* -------------------------------------------------------------------- */
47/* handle wrapper. note that this library uses integers when passing
48 handles to a function, and handle wrappers when returning handles.
49 the wrapper is used to provide Detach and Close methods */
50
51typedef struct {
Tim Petersf3250b02004-10-12 21:38:22 +000052 PyObject_HEAD
53 HANDLE handle;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000054} sp_handle_object;
55
Neal Norwitz227b5332006-03-22 09:28:35 +000056static PyTypeObject sp_handle_type;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000057
58static PyObject*
59sp_handle_new(HANDLE handle)
60{
Tim Petersf3250b02004-10-12 21:38:22 +000061 sp_handle_object* self;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000062
Tim Petersf3250b02004-10-12 21:38:22 +000063 self = PyObject_NEW(sp_handle_object, &sp_handle_type);
64 if (self == NULL)
65 return NULL;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000066
Tim Petersf3250b02004-10-12 21:38:22 +000067 self->handle = handle;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000068
Tim Petersf3250b02004-10-12 21:38:22 +000069 return (PyObject*) self;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000070}
71
72static PyObject*
73sp_handle_detach(sp_handle_object* self, PyObject* args)
74{
Tim Petersf3250b02004-10-12 21:38:22 +000075 HANDLE handle;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000076
Tim Petersf3250b02004-10-12 21:38:22 +000077 if (! PyArg_ParseTuple(args, ":Detach"))
78 return NULL;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000079
Tim Petersf3250b02004-10-12 21:38:22 +000080 handle = self->handle;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000081
Tim Petersf3250b02004-10-12 21:38:22 +000082 self->handle = NULL;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000083
Tim Petersf3250b02004-10-12 21:38:22 +000084 /* note: return the current handle, as an integer */
85 return PyInt_FromLong((long) handle);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000086}
87
88static PyObject*
89sp_handle_close(sp_handle_object* self, PyObject* args)
90{
Tim Petersf3250b02004-10-12 21:38:22 +000091 if (! PyArg_ParseTuple(args, ":Close"))
92 return NULL;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000093
Tim Petersf3250b02004-10-12 21:38:22 +000094 if (self->handle != INVALID_HANDLE_VALUE) {
95 CloseHandle(self->handle);
96 self->handle = INVALID_HANDLE_VALUE;
97 }
98 Py_INCREF(Py_None);
99 return Py_None;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000100}
101
102static void
103sp_handle_dealloc(sp_handle_object* self)
104{
Tim Petersf3250b02004-10-12 21:38:22 +0000105 if (self->handle != INVALID_HANDLE_VALUE)
106 CloseHandle(self->handle);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000107 PyObject_FREE(self);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000108}
109
110static PyMethodDef sp_handle_methods[] = {
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000111 {"Detach", (PyCFunction) sp_handle_detach, METH_VARARGS},
112 {"Close", (PyCFunction) sp_handle_close, METH_VARARGS},
Tim Petersf3250b02004-10-12 21:38:22 +0000113 {NULL, NULL}
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000114};
115
Tim Petersf3250b02004-10-12 21:38:22 +0000116static PyObject*
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000117sp_handle_getattr(sp_handle_object* self, char* name)
118{
Tim Petersf3250b02004-10-12 21:38:22 +0000119 return Py_FindMethod(sp_handle_methods, (PyObject*) self, name);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000120}
121
122static PyObject*
123sp_handle_as_int(sp_handle_object* self)
124{
Tim Petersf3250b02004-10-12 21:38:22 +0000125 return PyInt_FromLong((long) self->handle);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000126}
127
128static PyNumberMethods sp_handle_as_number;
129
Neal Norwitz227b5332006-03-22 09:28:35 +0000130static PyTypeObject sp_handle_type = {
Martin v. Löwis95c95ce2007-07-22 14:41:55 +0000131 PyVarObject_HEAD_INIT(NULL, 0)
Tim Petersf3250b02004-10-12 21:38:22 +0000132 "_subprocess_handle", sizeof(sp_handle_object), 0,
133 (destructor) sp_handle_dealloc, /*tp_dealloc*/
134 0, /*tp_print*/
135 (getattrfunc) sp_handle_getattr,/*tp_getattr*/
136 0, /*tp_setattr*/
137 0, /*tp_compare*/
138 0, /*tp_repr*/
139 &sp_handle_as_number, /*tp_as_number */
140 0, /*tp_as_sequence */
141 0, /*tp_as_mapping */
142 0 /*tp_hash*/
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000143};
144
145/* -------------------------------------------------------------------- */
146/* windows API functions */
147
148static PyObject *
149sp_GetStdHandle(PyObject* self, PyObject* args)
150{
Tim Petersf3250b02004-10-12 21:38:22 +0000151 HANDLE handle;
152 int std_handle;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000153
Tim Petersf3250b02004-10-12 21:38:22 +0000154 if (! PyArg_ParseTuple(args, "i:GetStdHandle", &std_handle))
155 return NULL;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000156
Tim Petersf3250b02004-10-12 21:38:22 +0000157 Py_BEGIN_ALLOW_THREADS
158 handle = GetStdHandle((DWORD) std_handle);
159 Py_END_ALLOW_THREADS
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000160
Tim Petersf3250b02004-10-12 21:38:22 +0000161 if (handle == INVALID_HANDLE_VALUE)
162 return PyErr_SetFromWindowsErr(GetLastError());
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000163
Tim Petersf3250b02004-10-12 21:38:22 +0000164 if (! handle) {
165 Py_INCREF(Py_None);
166 return Py_None;
167 }
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000168
Tim Petersf3250b02004-10-12 21:38:22 +0000169 /* note: returns integer, not handle object */
170 return PyInt_FromLong((long) handle);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000171}
172
173static PyObject *
174sp_GetCurrentProcess(PyObject* self, PyObject* args)
175{
Tim Petersf3250b02004-10-12 21:38:22 +0000176 if (! PyArg_ParseTuple(args, ":GetCurrentProcess"))
177 return NULL;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000178
Tim Petersf3250b02004-10-12 21:38:22 +0000179 return sp_handle_new(GetCurrentProcess());
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000180}
181
182static PyObject *
183sp_DuplicateHandle(PyObject* self, PyObject* args)
184{
Tim Petersf3250b02004-10-12 21:38:22 +0000185 HANDLE target_handle;
186 BOOL result;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000187
Tim Petersf3250b02004-10-12 21:38:22 +0000188 long source_process_handle;
189 long source_handle;
190 long target_process_handle;
191 int desired_access;
192 int inherit_handle;
193 int options = 0;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000194
Tim Petersf3250b02004-10-12 21:38:22 +0000195 if (! PyArg_ParseTuple(args, "lllii|i:DuplicateHandle",
196 &source_process_handle,
197 &source_handle,
198 &target_process_handle,
199 &desired_access,
200 &inherit_handle,
201 &options))
202 return NULL;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000203
Tim Petersf3250b02004-10-12 21:38:22 +0000204 Py_BEGIN_ALLOW_THREADS
205 result = DuplicateHandle(
206 (HANDLE) source_process_handle,
207 (HANDLE) source_handle,
208 (HANDLE) target_process_handle,
209 &target_handle,
210 desired_access,
211 inherit_handle,
212 options
213 );
214 Py_END_ALLOW_THREADS
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000215
Tim Petersf3250b02004-10-12 21:38:22 +0000216 if (! result)
217 return PyErr_SetFromWindowsErr(GetLastError());
218
219 return sp_handle_new(target_handle);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000220}
221
222static PyObject *
223sp_CreatePipe(PyObject* self, PyObject* args)
224{
Tim Petersf3250b02004-10-12 21:38:22 +0000225 HANDLE read_pipe;
226 HANDLE write_pipe;
227 BOOL result;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000228
Tim Petersf3250b02004-10-12 21:38:22 +0000229 PyObject* pipe_attributes; /* ignored */
230 int size;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000231
Tim Petersf3250b02004-10-12 21:38:22 +0000232 if (! PyArg_ParseTuple(args, "Oi:CreatePipe", &pipe_attributes, &size))
233 return NULL;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000234
Tim Petersf3250b02004-10-12 21:38:22 +0000235 Py_BEGIN_ALLOW_THREADS
236 result = CreatePipe(&read_pipe, &write_pipe, NULL, size);
237 Py_END_ALLOW_THREADS
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000238
Tim Petersf3250b02004-10-12 21:38:22 +0000239 if (! result)
240 return PyErr_SetFromWindowsErr(GetLastError());
241
242 return Py_BuildValue(
243 "NN", sp_handle_new(read_pipe), sp_handle_new(write_pipe));
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000244}
245
246/* helpers for createprocess */
247
248static int
249getint(PyObject* obj, char* name)
250{
Tim Petersf3250b02004-10-12 21:38:22 +0000251 PyObject* value;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000252 int ret;
Tim Petersf3250b02004-10-12 21:38:22 +0000253
254 value = PyObject_GetAttrString(obj, name);
255 if (! value) {
256 PyErr_Clear(); /* FIXME: propagate error? */
257 return 0;
258 }
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000259 ret = (int) PyInt_AsLong(value);
260 Py_DECREF(value);
261 return ret;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000262}
Tim Petersf3250b02004-10-12 21:38:22 +0000263
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000264static HANDLE
265gethandle(PyObject* obj, char* name)
266{
Tim Petersf3250b02004-10-12 21:38:22 +0000267 sp_handle_object* value;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000268 HANDLE ret;
Tim Petersf3250b02004-10-12 21:38:22 +0000269
270 value = (sp_handle_object*) PyObject_GetAttrString(obj, name);
271 if (! value) {
272 PyErr_Clear(); /* FIXME: propagate error? */
273 return NULL;
274 }
Martin v. Löwis95c95ce2007-07-22 14:41:55 +0000275 if (Py_Type(&value) != &sp_handle_type)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000276 ret = NULL;
277 else
278 ret = value->handle;
279 Py_DECREF(value);
280 return ret;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000281}
282
283static PyObject*
284getenvironment(PyObject* environment)
285{
Tim Petersf3250b02004-10-12 21:38:22 +0000286 int i, envsize;
287 PyObject* out = NULL;
288 PyObject* keys;
289 PyObject* values;
290 char* p;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000291
Tim Petersf3250b02004-10-12 21:38:22 +0000292 /* convert environment dictionary to windows enviroment string */
293 if (! PyMapping_Check(environment)) {
294 PyErr_SetString(
295 PyExc_TypeError, "environment must be dictionary or None");
296 return NULL;
297 }
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000298
Tim Petersf3250b02004-10-12 21:38:22 +0000299 envsize = PyMapping_Length(environment);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000300
Tim Petersf3250b02004-10-12 21:38:22 +0000301 keys = PyMapping_Keys(environment);
302 values = PyMapping_Values(environment);
303 if (!keys || !values)
304 goto error;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000305
Tim Petersf3250b02004-10-12 21:38:22 +0000306 out = PyString_FromStringAndSize(NULL, 2048);
307 if (! out)
308 goto error;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000309
Tim Petersf3250b02004-10-12 21:38:22 +0000310 p = PyString_AS_STRING(out);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000311
Tim Petersf3250b02004-10-12 21:38:22 +0000312 for (i = 0; i < envsize; i++) {
313 int ksize, vsize, totalsize;
314 PyObject* key = PyList_GET_ITEM(keys, i);
315 PyObject* value = PyList_GET_ITEM(values, i);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000316
Tim Petersf3250b02004-10-12 21:38:22 +0000317 if (! PyString_Check(key) || ! PyString_Check(value)) {
318 PyErr_SetString(PyExc_TypeError,
319 "environment can only contain strings");
320 goto error;
321 }
322 ksize = PyString_GET_SIZE(key);
323 vsize = PyString_GET_SIZE(value);
324 totalsize = (p - PyString_AS_STRING(out)) + ksize + 1 +
325 vsize + 1 + 1;
326 if (totalsize > PyString_GET_SIZE(out)) {
327 int offset = p - PyString_AS_STRING(out);
328 _PyString_Resize(&out, totalsize + 1024);
329 p = PyString_AS_STRING(out) + offset;
330 }
331 memcpy(p, PyString_AS_STRING(key), ksize);
332 p += ksize;
333 *p++ = '=';
334 memcpy(p, PyString_AS_STRING(value), vsize);
335 p += vsize;
336 *p++ = '\0';
337 }
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000338
Tim Petersf3250b02004-10-12 21:38:22 +0000339 /* add trailing null byte */
340 *p++ = '\0';
341 _PyString_Resize(&out, p - PyString_AS_STRING(out));
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000342
Tim Petersf3250b02004-10-12 21:38:22 +0000343 /* PyObject_Print(out, stdout, 0); */
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000344
Fredrik Lundhbb4692b2005-11-12 10:15:03 +0000345 Py_XDECREF(keys);
346 Py_XDECREF(values);
347
Tim Petersf3250b02004-10-12 21:38:22 +0000348 return out;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000349
Tim Petersf3250b02004-10-12 21:38:22 +0000350 error:
351 Py_XDECREF(out);
352 Py_XDECREF(keys);
353 Py_XDECREF(values);
354 return NULL;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000355}
356
357static PyObject *
358sp_CreateProcess(PyObject* self, PyObject* args)
359{
Tim Petersf3250b02004-10-12 21:38:22 +0000360 BOOL result;
361 PROCESS_INFORMATION pi;
362 STARTUPINFO si;
363 PyObject* environment;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000364
Tim Petersf3250b02004-10-12 21:38:22 +0000365 char* application_name;
366 char* command_line;
367 PyObject* process_attributes; /* ignored */
368 PyObject* thread_attributes; /* ignored */
369 int inherit_handles;
370 int creation_flags;
371 PyObject* env_mapping;
372 char* current_directory;
373 PyObject* startup_info;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000374
Tim Petersf3250b02004-10-12 21:38:22 +0000375 if (! PyArg_ParseTuple(args, "zzOOiiOzO:CreateProcess",
376 &application_name,
377 &command_line,
378 &process_attributes,
379 &thread_attributes,
380 &inherit_handles,
381 &creation_flags,
382 &env_mapping,
383 &current_directory,
384 &startup_info))
385 return NULL;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000386
Tim Petersf3250b02004-10-12 21:38:22 +0000387 ZeroMemory(&si, sizeof(si));
388 si.cb = sizeof(si);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000389
Tim Petersf3250b02004-10-12 21:38:22 +0000390 /* note: we only support a small subset of all SI attributes */
391 si.dwFlags = getint(startup_info, "dwFlags");
Peter Astrandc1d65362004-11-07 14:30:34 +0000392 si.wShowWindow = getint(startup_info, "wShowWindow");
Tim Petersf3250b02004-10-12 21:38:22 +0000393 si.hStdInput = gethandle(startup_info, "hStdInput");
394 si.hStdOutput = gethandle(startup_info, "hStdOutput");
395 si.hStdError = gethandle(startup_info, "hStdError");
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000396
Fredrik Lundh3a49e922005-11-12 10:15:14 +0000397 if (PyErr_Occurred())
398 return NULL;
399
Tim Petersf3250b02004-10-12 21:38:22 +0000400 if (env_mapping == Py_None)
401 environment = NULL;
402 else {
403 environment = getenvironment(env_mapping);
404 if (! environment)
405 return NULL;
406 }
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000407
Tim Petersf3250b02004-10-12 21:38:22 +0000408 Py_BEGIN_ALLOW_THREADS
409 result = CreateProcess(application_name,
410 command_line,
411 NULL,
412 NULL,
413 inherit_handles,
414 creation_flags,
415 environment ? PyString_AS_STRING(environment) : NULL,
416 current_directory,
417 &si,
418 &pi);
419 Py_END_ALLOW_THREADS
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000420
Tim Petersf3250b02004-10-12 21:38:22 +0000421 Py_XDECREF(environment);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000422
Tim Petersf3250b02004-10-12 21:38:22 +0000423 if (! result)
424 return PyErr_SetFromWindowsErr(GetLastError());
425
426 return Py_BuildValue("NNii",
427 sp_handle_new(pi.hProcess),
428 sp_handle_new(pi.hThread),
429 pi.dwProcessId,
430 pi.dwThreadId);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000431}
432
433static PyObject *
Fredrik Lundhe5152932005-12-18 21:06:46 +0000434sp_TerminateProcess(PyObject* self, PyObject* args)
435{
436 BOOL result;
437
438 long process;
439 int exit_code;
440 if (! PyArg_ParseTuple(args, "li:TerminateProcess", &process,
441 &exit_code))
442 return NULL;
443
444 result = TerminateProcess((HANDLE) process, exit_code);
445
446 if (! result)
447 return PyErr_SetFromWindowsErr(GetLastError());
448
449 Py_INCREF(Py_None);
450 return Py_None;
451}
452
453static PyObject *
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000454sp_GetExitCodeProcess(PyObject* self, PyObject* args)
455{
Tim Petersf3250b02004-10-12 21:38:22 +0000456 DWORD exit_code;
457 BOOL result;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000458
Tim Petersf3250b02004-10-12 21:38:22 +0000459 long process;
460 if (! PyArg_ParseTuple(args, "l:GetExitCodeProcess", &process))
461 return NULL;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000462
Tim Petersf3250b02004-10-12 21:38:22 +0000463 result = GetExitCodeProcess((HANDLE) process, &exit_code);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000464
Tim Petersf3250b02004-10-12 21:38:22 +0000465 if (! result)
466 return PyErr_SetFromWindowsErr(GetLastError());
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000467
Tim Petersf3250b02004-10-12 21:38:22 +0000468 return PyInt_FromLong(exit_code);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000469}
470
471static PyObject *
472sp_WaitForSingleObject(PyObject* self, PyObject* args)
473{
Tim Petersf3250b02004-10-12 21:38:22 +0000474 DWORD result;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000475
Tim Petersf3250b02004-10-12 21:38:22 +0000476 long handle;
477 int milliseconds;
478 if (! PyArg_ParseTuple(args, "li:WaitForSingleObject",
479 &handle,
480 &milliseconds))
481 return NULL;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000482
Tim Petersf3250b02004-10-12 21:38:22 +0000483 Py_BEGIN_ALLOW_THREADS
484 result = WaitForSingleObject((HANDLE) handle, (DWORD) milliseconds);
485 Py_END_ALLOW_THREADS
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000486
Tim Petersf3250b02004-10-12 21:38:22 +0000487 if (result == WAIT_FAILED)
488 return PyErr_SetFromWindowsErr(GetLastError());
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000489
Tim Petersf3250b02004-10-12 21:38:22 +0000490 return PyInt_FromLong((int) result);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000491}
492
493static PyObject *
494sp_GetVersion(PyObject* self, PyObject* args)
495{
Tim Petersf3250b02004-10-12 21:38:22 +0000496 if (! PyArg_ParseTuple(args, ":GetVersion"))
497 return NULL;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000498
Tim Petersf3250b02004-10-12 21:38:22 +0000499 return PyInt_FromLong((int) GetVersion());
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000500}
501
502static PyObject *
503sp_GetModuleFileName(PyObject* self, PyObject* args)
504{
Tim Petersf3250b02004-10-12 21:38:22 +0000505 BOOL result;
506 long module;
507 TCHAR filename[MAX_PATH];
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000508
Tim Petersf3250b02004-10-12 21:38:22 +0000509 if (! PyArg_ParseTuple(args, "l:GetModuleFileName", &module))
510 return NULL;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000511
Tim Petersf3250b02004-10-12 21:38:22 +0000512 result = GetModuleFileName((HMODULE)module, filename, MAX_PATH);
513 filename[MAX_PATH-1] = '\0';
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000514
Tim Petersf3250b02004-10-12 21:38:22 +0000515 if (! result)
516 return PyErr_SetFromWindowsErr(GetLastError());
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000517
Tim Petersf3250b02004-10-12 21:38:22 +0000518 return PyString_FromString(filename);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000519}
520
521static PyMethodDef sp_functions[] = {
Tim Petersf3250b02004-10-12 21:38:22 +0000522 {"GetStdHandle", sp_GetStdHandle, METH_VARARGS},
523 {"GetCurrentProcess", sp_GetCurrentProcess, METH_VARARGS},
524 {"DuplicateHandle", sp_DuplicateHandle, METH_VARARGS},
525 {"CreatePipe", sp_CreatePipe, METH_VARARGS},
526 {"CreateProcess", sp_CreateProcess, METH_VARARGS},
Fredrik Lundhe5152932005-12-18 21:06:46 +0000527 {"TerminateProcess", sp_TerminateProcess, METH_VARARGS},
Tim Petersf3250b02004-10-12 21:38:22 +0000528 {"GetExitCodeProcess", sp_GetExitCodeProcess, METH_VARARGS},
529 {"WaitForSingleObject", sp_WaitForSingleObject, METH_VARARGS},
530 {"GetVersion", sp_GetVersion, METH_VARARGS},
531 {"GetModuleFileName", sp_GetModuleFileName, METH_VARARGS},
532 {NULL, NULL}
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000533};
534
535/* -------------------------------------------------------------------- */
536
537static void
538defint(PyObject* d, const char* name, int value)
539{
Tim Petersf3250b02004-10-12 21:38:22 +0000540 PyObject* v = PyInt_FromLong((long) value);
541 if (v) {
542 PyDict_SetItemString(d, (char*) name, v);
543 Py_DECREF(v);
544 }
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000545}
546
547#if PY_VERSION_HEX >= 0x02030000
548PyMODINIT_FUNC
549#else
550DL_EXPORT(void)
551#endif
552init_subprocess()
553{
Tim Petersf3250b02004-10-12 21:38:22 +0000554 PyObject *d;
555 PyObject *m;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000556
Tim Petersf3250b02004-10-12 21:38:22 +0000557 /* patch up object descriptors */
Martin v. Löwis95c95ce2007-07-22 14:41:55 +0000558 Py_Type(&sp_handle_type) = &PyType_Type;
Tim Petersf3250b02004-10-12 21:38:22 +0000559 sp_handle_as_number.nb_int = (unaryfunc) sp_handle_as_int;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000560
Tim Petersf3250b02004-10-12 21:38:22 +0000561 m = Py_InitModule("_subprocess", sp_functions);
Neal Norwitz1ac754f2006-01-19 06:09:39 +0000562 if (m == NULL)
563 return;
Tim Petersf3250b02004-10-12 21:38:22 +0000564 d = PyModule_GetDict(m);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000565
Tim Petersf3250b02004-10-12 21:38:22 +0000566 /* constants */
567 defint(d, "STD_INPUT_HANDLE", STD_INPUT_HANDLE);
568 defint(d, "STD_OUTPUT_HANDLE", STD_OUTPUT_HANDLE);
569 defint(d, "STD_ERROR_HANDLE", STD_ERROR_HANDLE);
570 defint(d, "DUPLICATE_SAME_ACCESS", DUPLICATE_SAME_ACCESS);
571 defint(d, "STARTF_USESTDHANDLES", STARTF_USESTDHANDLES);
Peter Astrandc1d65362004-11-07 14:30:34 +0000572 defint(d, "STARTF_USESHOWWINDOW", STARTF_USESHOWWINDOW);
573 defint(d, "SW_HIDE", SW_HIDE);
Tim Petersf3250b02004-10-12 21:38:22 +0000574 defint(d, "INFINITE", INFINITE);
575 defint(d, "WAIT_OBJECT_0", WAIT_OBJECT_0);
576 defint(d, "CREATE_NEW_CONSOLE", CREATE_NEW_CONSOLE);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000577}