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