blob: f107c1340df1f1b7d04bd0b54911f73098cd1fe6 [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
35/* TODO: handle unicode command lines? */
36/* TODO: handle unicode environment? */
37
38#include "Python.h"
39
40#define WINDOWS_LEAN_AND_MEAN
41#include "windows.h"
42
43/* -------------------------------------------------------------------- */
44/* handle wrapper. note that this library uses integers when passing
45 handles to a function, and handle wrappers when returning handles.
46 the wrapper is used to provide Detach and Close methods */
47
48typedef struct {
Tim Petersf3250b02004-10-12 21:38:22 +000049 PyObject_HEAD
50 HANDLE handle;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000051} sp_handle_object;
52
53staticforward PyTypeObject sp_handle_type;
54
55static PyObject*
56sp_handle_new(HANDLE handle)
57{
Tim Petersf3250b02004-10-12 21:38:22 +000058 sp_handle_object* self;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000059
Tim Petersf3250b02004-10-12 21:38:22 +000060 self = PyObject_NEW(sp_handle_object, &sp_handle_type);
61 if (self == NULL)
62 return NULL;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000063
Tim Petersf3250b02004-10-12 21:38:22 +000064 self->handle = handle;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000065
Tim Petersf3250b02004-10-12 21:38:22 +000066 return (PyObject*) self;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000067}
68
69static PyObject*
70sp_handle_detach(sp_handle_object* self, PyObject* args)
71{
Tim Petersf3250b02004-10-12 21:38:22 +000072 HANDLE handle;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000073
Tim Petersf3250b02004-10-12 21:38:22 +000074 if (! PyArg_ParseTuple(args, ":Detach"))
75 return NULL;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000076
Tim Petersf3250b02004-10-12 21:38:22 +000077 handle = self->handle;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000078
Tim Petersf3250b02004-10-12 21:38:22 +000079 self->handle = NULL;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000080
Tim Petersf3250b02004-10-12 21:38:22 +000081 /* note: return the current handle, as an integer */
82 return PyInt_FromLong((long) handle);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000083}
84
85static PyObject*
86sp_handle_close(sp_handle_object* self, PyObject* args)
87{
Tim Petersf3250b02004-10-12 21:38:22 +000088 if (! PyArg_ParseTuple(args, ":Close"))
89 return NULL;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000090
Tim Petersf3250b02004-10-12 21:38:22 +000091 if (self->handle != INVALID_HANDLE_VALUE) {
92 CloseHandle(self->handle);
93 self->handle = INVALID_HANDLE_VALUE;
94 }
95 Py_INCREF(Py_None);
96 return Py_None;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000097}
98
99static void
100sp_handle_dealloc(sp_handle_object* self)
101{
Tim Petersf3250b02004-10-12 21:38:22 +0000102 if (self->handle != INVALID_HANDLE_VALUE)
103 CloseHandle(self->handle);
104 PyMem_DEL(self);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000105}
106
107static PyMethodDef sp_handle_methods[] = {
Tim Petersf3250b02004-10-12 21:38:22 +0000108 {"Detach", (PyCFunction) sp_handle_detach, 1},
109 {"Close", (PyCFunction) sp_handle_close, 1},
110 {NULL, NULL}
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000111};
112
Tim Petersf3250b02004-10-12 21:38:22 +0000113static PyObject*
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000114sp_handle_getattr(sp_handle_object* self, char* name)
115{
Tim Petersf3250b02004-10-12 21:38:22 +0000116 return Py_FindMethod(sp_handle_methods, (PyObject*) self, name);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000117}
118
119static PyObject*
120sp_handle_as_int(sp_handle_object* self)
121{
Tim Petersf3250b02004-10-12 21:38:22 +0000122 return PyInt_FromLong((long) self->handle);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000123}
124
125static PyNumberMethods sp_handle_as_number;
126
127statichere PyTypeObject sp_handle_type = {
Tim Petersf3250b02004-10-12 21:38:22 +0000128 PyObject_HEAD_INIT(NULL)
129 0, /*ob_size*/
130 "_subprocess_handle", sizeof(sp_handle_object), 0,
131 (destructor) sp_handle_dealloc, /*tp_dealloc*/
132 0, /*tp_print*/
133 (getattrfunc) sp_handle_getattr,/*tp_getattr*/
134 0, /*tp_setattr*/
135 0, /*tp_compare*/
136 0, /*tp_repr*/
137 &sp_handle_as_number, /*tp_as_number */
138 0, /*tp_as_sequence */
139 0, /*tp_as_mapping */
140 0 /*tp_hash*/
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000141};
142
143/* -------------------------------------------------------------------- */
144/* windows API functions */
145
146static PyObject *
147sp_GetStdHandle(PyObject* self, PyObject* args)
148{
Tim Petersf3250b02004-10-12 21:38:22 +0000149 HANDLE handle;
150 int std_handle;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000151
Tim Petersf3250b02004-10-12 21:38:22 +0000152 if (! PyArg_ParseTuple(args, "i:GetStdHandle", &std_handle))
153 return NULL;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000154
Tim Petersf3250b02004-10-12 21:38:22 +0000155 Py_BEGIN_ALLOW_THREADS
156 handle = GetStdHandle((DWORD) std_handle);
157 Py_END_ALLOW_THREADS
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000158
Tim Petersf3250b02004-10-12 21:38:22 +0000159 if (handle == INVALID_HANDLE_VALUE)
160 return PyErr_SetFromWindowsErr(GetLastError());
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000161
Tim Petersf3250b02004-10-12 21:38:22 +0000162 if (! handle) {
163 Py_INCREF(Py_None);
164 return Py_None;
165 }
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000166
Tim Petersf3250b02004-10-12 21:38:22 +0000167 /* note: returns integer, not handle object */
168 return PyInt_FromLong((long) handle);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000169}
170
171static PyObject *
172sp_GetCurrentProcess(PyObject* self, PyObject* args)
173{
Tim Petersf3250b02004-10-12 21:38:22 +0000174 if (! PyArg_ParseTuple(args, ":GetCurrentProcess"))
175 return NULL;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000176
Tim Petersf3250b02004-10-12 21:38:22 +0000177 return sp_handle_new(GetCurrentProcess());
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000178}
179
180static PyObject *
181sp_DuplicateHandle(PyObject* self, PyObject* args)
182{
Tim Petersf3250b02004-10-12 21:38:22 +0000183 HANDLE target_handle;
184 BOOL result;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000185
Tim Petersf3250b02004-10-12 21:38:22 +0000186 long source_process_handle;
187 long source_handle;
188 long target_process_handle;
189 int desired_access;
190 int inherit_handle;
191 int options = 0;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000192
Tim Petersf3250b02004-10-12 21:38:22 +0000193 if (! PyArg_ParseTuple(args, "lllii|i:DuplicateHandle",
194 &source_process_handle,
195 &source_handle,
196 &target_process_handle,
197 &desired_access,
198 &inherit_handle,
199 &options))
200 return NULL;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000201
Tim Petersf3250b02004-10-12 21:38:22 +0000202 Py_BEGIN_ALLOW_THREADS
203 result = DuplicateHandle(
204 (HANDLE) source_process_handle,
205 (HANDLE) source_handle,
206 (HANDLE) target_process_handle,
207 &target_handle,
208 desired_access,
209 inherit_handle,
210 options
211 );
212 Py_END_ALLOW_THREADS
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000213
Tim Petersf3250b02004-10-12 21:38:22 +0000214 if (! result)
215 return PyErr_SetFromWindowsErr(GetLastError());
216
217 return sp_handle_new(target_handle);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000218}
219
220static PyObject *
221sp_CreatePipe(PyObject* self, PyObject* args)
222{
Tim Petersf3250b02004-10-12 21:38:22 +0000223 HANDLE read_pipe;
224 HANDLE write_pipe;
225 BOOL result;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000226
Tim Petersf3250b02004-10-12 21:38:22 +0000227 PyObject* pipe_attributes; /* ignored */
228 int size;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000229
Tim Petersf3250b02004-10-12 21:38:22 +0000230 if (! PyArg_ParseTuple(args, "Oi:CreatePipe", &pipe_attributes, &size))
231 return NULL;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000232
Tim Petersf3250b02004-10-12 21:38:22 +0000233 Py_BEGIN_ALLOW_THREADS
234 result = CreatePipe(&read_pipe, &write_pipe, NULL, size);
235 Py_END_ALLOW_THREADS
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000236
Tim Petersf3250b02004-10-12 21:38:22 +0000237 if (! result)
238 return PyErr_SetFromWindowsErr(GetLastError());
239
240 return Py_BuildValue(
241 "NN", sp_handle_new(read_pipe), sp_handle_new(write_pipe));
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000242}
243
244/* helpers for createprocess */
245
246static int
247getint(PyObject* obj, char* name)
248{
Tim Petersf3250b02004-10-12 21:38:22 +0000249 PyObject* value;
250
251 value = PyObject_GetAttrString(obj, name);
252 if (! value) {
253 PyErr_Clear(); /* FIXME: propagate error? */
254 return 0;
255 }
256 return (int) PyInt_AsLong(value);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000257}
Tim Petersf3250b02004-10-12 21:38:22 +0000258
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000259static HANDLE
260gethandle(PyObject* obj, char* name)
261{
Tim Petersf3250b02004-10-12 21:38:22 +0000262 sp_handle_object* value;
263
264 value = (sp_handle_object*) PyObject_GetAttrString(obj, name);
265 if (! value) {
266 PyErr_Clear(); /* FIXME: propagate error? */
267 return NULL;
268 }
269 if (value->ob_type != &sp_handle_type)
270 return NULL;
271 return value->handle;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000272}
273
274static PyObject*
275getenvironment(PyObject* environment)
276{
Tim Petersf3250b02004-10-12 21:38:22 +0000277 int i, envsize;
278 PyObject* out = NULL;
279 PyObject* keys;
280 PyObject* values;
281 char* p;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000282
Tim Petersf3250b02004-10-12 21:38:22 +0000283 /* convert environment dictionary to windows enviroment string */
284 if (! PyMapping_Check(environment)) {
285 PyErr_SetString(
286 PyExc_TypeError, "environment must be dictionary or None");
287 return NULL;
288 }
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000289
Tim Petersf3250b02004-10-12 21:38:22 +0000290 envsize = PyMapping_Length(environment);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000291
Tim Petersf3250b02004-10-12 21:38:22 +0000292 keys = PyMapping_Keys(environment);
293 values = PyMapping_Values(environment);
294 if (!keys || !values)
295 goto error;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000296
Tim Petersf3250b02004-10-12 21:38:22 +0000297 out = PyString_FromStringAndSize(NULL, 2048);
298 if (! out)
299 goto error;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000300
Tim Petersf3250b02004-10-12 21:38:22 +0000301 p = PyString_AS_STRING(out);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000302
Tim Petersf3250b02004-10-12 21:38:22 +0000303 for (i = 0; i < envsize; i++) {
304 int ksize, vsize, totalsize;
305 PyObject* key = PyList_GET_ITEM(keys, i);
306 PyObject* value = PyList_GET_ITEM(values, i);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000307
Tim Petersf3250b02004-10-12 21:38:22 +0000308 if (! PyString_Check(key) || ! PyString_Check(value)) {
309 PyErr_SetString(PyExc_TypeError,
310 "environment can only contain strings");
311 goto error;
312 }
313 ksize = PyString_GET_SIZE(key);
314 vsize = PyString_GET_SIZE(value);
315 totalsize = (p - PyString_AS_STRING(out)) + ksize + 1 +
316 vsize + 1 + 1;
317 if (totalsize > PyString_GET_SIZE(out)) {
318 int offset = p - PyString_AS_STRING(out);
319 _PyString_Resize(&out, totalsize + 1024);
320 p = PyString_AS_STRING(out) + offset;
321 }
322 memcpy(p, PyString_AS_STRING(key), ksize);
323 p += ksize;
324 *p++ = '=';
325 memcpy(p, PyString_AS_STRING(value), vsize);
326 p += vsize;
327 *p++ = '\0';
328 }
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000329
Tim Petersf3250b02004-10-12 21:38:22 +0000330 /* add trailing null byte */
331 *p++ = '\0';
332 _PyString_Resize(&out, p - PyString_AS_STRING(out));
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000333
Tim Petersf3250b02004-10-12 21:38:22 +0000334 /* PyObject_Print(out, stdout, 0); */
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000335
Fredrik Lundhbb4692b2005-11-12 10:15:03 +0000336 Py_XDECREF(keys);
337 Py_XDECREF(values);
338
Tim Petersf3250b02004-10-12 21:38:22 +0000339 return out;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000340
Tim Petersf3250b02004-10-12 21:38:22 +0000341 error:
342 Py_XDECREF(out);
343 Py_XDECREF(keys);
344 Py_XDECREF(values);
345 return NULL;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000346}
347
348static PyObject *
349sp_CreateProcess(PyObject* self, PyObject* args)
350{
Tim Petersf3250b02004-10-12 21:38:22 +0000351 BOOL result;
352 PROCESS_INFORMATION pi;
353 STARTUPINFO si;
354 PyObject* environment;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000355
Tim Petersf3250b02004-10-12 21:38:22 +0000356 char* application_name;
357 char* command_line;
358 PyObject* process_attributes; /* ignored */
359 PyObject* thread_attributes; /* ignored */
360 int inherit_handles;
361 int creation_flags;
362 PyObject* env_mapping;
363 char* current_directory;
364 PyObject* startup_info;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000365
Tim Petersf3250b02004-10-12 21:38:22 +0000366 if (! PyArg_ParseTuple(args, "zzOOiiOzO:CreateProcess",
367 &application_name,
368 &command_line,
369 &process_attributes,
370 &thread_attributes,
371 &inherit_handles,
372 &creation_flags,
373 &env_mapping,
374 &current_directory,
375 &startup_info))
376 return NULL;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000377
Tim Petersf3250b02004-10-12 21:38:22 +0000378 ZeroMemory(&si, sizeof(si));
379 si.cb = sizeof(si);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000380
Tim Petersf3250b02004-10-12 21:38:22 +0000381 /* note: we only support a small subset of all SI attributes */
382 si.dwFlags = getint(startup_info, "dwFlags");
Peter Astrandc1d65362004-11-07 14:30:34 +0000383 si.wShowWindow = getint(startup_info, "wShowWindow");
Tim Petersf3250b02004-10-12 21:38:22 +0000384 si.hStdInput = gethandle(startup_info, "hStdInput");
385 si.hStdOutput = gethandle(startup_info, "hStdOutput");
386 si.hStdError = gethandle(startup_info, "hStdError");
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000387
Tim Petersf3250b02004-10-12 21:38:22 +0000388 if (env_mapping == Py_None)
389 environment = NULL;
390 else {
391 environment = getenvironment(env_mapping);
392 if (! environment)
393 return NULL;
394 }
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000395
Tim Petersf3250b02004-10-12 21:38:22 +0000396 Py_BEGIN_ALLOW_THREADS
397 result = CreateProcess(application_name,
398 command_line,
399 NULL,
400 NULL,
401 inherit_handles,
402 creation_flags,
403 environment ? PyString_AS_STRING(environment) : NULL,
404 current_directory,
405 &si,
406 &pi);
407 Py_END_ALLOW_THREADS
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000408
Tim Petersf3250b02004-10-12 21:38:22 +0000409 Py_XDECREF(environment);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000410
Tim Petersf3250b02004-10-12 21:38:22 +0000411 if (! result)
412 return PyErr_SetFromWindowsErr(GetLastError());
413
414 return Py_BuildValue("NNii",
415 sp_handle_new(pi.hProcess),
416 sp_handle_new(pi.hThread),
417 pi.dwProcessId,
418 pi.dwThreadId);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000419}
420
421static PyObject *
422sp_GetExitCodeProcess(PyObject* self, PyObject* args)
423{
Tim Petersf3250b02004-10-12 21:38:22 +0000424 DWORD exit_code;
425 BOOL result;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000426
Tim Petersf3250b02004-10-12 21:38:22 +0000427 long process;
428 if (! PyArg_ParseTuple(args, "l:GetExitCodeProcess", &process))
429 return NULL;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000430
Tim Petersf3250b02004-10-12 21:38:22 +0000431 result = GetExitCodeProcess((HANDLE) process, &exit_code);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000432
Tim Petersf3250b02004-10-12 21:38:22 +0000433 if (! result)
434 return PyErr_SetFromWindowsErr(GetLastError());
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000435
Tim Petersf3250b02004-10-12 21:38:22 +0000436 return PyInt_FromLong(exit_code);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000437}
438
439static PyObject *
440sp_WaitForSingleObject(PyObject* self, PyObject* args)
441{
Tim Petersf3250b02004-10-12 21:38:22 +0000442 DWORD result;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000443
Tim Petersf3250b02004-10-12 21:38:22 +0000444 long handle;
445 int milliseconds;
446 if (! PyArg_ParseTuple(args, "li:WaitForSingleObject",
447 &handle,
448 &milliseconds))
449 return NULL;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000450
Tim Petersf3250b02004-10-12 21:38:22 +0000451 Py_BEGIN_ALLOW_THREADS
452 result = WaitForSingleObject((HANDLE) handle, (DWORD) milliseconds);
453 Py_END_ALLOW_THREADS
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000454
Tim Petersf3250b02004-10-12 21:38:22 +0000455 if (result == WAIT_FAILED)
456 return PyErr_SetFromWindowsErr(GetLastError());
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000457
Tim Petersf3250b02004-10-12 21:38:22 +0000458 return PyInt_FromLong((int) result);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000459}
460
461static PyObject *
462sp_GetVersion(PyObject* self, PyObject* args)
463{
Tim Petersf3250b02004-10-12 21:38:22 +0000464 if (! PyArg_ParseTuple(args, ":GetVersion"))
465 return NULL;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000466
Tim Petersf3250b02004-10-12 21:38:22 +0000467 return PyInt_FromLong((int) GetVersion());
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000468}
469
470static PyObject *
471sp_GetModuleFileName(PyObject* self, PyObject* args)
472{
Tim Petersf3250b02004-10-12 21:38:22 +0000473 BOOL result;
474 long module;
475 TCHAR filename[MAX_PATH];
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000476
Tim Petersf3250b02004-10-12 21:38:22 +0000477 if (! PyArg_ParseTuple(args, "l:GetModuleFileName", &module))
478 return NULL;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000479
Tim Petersf3250b02004-10-12 21:38:22 +0000480 result = GetModuleFileName((HMODULE)module, filename, MAX_PATH);
481 filename[MAX_PATH-1] = '\0';
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000482
Tim Petersf3250b02004-10-12 21:38:22 +0000483 if (! result)
484 return PyErr_SetFromWindowsErr(GetLastError());
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000485
Tim Petersf3250b02004-10-12 21:38:22 +0000486 return PyString_FromString(filename);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000487}
488
489static PyMethodDef sp_functions[] = {
Tim Petersf3250b02004-10-12 21:38:22 +0000490 {"GetStdHandle", sp_GetStdHandle, METH_VARARGS},
491 {"GetCurrentProcess", sp_GetCurrentProcess, METH_VARARGS},
492 {"DuplicateHandle", sp_DuplicateHandle, METH_VARARGS},
493 {"CreatePipe", sp_CreatePipe, METH_VARARGS},
494 {"CreateProcess", sp_CreateProcess, METH_VARARGS},
495 {"GetExitCodeProcess", sp_GetExitCodeProcess, METH_VARARGS},
496 {"WaitForSingleObject", sp_WaitForSingleObject, METH_VARARGS},
497 {"GetVersion", sp_GetVersion, METH_VARARGS},
498 {"GetModuleFileName", sp_GetModuleFileName, METH_VARARGS},
499 {NULL, NULL}
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000500};
501
502/* -------------------------------------------------------------------- */
503
504static void
505defint(PyObject* d, const char* name, int value)
506{
Tim Petersf3250b02004-10-12 21:38:22 +0000507 PyObject* v = PyInt_FromLong((long) value);
508 if (v) {
509 PyDict_SetItemString(d, (char*) name, v);
510 Py_DECREF(v);
511 }
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000512}
513
514#if PY_VERSION_HEX >= 0x02030000
515PyMODINIT_FUNC
516#else
517DL_EXPORT(void)
518#endif
519init_subprocess()
520{
Tim Petersf3250b02004-10-12 21:38:22 +0000521 PyObject *d;
522 PyObject *m;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000523
Tim Petersf3250b02004-10-12 21:38:22 +0000524 /* patch up object descriptors */
525 sp_handle_type.ob_type = &PyType_Type;
526 sp_handle_as_number.nb_int = (unaryfunc) sp_handle_as_int;
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000527
Tim Petersf3250b02004-10-12 21:38:22 +0000528 m = Py_InitModule("_subprocess", sp_functions);
529 d = PyModule_GetDict(m);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000530
Tim Petersf3250b02004-10-12 21:38:22 +0000531 /* constants */
532 defint(d, "STD_INPUT_HANDLE", STD_INPUT_HANDLE);
533 defint(d, "STD_OUTPUT_HANDLE", STD_OUTPUT_HANDLE);
534 defint(d, "STD_ERROR_HANDLE", STD_ERROR_HANDLE);
535 defint(d, "DUPLICATE_SAME_ACCESS", DUPLICATE_SAME_ACCESS);
536 defint(d, "STARTF_USESTDHANDLES", STARTF_USESTDHANDLES);
Peter Astrandc1d65362004-11-07 14:30:34 +0000537 defint(d, "STARTF_USESHOWWINDOW", STARTF_USESHOWWINDOW);
538 defint(d, "SW_HIDE", SW_HIDE);
Tim Petersf3250b02004-10-12 21:38:22 +0000539 defint(d, "INFINITE", INFINITE);
540 defint(d, "WAIT_OBJECT_0", WAIT_OBJECT_0);
541 defint(d, "CREATE_NEW_CONSOLE", CREATE_NEW_CONSOLE);
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000542}