~ubuntu-branches/ubuntu/maverick/python3.1/maverick

« back to all changes in this revision

Viewing changes to PC/_subprocess.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2009-03-23 00:01:27 UTC
  • Revision ID: james.westby@ubuntu.com-20090323000127-5fstfxju4ufrhthq
Tags: upstream-3.1~a1+20090322
ImportĀ upstreamĀ versionĀ 3.1~a1+20090322

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
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
 
6
 * platforms might be added here as well.
 
7
 *
 
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>
 
11
 *
 
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:
 
15
 *
 
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
 
23
 * permission.
 
24
 *
 
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.
 
32
 *
 
33
 */
 
34
 
 
35
/* Licensed to PSF under a Contributor Agreement. */
 
36
/* See http://www.python.org/2.4/license for licensing details. */
 
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
 
 
48
typedef struct {
 
49
        PyObject_HEAD
 
50
        HANDLE handle;
 
51
} sp_handle_object;
 
52
 
 
53
static PyTypeObject sp_handle_type;
 
54
 
 
55
static PyObject*
 
56
sp_handle_new(HANDLE handle)
 
57
{
 
58
        sp_handle_object* self;
 
59
 
 
60
        self = PyObject_NEW(sp_handle_object, &sp_handle_type);
 
61
        if (self == NULL)
 
62
                return NULL;
 
63
 
 
64
        self->handle = handle;
 
65
 
 
66
        return (PyObject*) self;
 
67
}
 
68
 
 
69
#if defined(MS_WIN32) && !defined(MS_WIN64)
 
70
#define HANDLE_TO_PYNUM(handle) PyLong_FromLong((long) handle)
 
71
#define PY_HANDLE_PARAM "l"
 
72
#else
 
73
#define HANDLE_TO_PYNUM(handle) PyLong_FromLongLong((long long) handle)
 
74
#define PY_HANDLE_PARAM "L"
 
75
#endif
 
76
 
 
77
static PyObject*
 
78
sp_handle_detach(sp_handle_object* self, PyObject* args)
 
79
{
 
80
        HANDLE handle;
 
81
 
 
82
        if (! PyArg_ParseTuple(args, ":Detach"))
 
83
                return NULL;
 
84
 
 
85
        handle = self->handle;
 
86
 
 
87
        self->handle = INVALID_HANDLE_VALUE;
 
88
 
 
89
        /* note: return the current handle, as an integer */
 
90
        return HANDLE_TO_PYNUM(handle);
 
91
}
 
92
 
 
93
static PyObject*
 
94
sp_handle_close(sp_handle_object* self, PyObject* args)
 
95
{
 
96
        if (! PyArg_ParseTuple(args, ":Close"))
 
97
                return NULL;
 
98
 
 
99
        if (self->handle != INVALID_HANDLE_VALUE) {
 
100
                CloseHandle(self->handle);
 
101
                self->handle = INVALID_HANDLE_VALUE;
 
102
        }
 
103
        Py_INCREF(Py_None);
 
104
        return Py_None;
 
105
}
 
106
 
 
107
static void
 
108
sp_handle_dealloc(sp_handle_object* self)
 
109
{
 
110
        if (self->handle != INVALID_HANDLE_VALUE)
 
111
                CloseHandle(self->handle);
 
112
        PyObject_FREE(self);
 
113
}
 
114
 
 
115
static PyMethodDef sp_handle_methods[] = {
 
116
        {"Detach", (PyCFunction) sp_handle_detach, METH_VARARGS},
 
117
        {"Close",  (PyCFunction) sp_handle_close,  METH_VARARGS},
 
118
        {NULL, NULL}
 
119
};
 
120
 
 
121
static PyObject*
 
122
sp_handle_as_int(sp_handle_object* self)
 
123
{
 
124
        return HANDLE_TO_PYNUM(self->handle);
 
125
}
 
126
 
 
127
static PyNumberMethods sp_handle_as_number;
 
128
 
 
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*/
 
133
        0, /*tp_print*/
 
134
        0,                              /*tp_getattr*/
 
135
        0,                              /*tp_setattr*/
 
136
        0,                              /*tp_reserved*/
 
137
        0,                              /*tp_repr*/
 
138
        &sp_handle_as_number,           /*tp_as_number */
 
139
        0,                              /*tp_as_sequence */
 
140
        0,                              /*tp_as_mapping */
 
141
        0,                              /*tp_hash*/
 
142
        0,                              /*tp_call*/
 
143
        0,                              /*tp_str*/
 
144
        0,                              /*tp_getattro*/
 
145
        0,                              /*tp_setattro*/
 
146
        0,                              /*tp_as_buffer*/
 
147
        Py_TPFLAGS_DEFAULT,             /*tp_flags*/
 
148
        0,                              /*tp_doc*/
 
149
        0,                              /*tp_traverse*/
 
150
        0,                              /*tp_clear*/
 
151
        0,                              /*tp_richcompare*/
 
152
        0,                              /*tp_weaklistoffset*/
 
153
        0,                              /*tp_iter*/
 
154
        0,                              /*tp_iternext*/
 
155
        sp_handle_methods,              /*tp_methods*/
 
156
};
 
157
 
 
158
/* -------------------------------------------------------------------- */
 
159
/* windows API functions */
 
160
 
 
161
static PyObject *
 
162
sp_GetStdHandle(PyObject* self, PyObject* args)
 
163
{
 
164
        HANDLE handle;
 
165
        int std_handle;
 
166
 
 
167
        if (! PyArg_ParseTuple(args, "i:GetStdHandle", &std_handle))
 
168
                return NULL;
 
169
 
 
170
        Py_BEGIN_ALLOW_THREADS
 
171
        handle = GetStdHandle((DWORD) std_handle);
 
172
        Py_END_ALLOW_THREADS
 
173
 
 
174
        if (handle == INVALID_HANDLE_VALUE)
 
175
                return PyErr_SetFromWindowsErr(GetLastError());
 
176
 
 
177
        if (! handle) {
 
178
                Py_INCREF(Py_None);
 
179
                return Py_None;
 
180
        }
 
181
 
 
182
        /* note: returns integer, not handle object */
 
183
        return HANDLE_TO_PYNUM(handle);
 
184
}
 
185
 
 
186
static PyObject *
 
187
sp_GetCurrentProcess(PyObject* self, PyObject* args)
 
188
{
 
189
        if (! PyArg_ParseTuple(args, ":GetCurrentProcess"))
 
190
                return NULL;
 
191
 
 
192
        return sp_handle_new(GetCurrentProcess());
 
193
}
 
194
 
 
195
static PyObject *
 
196
sp_DuplicateHandle(PyObject* self, PyObject* args)
 
197
{
 
198
        HANDLE target_handle;
 
199
        BOOL result;
 
200
 
 
201
        HANDLE source_process_handle;
 
202
        HANDLE source_handle;
 
203
        HANDLE target_process_handle;
 
204
        int desired_access;
 
205
        int inherit_handle;
 
206
        int options = 0;
 
207
 
 
208
        if (! PyArg_ParseTuple(args,
 
209
                               PY_HANDLE_PARAM PY_HANDLE_PARAM PY_HANDLE_PARAM
 
210
                               "ii|i:DuplicateHandle",
 
211
                               &source_process_handle,
 
212
                               &source_handle,
 
213
                               &target_process_handle,
 
214
                               &desired_access,
 
215
                               &inherit_handle,
 
216
                               &options))
 
217
                return NULL;
 
218
 
 
219
        Py_BEGIN_ALLOW_THREADS
 
220
        result = DuplicateHandle(
 
221
                source_process_handle,
 
222
                source_handle,
 
223
                target_process_handle,
 
224
                &target_handle,
 
225
                desired_access,
 
226
                inherit_handle,
 
227
                options
 
228
        );
 
229
        Py_END_ALLOW_THREADS
 
230
 
 
231
        if (! result)
 
232
                return PyErr_SetFromWindowsErr(GetLastError());
 
233
 
 
234
        return sp_handle_new(target_handle);
 
235
}
 
236
 
 
237
static PyObject *
 
238
sp_CreatePipe(PyObject* self, PyObject* args)
 
239
{
 
240
        HANDLE read_pipe;
 
241
        HANDLE write_pipe;
 
242
        BOOL result;
 
243
 
 
244
        PyObject* pipe_attributes; /* ignored */
 
245
        int size;
 
246
 
 
247
        if (! PyArg_ParseTuple(args, "Oi:CreatePipe", &pipe_attributes, &size))
 
248
                return NULL;
 
249
 
 
250
        Py_BEGIN_ALLOW_THREADS
 
251
        result = CreatePipe(&read_pipe, &write_pipe, NULL, size);
 
252
        Py_END_ALLOW_THREADS
 
253
 
 
254
        if (! result)
 
255
                return PyErr_SetFromWindowsErr(GetLastError());
 
256
 
 
257
        return Py_BuildValue(
 
258
                "NN", sp_handle_new(read_pipe), sp_handle_new(write_pipe));
 
259
}
 
260
 
 
261
/* helpers for createprocess */
 
262
 
 
263
static int
 
264
getint(PyObject* obj, char* name)
 
265
{
 
266
        PyObject* value;
 
267
        int ret;
 
268
 
 
269
        value = PyObject_GetAttrString(obj, name);
 
270
        if (! value) {
 
271
                PyErr_Clear(); /* FIXME: propagate error? */
 
272
                return 0;
 
273
        }
 
274
        ret = (int) PyLong_AsLong(value);
 
275
        Py_DECREF(value);
 
276
        return ret;
 
277
}
 
278
 
 
279
static HANDLE
 
280
gethandle(PyObject* obj, char* name)
 
281
{
 
282
        sp_handle_object* value;
 
283
        HANDLE ret;
 
284
 
 
285
        value = (sp_handle_object*) PyObject_GetAttrString(obj, name);
 
286
        if (! value) {
 
287
                PyErr_Clear(); /* FIXME: propagate error? */
 
288
                return NULL;
 
289
        }
 
290
        if (Py_TYPE(value) != &sp_handle_type)
 
291
                ret = NULL;
 
292
        else
 
293
                ret = value->handle;
 
294
        Py_DECREF(value);
 
295
        return ret;
 
296
}
 
297
 
 
298
static PyObject*
 
299
getenvironment(PyObject* environment)
 
300
{
 
301
        int i, envsize;
 
302
        PyObject* out = NULL;
 
303
        PyObject* keys;
 
304
        PyObject* values;
 
305
        Py_UNICODE* p;
 
306
 
 
307
        /* convert environment dictionary to windows enviroment string */
 
308
        if (! PyMapping_Check(environment)) {
 
309
                PyErr_SetString(
 
310
                    PyExc_TypeError, "environment must be dictionary or None");
 
311
                return NULL;
 
312
        }
 
313
 
 
314
        envsize = PyMapping_Length(environment);
 
315
 
 
316
        keys = PyMapping_Keys(environment);
 
317
        values = PyMapping_Values(environment);
 
318
        if (!keys || !values)
 
319
                goto error;
 
320
 
 
321
        out = PyUnicode_FromUnicode(NULL, 2048);
 
322
        if (! out)
 
323
                goto error;
 
324
 
 
325
        p = PyUnicode_AS_UNICODE(out);
 
326
 
 
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);
 
331
 
 
332
                if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) {
 
333
                        PyErr_SetString(PyExc_TypeError,
 
334
                                "environment can only contain strings");
 
335
                        goto error;
 
336
                }
 
337
                ksize = PyUnicode_GET_SIZE(key);
 
338
                vsize = PyUnicode_GET_SIZE(value);
 
339
                totalsize = (p - PyUnicode_AS_UNICODE(out)) + ksize + 1 +
 
340
                                                             vsize + 1 + 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;
 
345
                }
 
346
                Py_UNICODE_COPY(p, PyUnicode_AS_UNICODE(key), ksize);
 
347
                p += ksize;
 
348
                *p++ = '=';
 
349
                Py_UNICODE_COPY(p, PyUnicode_AS_UNICODE(value), vsize);
 
350
                p += vsize;
 
351
                *p++ = '\0';
 
352
        }
 
353
 
 
354
        /* add trailing null byte */
 
355
        *p++ = '\0';
 
356
        PyUnicode_Resize(&out, p - PyUnicode_AS_UNICODE(out));
 
357
 
 
358
        /* PyObject_Print(out, stdout, 0); */
 
359
 
 
360
        Py_XDECREF(keys);
 
361
        Py_XDECREF(values);
 
362
 
 
363
        return out;
 
364
 
 
365
 error:
 
366
        Py_XDECREF(out);
 
367
        Py_XDECREF(keys);
 
368
        Py_XDECREF(values);
 
369
        return NULL;
 
370
}
 
371
 
 
372
static PyObject *
 
373
sp_CreateProcess(PyObject* self, PyObject* args)
 
374
{
 
375
        BOOL result;
 
376
        PROCESS_INFORMATION pi;
 
377
        STARTUPINFOW si;
 
378
        PyObject* environment;
 
379
 
 
380
        Py_UNICODE* application_name;
 
381
        Py_UNICODE* command_line;
 
382
        PyObject* process_attributes; /* ignored */
 
383
        PyObject* thread_attributes; /* ignored */
 
384
        int inherit_handles;
 
385
        int creation_flags;
 
386
        PyObject* env_mapping;
 
387
        Py_UNICODE* current_directory;
 
388
        PyObject* startup_info;
 
389
 
 
390
        if (! PyArg_ParseTuple(args, "ZZOOiiOZO:CreateProcess",
 
391
                               &application_name,
 
392
                               &command_line,
 
393
                               &process_attributes,
 
394
                               &thread_attributes,
 
395
                               &inherit_handles,
 
396
                               &creation_flags,
 
397
                               &env_mapping,
 
398
                               &current_directory,
 
399
                               &startup_info))
 
400
                return NULL;
 
401
 
 
402
        ZeroMemory(&si, sizeof(si));
 
403
        si.cb = sizeof(si);
 
404
 
 
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");
 
411
 
 
412
        if (PyErr_Occurred())
 
413
                return NULL;
 
414
 
 
415
        if (env_mapping == Py_None)
 
416
                environment = NULL;
 
417
        else {
 
418
                environment = getenvironment(env_mapping);
 
419
                if (! environment)
 
420
                        return NULL;
 
421
        }
 
422
 
 
423
        Py_BEGIN_ALLOW_THREADS
 
424
        result = CreateProcessW(application_name,
 
425
                               command_line,
 
426
                               NULL,
 
427
                               NULL,
 
428
                               inherit_handles,
 
429
                               creation_flags | CREATE_UNICODE_ENVIRONMENT,
 
430
                               environment ? PyUnicode_AS_UNICODE(environment) : NULL,
 
431
                               current_directory,
 
432
                               &si,
 
433
                               &pi);
 
434
        Py_END_ALLOW_THREADS
 
435
 
 
436
        Py_XDECREF(environment);
 
437
 
 
438
        if (! result)
 
439
                return PyErr_SetFromWindowsErr(GetLastError());
 
440
 
 
441
        return Py_BuildValue("NNii",
 
442
                             sp_handle_new(pi.hProcess),
 
443
                             sp_handle_new(pi.hThread),
 
444
                             pi.dwProcessId,
 
445
                             pi.dwThreadId);
 
446
}
 
447
 
 
448
static PyObject *
 
449
sp_TerminateProcess(PyObject* self, PyObject* args)
 
450
{
 
451
        BOOL result;
 
452
 
 
453
        HANDLE process;
 
454
        int exit_code;
 
455
        if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM "i:TerminateProcess",
 
456
                               &process, &exit_code))
 
457
                return NULL;
 
458
 
 
459
        result = TerminateProcess(process, exit_code);
 
460
 
 
461
        if (! result)
 
462
                return PyErr_SetFromWindowsErr(GetLastError());
 
463
 
 
464
        Py_INCREF(Py_None);
 
465
        return Py_None;
 
466
}
 
467
 
 
468
static PyObject *
 
469
sp_GetExitCodeProcess(PyObject* self, PyObject* args)
 
470
{
 
471
        DWORD exit_code;
 
472
        BOOL result;
 
473
 
 
474
        HANDLE process;
 
475
        if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM ":GetExitCodeProcess", &process))
 
476
                return NULL;
 
477
 
 
478
        result = GetExitCodeProcess(process, &exit_code);
 
479
 
 
480
        if (! result)
 
481
                return PyErr_SetFromWindowsErr(GetLastError());
 
482
 
 
483
        return PyLong_FromLong(exit_code);
 
484
}
 
485
 
 
486
static PyObject *
 
487
sp_WaitForSingleObject(PyObject* self, PyObject* args)
 
488
{
 
489
        DWORD result;
 
490
 
 
491
        HANDLE handle;
 
492
        int milliseconds;
 
493
        if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM "i:WaitForSingleObject",
 
494
                                     &handle,
 
495
                                     &milliseconds))
 
496
                return NULL;
 
497
 
 
498
        Py_BEGIN_ALLOW_THREADS
 
499
        result = WaitForSingleObject(handle, (DWORD) milliseconds);
 
500
        Py_END_ALLOW_THREADS
 
501
 
 
502
        if (result == WAIT_FAILED)
 
503
                return PyErr_SetFromWindowsErr(GetLastError());
 
504
 
 
505
        return PyLong_FromLong((int) result);
 
506
}
 
507
 
 
508
static PyObject *
 
509
sp_GetVersion(PyObject* self, PyObject* args)
 
510
{
 
511
        if (! PyArg_ParseTuple(args, ":GetVersion"))
 
512
                return NULL;
 
513
 
 
514
        return PyLong_FromLong((int) GetVersion());
 
515
}
 
516
 
 
517
static PyObject *
 
518
sp_GetModuleFileName(PyObject* self, PyObject* args)
 
519
{
 
520
        BOOL result;
 
521
        HMODULE module;
 
522
        WCHAR filename[MAX_PATH];
 
523
 
 
524
        if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM ":GetModuleFileName",
 
525
                               &module))
 
526
                return NULL;
 
527
 
 
528
        result = GetModuleFileNameW(module, filename, MAX_PATH);
 
529
        filename[MAX_PATH-1] = '\0';
 
530
 
 
531
        if (! result)
 
532
                return PyErr_SetFromWindowsErr(GetLastError());
 
533
 
 
534
        return PyUnicode_FromUnicode(filename, Py_UNICODE_strlen(filename));
 
535
}
 
536
 
 
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},
 
548
        {NULL, NULL}
 
549
};
 
550
 
 
551
/* -------------------------------------------------------------------- */
 
552
 
 
553
static void
 
554
defint(PyObject* d, const char* name, int value)
 
555
{
 
556
        PyObject* v = PyLong_FromLong((long) value);
 
557
        if (v) {
 
558
                PyDict_SetItemString(d, (char*) name, v);
 
559
                Py_DECREF(v);
 
560
        }
 
561
}
 
562
 
 
563
static struct PyModuleDef _subprocessmodule = {
 
564
        PyModuleDef_HEAD_INIT,
 
565
        "_subprocess",
 
566
        NULL,
 
567
        -1,
 
568
        sp_functions,
 
569
        NULL,
 
570
        NULL,
 
571
        NULL,
 
572
        NULL
 
573
};
 
574
 
 
575
PyMODINIT_FUNC
 
576
PyInit__subprocess()
 
577
{
 
578
        PyObject *d;
 
579
        PyObject *m;
 
580
 
 
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)
 
584
                return NULL;
 
585
 
 
586
        m = PyModule_Create(&_subprocessmodule);
 
587
        if (m == NULL)
 
588
                return NULL;
 
589
        d = PyModule_GetDict(m);
 
590
 
 
591
        /* constants */
 
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);
 
602
        return m;
 
603
}