ยปCore Development>Code coverage>Modules/_winapi.c

Python code coverage for Modules/_winapi.c

#countcontent
1n/a/*
2n/a * Support routines from the Windows API
3n/a *
4n/a * This module was originally created by merging PC/_subprocess.c with
5n/a * Modules/_multiprocessing/win32_functions.c.
6n/a *
7n/a * Copyright (c) 2004 by Fredrik Lundh <fredrik@pythonware.com>
8n/a * Copyright (c) 2004 by Secret Labs AB, http://www.pythonware.com
9n/a * Copyright (c) 2004 by Peter Astrand <astrand@lysator.liu.se>
10n/a *
11n/a * By obtaining, using, and/or copying this software and/or its
12n/a * associated documentation, you agree that you have read, understood,
13n/a * and will comply with the following terms and conditions:
14n/a *
15n/a * Permission to use, copy, modify, and distribute this software and
16n/a * its associated documentation for any purpose and without fee is
17n/a * hereby granted, provided that the above copyright notice appears in
18n/a * all copies, and that both that copyright notice and this permission
19n/a * notice appear in supporting documentation, and that the name of the
20n/a * authors not be used in advertising or publicity pertaining to
21n/a * distribution of the software without specific, written prior
22n/a * permission.
23n/a *
24n/a * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
25n/a * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
26n/a * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
27n/a * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
28n/a * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
29n/a * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
30n/a * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
31n/a *
32n/a */
33n/a
34n/a/* Licensed to PSF under a Contributor Agreement. */
35n/a/* See http://www.python.org/2.4/license for licensing details. */
36n/a
37n/a#include "Python.h"
38n/a#include "structmember.h"
39n/a
40n/a#define WINDOWS_LEAN_AND_MEAN
41n/a#include "windows.h"
42n/a#include <crtdbg.h>
43n/a#include "winreparse.h"
44n/a
45n/a#if defined(MS_WIN32) && !defined(MS_WIN64)
46n/a#define HANDLE_TO_PYNUM(handle) \
47n/a PyLong_FromUnsignedLong((unsigned long) handle)
48n/a#define PYNUM_TO_HANDLE(obj) ((HANDLE)PyLong_AsUnsignedLong(obj))
49n/a#define F_POINTER "k"
50n/a#define T_POINTER T_ULONG
51n/a#else
52n/a#define HANDLE_TO_PYNUM(handle) \
53n/a PyLong_FromUnsignedLongLong((unsigned long long) handle)
54n/a#define PYNUM_TO_HANDLE(obj) ((HANDLE)PyLong_AsUnsignedLongLong(obj))
55n/a#define F_POINTER "K"
56n/a#define T_POINTER T_ULONGLONG
57n/a#endif
58n/a
59n/a#define F_HANDLE F_POINTER
60n/a#define F_DWORD "k"
61n/a
62n/a#define T_HANDLE T_POINTER
63n/a
64n/a#define DWORD_MAX 4294967295U
65n/a
66n/a/* Grab CancelIoEx dynamically from kernel32 */
67n/astatic int has_CancelIoEx = -1;
68n/astatic BOOL (CALLBACK *Py_CancelIoEx)(HANDLE, LPOVERLAPPED);
69n/a
70n/astatic int
71n/acheck_CancelIoEx()
72n/a{
73n/a if (has_CancelIoEx == -1)
74n/a {
75n/a HINSTANCE hKernel32 = GetModuleHandle("KERNEL32");
76n/a * (FARPROC *) &Py_CancelIoEx = GetProcAddress(hKernel32,
77n/a "CancelIoEx");
78n/a has_CancelIoEx = (Py_CancelIoEx != NULL);
79n/a }
80n/a return has_CancelIoEx;
81n/a}
82n/a
83n/a
84n/a/*
85n/a * A Python object wrapping an OVERLAPPED structure and other useful data
86n/a * for overlapped I/O
87n/a */
88n/a
89n/atypedef struct {
90n/a PyObject_HEAD
91n/a OVERLAPPED overlapped;
92n/a /* For convenience, we store the file handle too */
93n/a HANDLE handle;
94n/a /* Whether there's I/O in flight */
95n/a int pending;
96n/a /* Whether I/O completed successfully */
97n/a int completed;
98n/a /* Buffer used for reading (optional) */
99n/a PyObject *read_buffer;
100n/a /* Buffer used for writing (optional) */
101n/a Py_buffer write_buffer;
102n/a} OverlappedObject;
103n/a
104n/astatic void
105n/aoverlapped_dealloc(OverlappedObject *self)
106n/a{
107n/a DWORD bytes;
108n/a int err = GetLastError();
109n/a
110n/a if (self->pending) {
111n/a if (check_CancelIoEx() &&
112n/a Py_CancelIoEx(self->handle, &self->overlapped) &&
113n/a GetOverlappedResult(self->handle, &self->overlapped, &bytes, TRUE))
114n/a {
115n/a /* The operation is no longer pending -- nothing to do. */
116n/a }
117n/a else if (_Py_Finalizing == NULL)
118n/a {
119n/a /* The operation is still pending -- give a warning. This
120n/a will probably only happen on Windows XP. */
121n/a PyErr_SetString(PyExc_RuntimeError,
122n/a "I/O operations still in flight while destroying "
123n/a "Overlapped object, the process may crash");
124n/a PyErr_WriteUnraisable(NULL);
125n/a }
126n/a else
127n/a {
128n/a /* The operation is still pending, but the process is
129n/a probably about to exit, so we need not worry too much
130n/a about memory leaks. Leaking self prevents a potential
131n/a crash. This can happen when a daemon thread is cleaned
132n/a up at exit -- see #19565. We only expect to get here
133n/a on Windows XP. */
134n/a CloseHandle(self->overlapped.hEvent);
135n/a SetLastError(err);
136n/a return;
137n/a }
138n/a }
139n/a
140n/a CloseHandle(self->overlapped.hEvent);
141n/a SetLastError(err);
142n/a if (self->write_buffer.obj)
143n/a PyBuffer_Release(&self->write_buffer);
144n/a Py_CLEAR(self->read_buffer);
145n/a PyObject_Del(self);
146n/a}
147n/a
148n/a/*[clinic input]
149n/amodule _winapi
150n/aclass _winapi.Overlapped "OverlappedObject *" "&OverlappedType"
151n/a[clinic start generated code]*/
152n/a/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c13d3f5fd1dabb84]*/
153n/a
154n/a/*[python input]
155n/adef create_converter(type_, format_unit):
156n/a name = type_ + '_converter'
157n/a # registered upon creation by CConverter's metaclass
158n/a type(name, (CConverter,), {'type': type_, 'format_unit': format_unit})
159n/a
160n/a# format unit differs between platforms for these
161n/acreate_converter('HANDLE', '" F_HANDLE "')
162n/acreate_converter('HMODULE', '" F_HANDLE "')
163n/acreate_converter('LPSECURITY_ATTRIBUTES', '" F_POINTER "')
164n/a
165n/acreate_converter('BOOL', 'i') # F_BOOL used previously (always 'i')
166n/acreate_converter('DWORD', 'k') # F_DWORD is always "k" (which is much shorter)
167n/acreate_converter('LPCTSTR', 's')
168n/acreate_converter('LPWSTR', 'u')
169n/acreate_converter('UINT', 'I') # F_UINT used previously (always 'I')
170n/a
171n/aclass HANDLE_return_converter(CReturnConverter):
172n/a type = 'HANDLE'
173n/a
174n/a def render(self, function, data):
175n/a self.declare(data)
176n/a self.err_occurred_if("_return_value == INVALID_HANDLE_VALUE", data)
177n/a data.return_conversion.append(
178n/a 'if (_return_value == NULL) {\n Py_RETURN_NONE;\n}\n')
179n/a data.return_conversion.append(
180n/a 'return_value = HANDLE_TO_PYNUM(_return_value);\n')
181n/a
182n/aclass DWORD_return_converter(CReturnConverter):
183n/a type = 'DWORD'
184n/a
185n/a def render(self, function, data):
186n/a self.declare(data)
187n/a self.err_occurred_if("_return_value == DWORD_MAX", data)
188n/a data.return_conversion.append(
189n/a 'return_value = Py_BuildValue("k", _return_value);\n')
190n/a[python start generated code]*/
191n/a/*[python end generated code: output=da39a3ee5e6b4b0d input=94819e72d2c6d558]*/
192n/a
193n/a#include "clinic/_winapi.c.h"
194n/a
195n/a/*[clinic input]
196n/a_winapi.Overlapped.GetOverlappedResult
197n/a
198n/a wait: bool
199n/a /
200n/a[clinic start generated code]*/
201n/a
202n/astatic PyObject *
203n/a_winapi_Overlapped_GetOverlappedResult_impl(OverlappedObject *self, int wait)
204n/a/*[clinic end generated code: output=bdd0c1ed6518cd03 input=194505ee8e0e3565]*/
205n/a{
206n/a BOOL res;
207n/a DWORD transferred = 0;
208n/a DWORD err;
209n/a
210n/a Py_BEGIN_ALLOW_THREADS
211n/a res = GetOverlappedResult(self->handle, &self->overlapped, &transferred,
212n/a wait != 0);
213n/a Py_END_ALLOW_THREADS
214n/a
215n/a err = res ? ERROR_SUCCESS : GetLastError();
216n/a switch (err) {
217n/a case ERROR_SUCCESS:
218n/a case ERROR_MORE_DATA:
219n/a case ERROR_OPERATION_ABORTED:
220n/a self->completed = 1;
221n/a self->pending = 0;
222n/a break;
223n/a case ERROR_IO_INCOMPLETE:
224n/a break;
225n/a default:
226n/a self->pending = 0;
227n/a return PyErr_SetExcFromWindowsErr(PyExc_IOError, err);
228n/a }
229n/a if (self->completed && self->read_buffer != NULL) {
230n/a assert(PyBytes_CheckExact(self->read_buffer));
231n/a if (transferred != PyBytes_GET_SIZE(self->read_buffer) &&
232n/a _PyBytes_Resize(&self->read_buffer, transferred))
233n/a return NULL;
234n/a }
235n/a return Py_BuildValue("II", (unsigned) transferred, (unsigned) err);
236n/a}
237n/a
238n/a/*[clinic input]
239n/a_winapi.Overlapped.getbuffer
240n/a[clinic start generated code]*/
241n/a
242n/astatic PyObject *
243n/a_winapi_Overlapped_getbuffer_impl(OverlappedObject *self)
244n/a/*[clinic end generated code: output=95a3eceefae0f748 input=347fcfd56b4ceabd]*/
245n/a{
246n/a PyObject *res;
247n/a if (!self->completed) {
248n/a PyErr_SetString(PyExc_ValueError,
249n/a "can't get read buffer before GetOverlappedResult() "
250n/a "signals the operation completed");
251n/a return NULL;
252n/a }
253n/a res = self->read_buffer ? self->read_buffer : Py_None;
254n/a Py_INCREF(res);
255n/a return res;
256n/a}
257n/a
258n/a/*[clinic input]
259n/a_winapi.Overlapped.cancel
260n/a[clinic start generated code]*/
261n/a
262n/astatic PyObject *
263n/a_winapi_Overlapped_cancel_impl(OverlappedObject *self)
264n/a/*[clinic end generated code: output=fcb9ab5df4ebdae5 input=cbf3da142290039f]*/
265n/a{
266n/a BOOL res = TRUE;
267n/a
268n/a if (self->pending) {
269n/a Py_BEGIN_ALLOW_THREADS
270n/a if (check_CancelIoEx())
271n/a res = Py_CancelIoEx(self->handle, &self->overlapped);
272n/a else
273n/a res = CancelIo(self->handle);
274n/a Py_END_ALLOW_THREADS
275n/a }
276n/a
277n/a /* CancelIoEx returns ERROR_NOT_FOUND if the I/O completed in-between */
278n/a if (!res && GetLastError() != ERROR_NOT_FOUND)
279n/a return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
280n/a self->pending = 0;
281n/a Py_RETURN_NONE;
282n/a}
283n/a
284n/astatic PyMethodDef overlapped_methods[] = {
285n/a _WINAPI_OVERLAPPED_GETOVERLAPPEDRESULT_METHODDEF
286n/a _WINAPI_OVERLAPPED_GETBUFFER_METHODDEF
287n/a _WINAPI_OVERLAPPED_CANCEL_METHODDEF
288n/a {NULL}
289n/a};
290n/a
291n/astatic PyMemberDef overlapped_members[] = {
292n/a {"event", T_HANDLE,
293n/a offsetof(OverlappedObject, overlapped) + offsetof(OVERLAPPED, hEvent),
294n/a READONLY, "overlapped event handle"},
295n/a {NULL}
296n/a};
297n/a
298n/aPyTypeObject OverlappedType = {
299n/a PyVarObject_HEAD_INIT(NULL, 0)
300n/a /* tp_name */ "_winapi.Overlapped",
301n/a /* tp_basicsize */ sizeof(OverlappedObject),
302n/a /* tp_itemsize */ 0,
303n/a /* tp_dealloc */ (destructor) overlapped_dealloc,
304n/a /* tp_print */ 0,
305n/a /* tp_getattr */ 0,
306n/a /* tp_setattr */ 0,
307n/a /* tp_reserved */ 0,
308n/a /* tp_repr */ 0,
309n/a /* tp_as_number */ 0,
310n/a /* tp_as_sequence */ 0,
311n/a /* tp_as_mapping */ 0,
312n/a /* tp_hash */ 0,
313n/a /* tp_call */ 0,
314n/a /* tp_str */ 0,
315n/a /* tp_getattro */ 0,
316n/a /* tp_setattro */ 0,
317n/a /* tp_as_buffer */ 0,
318n/a /* tp_flags */ Py_TPFLAGS_DEFAULT,
319n/a /* tp_doc */ "OVERLAPPED structure wrapper",
320n/a /* tp_traverse */ 0,
321n/a /* tp_clear */ 0,
322n/a /* tp_richcompare */ 0,
323n/a /* tp_weaklistoffset */ 0,
324n/a /* tp_iter */ 0,
325n/a /* tp_iternext */ 0,
326n/a /* tp_methods */ overlapped_methods,
327n/a /* tp_members */ overlapped_members,
328n/a /* tp_getset */ 0,
329n/a /* tp_base */ 0,
330n/a /* tp_dict */ 0,
331n/a /* tp_descr_get */ 0,
332n/a /* tp_descr_set */ 0,
333n/a /* tp_dictoffset */ 0,
334n/a /* tp_init */ 0,
335n/a /* tp_alloc */ 0,
336n/a /* tp_new */ 0,
337n/a};
338n/a
339n/astatic OverlappedObject *
340n/anew_overlapped(HANDLE handle)
341n/a{
342n/a OverlappedObject *self;
343n/a
344n/a self = PyObject_New(OverlappedObject, &OverlappedType);
345n/a if (!self)
346n/a return NULL;
347n/a self->handle = handle;
348n/a self->read_buffer = NULL;
349n/a self->pending = 0;
350n/a self->completed = 0;
351n/a memset(&self->overlapped, 0, sizeof(OVERLAPPED));
352n/a memset(&self->write_buffer, 0, sizeof(Py_buffer));
353n/a /* Manual reset, initially non-signalled */
354n/a self->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
355n/a return self;
356n/a}
357n/a
358n/a/* -------------------------------------------------------------------- */
359n/a/* windows API functions */
360n/a
361n/a/*[clinic input]
362n/a_winapi.CloseHandle
363n/a
364n/a handle: HANDLE
365n/a /
366n/a
367n/aClose handle.
368n/a[clinic start generated code]*/
369n/a
370n/astatic PyObject *
371n/a_winapi_CloseHandle_impl(PyObject *module, HANDLE handle)
372n/a/*[clinic end generated code: output=7ad37345f07bd782 input=7f0e4ac36e0352b8]*/
373n/a{
374n/a BOOL success;
375n/a
376n/a Py_BEGIN_ALLOW_THREADS
377n/a success = CloseHandle(handle);
378n/a Py_END_ALLOW_THREADS
379n/a
380n/a if (!success)
381n/a return PyErr_SetFromWindowsErr(0);
382n/a
383n/a Py_RETURN_NONE;
384n/a}
385n/a
386n/a/*[clinic input]
387n/a_winapi.ConnectNamedPipe
388n/a
389n/a handle: HANDLE
390n/a overlapped as use_overlapped: int(c_default='0') = False
391n/a[clinic start generated code]*/
392n/a
393n/astatic PyObject *
394n/a_winapi_ConnectNamedPipe_impl(PyObject *module, HANDLE handle,
395n/a int use_overlapped)
396n/a/*[clinic end generated code: output=335a0e7086800671 input=edc83da007ebf3be]*/
397n/a{
398n/a BOOL success;
399n/a OverlappedObject *overlapped = NULL;
400n/a
401n/a if (use_overlapped) {
402n/a overlapped = new_overlapped(handle);
403n/a if (!overlapped)
404n/a return NULL;
405n/a }
406n/a
407n/a Py_BEGIN_ALLOW_THREADS
408n/a success = ConnectNamedPipe(handle,
409n/a overlapped ? &overlapped->overlapped : NULL);
410n/a Py_END_ALLOW_THREADS
411n/a
412n/a if (overlapped) {
413n/a int err = GetLastError();
414n/a /* Overlapped ConnectNamedPipe never returns a success code */
415n/a assert(success == 0);
416n/a if (err == ERROR_IO_PENDING)
417n/a overlapped->pending = 1;
418n/a else if (err == ERROR_PIPE_CONNECTED)
419n/a SetEvent(overlapped->overlapped.hEvent);
420n/a else {
421n/a Py_DECREF(overlapped);
422n/a return PyErr_SetFromWindowsErr(err);
423n/a }
424n/a return (PyObject *) overlapped;
425n/a }
426n/a if (!success)
427n/a return PyErr_SetFromWindowsErr(0);
428n/a
429n/a Py_RETURN_NONE;
430n/a}
431n/a
432n/a/*[clinic input]
433n/a_winapi.CreateFile -> HANDLE
434n/a
435n/a file_name: LPCTSTR
436n/a desired_access: DWORD
437n/a share_mode: DWORD
438n/a security_attributes: LPSECURITY_ATTRIBUTES
439n/a creation_disposition: DWORD
440n/a flags_and_attributes: DWORD
441n/a template_file: HANDLE
442n/a /
443n/a[clinic start generated code]*/
444n/a
445n/astatic HANDLE
446n/a_winapi_CreateFile_impl(PyObject *module, LPCTSTR file_name,
447n/a DWORD desired_access, DWORD share_mode,
448n/a LPSECURITY_ATTRIBUTES security_attributes,
449n/a DWORD creation_disposition,
450n/a DWORD flags_and_attributes, HANDLE template_file)
451n/a/*[clinic end generated code: output=417ddcebfc5a3d53 input=6423c3e40372dbd5]*/
452n/a{
453n/a HANDLE handle;
454n/a
455n/a Py_BEGIN_ALLOW_THREADS
456n/a handle = CreateFile(file_name, desired_access,
457n/a share_mode, security_attributes,
458n/a creation_disposition,
459n/a flags_and_attributes, template_file);
460n/a Py_END_ALLOW_THREADS
461n/a
462n/a if (handle == INVALID_HANDLE_VALUE)
463n/a PyErr_SetFromWindowsErr(0);
464n/a
465n/a return handle;
466n/a}
467n/a
468n/a/*[clinic input]
469n/a_winapi.CreateJunction
470n/a
471n/a src_path: LPWSTR
472n/a dst_path: LPWSTR
473n/a /
474n/a[clinic start generated code]*/
475n/a
476n/astatic PyObject *
477n/a_winapi_CreateJunction_impl(PyObject *module, LPWSTR src_path,
478n/a LPWSTR dst_path)
479n/a/*[clinic end generated code: output=66b7eb746e1dfa25 input=8cd1f9964b6e3d36]*/
480n/a{
481n/a /* Privilege adjustment */
482n/a HANDLE token = NULL;
483n/a TOKEN_PRIVILEGES tp;
484n/a
485n/a /* Reparse data buffer */
486n/a const USHORT prefix_len = 4;
487n/a USHORT print_len = 0;
488n/a USHORT rdb_size = 0;
489n/a _Py_PREPARSE_DATA_BUFFER rdb = NULL;
490n/a
491n/a /* Junction point creation */
492n/a HANDLE junction = NULL;
493n/a DWORD ret = 0;
494n/a
495n/a if (src_path == NULL || dst_path == NULL)
496n/a return PyErr_SetFromWindowsErr(ERROR_INVALID_PARAMETER);
497n/a
498n/a if (wcsncmp(src_path, L"\\??\\", prefix_len) == 0)
499n/a return PyErr_SetFromWindowsErr(ERROR_INVALID_PARAMETER);
500n/a
501n/a /* Adjust privileges to allow rewriting directory entry as a
502n/a junction point. */
503n/a if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))
504n/a goto cleanup;
505n/a
506n/a if (!LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &tp.Privileges[0].Luid))
507n/a goto cleanup;
508n/a
509n/a tp.PrivilegeCount = 1;
510n/a tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
511n/a if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES),
512n/a NULL, NULL))
513n/a goto cleanup;
514n/a
515n/a if (GetFileAttributesW(src_path) == INVALID_FILE_ATTRIBUTES)
516n/a goto cleanup;
517n/a
518n/a /* Store the absolute link target path length in print_len. */
519n/a print_len = (USHORT)GetFullPathNameW(src_path, 0, NULL, NULL);
520n/a if (print_len == 0)
521n/a goto cleanup;
522n/a
523n/a /* NUL terminator should not be part of print_len. */
524n/a --print_len;
525n/a
526n/a /* REPARSE_DATA_BUFFER usage is heavily under-documented, especially for
527n/a junction points. Here's what I've learned along the way:
528n/a - A junction point has two components: a print name and a substitute
529n/a name. They both describe the link target, but the substitute name is
530n/a the physical target and the print name is shown in directory listings.
531n/a - The print name must be a native name, prefixed with "\??\".
532n/a - Both names are stored after each other in the same buffer (the
533n/a PathBuffer) and both must be NUL-terminated.
534n/a - There are four members defining their respective offset and length
535n/a inside PathBuffer: SubstituteNameOffset, SubstituteNameLength,
536n/a PrintNameOffset and PrintNameLength.
537n/a - The total size we need to allocate for the REPARSE_DATA_BUFFER, thus,
538n/a is the sum of:
539n/a - the fixed header size (REPARSE_DATA_BUFFER_HEADER_SIZE)
540n/a - the size of the MountPointReparseBuffer member without the PathBuffer
541n/a - the size of the prefix ("\??\") in bytes
542n/a - the size of the print name in bytes
543n/a - the size of the substitute name in bytes
544n/a - the size of two NUL terminators in bytes */
545n/a rdb_size = _Py_REPARSE_DATA_BUFFER_HEADER_SIZE +
546n/a sizeof(rdb->MountPointReparseBuffer) -
547n/a sizeof(rdb->MountPointReparseBuffer.PathBuffer) +
548n/a /* Two +1's for NUL terminators. */
549n/a (prefix_len + print_len + 1 + print_len + 1) * sizeof(WCHAR);
550n/a rdb = (_Py_PREPARSE_DATA_BUFFER)PyMem_RawMalloc(rdb_size);
551n/a if (rdb == NULL)
552n/a goto cleanup;
553n/a
554n/a memset(rdb, 0, rdb_size);
555n/a rdb->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
556n/a rdb->ReparseDataLength = rdb_size - _Py_REPARSE_DATA_BUFFER_HEADER_SIZE;
557n/a rdb->MountPointReparseBuffer.SubstituteNameOffset = 0;
558n/a rdb->MountPointReparseBuffer.SubstituteNameLength =
559n/a (prefix_len + print_len) * sizeof(WCHAR);
560n/a rdb->MountPointReparseBuffer.PrintNameOffset =
561n/a rdb->MountPointReparseBuffer.SubstituteNameLength + sizeof(WCHAR);
562n/a rdb->MountPointReparseBuffer.PrintNameLength = print_len * sizeof(WCHAR);
563n/a
564n/a /* Store the full native path of link target at the substitute name
565n/a offset (0). */
566n/a wcscpy(rdb->MountPointReparseBuffer.PathBuffer, L"\\??\\");
567n/a if (GetFullPathNameW(src_path, print_len + 1,
568n/a rdb->MountPointReparseBuffer.PathBuffer + prefix_len,
569n/a NULL) == 0)
570n/a goto cleanup;
571n/a
572n/a /* Copy everything but the native prefix to the print name offset. */
573n/a wcscpy(rdb->MountPointReparseBuffer.PathBuffer +
574n/a prefix_len + print_len + 1,
575n/a rdb->MountPointReparseBuffer.PathBuffer + prefix_len);
576n/a
577n/a /* Create a directory for the junction point. */
578n/a if (!CreateDirectoryW(dst_path, NULL))
579n/a goto cleanup;
580n/a
581n/a junction = CreateFileW(dst_path, GENERIC_READ | GENERIC_WRITE, 0, NULL,
582n/a OPEN_EXISTING,
583n/a FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL);
584n/a if (junction == INVALID_HANDLE_VALUE)
585n/a goto cleanup;
586n/a
587n/a /* Make the directory entry a junction point. */
588n/a if (!DeviceIoControl(junction, FSCTL_SET_REPARSE_POINT, rdb, rdb_size,
589n/a NULL, 0, &ret, NULL))
590n/a goto cleanup;
591n/a
592n/acleanup:
593n/a ret = GetLastError();
594n/a
595n/a CloseHandle(token);
596n/a CloseHandle(junction);
597n/a PyMem_RawFree(rdb);
598n/a
599n/a if (ret != 0)
600n/a return PyErr_SetFromWindowsErr(ret);
601n/a
602n/a Py_RETURN_NONE;
603n/a}
604n/a
605n/a/*[clinic input]
606n/a_winapi.CreateNamedPipe -> HANDLE
607n/a
608n/a name: LPCTSTR
609n/a open_mode: DWORD
610n/a pipe_mode: DWORD
611n/a max_instances: DWORD
612n/a out_buffer_size: DWORD
613n/a in_buffer_size: DWORD
614n/a default_timeout: DWORD
615n/a security_attributes: LPSECURITY_ATTRIBUTES
616n/a /
617n/a[clinic start generated code]*/
618n/a
619n/astatic HANDLE
620n/a_winapi_CreateNamedPipe_impl(PyObject *module, LPCTSTR name, DWORD open_mode,
621n/a DWORD pipe_mode, DWORD max_instances,
622n/a DWORD out_buffer_size, DWORD in_buffer_size,
623n/a DWORD default_timeout,
624n/a LPSECURITY_ATTRIBUTES security_attributes)
625n/a/*[clinic end generated code: output=80f8c07346a94fbc input=5a73530b84d8bc37]*/
626n/a{
627n/a HANDLE handle;
628n/a
629n/a Py_BEGIN_ALLOW_THREADS
630n/a handle = CreateNamedPipe(name, open_mode, pipe_mode,
631n/a max_instances, out_buffer_size,
632n/a in_buffer_size, default_timeout,
633n/a security_attributes);
634n/a Py_END_ALLOW_THREADS
635n/a
636n/a if (handle == INVALID_HANDLE_VALUE)
637n/a PyErr_SetFromWindowsErr(0);
638n/a
639n/a return handle;
640n/a}
641n/a
642n/a/*[clinic input]
643n/a_winapi.CreatePipe
644n/a
645n/a pipe_attrs: object
646n/a Ignored internally, can be None.
647n/a size: DWORD
648n/a /
649n/a
650n/aCreate an anonymous pipe.
651n/a
652n/aReturns a 2-tuple of handles, to the read and write ends of the pipe.
653n/a[clinic start generated code]*/
654n/a
655n/astatic PyObject *
656n/a_winapi_CreatePipe_impl(PyObject *module, PyObject *pipe_attrs, DWORD size)
657n/a/*[clinic end generated code: output=1c4411d8699f0925 input=c4f2cfa56ef68d90]*/
658n/a{
659n/a HANDLE read_pipe;
660n/a HANDLE write_pipe;
661n/a BOOL result;
662n/a
663n/a Py_BEGIN_ALLOW_THREADS
664n/a result = CreatePipe(&read_pipe, &write_pipe, NULL, size);
665n/a Py_END_ALLOW_THREADS
666n/a
667n/a if (! result)
668n/a return PyErr_SetFromWindowsErr(GetLastError());
669n/a
670n/a return Py_BuildValue(
671n/a "NN", HANDLE_TO_PYNUM(read_pipe), HANDLE_TO_PYNUM(write_pipe));
672n/a}
673n/a
674n/a/* helpers for createprocess */
675n/a
676n/astatic unsigned long
677n/agetulong(PyObject* obj, const char* name)
678n/a{
679n/a PyObject* value;
680n/a unsigned long ret;
681n/a
682n/a value = PyObject_GetAttrString(obj, name);
683n/a if (! value) {
684n/a PyErr_Clear(); /* FIXME: propagate error? */
685n/a return 0;
686n/a }
687n/a ret = PyLong_AsUnsignedLong(value);
688n/a Py_DECREF(value);
689n/a return ret;
690n/a}
691n/a
692n/astatic HANDLE
693n/agethandle(PyObject* obj, const char* name)
694n/a{
695n/a PyObject* value;
696n/a HANDLE ret;
697n/a
698n/a value = PyObject_GetAttrString(obj, name);
699n/a if (! value) {
700n/a PyErr_Clear(); /* FIXME: propagate error? */
701n/a return NULL;
702n/a }
703n/a if (value == Py_None)
704n/a ret = NULL;
705n/a else
706n/a ret = PYNUM_TO_HANDLE(value);
707n/a Py_DECREF(value);
708n/a return ret;
709n/a}
710n/a
711n/astatic PyObject*
712n/agetenvironment(PyObject* environment)
713n/a{
714n/a Py_ssize_t i, envsize, totalsize;
715n/a Py_UCS4 *buffer = NULL, *p, *end;
716n/a PyObject *keys, *values, *res;
717n/a
718n/a /* convert environment dictionary to windows environment string */
719n/a if (! PyMapping_Check(environment)) {
720n/a PyErr_SetString(
721n/a PyExc_TypeError, "environment must be dictionary or None");
722n/a return NULL;
723n/a }
724n/a
725n/a envsize = PyMapping_Length(environment);
726n/a
727n/a keys = PyMapping_Keys(environment);
728n/a values = PyMapping_Values(environment);
729n/a if (!keys || !values)
730n/a goto error;
731n/a
732n/a totalsize = 1; /* trailing null character */
733n/a for (i = 0; i < envsize; i++) {
734n/a PyObject* key = PyList_GET_ITEM(keys, i);
735n/a PyObject* value = PyList_GET_ITEM(values, i);
736n/a
737n/a if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) {
738n/a PyErr_SetString(PyExc_TypeError,
739n/a "environment can only contain strings");
740n/a goto error;
741n/a }
742n/a if (totalsize > PY_SSIZE_T_MAX - PyUnicode_GET_LENGTH(key) - 1) {
743n/a PyErr_SetString(PyExc_OverflowError, "environment too long");
744n/a goto error;
745n/a }
746n/a totalsize += PyUnicode_GET_LENGTH(key) + 1; /* +1 for '=' */
747n/a if (totalsize > PY_SSIZE_T_MAX - PyUnicode_GET_LENGTH(value) - 1) {
748n/a PyErr_SetString(PyExc_OverflowError, "environment too long");
749n/a goto error;
750n/a }
751n/a totalsize += PyUnicode_GET_LENGTH(value) + 1; /* +1 for '\0' */
752n/a }
753n/a
754n/a buffer = PyMem_NEW(Py_UCS4, totalsize);
755n/a if (! buffer) {
756n/a PyErr_NoMemory();
757n/a goto error;
758n/a }
759n/a p = buffer;
760n/a end = buffer + totalsize;
761n/a
762n/a for (i = 0; i < envsize; i++) {
763n/a PyObject* key = PyList_GET_ITEM(keys, i);
764n/a PyObject* value = PyList_GET_ITEM(values, i);
765n/a if (!PyUnicode_AsUCS4(key, p, end - p, 0))
766n/a goto error;
767n/a p += PyUnicode_GET_LENGTH(key);
768n/a *p++ = '=';
769n/a if (!PyUnicode_AsUCS4(value, p, end - p, 0))
770n/a goto error;
771n/a p += PyUnicode_GET_LENGTH(value);
772n/a *p++ = '\0';
773n/a }
774n/a
775n/a /* add trailing null byte */
776n/a *p++ = '\0';
777n/a assert(p == end);
778n/a
779n/a Py_XDECREF(keys);
780n/a Py_XDECREF(values);
781n/a
782n/a res = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buffer, p - buffer);
783n/a PyMem_Free(buffer);
784n/a return res;
785n/a
786n/a error:
787n/a PyMem_Free(buffer);
788n/a Py_XDECREF(keys);
789n/a Py_XDECREF(values);
790n/a return NULL;
791n/a}
792n/a
793n/a/*[clinic input]
794n/a_winapi.CreateProcess
795n/a
796n/a application_name: Py_UNICODE(accept={str, NoneType})
797n/a command_line: Py_UNICODE(accept={str, NoneType})
798n/a proc_attrs: object
799n/a Ignored internally, can be None.
800n/a thread_attrs: object
801n/a Ignored internally, can be None.
802n/a inherit_handles: BOOL
803n/a creation_flags: DWORD
804n/a env_mapping: object
805n/a current_directory: Py_UNICODE(accept={str, NoneType})
806n/a startup_info: object
807n/a /
808n/a
809n/aCreate a new process and its primary thread.
810n/a
811n/aThe return value is a tuple of the process handle, thread handle,
812n/aprocess ID, and thread ID.
813n/a[clinic start generated code]*/
814n/a
815n/astatic PyObject *
816n/a_winapi_CreateProcess_impl(PyObject *module, Py_UNICODE *application_name,
817n/a Py_UNICODE *command_line, PyObject *proc_attrs,
818n/a PyObject *thread_attrs, BOOL inherit_handles,
819n/a DWORD creation_flags, PyObject *env_mapping,
820n/a Py_UNICODE *current_directory,
821n/a PyObject *startup_info)
822n/a/*[clinic end generated code: output=4652a33aff4b0ae1 input=4a43b05038d639bb]*/
823n/a{
824n/a BOOL result;
825n/a PROCESS_INFORMATION pi;
826n/a STARTUPINFOW si;
827n/a PyObject* environment;
828n/a wchar_t *wenvironment;
829n/a
830n/a ZeroMemory(&si, sizeof(si));
831n/a si.cb = sizeof(si);
832n/a
833n/a /* note: we only support a small subset of all SI attributes */
834n/a si.dwFlags = getulong(startup_info, "dwFlags");
835n/a si.wShowWindow = (WORD)getulong(startup_info, "wShowWindow");
836n/a si.hStdInput = gethandle(startup_info, "hStdInput");
837n/a si.hStdOutput = gethandle(startup_info, "hStdOutput");
838n/a si.hStdError = gethandle(startup_info, "hStdError");
839n/a if (PyErr_Occurred())
840n/a return NULL;
841n/a
842n/a if (env_mapping != Py_None) {
843n/a environment = getenvironment(env_mapping);
844n/a if (! environment)
845n/a return NULL;
846n/a wenvironment = PyUnicode_AsUnicode(environment);
847n/a if (wenvironment == NULL)
848n/a {
849n/a Py_XDECREF(environment);
850n/a return NULL;
851n/a }
852n/a }
853n/a else {
854n/a environment = NULL;
855n/a wenvironment = NULL;
856n/a }
857n/a
858n/a Py_BEGIN_ALLOW_THREADS
859n/a result = CreateProcessW(application_name,
860n/a command_line,
861n/a NULL,
862n/a NULL,
863n/a inherit_handles,
864n/a creation_flags | CREATE_UNICODE_ENVIRONMENT,
865n/a wenvironment,
866n/a current_directory,
867n/a &si,
868n/a &pi);
869n/a Py_END_ALLOW_THREADS
870n/a
871n/a Py_XDECREF(environment);
872n/a
873n/a if (! result)
874n/a return PyErr_SetFromWindowsErr(GetLastError());
875n/a
876n/a return Py_BuildValue("NNkk",
877n/a HANDLE_TO_PYNUM(pi.hProcess),
878n/a HANDLE_TO_PYNUM(pi.hThread),
879n/a pi.dwProcessId,
880n/a pi.dwThreadId);
881n/a}
882n/a
883n/a/*[clinic input]
884n/a_winapi.DuplicateHandle -> HANDLE
885n/a
886n/a source_process_handle: HANDLE
887n/a source_handle: HANDLE
888n/a target_process_handle: HANDLE
889n/a desired_access: DWORD
890n/a inherit_handle: BOOL
891n/a options: DWORD = 0
892n/a /
893n/a
894n/aReturn a duplicate handle object.
895n/a
896n/aThe duplicate handle refers to the same object as the original
897n/ahandle. Therefore, any changes to the object are reflected
898n/athrough both handles.
899n/a[clinic start generated code]*/
900n/a
901n/astatic HANDLE
902n/a_winapi_DuplicateHandle_impl(PyObject *module, HANDLE source_process_handle,
903n/a HANDLE source_handle,
904n/a HANDLE target_process_handle,
905n/a DWORD desired_access, BOOL inherit_handle,
906n/a DWORD options)
907n/a/*[clinic end generated code: output=ad9711397b5dcd4e input=b933e3f2356a8c12]*/
908n/a{
909n/a HANDLE target_handle;
910n/a BOOL result;
911n/a
912n/a Py_BEGIN_ALLOW_THREADS
913n/a result = DuplicateHandle(
914n/a source_process_handle,
915n/a source_handle,
916n/a target_process_handle,
917n/a &target_handle,
918n/a desired_access,
919n/a inherit_handle,
920n/a options
921n/a );
922n/a Py_END_ALLOW_THREADS
923n/a
924n/a if (! result) {
925n/a PyErr_SetFromWindowsErr(GetLastError());
926n/a return INVALID_HANDLE_VALUE;
927n/a }
928n/a
929n/a return target_handle;
930n/a}
931n/a
932n/a/*[clinic input]
933n/a_winapi.ExitProcess
934n/a
935n/a ExitCode: UINT
936n/a /
937n/a
938n/a[clinic start generated code]*/
939n/a
940n/astatic PyObject *
941n/a_winapi_ExitProcess_impl(PyObject *module, UINT ExitCode)
942n/a/*[clinic end generated code: output=a387deb651175301 input=4f05466a9406c558]*/
943n/a{
944n/a #if defined(Py_DEBUG)
945n/a SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOALIGNMENTFAULTEXCEPT|
946n/a SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX);
947n/a _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
948n/a #endif
949n/a
950n/a ExitProcess(ExitCode);
951n/a
952n/a return NULL;
953n/a}
954n/a
955n/a/*[clinic input]
956n/a_winapi.GetCurrentProcess -> HANDLE
957n/a
958n/aReturn a handle object for the current process.
959n/a[clinic start generated code]*/
960n/a
961n/astatic HANDLE
962n/a_winapi_GetCurrentProcess_impl(PyObject *module)
963n/a/*[clinic end generated code: output=ddeb4dd2ffadf344 input=b213403fd4b96b41]*/
964n/a{
965n/a return GetCurrentProcess();
966n/a}
967n/a
968n/a/*[clinic input]
969n/a_winapi.GetExitCodeProcess -> DWORD
970n/a
971n/a process: HANDLE
972n/a /
973n/a
974n/aReturn the termination status of the specified process.
975n/a[clinic start generated code]*/
976n/a
977n/astatic DWORD
978n/a_winapi_GetExitCodeProcess_impl(PyObject *module, HANDLE process)
979n/a/*[clinic end generated code: output=b4620bdf2bccf36b input=61b6bfc7dc2ee374]*/
980n/a{
981n/a DWORD exit_code;
982n/a BOOL result;
983n/a
984n/a result = GetExitCodeProcess(process, &exit_code);
985n/a
986n/a if (! result) {
987n/a PyErr_SetFromWindowsErr(GetLastError());
988n/a exit_code = DWORD_MAX;
989n/a }
990n/a
991n/a return exit_code;
992n/a}
993n/a
994n/a/*[clinic input]
995n/a_winapi.GetLastError -> DWORD
996n/a[clinic start generated code]*/
997n/a
998n/astatic DWORD
999n/a_winapi_GetLastError_impl(PyObject *module)
1000n/a/*[clinic end generated code: output=8585b827cb1a92c5 input=62d47fb9bce038ba]*/
1001n/a{
1002n/a return GetLastError();
1003n/a}
1004n/a
1005n/a/*[clinic input]
1006n/a_winapi.GetModuleFileName
1007n/a
1008n/a module_handle: HMODULE
1009n/a /
1010n/a
1011n/aReturn the fully-qualified path for the file that contains module.
1012n/a
1013n/aThe module must have been loaded by the current process.
1014n/a
1015n/aThe module parameter should be a handle to the loaded module
1016n/awhose path is being requested. If this parameter is 0,
1017n/aGetModuleFileName retrieves the path of the executable file
1018n/aof the current process.
1019n/a[clinic start generated code]*/
1020n/a
1021n/astatic PyObject *
1022n/a_winapi_GetModuleFileName_impl(PyObject *module, HMODULE module_handle)
1023n/a/*[clinic end generated code: output=85b4b728c5160306 input=6d66ff7deca5d11f]*/
1024n/a{
1025n/a BOOL result;
1026n/a WCHAR filename[MAX_PATH];
1027n/a
1028n/a result = GetModuleFileNameW(module_handle, filename, MAX_PATH);
1029n/a filename[MAX_PATH-1] = '\0';
1030n/a
1031n/a if (! result)
1032n/a return PyErr_SetFromWindowsErr(GetLastError());
1033n/a
1034n/a return PyUnicode_FromWideChar(filename, wcslen(filename));
1035n/a}
1036n/a
1037n/a/*[clinic input]
1038n/a_winapi.GetStdHandle -> HANDLE
1039n/a
1040n/a std_handle: DWORD
1041n/a One of STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, or STD_ERROR_HANDLE.
1042n/a /
1043n/a
1044n/aReturn a handle to the specified standard device.
1045n/a
1046n/aThe integer associated with the handle object is returned.
1047n/a[clinic start generated code]*/
1048n/a
1049n/astatic HANDLE
1050n/a_winapi_GetStdHandle_impl(PyObject *module, DWORD std_handle)
1051n/a/*[clinic end generated code: output=0e613001e73ab614 input=07016b06a2fc8826]*/
1052n/a{
1053n/a HANDLE handle;
1054n/a
1055n/a Py_BEGIN_ALLOW_THREADS
1056n/a handle = GetStdHandle(std_handle);
1057n/a Py_END_ALLOW_THREADS
1058n/a
1059n/a if (handle == INVALID_HANDLE_VALUE)
1060n/a PyErr_SetFromWindowsErr(GetLastError());
1061n/a
1062n/a return handle;
1063n/a}
1064n/a
1065n/a/*[clinic input]
1066n/a_winapi.GetVersion -> long
1067n/a
1068n/aReturn the version number of the current operating system.
1069n/a[clinic start generated code]*/
1070n/a
1071n/astatic long
1072n/a_winapi_GetVersion_impl(PyObject *module)
1073n/a/*[clinic end generated code: output=e41f0db5a3b82682 input=e21dff8d0baeded2]*/
1074n/a/* Disable deprecation warnings about GetVersionEx as the result is
1075n/a being passed straight through to the caller, who is responsible for
1076n/a using it correctly. */
1077n/a#pragma warning(push)
1078n/a#pragma warning(disable:4996)
1079n/a
1080n/a{
1081n/a return GetVersion();
1082n/a}
1083n/a
1084n/a#pragma warning(pop)
1085n/a
1086n/a/*[clinic input]
1087n/a_winapi.OpenProcess -> HANDLE
1088n/a
1089n/a desired_access: DWORD
1090n/a inherit_handle: BOOL
1091n/a process_id: DWORD
1092n/a /
1093n/a[clinic start generated code]*/
1094n/a
1095n/astatic HANDLE
1096n/a_winapi_OpenProcess_impl(PyObject *module, DWORD desired_access,
1097n/a BOOL inherit_handle, DWORD process_id)
1098n/a/*[clinic end generated code: output=b42b6b81ea5a0fc3 input=ec98c4cf4ea2ec36]*/
1099n/a{
1100n/a HANDLE handle;
1101n/a
1102n/a handle = OpenProcess(desired_access, inherit_handle, process_id);
1103n/a if (handle == NULL) {
1104n/a PyErr_SetFromWindowsErr(0);
1105n/a handle = INVALID_HANDLE_VALUE;
1106n/a }
1107n/a
1108n/a return handle;
1109n/a}
1110n/a
1111n/a/*[clinic input]
1112n/a_winapi.PeekNamedPipe
1113n/a
1114n/a handle: HANDLE
1115n/a size: int = 0
1116n/a /
1117n/a[clinic start generated code]*/
1118n/a
1119n/astatic PyObject *
1120n/a_winapi_PeekNamedPipe_impl(PyObject *module, HANDLE handle, int size)
1121n/a/*[clinic end generated code: output=d0c3e29e49d323dd input=c7aa53bfbce69d70]*/
1122n/a{
1123n/a PyObject *buf = NULL;
1124n/a DWORD nread, navail, nleft;
1125n/a BOOL ret;
1126n/a
1127n/a if (size < 0) {
1128n/a PyErr_SetString(PyExc_ValueError, "negative size");
1129n/a return NULL;
1130n/a }
1131n/a
1132n/a if (size) {
1133n/a buf = PyBytes_FromStringAndSize(NULL, size);
1134n/a if (!buf)
1135n/a return NULL;
1136n/a Py_BEGIN_ALLOW_THREADS
1137n/a ret = PeekNamedPipe(handle, PyBytes_AS_STRING(buf), size, &nread,
1138n/a &navail, &nleft);
1139n/a Py_END_ALLOW_THREADS
1140n/a if (!ret) {
1141n/a Py_DECREF(buf);
1142n/a return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
1143n/a }
1144n/a if (_PyBytes_Resize(&buf, nread))
1145n/a return NULL;
1146n/a return Py_BuildValue("Nii", buf, navail, nleft);
1147n/a }
1148n/a else {
1149n/a Py_BEGIN_ALLOW_THREADS
1150n/a ret = PeekNamedPipe(handle, NULL, 0, NULL, &navail, &nleft);
1151n/a Py_END_ALLOW_THREADS
1152n/a if (!ret) {
1153n/a return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
1154n/a }
1155n/a return Py_BuildValue("ii", navail, nleft);
1156n/a }
1157n/a}
1158n/a
1159n/a/*[clinic input]
1160n/a_winapi.ReadFile
1161n/a
1162n/a handle: HANDLE
1163n/a size: int
1164n/a overlapped as use_overlapped: int(c_default='0') = False
1165n/a[clinic start generated code]*/
1166n/a
1167n/astatic PyObject *
1168n/a_winapi_ReadFile_impl(PyObject *module, HANDLE handle, int size,
1169n/a int use_overlapped)
1170n/a/*[clinic end generated code: output=492029ca98161d84 input=8dd810194e86ac7d]*/
1171n/a{
1172n/a DWORD nread;
1173n/a PyObject *buf;
1174n/a BOOL ret;
1175n/a DWORD err;
1176n/a OverlappedObject *overlapped = NULL;
1177n/a
1178n/a buf = PyBytes_FromStringAndSize(NULL, size);
1179n/a if (!buf)
1180n/a return NULL;
1181n/a if (use_overlapped) {
1182n/a overlapped = new_overlapped(handle);
1183n/a if (!overlapped) {
1184n/a Py_DECREF(buf);
1185n/a return NULL;
1186n/a }
1187n/a /* Steals reference to buf */
1188n/a overlapped->read_buffer = buf;
1189n/a }
1190n/a
1191n/a Py_BEGIN_ALLOW_THREADS
1192n/a ret = ReadFile(handle, PyBytes_AS_STRING(buf), size, &nread,
1193n/a overlapped ? &overlapped->overlapped : NULL);
1194n/a Py_END_ALLOW_THREADS
1195n/a
1196n/a err = ret ? 0 : GetLastError();
1197n/a
1198n/a if (overlapped) {
1199n/a if (!ret) {
1200n/a if (err == ERROR_IO_PENDING)
1201n/a overlapped->pending = 1;
1202n/a else if (err != ERROR_MORE_DATA) {
1203n/a Py_DECREF(overlapped);
1204n/a return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
1205n/a }
1206n/a }
1207n/a return Py_BuildValue("NI", (PyObject *) overlapped, err);
1208n/a }
1209n/a
1210n/a if (!ret && err != ERROR_MORE_DATA) {
1211n/a Py_DECREF(buf);
1212n/a return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
1213n/a }
1214n/a if (_PyBytes_Resize(&buf, nread))
1215n/a return NULL;
1216n/a return Py_BuildValue("NI", buf, err);
1217n/a}
1218n/a
1219n/a/*[clinic input]
1220n/a_winapi.SetNamedPipeHandleState
1221n/a
1222n/a named_pipe: HANDLE
1223n/a mode: object
1224n/a max_collection_count: object
1225n/a collect_data_timeout: object
1226n/a /
1227n/a[clinic start generated code]*/
1228n/a
1229n/astatic PyObject *
1230n/a_winapi_SetNamedPipeHandleState_impl(PyObject *module, HANDLE named_pipe,
1231n/a PyObject *mode,
1232n/a PyObject *max_collection_count,
1233n/a PyObject *collect_data_timeout)
1234n/a/*[clinic end generated code: output=f2129d222cbfa095 input=9142d72163d0faa6]*/
1235n/a{
1236n/a PyObject *oArgs[3] = {mode, max_collection_count, collect_data_timeout};
1237n/a DWORD dwArgs[3], *pArgs[3] = {NULL, NULL, NULL};
1238n/a int i;
1239n/a
1240n/a PyErr_Clear();
1241n/a
1242n/a for (i = 0 ; i < 3 ; i++) {
1243n/a if (oArgs[i] != Py_None) {
1244n/a dwArgs[i] = PyLong_AsUnsignedLongMask(oArgs[i]);
1245n/a if (PyErr_Occurred())
1246n/a return NULL;
1247n/a pArgs[i] = &dwArgs[i];
1248n/a }
1249n/a }
1250n/a
1251n/a if (!SetNamedPipeHandleState(named_pipe, pArgs[0], pArgs[1], pArgs[2]))
1252n/a return PyErr_SetFromWindowsErr(0);
1253n/a
1254n/a Py_RETURN_NONE;
1255n/a}
1256n/a
1257n/a
1258n/a/*[clinic input]
1259n/a_winapi.TerminateProcess
1260n/a
1261n/a handle: HANDLE
1262n/a exit_code: UINT
1263n/a /
1264n/a
1265n/aTerminate the specified process and all of its threads.
1266n/a[clinic start generated code]*/
1267n/a
1268n/astatic PyObject *
1269n/a_winapi_TerminateProcess_impl(PyObject *module, HANDLE handle,
1270n/a UINT exit_code)
1271n/a/*[clinic end generated code: output=f4e99ac3f0b1f34a input=d6bc0aa1ee3bb4df]*/
1272n/a{
1273n/a BOOL result;
1274n/a
1275n/a result = TerminateProcess(handle, exit_code);
1276n/a
1277n/a if (! result)
1278n/a return PyErr_SetFromWindowsErr(GetLastError());
1279n/a
1280n/a Py_RETURN_NONE;
1281n/a}
1282n/a
1283n/a/*[clinic input]
1284n/a_winapi.WaitNamedPipe
1285n/a
1286n/a name: LPCTSTR
1287n/a timeout: DWORD
1288n/a /
1289n/a[clinic start generated code]*/
1290n/a
1291n/astatic PyObject *
1292n/a_winapi_WaitNamedPipe_impl(PyObject *module, LPCTSTR name, DWORD timeout)
1293n/a/*[clinic end generated code: output=c2866f4439b1fe38 input=36fc781291b1862c]*/
1294n/a{
1295n/a BOOL success;
1296n/a
1297n/a Py_BEGIN_ALLOW_THREADS
1298n/a success = WaitNamedPipe(name, timeout);
1299n/a Py_END_ALLOW_THREADS
1300n/a
1301n/a if (!success)
1302n/a return PyErr_SetFromWindowsErr(0);
1303n/a
1304n/a Py_RETURN_NONE;
1305n/a}
1306n/a
1307n/a/*[clinic input]
1308n/a_winapi.WaitForMultipleObjects
1309n/a
1310n/a handle_seq: object
1311n/a wait_flag: BOOL
1312n/a milliseconds: DWORD(c_default='INFINITE') = _winapi.INFINITE
1313n/a /
1314n/a[clinic start generated code]*/
1315n/a
1316n/astatic PyObject *
1317n/a_winapi_WaitForMultipleObjects_impl(PyObject *module, PyObject *handle_seq,
1318n/a BOOL wait_flag, DWORD milliseconds)
1319n/a/*[clinic end generated code: output=295e3f00b8e45899 input=36f76ca057cd28a0]*/
1320n/a{
1321n/a DWORD result;
1322n/a HANDLE handles[MAXIMUM_WAIT_OBJECTS];
1323n/a HANDLE sigint_event = NULL;
1324n/a Py_ssize_t nhandles, i;
1325n/a
1326n/a if (!PySequence_Check(handle_seq)) {
1327n/a PyErr_Format(PyExc_TypeError,
1328n/a "sequence type expected, got '%s'",
1329n/a Py_TYPE(handle_seq)->tp_name);
1330n/a return NULL;
1331n/a }
1332n/a nhandles = PySequence_Length(handle_seq);
1333n/a if (nhandles == -1)
1334n/a return NULL;
1335n/a if (nhandles < 0 || nhandles >= MAXIMUM_WAIT_OBJECTS - 1) {
1336n/a PyErr_Format(PyExc_ValueError,
1337n/a "need at most %zd handles, got a sequence of length %zd",
1338n/a MAXIMUM_WAIT_OBJECTS - 1, nhandles);
1339n/a return NULL;
1340n/a }
1341n/a for (i = 0; i < nhandles; i++) {
1342n/a HANDLE h;
1343n/a PyObject *v = PySequence_GetItem(handle_seq, i);
1344n/a if (v == NULL)
1345n/a return NULL;
1346n/a if (!PyArg_Parse(v, F_HANDLE, &h)) {
1347n/a Py_DECREF(v);
1348n/a return NULL;
1349n/a }
1350n/a handles[i] = h;
1351n/a Py_DECREF(v);
1352n/a }
1353n/a /* If this is the main thread then make the wait interruptible
1354n/a by Ctrl-C unless we are waiting for *all* handles */
1355n/a if (!wait_flag && _PyOS_IsMainThread()) {
1356n/a sigint_event = _PyOS_SigintEvent();
1357n/a assert(sigint_event != NULL);
1358n/a handles[nhandles++] = sigint_event;
1359n/a }
1360n/a
1361n/a Py_BEGIN_ALLOW_THREADS
1362n/a if (sigint_event != NULL)
1363n/a ResetEvent(sigint_event);
1364n/a result = WaitForMultipleObjects((DWORD) nhandles, handles,
1365n/a wait_flag, milliseconds);
1366n/a Py_END_ALLOW_THREADS
1367n/a
1368n/a if (result == WAIT_FAILED)
1369n/a return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
1370n/a else if (sigint_event != NULL && result == WAIT_OBJECT_0 + nhandles - 1) {
1371n/a errno = EINTR;
1372n/a return PyErr_SetFromErrno(PyExc_IOError);
1373n/a }
1374n/a
1375n/a return PyLong_FromLong((int) result);
1376n/a}
1377n/a
1378n/a/*[clinic input]
1379n/a_winapi.WaitForSingleObject -> long
1380n/a
1381n/a handle: HANDLE
1382n/a milliseconds: DWORD
1383n/a /
1384n/a
1385n/aWait for a single object.
1386n/a
1387n/aWait until the specified object is in the signaled state or
1388n/athe time-out interval elapses. The timeout value is specified
1389n/ain milliseconds.
1390n/a[clinic start generated code]*/
1391n/a
1392n/astatic long
1393n/a_winapi_WaitForSingleObject_impl(PyObject *module, HANDLE handle,
1394n/a DWORD milliseconds)
1395n/a/*[clinic end generated code: output=3c4715d8f1b39859 input=443d1ab076edc7b1]*/
1396n/a{
1397n/a DWORD result;
1398n/a
1399n/a Py_BEGIN_ALLOW_THREADS
1400n/a result = WaitForSingleObject(handle, milliseconds);
1401n/a Py_END_ALLOW_THREADS
1402n/a
1403n/a if (result == WAIT_FAILED) {
1404n/a PyErr_SetFromWindowsErr(GetLastError());
1405n/a return -1;
1406n/a }
1407n/a
1408n/a return result;
1409n/a}
1410n/a
1411n/a/*[clinic input]
1412n/a_winapi.WriteFile
1413n/a
1414n/a handle: HANDLE
1415n/a buffer: object
1416n/a overlapped as use_overlapped: int(c_default='0') = False
1417n/a[clinic start generated code]*/
1418n/a
1419n/astatic PyObject *
1420n/a_winapi_WriteFile_impl(PyObject *module, HANDLE handle, PyObject *buffer,
1421n/a int use_overlapped)
1422n/a/*[clinic end generated code: output=2ca80f6bf3fa92e3 input=51846a5af52053fd]*/
1423n/a{
1424n/a Py_buffer _buf, *buf;
1425n/a DWORD len, written;
1426n/a BOOL ret;
1427n/a DWORD err;
1428n/a OverlappedObject *overlapped = NULL;
1429n/a
1430n/a if (use_overlapped) {
1431n/a overlapped = new_overlapped(handle);
1432n/a if (!overlapped)
1433n/a return NULL;
1434n/a buf = &overlapped->write_buffer;
1435n/a }
1436n/a else
1437n/a buf = &_buf;
1438n/a
1439n/a if (!PyArg_Parse(buffer, "y*", buf)) {
1440n/a Py_XDECREF(overlapped);
1441n/a return NULL;
1442n/a }
1443n/a
1444n/a Py_BEGIN_ALLOW_THREADS
1445n/a len = (DWORD)Py_MIN(buf->len, DWORD_MAX);
1446n/a ret = WriteFile(handle, buf->buf, len, &written,
1447n/a overlapped ? &overlapped->overlapped : NULL);
1448n/a Py_END_ALLOW_THREADS
1449n/a
1450n/a err = ret ? 0 : GetLastError();
1451n/a
1452n/a if (overlapped) {
1453n/a if (!ret) {
1454n/a if (err == ERROR_IO_PENDING)
1455n/a overlapped->pending = 1;
1456n/a else {
1457n/a Py_DECREF(overlapped);
1458n/a return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
1459n/a }
1460n/a }
1461n/a return Py_BuildValue("NI", (PyObject *) overlapped, err);
1462n/a }
1463n/a
1464n/a PyBuffer_Release(buf);
1465n/a if (!ret)
1466n/a return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
1467n/a return Py_BuildValue("II", written, err);
1468n/a}
1469n/a
1470n/a
1471n/astatic PyMethodDef winapi_functions[] = {
1472n/a _WINAPI_CLOSEHANDLE_METHODDEF
1473n/a _WINAPI_CONNECTNAMEDPIPE_METHODDEF
1474n/a _WINAPI_CREATEFILE_METHODDEF
1475n/a _WINAPI_CREATENAMEDPIPE_METHODDEF
1476n/a _WINAPI_CREATEPIPE_METHODDEF
1477n/a _WINAPI_CREATEPROCESS_METHODDEF
1478n/a _WINAPI_CREATEJUNCTION_METHODDEF
1479n/a _WINAPI_DUPLICATEHANDLE_METHODDEF
1480n/a _WINAPI_EXITPROCESS_METHODDEF
1481n/a _WINAPI_GETCURRENTPROCESS_METHODDEF
1482n/a _WINAPI_GETEXITCODEPROCESS_METHODDEF
1483n/a _WINAPI_GETLASTERROR_METHODDEF
1484n/a _WINAPI_GETMODULEFILENAME_METHODDEF
1485n/a _WINAPI_GETSTDHANDLE_METHODDEF
1486n/a _WINAPI_GETVERSION_METHODDEF
1487n/a _WINAPI_OPENPROCESS_METHODDEF
1488n/a _WINAPI_PEEKNAMEDPIPE_METHODDEF
1489n/a _WINAPI_READFILE_METHODDEF
1490n/a _WINAPI_SETNAMEDPIPEHANDLESTATE_METHODDEF
1491n/a _WINAPI_TERMINATEPROCESS_METHODDEF
1492n/a _WINAPI_WAITNAMEDPIPE_METHODDEF
1493n/a _WINAPI_WAITFORMULTIPLEOBJECTS_METHODDEF
1494n/a _WINAPI_WAITFORSINGLEOBJECT_METHODDEF
1495n/a _WINAPI_WRITEFILE_METHODDEF
1496n/a {NULL, NULL}
1497n/a};
1498n/a
1499n/astatic struct PyModuleDef winapi_module = {
1500n/a PyModuleDef_HEAD_INIT,
1501n/a "_winapi",
1502n/a NULL,
1503n/a -1,
1504n/a winapi_functions,
1505n/a NULL,
1506n/a NULL,
1507n/a NULL,
1508n/a NULL
1509n/a};
1510n/a
1511n/a#define WINAPI_CONSTANT(fmt, con) \
1512n/a PyDict_SetItemString(d, #con, Py_BuildValue(fmt, con))
1513n/a
1514n/aPyMODINIT_FUNC
1515n/aPyInit__winapi(void)
1516n/a{
1517n/a PyObject *d;
1518n/a PyObject *m;
1519n/a
1520n/a if (PyType_Ready(&OverlappedType) < 0)
1521n/a return NULL;
1522n/a
1523n/a m = PyModule_Create(&winapi_module);
1524n/a if (m == NULL)
1525n/a return NULL;
1526n/a d = PyModule_GetDict(m);
1527n/a
1528n/a PyDict_SetItemString(d, "Overlapped", (PyObject *) &OverlappedType);
1529n/a
1530n/a /* constants */
1531n/a WINAPI_CONSTANT(F_DWORD, CREATE_NEW_CONSOLE);
1532n/a WINAPI_CONSTANT(F_DWORD, CREATE_NEW_PROCESS_GROUP);
1533n/a WINAPI_CONSTANT(F_DWORD, DUPLICATE_SAME_ACCESS);
1534n/a WINAPI_CONSTANT(F_DWORD, DUPLICATE_CLOSE_SOURCE);
1535n/a WINAPI_CONSTANT(F_DWORD, ERROR_ALREADY_EXISTS);
1536n/a WINAPI_CONSTANT(F_DWORD, ERROR_BROKEN_PIPE);
1537n/a WINAPI_CONSTANT(F_DWORD, ERROR_IO_PENDING);
1538n/a WINAPI_CONSTANT(F_DWORD, ERROR_MORE_DATA);
1539n/a WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED);
1540n/a WINAPI_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES);
1541n/a WINAPI_CONSTANT(F_DWORD, ERROR_MORE_DATA);
1542n/a WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED);
1543n/a WINAPI_CONSTANT(F_DWORD, ERROR_NO_DATA);
1544n/a WINAPI_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES);
1545n/a WINAPI_CONSTANT(F_DWORD, ERROR_OPERATION_ABORTED);
1546n/a WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_BUSY);
1547n/a WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_CONNECTED);
1548n/a WINAPI_CONSTANT(F_DWORD, ERROR_SEM_TIMEOUT);
1549n/a WINAPI_CONSTANT(F_DWORD, FILE_FLAG_FIRST_PIPE_INSTANCE);
1550n/a WINAPI_CONSTANT(F_DWORD, FILE_FLAG_OVERLAPPED);
1551n/a WINAPI_CONSTANT(F_DWORD, FILE_GENERIC_READ);
1552n/a WINAPI_CONSTANT(F_DWORD, FILE_GENERIC_WRITE);
1553n/a WINAPI_CONSTANT(F_DWORD, GENERIC_READ);
1554n/a WINAPI_CONSTANT(F_DWORD, GENERIC_WRITE);
1555n/a WINAPI_CONSTANT(F_DWORD, INFINITE);
1556n/a WINAPI_CONSTANT(F_DWORD, NMPWAIT_WAIT_FOREVER);
1557n/a WINAPI_CONSTANT(F_DWORD, OPEN_EXISTING);
1558n/a WINAPI_CONSTANT(F_DWORD, PIPE_ACCESS_DUPLEX);
1559n/a WINAPI_CONSTANT(F_DWORD, PIPE_ACCESS_INBOUND);
1560n/a WINAPI_CONSTANT(F_DWORD, PIPE_READMODE_MESSAGE);
1561n/a WINAPI_CONSTANT(F_DWORD, PIPE_TYPE_MESSAGE);
1562n/a WINAPI_CONSTANT(F_DWORD, PIPE_UNLIMITED_INSTANCES);
1563n/a WINAPI_CONSTANT(F_DWORD, PIPE_WAIT);
1564n/a WINAPI_CONSTANT(F_DWORD, PROCESS_ALL_ACCESS);
1565n/a WINAPI_CONSTANT(F_DWORD, PROCESS_DUP_HANDLE);
1566n/a WINAPI_CONSTANT(F_DWORD, STARTF_USESHOWWINDOW);
1567n/a WINAPI_CONSTANT(F_DWORD, STARTF_USESTDHANDLES);
1568n/a WINAPI_CONSTANT(F_DWORD, STD_INPUT_HANDLE);
1569n/a WINAPI_CONSTANT(F_DWORD, STD_OUTPUT_HANDLE);
1570n/a WINAPI_CONSTANT(F_DWORD, STD_ERROR_HANDLE);
1571n/a WINAPI_CONSTANT(F_DWORD, STILL_ACTIVE);
1572n/a WINAPI_CONSTANT(F_DWORD, SW_HIDE);
1573n/a WINAPI_CONSTANT(F_DWORD, WAIT_OBJECT_0);
1574n/a WINAPI_CONSTANT(F_DWORD, WAIT_ABANDONED_0);
1575n/a WINAPI_CONSTANT(F_DWORD, WAIT_TIMEOUT);
1576n/a
1577n/a WINAPI_CONSTANT("i", NULL);
1578n/a
1579n/a return m;
1580n/a}