56
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;
58
sp_handle_object* self;
60
self = PyObject_NEW(sp_handle_object, &sp_handle_type);
64
self->handle = handle;
66
return (PyObject*) self;
69
69
#if defined(MS_WIN32) && !defined(MS_WIN64)
70
#define HANDLE_TO_PYNUM(handle) PyLong_FromLong((long) handle)
71
#define PY_HANDLE_PARAM "l"
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"
73
#define HANDLE_TO_PYNUM(handle) PyLong_FromLongLong((long long) handle)
74
#define PY_HANDLE_PARAM "L"
78
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);
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
94
sp_handle_close(sp_handle_object* self, PyObject* args)
96
if (! PyArg_ParseTuple(args, ":Close"))
96
if (! PyArg_ParseTuple(args, ":Close"))
99
if (self->handle != INVALID_HANDLE_VALUE) {
100
CloseHandle(self->handle);
101
self->handle = INVALID_HANDLE_VALUE;
99
if (self->handle != INVALID_HANDLE_VALUE) {
100
CloseHandle(self->handle);
101
self->handle = INVALID_HANDLE_VALUE;
108
108
sp_handle_dealloc(sp_handle_object* self)
110
if (self->handle != INVALID_HANDLE_VALUE)
111
CloseHandle(self->handle);
110
if (self->handle != INVALID_HANDLE_VALUE)
111
CloseHandle(self->handle);
115
115
static PyMethodDef sp_handle_methods[] = {
116
{"Detach", (PyCFunction) sp_handle_detach, METH_VARARGS},
117
{"Close", (PyCFunction) sp_handle_close, METH_VARARGS},
116
{"Detach", (PyCFunction) sp_handle_detach, METH_VARARGS},
117
{"Close", (PyCFunction) sp_handle_close, METH_VARARGS},
122
122
sp_handle_as_int(sp_handle_object* self)
124
return HANDLE_TO_PYNUM(self->handle);
124
return HANDLE_TO_PYNUM(self->handle);
127
127
static PyNumberMethods sp_handle_as_number;
129
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*/
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
158
/* -------------------------------------------------------------------- */
159
159
/* windows API functions */
161
PyDoc_STRVAR(GetStdHandle_doc,
162
"GetStdHandle(handle) -> integer\n\
164
Return a handle to the specified standard device\n\
165
(STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE).\n\
166
The integer associated with the handle object is returned.");
161
168
static PyObject *
162
169
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);
174
if (! PyArg_ParseTuple(args, "i:GetStdHandle", &std_handle))
177
Py_BEGIN_ALLOW_THREADS
178
handle = GetStdHandle((DWORD) std_handle);
181
if (handle == INVALID_HANDLE_VALUE)
182
return PyErr_SetFromWindowsErr(GetLastError());
189
/* note: returns integer, not handle object */
190
return HANDLE_TO_PYNUM(handle);
193
PyDoc_STRVAR(GetCurrentProcess_doc,
194
"GetCurrentProcess() -> handle\n\
196
Return a handle object for the current process.");
186
198
static PyObject *
187
199
sp_GetCurrentProcess(PyObject* self, PyObject* args)
189
if (! PyArg_ParseTuple(args, ":GetCurrentProcess"))
201
if (! PyArg_ParseTuple(args, ":GetCurrentProcess"))
192
return sp_handle_new(GetCurrentProcess());
204
return sp_handle_new(GetCurrentProcess());
207
PyDoc_STRVAR(DuplicateHandle_doc,
208
"DuplicateHandle(source_proc_handle, source_handle,\n\
209
target_proc_handle, target_handle, access,\n\
210
inherit[, options]) -> handle\n\
212
Return a duplicate handle object.\n\
214
The duplicate handle refers to the same object as the original\n\
215
handle. Therefore, any changes to the object are reflected\n\
216
through both handles.");
195
218
static PyObject *
196
219
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);
221
HANDLE target_handle;
224
HANDLE source_process_handle;
225
HANDLE source_handle;
226
HANDLE target_process_handle;
231
if (! PyArg_ParseTuple(args,
232
PY_HANDLE_PARAM PY_HANDLE_PARAM PY_HANDLE_PARAM
233
"ii|i:DuplicateHandle",
234
&source_process_handle,
236
&target_process_handle,
242
Py_BEGIN_ALLOW_THREADS
243
result = DuplicateHandle(
244
source_process_handle,
246
target_process_handle,
255
return PyErr_SetFromWindowsErr(GetLastError());
257
return sp_handle_new(target_handle);
260
PyDoc_STRVAR(CreatePipe_doc,
261
"CreatePipe(pipe_attrs, size) -> (read_handle, write_handle)\n\
263
Create an anonymous pipe, and return handles to the read and\n\
264
write ends of the pipe.\n\
266
pipe_attrs is ignored internally and can be None.");
237
268
static PyObject *
238
269
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));
275
PyObject* pipe_attributes; /* ignored */
278
if (! PyArg_ParseTuple(args, "Oi:CreatePipe", &pipe_attributes, &size))
281
Py_BEGIN_ALLOW_THREADS
282
result = CreatePipe(&read_pipe, &write_pipe, NULL, size);
286
return PyErr_SetFromWindowsErr(GetLastError());
288
return Py_BuildValue(
289
"NN", sp_handle_new(read_pipe), sp_handle_new(write_pipe));
261
292
/* helpers for createprocess */
264
295
getint(PyObject* obj, char* name)
269
value = PyObject_GetAttrString(obj, name);
271
PyErr_Clear(); /* FIXME: propagate error? */
274
ret = (int) PyLong_AsLong(value);
300
value = PyObject_GetAttrString(obj, name);
302
PyErr_Clear(); /* FIXME: propagate error? */
305
ret = (int) PyLong_AsLong(value);
280
311
gethandle(PyObject* obj, char* name)
282
sp_handle_object* value;
313
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)
316
value = (sp_handle_object*) PyObject_GetAttrString(obj, name);
318
PyErr_Clear(); /* FIXME: propagate error? */
321
if (Py_TYPE(value) != &sp_handle_type)
299
330
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); */
333
PyObject* out = NULL;
338
/* convert environment dictionary to windows enviroment string */
339
if (! PyMapping_Check(environment)) {
341
PyExc_TypeError, "environment must be dictionary or None");
345
envsize = PyMapping_Length(environment);
347
keys = PyMapping_Keys(environment);
348
values = PyMapping_Values(environment);
349
if (!keys || !values)
352
out = PyUnicode_FromUnicode(NULL, 2048);
356
p = PyUnicode_AS_UNICODE(out);
358
for (i = 0; i < envsize; i++) {
359
int ksize, vsize, totalsize;
360
PyObject* key = PyList_GET_ITEM(keys, i);
361
PyObject* value = PyList_GET_ITEM(values, i);
363
if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) {
364
PyErr_SetString(PyExc_TypeError,
365
"environment can only contain strings");
368
ksize = PyUnicode_GET_SIZE(key);
369
vsize = PyUnicode_GET_SIZE(value);
370
totalsize = (p - PyUnicode_AS_UNICODE(out)) + ksize + 1 +
372
if (totalsize > PyUnicode_GET_SIZE(out)) {
373
int offset = p - PyUnicode_AS_UNICODE(out);
374
PyUnicode_Resize(&out, totalsize + 1024);
375
p = PyUnicode_AS_UNICODE(out) + offset;
377
Py_UNICODE_COPY(p, PyUnicode_AS_UNICODE(key), ksize);
380
Py_UNICODE_COPY(p, PyUnicode_AS_UNICODE(value), vsize);
385
/* add trailing null byte */
387
PyUnicode_Resize(&out, p - PyUnicode_AS_UNICODE(out));
389
/* PyObject_Print(out, stdout, 0); */
403
PyDoc_STRVAR(CreateProcess_doc,
404
"CreateProcess(app_name, cmd_line, proc_attrs, thread_attrs,\n\
405
inherit, flags, env_mapping, curdir,\n\
406
startup_info) -> (proc_handle, thread_handle,\n\
409
Create a new process and its primary thread. The return\n\
410
value is a tuple of the process handle, thread handle,\n\
411
process ID, and thread ID.\n\
413
proc_attrs and thread_attrs are ignored internally and can be None.");
372
415
static PyObject *
373
416
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),
419
PROCESS_INFORMATION pi;
421
PyObject* environment;
423
Py_UNICODE* application_name;
424
Py_UNICODE* command_line;
425
PyObject* process_attributes; /* ignored */
426
PyObject* thread_attributes; /* ignored */
429
PyObject* env_mapping;
430
Py_UNICODE* current_directory;
431
PyObject* startup_info;
433
if (! PyArg_ParseTuple(args, "ZZOOiiOZO:CreateProcess",
445
ZeroMemory(&si, sizeof(si));
448
/* note: we only support a small subset of all SI attributes */
449
si.dwFlags = getint(startup_info, "dwFlags");
450
si.wShowWindow = getint(startup_info, "wShowWindow");
451
si.hStdInput = gethandle(startup_info, "hStdInput");
452
si.hStdOutput = gethandle(startup_info, "hStdOutput");
453
si.hStdError = gethandle(startup_info, "hStdError");
455
if (PyErr_Occurred())
458
if (env_mapping == Py_None)
461
environment = getenvironment(env_mapping);
466
Py_BEGIN_ALLOW_THREADS
467
result = CreateProcessW(application_name,
472
creation_flags | CREATE_UNICODE_ENVIRONMENT,
473
environment ? PyUnicode_AS_UNICODE(environment) : NULL,
479
Py_XDECREF(environment);
482
return PyErr_SetFromWindowsErr(GetLastError());
484
return Py_BuildValue("NNii",
485
sp_handle_new(pi.hProcess),
486
sp_handle_new(pi.hThread),
491
PyDoc_STRVAR(TerminateProcess_doc,
492
"TerminateProcess(handle, exit_code) -> None\n\
494
Terminate the specified process and all of its threads.");
448
496
static PyObject *
449
497
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());
503
if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM "i:TerminateProcess",
504
&process, &exit_code))
507
result = TerminateProcess(process, exit_code);
510
return PyErr_SetFromWindowsErr(GetLastError());
516
PyDoc_STRVAR(GetExitCodeProcess_doc,
517
"GetExitCodeProcess(handle) -> Exit code\n\
519
Return the termination status of the specified process.");
468
521
static PyObject *
469
522
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);
528
if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM ":GetExitCodeProcess", &process))
531
result = GetExitCodeProcess(process, &exit_code);
534
return PyErr_SetFromWindowsErr(GetLastError());
536
return PyLong_FromLong(exit_code);
539
PyDoc_STRVAR(WaitForSingleObject_doc,
540
"WaitForSingleObject(handle, timeout) -> result\n\
542
Wait until the specified object is in the signaled state or\n\
543
the time-out interval elapses. The timeout value is specified\n\
486
546
static PyObject *
487
547
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);
553
if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM "i:WaitForSingleObject",
558
Py_BEGIN_ALLOW_THREADS
559
result = WaitForSingleObject(handle, (DWORD) milliseconds);
562
if (result == WAIT_FAILED)
563
return PyErr_SetFromWindowsErr(GetLastError());
565
return PyLong_FromLong((int) result);
568
PyDoc_STRVAR(GetVersion_doc,
569
"GetVersion() -> version\n\
571
Return the version number of the current operating system.");
508
573
static PyObject *
509
574
sp_GetVersion(PyObject* self, PyObject* args)
511
if (! PyArg_ParseTuple(args, ":GetVersion"))
576
if (! PyArg_ParseTuple(args, ":GetVersion"))
514
return PyLong_FromLong((int) GetVersion());
579
return PyLong_FromLong((int) GetVersion());
582
PyDoc_STRVAR(GetModuleFileName_doc,
583
"GetModuleFileName(module) -> path\n\
585
Return the fully-qualified path for the file that contains\n\
586
the specified module. The module must have been loaded by the\n\
589
The module parameter should be a handle to the loaded module\n\
590
whose path is being requested. If this parameter is 0, \n\
591
GetModuleFileName retrieves the path of the executable file\n\
592
of the current process.");
517
594
static PyObject *
518
595
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));
599
WCHAR filename[MAX_PATH];
601
if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM ":GetModuleFileName",
605
result = GetModuleFileNameW(module, filename, MAX_PATH);
606
filename[MAX_PATH-1] = '\0';
609
return PyErr_SetFromWindowsErr(GetLastError());
611
return PyUnicode_FromUnicode(filename, Py_UNICODE_strlen(filename));
537
614
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},
615
{"GetStdHandle", sp_GetStdHandle, METH_VARARGS, GetStdHandle_doc},
616
{"GetCurrentProcess", sp_GetCurrentProcess, METH_VARARGS,
617
GetCurrentProcess_doc},
618
{"DuplicateHandle", sp_DuplicateHandle, METH_VARARGS,
619
DuplicateHandle_doc},
620
{"CreatePipe", sp_CreatePipe, METH_VARARGS, CreatePipe_doc},
621
{"CreateProcess", sp_CreateProcess, METH_VARARGS, CreateProcess_doc},
622
{"TerminateProcess", sp_TerminateProcess, METH_VARARGS,
623
TerminateProcess_doc},
624
{"GetExitCodeProcess", sp_GetExitCodeProcess, METH_VARARGS,
625
GetExitCodeProcess_doc},
626
{"WaitForSingleObject", sp_WaitForSingleObject, METH_VARARGS,
627
WaitForSingleObject_doc},
628
{"GetVersion", sp_GetVersion, METH_VARARGS, GetVersion_doc},
629
{"GetModuleFileName", sp_GetModuleFileName, METH_VARARGS,
630
GetModuleFileName_doc},
551
634
/* -------------------------------------------------------------------- */