2
* support routines for subprocess module
4
* Currently, this extension module is only required when using the
5
* subprocess module on Windows, but in the future, stubs for other
6
* platforms might be added here as well.
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>
12
* 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:
16
* 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
25
* 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.
35
/* Licensed to PSF under a Contributor Agreement. */
36
/* See http://www.python.org/2.4/license for licensing details. */
40
#define WINDOWS_LEAN_AND_MEAN
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 */
53
static PyTypeObject sp_handle_type;
56
sp_handle_new(HANDLE handle)
58
sp_handle_object* self;
60
self = PyObject_NEW(sp_handle_object, &sp_handle_type);
64
self->handle = handle;
66
return (PyObject*) self;
69
#if defined(MS_WIN32) && !defined(MS_WIN64)
70
#define HANDLE_TO_PYNUM(handle) PyLong_FromLong((long) handle)
71
#define PY_HANDLE_PARAM "l"
73
#define HANDLE_TO_PYNUM(handle) PyLong_FromLongLong((long long) handle)
74
#define PY_HANDLE_PARAM "L"
78
sp_handle_detach(sp_handle_object* self, PyObject* args)
82
if (! PyArg_ParseTuple(args, ":Detach"))
85
handle = self->handle;
87
self->handle = INVALID_HANDLE_VALUE;
89
/* note: return the current handle, as an integer */
90
return HANDLE_TO_PYNUM(handle);
94
sp_handle_close(sp_handle_object* self, PyObject* args)
96
if (! PyArg_ParseTuple(args, ":Close"))
99
if (self->handle != INVALID_HANDLE_VALUE) {
100
CloseHandle(self->handle);
101
self->handle = INVALID_HANDLE_VALUE;
108
sp_handle_dealloc(sp_handle_object* self)
110
if (self->handle != INVALID_HANDLE_VALUE)
111
CloseHandle(self->handle);
115
static PyMethodDef sp_handle_methods[] = {
116
{"Detach", (PyCFunction) sp_handle_detach, METH_VARARGS},
117
{"Close", (PyCFunction) sp_handle_close, METH_VARARGS},
122
sp_handle_as_int(sp_handle_object* self)
124
return HANDLE_TO_PYNUM(self->handle);
127
static PyNumberMethods sp_handle_as_number;
129
static PyTypeObject sp_handle_type = {
130
PyVarObject_HEAD_INIT(NULL, 0)
131
"_subprocess_handle", sizeof(sp_handle_object), 0,
132
(destructor) sp_handle_dealloc, /*tp_dealloc*/
138
&sp_handle_as_number, /*tp_as_number */
139
0, /*tp_as_sequence */
140
0, /*tp_as_mapping */
147
Py_TPFLAGS_DEFAULT, /*tp_flags*/
151
0, /*tp_richcompare*/
152
0, /*tp_weaklistoffset*/
155
sp_handle_methods, /*tp_methods*/
158
/* -------------------------------------------------------------------- */
159
/* windows API functions */
162
sp_GetStdHandle(PyObject* self, PyObject* args)
167
if (! PyArg_ParseTuple(args, "i:GetStdHandle", &std_handle))
170
Py_BEGIN_ALLOW_THREADS
171
handle = GetStdHandle((DWORD) std_handle);
174
if (handle == INVALID_HANDLE_VALUE)
175
return PyErr_SetFromWindowsErr(GetLastError());
182
/* note: returns integer, not handle object */
183
return HANDLE_TO_PYNUM(handle);
187
sp_GetCurrentProcess(PyObject* self, PyObject* args)
189
if (! PyArg_ParseTuple(args, ":GetCurrentProcess"))
192
return sp_handle_new(GetCurrentProcess());
196
sp_DuplicateHandle(PyObject* self, PyObject* args)
198
HANDLE target_handle;
201
HANDLE source_process_handle;
202
HANDLE source_handle;
203
HANDLE target_process_handle;
208
if (! PyArg_ParseTuple(args,
209
PY_HANDLE_PARAM PY_HANDLE_PARAM PY_HANDLE_PARAM
210
"ii|i:DuplicateHandle",
211
&source_process_handle,
213
&target_process_handle,
219
Py_BEGIN_ALLOW_THREADS
220
result = DuplicateHandle(
221
source_process_handle,
223
target_process_handle,
232
return PyErr_SetFromWindowsErr(GetLastError());
234
return sp_handle_new(target_handle);
238
sp_CreatePipe(PyObject* self, PyObject* args)
244
PyObject* pipe_attributes; /* ignored */
247
if (! PyArg_ParseTuple(args, "Oi:CreatePipe", &pipe_attributes, &size))
250
Py_BEGIN_ALLOW_THREADS
251
result = CreatePipe(&read_pipe, &write_pipe, NULL, size);
255
return PyErr_SetFromWindowsErr(GetLastError());
257
return Py_BuildValue(
258
"NN", sp_handle_new(read_pipe), sp_handle_new(write_pipe));
261
/* helpers for createprocess */
264
getint(PyObject* obj, char* name)
269
value = PyObject_GetAttrString(obj, name);
271
PyErr_Clear(); /* FIXME: propagate error? */
274
ret = (int) PyLong_AsLong(value);
280
gethandle(PyObject* obj, char* name)
282
sp_handle_object* value;
285
value = (sp_handle_object*) PyObject_GetAttrString(obj, name);
287
PyErr_Clear(); /* FIXME: propagate error? */
290
if (Py_TYPE(value) != &sp_handle_type)
299
getenvironment(PyObject* environment)
302
PyObject* out = NULL;
307
/* convert environment dictionary to windows enviroment string */
308
if (! PyMapping_Check(environment)) {
310
PyExc_TypeError, "environment must be dictionary or None");
314
envsize = PyMapping_Length(environment);
316
keys = PyMapping_Keys(environment);
317
values = PyMapping_Values(environment);
318
if (!keys || !values)
321
out = PyUnicode_FromUnicode(NULL, 2048);
325
p = PyUnicode_AS_UNICODE(out);
327
for (i = 0; i < envsize; i++) {
328
int ksize, vsize, totalsize;
329
PyObject* key = PyList_GET_ITEM(keys, i);
330
PyObject* value = PyList_GET_ITEM(values, i);
332
if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) {
333
PyErr_SetString(PyExc_TypeError,
334
"environment can only contain strings");
337
ksize = PyUnicode_GET_SIZE(key);
338
vsize = PyUnicode_GET_SIZE(value);
339
totalsize = (p - PyUnicode_AS_UNICODE(out)) + ksize + 1 +
341
if (totalsize > PyUnicode_GET_SIZE(out)) {
342
int offset = p - PyUnicode_AS_UNICODE(out);
343
PyUnicode_Resize(&out, totalsize + 1024);
344
p = PyUnicode_AS_UNICODE(out) + offset;
346
Py_UNICODE_COPY(p, PyUnicode_AS_UNICODE(key), ksize);
349
Py_UNICODE_COPY(p, PyUnicode_AS_UNICODE(value), vsize);
354
/* add trailing null byte */
356
PyUnicode_Resize(&out, p - PyUnicode_AS_UNICODE(out));
358
/* PyObject_Print(out, stdout, 0); */
373
sp_CreateProcess(PyObject* self, PyObject* args)
376
PROCESS_INFORMATION pi;
378
PyObject* environment;
380
Py_UNICODE* application_name;
381
Py_UNICODE* command_line;
382
PyObject* process_attributes; /* ignored */
383
PyObject* thread_attributes; /* ignored */
386
PyObject* env_mapping;
387
Py_UNICODE* current_directory;
388
PyObject* startup_info;
390
if (! PyArg_ParseTuple(args, "ZZOOiiOZO:CreateProcess",
402
ZeroMemory(&si, sizeof(si));
405
/* note: we only support a small subset of all SI attributes */
406
si.dwFlags = getint(startup_info, "dwFlags");
407
si.wShowWindow = getint(startup_info, "wShowWindow");
408
si.hStdInput = gethandle(startup_info, "hStdInput");
409
si.hStdOutput = gethandle(startup_info, "hStdOutput");
410
si.hStdError = gethandle(startup_info, "hStdError");
412
if (PyErr_Occurred())
415
if (env_mapping == Py_None)
418
environment = getenvironment(env_mapping);
423
Py_BEGIN_ALLOW_THREADS
424
result = CreateProcessW(application_name,
429
creation_flags | CREATE_UNICODE_ENVIRONMENT,
430
environment ? PyUnicode_AS_UNICODE(environment) : NULL,
436
Py_XDECREF(environment);
439
return PyErr_SetFromWindowsErr(GetLastError());
441
return Py_BuildValue("NNii",
442
sp_handle_new(pi.hProcess),
443
sp_handle_new(pi.hThread),
449
sp_TerminateProcess(PyObject* self, PyObject* args)
455
if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM "i:TerminateProcess",
456
&process, &exit_code))
459
result = TerminateProcess(process, exit_code);
462
return PyErr_SetFromWindowsErr(GetLastError());
469
sp_GetExitCodeProcess(PyObject* self, PyObject* args)
475
if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM ":GetExitCodeProcess", &process))
478
result = GetExitCodeProcess(process, &exit_code);
481
return PyErr_SetFromWindowsErr(GetLastError());
483
return PyLong_FromLong(exit_code);
487
sp_WaitForSingleObject(PyObject* self, PyObject* args)
493
if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM "i:WaitForSingleObject",
498
Py_BEGIN_ALLOW_THREADS
499
result = WaitForSingleObject(handle, (DWORD) milliseconds);
502
if (result == WAIT_FAILED)
503
return PyErr_SetFromWindowsErr(GetLastError());
505
return PyLong_FromLong((int) result);
509
sp_GetVersion(PyObject* self, PyObject* args)
511
if (! PyArg_ParseTuple(args, ":GetVersion"))
514
return PyLong_FromLong((int) GetVersion());
518
sp_GetModuleFileName(PyObject* self, PyObject* args)
522
WCHAR filename[MAX_PATH];
524
if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM ":GetModuleFileName",
528
result = GetModuleFileNameW(module, filename, MAX_PATH);
529
filename[MAX_PATH-1] = '\0';
532
return PyErr_SetFromWindowsErr(GetLastError());
534
return PyUnicode_FromUnicode(filename, Py_UNICODE_strlen(filename));
537
static PyMethodDef sp_functions[] = {
538
{"GetStdHandle", sp_GetStdHandle, METH_VARARGS},
539
{"GetCurrentProcess", sp_GetCurrentProcess, METH_VARARGS},
540
{"DuplicateHandle", sp_DuplicateHandle, METH_VARARGS},
541
{"CreatePipe", sp_CreatePipe, METH_VARARGS},
542
{"CreateProcess", sp_CreateProcess, METH_VARARGS},
543
{"TerminateProcess", sp_TerminateProcess, METH_VARARGS},
544
{"GetExitCodeProcess", sp_GetExitCodeProcess, METH_VARARGS},
545
{"WaitForSingleObject", sp_WaitForSingleObject, METH_VARARGS},
546
{"GetVersion", sp_GetVersion, METH_VARARGS},
547
{"GetModuleFileName", sp_GetModuleFileName, METH_VARARGS},
551
/* -------------------------------------------------------------------- */
554
defint(PyObject* d, const char* name, int value)
556
PyObject* v = PyLong_FromLong((long) value);
558
PyDict_SetItemString(d, (char*) name, v);
563
static struct PyModuleDef _subprocessmodule = {
564
PyModuleDef_HEAD_INIT,
581
/* patch up object descriptors */
582
sp_handle_as_number.nb_int = (unaryfunc) sp_handle_as_int;
583
if (PyType_Ready(&sp_handle_type) < 0)
586
m = PyModule_Create(&_subprocessmodule);
589
d = PyModule_GetDict(m);
592
defint(d, "STD_INPUT_HANDLE", STD_INPUT_HANDLE);
593
defint(d, "STD_OUTPUT_HANDLE", STD_OUTPUT_HANDLE);
594
defint(d, "STD_ERROR_HANDLE", STD_ERROR_HANDLE);
595
defint(d, "DUPLICATE_SAME_ACCESS", DUPLICATE_SAME_ACCESS);
596
defint(d, "STARTF_USESTDHANDLES", STARTF_USESTDHANDLES);
597
defint(d, "STARTF_USESHOWWINDOW", STARTF_USESHOWWINDOW);
598
defint(d, "SW_HIDE", SW_HIDE);
599
defint(d, "INFINITE", INFINITE);
600
defint(d, "WAIT_OBJECT_0", WAIT_OBJECT_0);
601
defint(d, "CREATE_NEW_CONSOLE", CREATE_NEW_CONSOLE);