1 /* 2 * Support for overlapped IO 3 * 4 * Some code borrowed from Modules/_winapi.c of CPython 5 */ 6 7 /* XXX check overflow and DWORD <-> Py_ssize_t conversions 8 Check itemsize */ 9 10 #include "Python.h" 11 #include "structmember.h" 12 13 #define WINDOWS_LEAN_AND_MEAN 14 #include <winsock2.h> 15 #include <ws2tcpip.h> 16 #include <mswsock.h> 17 18 #if defined(MS_WIN32) && !defined(MS_WIN64) 19 # define F_POINTER "k" 20 # define T_POINTER T_ULONG 21 #else 22 # define F_POINTER "K" 23 # define T_POINTER T_ULONGLONG 24 #endif 25 26 /* Compatibility with Python 3.3 */ 27 #if PY_VERSION_HEX < 0x03040000 28 # define PyMem_RawMalloc PyMem_Malloc 29 # define PyMem_RawFree PyMem_Free 30 #endif 31 32 #define F_HANDLE F_POINTER 33 #define F_ULONG_PTR F_POINTER 34 #define F_DWORD "k" 35 #define F_BOOL "i" 36 #define F_UINT "I" 37 38 #define T_HANDLE T_POINTER 39 40 enum {TYPE_NONE, TYPE_NOT_STARTED, TYPE_READ, TYPE_READINTO, TYPE_WRITE, 41 TYPE_ACCEPT, TYPE_CONNECT, TYPE_DISCONNECT, TYPE_CONNECT_NAMED_PIPE, 42 TYPE_WAIT_NAMED_PIPE_AND_CONNECT, TYPE_TRANSMIT_FILE}; 43 44 typedef struct { 45 PyObject_HEAD 46 OVERLAPPED overlapped; 47 /* For convenience, we store the file handle too */ 48 HANDLE handle; 49 /* Error returned by last method call */ 50 DWORD error; 51 /* Type of operation */ 52 DWORD type; 53 union { 54 /* Buffer allocated by us: TYPE_READ and TYPE_ACCEPT */ 55 PyObject *allocated_buffer; 56 /* Buffer passed by the user: TYPE_WRITE and TYPE_READINTO */ 57 Py_buffer user_buffer; 58 }; 59 } OverlappedObject; 60 61 /* 62 * Map Windows error codes to subclasses of OSError 63 */ 64 65 static PyObject * 66 SetFromWindowsErr(DWORD err) 67 { 68 PyObject *exception_type; 69 70 if (err == 0) 71 err = GetLastError(); 72 switch (err) { 73 case ERROR_CONNECTION_REFUSED: 74 exception_type = PyExc_ConnectionRefusedError; 75 break; 76 case ERROR_CONNECTION_ABORTED: 77 exception_type = PyExc_ConnectionAbortedError; 78 break; 79 default: 80 exception_type = PyExc_OSError; 81 } 82 return PyErr_SetExcFromWindowsErr(exception_type, err); 83 } 84 85 /* 86 * Some functions should be loaded at runtime 87 */ 88 89 static LPFN_ACCEPTEX Py_AcceptEx = NULL; 90 static LPFN_CONNECTEX Py_ConnectEx = NULL; 91 static LPFN_DISCONNECTEX Py_DisconnectEx = NULL; 92 static LPFN_TRANSMITFILE Py_TransmitFile = NULL; 93 static BOOL (CALLBACK *Py_CancelIoEx)(HANDLE, LPOVERLAPPED) = NULL; 94 95 #define GET_WSA_POINTER(s, x) \ 96 (SOCKET_ERROR != WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, \ 97 &Guid##x, sizeof(Guid##x), &Py_##x, \ 98 sizeof(Py_##x), &dwBytes, NULL, NULL)) 99 100 static int 101 initialize_function_pointers(void) 102 { 103 GUID GuidAcceptEx = WSAID_ACCEPTEX; 104 GUID GuidConnectEx = WSAID_CONNECTEX; 105 GUID GuidDisconnectEx = WSAID_DISCONNECTEX; 106 GUID GuidTransmitFile = WSAID_TRANSMITFILE; 107 HINSTANCE hKernel32; 108 SOCKET s; 109 DWORD dwBytes; 110 111 s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 112 if (s == INVALID_SOCKET) { 113 SetFromWindowsErr(WSAGetLastError()); 114 return -1; 115 } 116 117 if (!GET_WSA_POINTER(s, AcceptEx) || 118 !GET_WSA_POINTER(s, ConnectEx) || 119 !GET_WSA_POINTER(s, DisconnectEx) || 120 !GET_WSA_POINTER(s, TransmitFile)) 121 { 122 closesocket(s); 123 SetFromWindowsErr(WSAGetLastError()); 124 return -1; 125 } 126 127 closesocket(s); 128 129 /* On WinXP we will have Py_CancelIoEx == NULL */ 130 hKernel32 = GetModuleHandle("KERNEL32"); 131 *(FARPROC *)&Py_CancelIoEx = GetProcAddress(hKernel32, "CancelIoEx"); 132 return 0; 133 } 134 135 /* 136 * Completion port stuff 137 */ 138 139 PyDoc_STRVAR( 140 CreateIoCompletionPort_doc, 141 "CreateIoCompletionPort(handle, port, key, concurrency) -> port\n\n" 142 "Create a completion port or register a handle with a port."); 143 144 static PyObject * 145 overlapped_CreateIoCompletionPort(PyObject *self, PyObject *args) 146 { 147 HANDLE FileHandle; 148 HANDLE ExistingCompletionPort; 149 ULONG_PTR CompletionKey; 150 DWORD NumberOfConcurrentThreads; 151 HANDLE ret; 152 153 if (!PyArg_ParseTuple(args, F_HANDLE F_HANDLE F_ULONG_PTR F_DWORD, 154 &FileHandle, &ExistingCompletionPort, &CompletionKey, 155 &NumberOfConcurrentThreads)) 156 return NULL; 157 158 Py_BEGIN_ALLOW_THREADS 159 ret = CreateIoCompletionPort(FileHandle, ExistingCompletionPort, 160 CompletionKey, NumberOfConcurrentThreads); 161 Py_END_ALLOW_THREADS 162 163 if (ret == NULL) 164 return SetFromWindowsErr(0); 165 return Py_BuildValue(F_HANDLE, ret); 166 } 167 168 PyDoc_STRVAR( 169 GetQueuedCompletionStatus_doc, 170 "GetQueuedCompletionStatus(port, msecs) -> (err, bytes, key, address)\n\n" 171 "Get a message from completion port. Wait for up to msecs milliseconds."); 172 173 static PyObject * 174 overlapped_GetQueuedCompletionStatus(PyObject *self, PyObject *args) 175 { 176 HANDLE CompletionPort = NULL; 177 DWORD NumberOfBytes = 0; 178 ULONG_PTR CompletionKey = 0; 179 OVERLAPPED *Overlapped = NULL; 180 DWORD Milliseconds; 181 DWORD err; 182 BOOL ret; 183 184 if (!PyArg_ParseTuple(args, F_HANDLE F_DWORD, 185 &CompletionPort, &Milliseconds)) 186 return NULL; 187 188 Py_BEGIN_ALLOW_THREADS 189 ret = GetQueuedCompletionStatus(CompletionPort, &NumberOfBytes, 190 &CompletionKey, &Overlapped, Milliseconds); 191 Py_END_ALLOW_THREADS 192 193 err = ret ? ERROR_SUCCESS : GetLastError(); 194 if (Overlapped == NULL) { 195 if (err == WAIT_TIMEOUT) 196 Py_RETURN_NONE; 197 else 198 return SetFromWindowsErr(err); 199 } 200 return Py_BuildValue(F_DWORD F_DWORD F_ULONG_PTR F_POINTER, 201 err, NumberOfBytes, CompletionKey, Overlapped); 202 } 203 204 PyDoc_STRVAR( 205 PostQueuedCompletionStatus_doc, 206 "PostQueuedCompletionStatus(port, bytes, key, address) -> None\n\n" 207 "Post a message to completion port."); 208 209 static PyObject * 210 overlapped_PostQueuedCompletionStatus(PyObject *self, PyObject *args) 211 { 212 HANDLE CompletionPort; 213 DWORD NumberOfBytes; 214 ULONG_PTR CompletionKey; 215 OVERLAPPED *Overlapped; 216 BOOL ret; 217 218 if (!PyArg_ParseTuple(args, F_HANDLE F_DWORD F_ULONG_PTR F_POINTER, 219 &CompletionPort, &NumberOfBytes, &CompletionKey, 220 &Overlapped)) 221 return NULL; 222 223 Py_BEGIN_ALLOW_THREADS 224 ret = PostQueuedCompletionStatus(CompletionPort, NumberOfBytes, 225 CompletionKey, Overlapped); 226 Py_END_ALLOW_THREADS 227 228 if (!ret) 229 return SetFromWindowsErr(0); 230 Py_RETURN_NONE; 231 } 232 233 /* 234 * Wait for a handle 235 */ 236 237 struct PostCallbackData { 238 HANDLE CompletionPort; 239 LPOVERLAPPED Overlapped; 240 }; 241 242 static VOID CALLBACK 243 PostToQueueCallback(PVOID lpParameter, BOOL TimerOrWaitFired) 244 { 245 struct PostCallbackData *p = (struct PostCallbackData*) lpParameter; 246 247 PostQueuedCompletionStatus(p->CompletionPort, TimerOrWaitFired, 248 0, p->Overlapped); 249 /* ignore possible error! */ 250 PyMem_RawFree(p); 251 } 252 253 PyDoc_STRVAR( 254 RegisterWaitWithQueue_doc, 255 "RegisterWaitWithQueue(Object, CompletionPort, Overlapped, Timeout)\n" 256 " -> WaitHandle\n\n" 257 "Register wait for Object; when complete CompletionPort is notified.\n"); 258 259 static PyObject * 260 overlapped_RegisterWaitWithQueue(PyObject *self, PyObject *args) 261 { 262 HANDLE NewWaitObject; 263 HANDLE Object; 264 ULONG Milliseconds; 265 struct PostCallbackData data, *pdata; 266 267 if (!PyArg_ParseTuple(args, F_HANDLE F_HANDLE F_POINTER F_DWORD, 268 &Object, 269 &data.CompletionPort, 270 &data.Overlapped, 271 &Milliseconds)) 272 return NULL; 273 274 /* Use PyMem_RawMalloc() rather than PyMem_Malloc(), since 275 PostToQueueCallback() will call PyMem_Free() from a new C thread 276 which doesn't hold the GIL. */ 277 pdata = PyMem_RawMalloc(sizeof(struct PostCallbackData)); 278 if (pdata == NULL) 279 return SetFromWindowsErr(0); 280 281 *pdata = data; 282 283 if (!RegisterWaitForSingleObject( 284 &NewWaitObject, Object, (WAITORTIMERCALLBACK)PostToQueueCallback, 285 pdata, Milliseconds, 286 WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE)) 287 { 288 PyMem_RawFree(pdata); 289 return SetFromWindowsErr(0); 290 } 291 292 return Py_BuildValue(F_HANDLE, NewWaitObject); 293 } 294 295 PyDoc_STRVAR( 296 UnregisterWait_doc, 297 "UnregisterWait(WaitHandle) -> None\n\n" 298 "Unregister wait handle.\n"); 299 300 static PyObject * 301 overlapped_UnregisterWait(PyObject *self, PyObject *args) 302 { 303 HANDLE WaitHandle; 304 BOOL ret; 305 306 if (!PyArg_ParseTuple(args, F_HANDLE, &WaitHandle)) 307 return NULL; 308 309 Py_BEGIN_ALLOW_THREADS 310 ret = UnregisterWait(WaitHandle); 311 Py_END_ALLOW_THREADS 312 313 if (!ret) 314 return SetFromWindowsErr(0); 315 Py_RETURN_NONE; 316 } 317 318 PyDoc_STRVAR( 319 UnregisterWaitEx_doc, 320 "UnregisterWaitEx(WaitHandle, Event) -> None\n\n" 321 "Unregister wait handle.\n"); 322 323 static PyObject * 324 overlapped_UnregisterWaitEx(PyObject *self, PyObject *args) 325 { 326 HANDLE WaitHandle, Event; 327 BOOL ret; 328 329 if (!PyArg_ParseTuple(args, F_HANDLE F_HANDLE, &WaitHandle, &Event)) 330 return NULL; 331 332 Py_BEGIN_ALLOW_THREADS 333 ret = UnregisterWaitEx(WaitHandle, Event); 334 Py_END_ALLOW_THREADS 335 336 if (!ret) 337 return SetFromWindowsErr(0); 338 Py_RETURN_NONE; 339 } 340 341 /* 342 * Event functions -- currently only used by tests 343 */ 344 345 PyDoc_STRVAR( 346 CreateEvent_doc, 347 "CreateEvent(EventAttributes, ManualReset, InitialState, Name)" 348 " -> Handle\n\n" 349 "Create an event. EventAttributes must be None.\n"); 350 351 static PyObject * 352 overlapped_CreateEvent(PyObject *self, PyObject *args) 353 { 354 PyObject *EventAttributes; 355 BOOL ManualReset; 356 BOOL InitialState; 357 Py_UNICODE *Name; 358 HANDLE Event; 359 360 if (!PyArg_ParseTuple(args, "O" F_BOOL F_BOOL "Z", 361 &EventAttributes, &ManualReset, 362 &InitialState, &Name)) 363 return NULL; 364 365 if (EventAttributes != Py_None) { 366 PyErr_SetString(PyExc_ValueError, "EventAttributes must be None"); 367 return NULL; 368 } 369 370 Py_BEGIN_ALLOW_THREADS 371 Event = CreateEventW(NULL, ManualReset, InitialState, Name); 372 Py_END_ALLOW_THREADS 373 374 if (Event == NULL) 375 return SetFromWindowsErr(0); 376 return Py_BuildValue(F_HANDLE, Event); 377 } 378 379 PyDoc_STRVAR( 380 SetEvent_doc, 381 "SetEvent(Handle) -> None\n\n" 382 "Set event.\n"); 383 384 static PyObject * 385 overlapped_SetEvent(PyObject *self, PyObject *args) 386 { 387 HANDLE Handle; 388 BOOL ret; 389 390 if (!PyArg_ParseTuple(args, F_HANDLE, &Handle)) 391 return NULL; 392 393 Py_BEGIN_ALLOW_THREADS 394 ret = SetEvent(Handle); 395 Py_END_ALLOW_THREADS 396 397 if (!ret) 398 return SetFromWindowsErr(0); 399 Py_RETURN_NONE; 400 } 401 402 PyDoc_STRVAR( 403 ResetEvent_doc, 404 "ResetEvent(Handle) -> None\n\n" 405 "Reset event.\n"); 406 407 static PyObject * 408 overlapped_ResetEvent(PyObject *self, PyObject *args) 409 { 410 HANDLE Handle; 411 BOOL ret; 412 413 if (!PyArg_ParseTuple(args, F_HANDLE, &Handle)) 414 return NULL; 415 416 Py_BEGIN_ALLOW_THREADS 417 ret = ResetEvent(Handle); 418 Py_END_ALLOW_THREADS 419 420 if (!ret) 421 return SetFromWindowsErr(0); 422 Py_RETURN_NONE; 423 } 424 425 /* 426 * Bind socket handle to local port without doing slow getaddrinfo() 427 */ 428 429 PyDoc_STRVAR( 430 BindLocal_doc, 431 "BindLocal(handle, family) -> None\n\n" 432 "Bind a socket handle to an arbitrary local port.\n" 433 "family should AF_INET or AF_INET6.\n"); 434 435 static PyObject * 436 overlapped_BindLocal(PyObject *self, PyObject *args) 437 { 438 SOCKET Socket; 439 int Family; 440 BOOL ret; 441 442 if (!PyArg_ParseTuple(args, F_HANDLE "i", &Socket, &Family)) 443 return NULL; 444 445 if (Family == AF_INET) { 446 struct sockaddr_in addr; 447 memset(&addr, 0, sizeof(addr)); 448 addr.sin_family = AF_INET; 449 addr.sin_port = 0; 450 addr.sin_addr.S_un.S_addr = INADDR_ANY; 451 ret = bind(Socket, (SOCKADDR*)&addr, sizeof(addr)) != SOCKET_ERROR; 452 } else if (Family == AF_INET6) { 453 struct sockaddr_in6 addr; 454 memset(&addr, 0, sizeof(addr)); 455 addr.sin6_family = AF_INET6; 456 addr.sin6_port = 0; 457 addr.sin6_addr = in6addr_any; 458 ret = bind(Socket, (SOCKADDR*)&addr, sizeof(addr)) != SOCKET_ERROR; 459 } else { 460 PyErr_SetString(PyExc_ValueError, "expected tuple of length 2 or 4"); 461 return NULL; 462 } 463 464 if (!ret) 465 return SetFromWindowsErr(WSAGetLastError()); 466 Py_RETURN_NONE; 467 } 468 469 /* 470 * Windows equivalent of os.strerror() -- compare _ctypes/callproc.c 471 */ 472 473 PyDoc_STRVAR( 474 FormatMessage_doc, 475 "FormatMessage(error_code) -> error_message\n\n" 476 "Return error message for an error code."); 477 478 static PyObject * 479 overlapped_FormatMessage(PyObject *ignore, PyObject *args) 480 { 481 DWORD code, n; 482 WCHAR *lpMsgBuf; 483 PyObject *res; 484 485 if (!PyArg_ParseTuple(args, F_DWORD, &code)) 486 return NULL; 487 488 n = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | 489 FORMAT_MESSAGE_FROM_SYSTEM, 490 NULL, 491 code, 492 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 493 (LPWSTR) &lpMsgBuf, 494 0, 495 NULL); 496 if (n) { 497 while (iswspace(lpMsgBuf[n-1])) 498 --n; 499 lpMsgBuf[n] = L'\0'; 500 res = Py_BuildValue("u", lpMsgBuf); 501 } else { 502 res = PyUnicode_FromFormat("unknown error code %u", code); 503 } 504 LocalFree(lpMsgBuf); 505 return res; 506 } 507 508 509 /* 510 * Mark operation as completed - used when reading produces ERROR_BROKEN_PIPE 511 */ 512 513 static void 514 mark_as_completed(OVERLAPPED *ov) 515 { 516 ov->Internal = 0; 517 if (ov->hEvent != NULL) 518 SetEvent(ov->hEvent); 519 } 520 521 /* 522 * A Python object wrapping an OVERLAPPED structure and other useful data 523 * for overlapped I/O 524 */ 525 526 PyDoc_STRVAR( 527 Overlapped_doc, 528 "Overlapped object"); 529 530 static PyObject * 531 Overlapped_new(PyTypeObject *type, PyObject *args, PyObject *kwds) 532 { 533 OverlappedObject *self; 534 HANDLE event = INVALID_HANDLE_VALUE; 535 static char *kwlist[] = {"event", NULL}; 536 537 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|" F_HANDLE, kwlist, &event)) 538 return NULL; 539 540 if (event == INVALID_HANDLE_VALUE) { 541 event = CreateEvent(NULL, TRUE, FALSE, NULL); 542 if (event == NULL) 543 return SetFromWindowsErr(0); 544 } 545 546 self = PyObject_New(OverlappedObject, type); 547 if (self == NULL) { 548 if (event != NULL) 549 CloseHandle(event); 550 return NULL; 551 } 552 553 self->handle = NULL; 554 self->error = 0; 555 self->type = TYPE_NONE; 556 self->allocated_buffer = NULL; 557 memset(&self->overlapped, 0, sizeof(OVERLAPPED)); 558 memset(&self->user_buffer, 0, sizeof(Py_buffer)); 559 if (event) 560 self->overlapped.hEvent = event; 561 return (PyObject *)self; 562 } 563 564 565 /* Note (bpo-32710): OverlappedType.tp_clear is not defined to not release 566 buffers while overlapped are still running, to prevent a crash. */ 567 static int 568 Overlapped_clear(OverlappedObject *self) 569 { 570 switch (self->type) { 571 case TYPE_READ: 572 case TYPE_ACCEPT: 573 Py_CLEAR(self->allocated_buffer); 574 break; 575 case TYPE_WRITE: 576 case TYPE_READINTO: 577 if (self->user_buffer.obj) { 578 PyBuffer_Release(&self->user_buffer); 579 } 580 break; 581 } 582 self->type = TYPE_NOT_STARTED; 583 return 0; 584 } 585 586 static void 587 Overlapped_dealloc(OverlappedObject *self) 588 { 589 DWORD bytes; 590 DWORD olderr = GetLastError(); 591 BOOL wait = FALSE; 592 BOOL ret; 593 594 if (!HasOverlappedIoCompleted(&self->overlapped) && 595 self->type != TYPE_NOT_STARTED) 596 { 597 if (Py_CancelIoEx && Py_CancelIoEx(self->handle, &self->overlapped)) 598 wait = TRUE; 599 600 Py_BEGIN_ALLOW_THREADS 601 ret = GetOverlappedResult(self->handle, &self->overlapped, 602 &bytes, wait); 603 Py_END_ALLOW_THREADS 604 605 switch (ret ? ERROR_SUCCESS : GetLastError()) { 606 case ERROR_SUCCESS: 607 case ERROR_NOT_FOUND: 608 case ERROR_OPERATION_ABORTED: 609 break; 610 default: 611 PyErr_Format( 612 PyExc_RuntimeError, 613 "%R still has pending operation at " 614 "deallocation, the process may crash", self); 615 PyErr_WriteUnraisable(NULL); 616 } 617 } 618 619 if (self->overlapped.hEvent != NULL) { 620 CloseHandle(self->overlapped.hEvent); 621 } 622 623 Overlapped_clear(self); 624 PyObject_Del(self); 625 SetLastError(olderr); 626 } 627 628 PyDoc_STRVAR( 629 Overlapped_cancel_doc, 630 "cancel() -> None\n\n" 631 "Cancel overlapped operation"); 632 633 static PyObject * 634 Overlapped_cancel(OverlappedObject *self) 635 { 636 BOOL ret = TRUE; 637 638 if (self->type == TYPE_NOT_STARTED 639 || self->type == TYPE_WAIT_NAMED_PIPE_AND_CONNECT) 640 Py_RETURN_NONE; 641 642 if (!HasOverlappedIoCompleted(&self->overlapped)) { 643 Py_BEGIN_ALLOW_THREADS 644 if (Py_CancelIoEx) 645 ret = Py_CancelIoEx(self->handle, &self->overlapped); 646 else 647 ret = CancelIo(self->handle); 648 Py_END_ALLOW_THREADS 649 } 650 651 /* CancelIoEx returns ERROR_NOT_FOUND if the I/O completed in-between */ 652 if (!ret && GetLastError() != ERROR_NOT_FOUND) 653 return SetFromWindowsErr(0); 654 Py_RETURN_NONE; 655 } 656 657 PyDoc_STRVAR( 658 Overlapped_getresult_doc, 659 "getresult(wait=False) -> result\n\n" 660 "Retrieve result of operation. If wait is true then it blocks\n" 661 "until the operation is finished. If wait is false and the\n" 662 "operation is still pending then an error is raised."); 663 664 static PyObject * 665 Overlapped_getresult(OverlappedObject *self, PyObject *args) 666 { 667 BOOL wait = FALSE; 668 DWORD transferred = 0; 669 BOOL ret; 670 DWORD err; 671 672 if (!PyArg_ParseTuple(args, "|" F_BOOL, &wait)) 673 return NULL; 674 675 if (self->type == TYPE_NONE) { 676 PyErr_SetString(PyExc_ValueError, "operation not yet attempted"); 677 return NULL; 678 } 679 680 if (self->type == TYPE_NOT_STARTED) { 681 PyErr_SetString(PyExc_ValueError, "operation failed to start"); 682 return NULL; 683 } 684 685 Py_BEGIN_ALLOW_THREADS 686 ret = GetOverlappedResult(self->handle, &self->overlapped, &transferred, 687 wait); 688 Py_END_ALLOW_THREADS 689 690 self->error = err = ret ? ERROR_SUCCESS : GetLastError(); 691 switch (err) { 692 case ERROR_SUCCESS: 693 case ERROR_MORE_DATA: 694 break; 695 case ERROR_BROKEN_PIPE: 696 if (self->type == TYPE_READ || self->type == TYPE_READINTO) 697 break; 698 /* fall through */ 699 default: 700 return SetFromWindowsErr(err); 701 } 702 703 switch (self->type) { 704 case TYPE_READ: 705 assert(PyBytes_CheckExact(self->allocated_buffer)); 706 if (transferred != PyBytes_GET_SIZE(self->allocated_buffer) && 707 _PyBytes_Resize(&self->allocated_buffer, transferred)) 708 return NULL; 709 Py_INCREF(self->allocated_buffer); 710 return self->allocated_buffer; 711 default: 712 return PyLong_FromUnsignedLong((unsigned long) transferred); 713 } 714 } 715 716 static PyObject * 717 do_ReadFile(OverlappedObject *self, HANDLE handle, 718 char *bufstart, DWORD buflen) 719 { 720 DWORD nread; 721 int ret; 722 DWORD err; 723 724 Py_BEGIN_ALLOW_THREADS 725 ret = ReadFile(handle, bufstart, buflen, &nread, 726 &self->overlapped); 727 Py_END_ALLOW_THREADS 728 729 self->error = err = ret ? ERROR_SUCCESS : GetLastError(); 730 switch (err) { 731 case ERROR_BROKEN_PIPE: 732 mark_as_completed(&self->overlapped); 733 return SetFromWindowsErr(err); 734 case ERROR_SUCCESS: 735 case ERROR_MORE_DATA: 736 case ERROR_IO_PENDING: 737 Py_RETURN_NONE; 738 default: 739 Overlapped_clear(self); 740 return SetFromWindowsErr(err); 741 } 742 } 743 744 PyDoc_STRVAR( 745 Overlapped_ReadFile_doc, 746 "ReadFile(handle, size) -> Overlapped[message]\n\n" 747 "Start overlapped read"); 748 749 static PyObject * 750 Overlapped_ReadFile(OverlappedObject *self, PyObject *args) 751 { 752 HANDLE handle; 753 DWORD size; 754 PyObject *buf; 755 756 if (!PyArg_ParseTuple(args, F_HANDLE F_DWORD, &handle, &size)) 757 return NULL; 758 759 if (self->type != TYPE_NONE) { 760 PyErr_SetString(PyExc_ValueError, "operation already attempted"); 761 return NULL; 762 } 763 764 #if SIZEOF_SIZE_T <= SIZEOF_LONG 765 size = Py_MIN(size, (DWORD)PY_SSIZE_T_MAX); 766 #endif 767 buf = PyBytes_FromStringAndSize(NULL, Py_MAX(size, 1)); 768 if (buf == NULL) 769 return NULL; 770 771 self->type = TYPE_READ; 772 self->handle = handle; 773 self->allocated_buffer = buf; 774 775 return do_ReadFile(self, handle, PyBytes_AS_STRING(buf), size); 776 } 777 778 PyDoc_STRVAR( 779 Overlapped_ReadFileInto_doc, 780 "ReadFileInto(handle, buf) -> Overlapped[bytes_transferred]\n\n" 781 "Start overlapped receive"); 782 783 static PyObject * 784 Overlapped_ReadFileInto(OverlappedObject *self, PyObject *args) 785 { 786 HANDLE handle; 787 PyObject *bufobj; 788 789 if (!PyArg_ParseTuple(args, F_HANDLE "O", &handle, &bufobj)) 790 return NULL; 791 792 if (self->type != TYPE_NONE) { 793 PyErr_SetString(PyExc_ValueError, "operation already attempted"); 794 return NULL; 795 } 796 797 if (!PyArg_Parse(bufobj, "y*", &self->user_buffer)) 798 return NULL; 799 800 #if SIZEOF_SIZE_T > SIZEOF_LONG 801 if (self->user_buffer.len > (Py_ssize_t)ULONG_MAX) { 802 PyBuffer_Release(&self->user_buffer); 803 PyErr_SetString(PyExc_ValueError, "buffer too large"); 804 return NULL; 805 } 806 #endif 807 808 self->type = TYPE_READINTO; 809 self->handle = handle; 810 811 return do_ReadFile(self, handle, self->user_buffer.buf, 812 (DWORD)self->user_buffer.len); 813 } 814 815 static PyObject * 816 do_WSARecv(OverlappedObject *self, HANDLE handle, 817 char *bufstart, DWORD buflen, DWORD flags) 818 { 819 DWORD nread; 820 WSABUF wsabuf; 821 int ret; 822 DWORD err; 823 824 wsabuf.buf = bufstart; 825 wsabuf.len = buflen; 826 827 Py_BEGIN_ALLOW_THREADS 828 ret = WSARecv((SOCKET)handle, &wsabuf, 1, &nread, &flags, 829 &self->overlapped, NULL); 830 Py_END_ALLOW_THREADS 831 832 self->error = err = (ret < 0 ? WSAGetLastError() : ERROR_SUCCESS); 833 switch (err) { 834 case ERROR_BROKEN_PIPE: 835 mark_as_completed(&self->overlapped); 836 return SetFromWindowsErr(err); 837 case ERROR_SUCCESS: 838 case ERROR_MORE_DATA: 839 case ERROR_IO_PENDING: 840 Py_RETURN_NONE; 841 default: 842 Overlapped_clear(self); 843 return SetFromWindowsErr(err); 844 } 845 } 846 847 PyDoc_STRVAR( 848 Overlapped_WSARecv_doc, 849 "RecvFile(handle, size, flags) -> Overlapped[message]\n\n" 850 "Start overlapped receive"); 851 852 static PyObject * 853 Overlapped_WSARecv(OverlappedObject *self, PyObject *args) 854 { 855 HANDLE handle; 856 DWORD size; 857 DWORD flags = 0; 858 PyObject *buf; 859 860 if (!PyArg_ParseTuple(args, F_HANDLE F_DWORD "|" F_DWORD, 861 &handle, &size, &flags)) 862 return NULL; 863 864 if (self->type != TYPE_NONE) { 865 PyErr_SetString(PyExc_ValueError, "operation already attempted"); 866 return NULL; 867 } 868 869 #if SIZEOF_SIZE_T <= SIZEOF_LONG 870 size = Py_MIN(size, (DWORD)PY_SSIZE_T_MAX); 871 #endif 872 buf = PyBytes_FromStringAndSize(NULL, Py_MAX(size, 1)); 873 if (buf == NULL) 874 return NULL; 875 876 self->type = TYPE_READ; 877 self->handle = handle; 878 self->allocated_buffer = buf; 879 880 return do_WSARecv(self, handle, PyBytes_AS_STRING(buf), size, flags); 881 } 882 883 PyDoc_STRVAR( 884 Overlapped_WSARecvInto_doc, 885 "WSARecvInto(handle, buf, flags) -> Overlapped[bytes_transferred]\n\n" 886 "Start overlapped receive"); 887 888 static PyObject * 889 Overlapped_WSARecvInto(OverlappedObject *self, PyObject *args) 890 { 891 HANDLE handle; 892 PyObject *bufobj; 893 DWORD flags; 894 895 if (!PyArg_ParseTuple(args, F_HANDLE "O" F_DWORD, 896 &handle, &bufobj, &flags)) 897 return NULL; 898 899 if (self->type != TYPE_NONE) { 900 PyErr_SetString(PyExc_ValueError, "operation already attempted"); 901 return NULL; 902 } 903 904 if (!PyArg_Parse(bufobj, "y*", &self->user_buffer)) 905 return NULL; 906 907 #if SIZEOF_SIZE_T > SIZEOF_LONG 908 if (self->user_buffer.len > (Py_ssize_t)ULONG_MAX) { 909 PyBuffer_Release(&self->user_buffer); 910 PyErr_SetString(PyExc_ValueError, "buffer too large"); 911 return NULL; 912 } 913 #endif 914 915 self->type = TYPE_READINTO; 916 self->handle = handle; 917 918 return do_WSARecv(self, handle, self->user_buffer.buf, 919 (DWORD)self->user_buffer.len, flags); 920 } 921 922 PyDoc_STRVAR( 923 Overlapped_WriteFile_doc, 924 "WriteFile(handle, buf) -> Overlapped[bytes_transferred]\n\n" 925 "Start overlapped write"); 926 927 static PyObject * 928 Overlapped_WriteFile(OverlappedObject *self, PyObject *args) 929 { 930 HANDLE handle; 931 PyObject *bufobj; 932 DWORD written; 933 BOOL ret; 934 DWORD err; 935 936 if (!PyArg_ParseTuple(args, F_HANDLE "O", &handle, &bufobj)) 937 return NULL; 938 939 if (self->type != TYPE_NONE) { 940 PyErr_SetString(PyExc_ValueError, "operation already attempted"); 941 return NULL; 942 } 943 944 if (!PyArg_Parse(bufobj, "y*", &self->user_buffer)) 945 return NULL; 946 947 #if SIZEOF_SIZE_T > SIZEOF_LONG 948 if (self->user_buffer.len > (Py_ssize_t)ULONG_MAX) { 949 PyBuffer_Release(&self->user_buffer); 950 PyErr_SetString(PyExc_ValueError, "buffer too large"); 951 return NULL; 952 } 953 #endif 954 955 self->type = TYPE_WRITE; 956 self->handle = handle; 957 958 Py_BEGIN_ALLOW_THREADS 959 ret = WriteFile(handle, self->user_buffer.buf, 960 (DWORD)self->user_buffer.len, 961 &written, &self->overlapped); 962 Py_END_ALLOW_THREADS 963 964 self->error = err = ret ? ERROR_SUCCESS : GetLastError(); 965 switch (err) { 966 case ERROR_SUCCESS: 967 case ERROR_IO_PENDING: 968 Py_RETURN_NONE; 969 default: 970 Overlapped_clear(self); 971 return SetFromWindowsErr(err); 972 } 973 } 974 975 PyDoc_STRVAR( 976 Overlapped_WSASend_doc, 977 "WSASend(handle, buf, flags) -> Overlapped[bytes_transferred]\n\n" 978 "Start overlapped send"); 979 980 static PyObject * 981 Overlapped_WSASend(OverlappedObject *self, PyObject *args) 982 { 983 HANDLE handle; 984 PyObject *bufobj; 985 DWORD flags; 986 DWORD written; 987 WSABUF wsabuf; 988 int ret; 989 DWORD err; 990 991 if (!PyArg_ParseTuple(args, F_HANDLE "O" F_DWORD, 992 &handle, &bufobj, &flags)) 993 return NULL; 994 995 if (self->type != TYPE_NONE) { 996 PyErr_SetString(PyExc_ValueError, "operation already attempted"); 997 return NULL; 998 } 999 1000 if (!PyArg_Parse(bufobj, "y*", &self->user_buffer)) 1001 return NULL; 1002 1003 #if SIZEOF_SIZE_T > SIZEOF_LONG 1004 if (self->user_buffer.len > (Py_ssize_t)ULONG_MAX) { 1005 PyBuffer_Release(&self->user_buffer); 1006 PyErr_SetString(PyExc_ValueError, "buffer too large"); 1007 return NULL; 1008 } 1009 #endif 1010 1011 self->type = TYPE_WRITE; 1012 self->handle = handle; 1013 wsabuf.len = (DWORD)self->user_buffer.len; 1014 wsabuf.buf = self->user_buffer.buf; 1015 1016 Py_BEGIN_ALLOW_THREADS 1017 ret = WSASend((SOCKET)handle, &wsabuf, 1, &written, flags, 1018 &self->overlapped, NULL); 1019 Py_END_ALLOW_THREADS 1020 1021 self->error = err = (ret < 0 ? WSAGetLastError() : ERROR_SUCCESS); 1022 switch (err) { 1023 case ERROR_SUCCESS: 1024 case ERROR_IO_PENDING: 1025 Py_RETURN_NONE; 1026 default: 1027 Overlapped_clear(self); 1028 return SetFromWindowsErr(err); 1029 } 1030 } 1031 1032 PyDoc_STRVAR( 1033 Overlapped_AcceptEx_doc, 1034 "AcceptEx(listen_handle, accept_handle) -> Overlapped[address_as_bytes]\n\n" 1035 "Start overlapped wait for client to connect"); 1036 1037 static PyObject * 1038 Overlapped_AcceptEx(OverlappedObject *self, PyObject *args) 1039 { 1040 SOCKET ListenSocket; 1041 SOCKET AcceptSocket; 1042 DWORD BytesReceived; 1043 DWORD size; 1044 PyObject *buf; 1045 BOOL ret; 1046 DWORD err; 1047 1048 if (!PyArg_ParseTuple(args, F_HANDLE F_HANDLE, 1049 &ListenSocket, &AcceptSocket)) 1050 return NULL; 1051 1052 if (self->type != TYPE_NONE) { 1053 PyErr_SetString(PyExc_ValueError, "operation already attempted"); 1054 return NULL; 1055 } 1056 1057 size = sizeof(struct sockaddr_in6) + 16; 1058 buf = PyBytes_FromStringAndSize(NULL, size*2); 1059 if (!buf) 1060 return NULL; 1061 1062 self->type = TYPE_ACCEPT; 1063 self->handle = (HANDLE)ListenSocket; 1064 self->allocated_buffer = buf; 1065 1066 Py_BEGIN_ALLOW_THREADS 1067 ret = Py_AcceptEx(ListenSocket, AcceptSocket, PyBytes_AS_STRING(buf), 1068 0, size, size, &BytesReceived, &self->overlapped); 1069 Py_END_ALLOW_THREADS 1070 1071 self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError(); 1072 switch (err) { 1073 case ERROR_SUCCESS: 1074 case ERROR_IO_PENDING: 1075 Py_RETURN_NONE; 1076 default: 1077 Overlapped_clear(self); 1078 return SetFromWindowsErr(err); 1079 } 1080 } 1081 1082 1083 static int 1084 parse_address(PyObject *obj, SOCKADDR *Address, int Length) 1085 { 1086 Py_UNICODE *Host; 1087 unsigned short Port; 1088 unsigned long FlowInfo; 1089 unsigned long ScopeId; 1090 1091 memset(Address, 0, Length); 1092 1093 if (PyArg_ParseTuple(obj, "uH", &Host, &Port)) 1094 { 1095 Address->sa_family = AF_INET; 1096 if (WSAStringToAddressW(Host, AF_INET, NULL, Address, &Length) < 0) { 1097 SetFromWindowsErr(WSAGetLastError()); 1098 return -1; 1099 } 1100 ((SOCKADDR_IN*)Address)->sin_port = htons(Port); 1101 return Length; 1102 } 1103 else if (PyArg_ParseTuple(obj, 1104 "uHkk;ConnectEx(): illegal address_as_bytes " 1105 "argument", &Host, &Port, &FlowInfo, &ScopeId)) 1106 { 1107 PyErr_Clear(); 1108 Address->sa_family = AF_INET6; 1109 if (WSAStringToAddressW(Host, AF_INET6, NULL, Address, &Length) < 0) { 1110 SetFromWindowsErr(WSAGetLastError()); 1111 return -1; 1112 } 1113 ((SOCKADDR_IN6*)Address)->sin6_port = htons(Port); 1114 ((SOCKADDR_IN6*)Address)->sin6_flowinfo = FlowInfo; 1115 ((SOCKADDR_IN6*)Address)->sin6_scope_id = ScopeId; 1116 return Length; 1117 } 1118 1119 return -1; 1120 } 1121 1122 1123 PyDoc_STRVAR( 1124 Overlapped_ConnectEx_doc, 1125 "ConnectEx(client_handle, address_as_bytes) -> Overlapped[None]\n\n" 1126 "Start overlapped connect. client_handle should be unbound."); 1127 1128 static PyObject * 1129 Overlapped_ConnectEx(OverlappedObject *self, PyObject *args) 1130 { 1131 SOCKET ConnectSocket; 1132 PyObject *AddressObj; 1133 char AddressBuf[sizeof(struct sockaddr_in6)]; 1134 SOCKADDR *Address = (SOCKADDR*)AddressBuf; 1135 int Length; 1136 BOOL ret; 1137 DWORD err; 1138 1139 if (!PyArg_ParseTuple(args, F_HANDLE "O!:ConnectEx", 1140 &ConnectSocket, &PyTuple_Type, &AddressObj)) 1141 { 1142 return NULL; 1143 } 1144 1145 if (self->type != TYPE_NONE) { 1146 PyErr_SetString(PyExc_ValueError, "operation already attempted"); 1147 return NULL; 1148 } 1149 1150 Length = sizeof(AddressBuf); 1151 Length = parse_address(AddressObj, Address, Length); 1152 if (Length < 0) 1153 return NULL; 1154 1155 self->type = TYPE_CONNECT; 1156 self->handle = (HANDLE)ConnectSocket; 1157 1158 Py_BEGIN_ALLOW_THREADS 1159 ret = Py_ConnectEx(ConnectSocket, Address, Length, 1160 NULL, 0, NULL, &self->overlapped); 1161 Py_END_ALLOW_THREADS 1162 1163 self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError(); 1164 switch (err) { 1165 case ERROR_SUCCESS: 1166 case ERROR_IO_PENDING: 1167 Py_RETURN_NONE; 1168 default: 1169 Overlapped_clear(self); 1170 return SetFromWindowsErr(err); 1171 } 1172 } 1173 1174 PyDoc_STRVAR( 1175 Overlapped_DisconnectEx_doc, 1176 "DisconnectEx(handle, flags) -> Overlapped[None]\n\n" 1177 "Start overlapped connect. client_handle should be unbound."); 1178 1179 static PyObject * 1180 Overlapped_DisconnectEx(OverlappedObject *self, PyObject *args) 1181 { 1182 SOCKET Socket; 1183 DWORD flags; 1184 BOOL ret; 1185 DWORD err; 1186 1187 if (!PyArg_ParseTuple(args, F_HANDLE F_DWORD, &Socket, &flags)) 1188 return NULL; 1189 1190 if (self->type != TYPE_NONE) { 1191 PyErr_SetString(PyExc_ValueError, "operation already attempted"); 1192 return NULL; 1193 } 1194 1195 self->type = TYPE_DISCONNECT; 1196 self->handle = (HANDLE)Socket; 1197 1198 Py_BEGIN_ALLOW_THREADS 1199 ret = Py_DisconnectEx(Socket, &self->overlapped, flags, 0); 1200 Py_END_ALLOW_THREADS 1201 1202 self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError(); 1203 switch (err) { 1204 case ERROR_SUCCESS: 1205 case ERROR_IO_PENDING: 1206 Py_RETURN_NONE; 1207 default: 1208 Overlapped_clear(self); 1209 return SetFromWindowsErr(err); 1210 } 1211 } 1212 1213 PyDoc_STRVAR( 1214 Overlapped_TransmitFile_doc, 1215 "TransmitFile(socket, file, offset, offset_high, " 1216 "count_to_write, count_per_send, flags) " 1217 "-> Overlapped[None]\n\n" 1218 "Transmit file data over a connected socket."); 1219 1220 static PyObject * 1221 Overlapped_TransmitFile(OverlappedObject *self, PyObject *args) 1222 { 1223 SOCKET Socket; 1224 HANDLE File; 1225 DWORD offset; 1226 DWORD offset_high; 1227 DWORD count_to_write; 1228 DWORD count_per_send; 1229 DWORD flags; 1230 BOOL ret; 1231 DWORD err; 1232 1233 if (!PyArg_ParseTuple(args, 1234 F_HANDLE F_HANDLE F_DWORD F_DWORD 1235 F_DWORD F_DWORD F_DWORD, 1236 &Socket, &File, &offset, &offset_high, 1237 &count_to_write, &count_per_send, 1238 &flags)) 1239 return NULL; 1240 1241 if (self->type != TYPE_NONE) { 1242 PyErr_SetString(PyExc_ValueError, "operation already attempted"); 1243 return NULL; 1244 } 1245 1246 self->type = TYPE_TRANSMIT_FILE; 1247 self->handle = (HANDLE)Socket; 1248 self->overlapped.Offset = offset; 1249 self->overlapped.OffsetHigh = offset_high; 1250 1251 Py_BEGIN_ALLOW_THREADS 1252 ret = Py_TransmitFile(Socket, File, count_to_write, count_per_send, 1253 &self->overlapped, 1254 NULL, flags); 1255 Py_END_ALLOW_THREADS 1256 1257 self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError(); 1258 switch (err) { 1259 case ERROR_SUCCESS: 1260 case ERROR_IO_PENDING: 1261 Py_RETURN_NONE; 1262 default: 1263 Overlapped_clear(self); 1264 return SetFromWindowsErr(err); 1265 } 1266 } 1267 1268 PyDoc_STRVAR( 1269 Overlapped_ConnectNamedPipe_doc, 1270 "ConnectNamedPipe(handle) -> Overlapped[None]\n\n" 1271 "Start overlapped wait for a client to connect."); 1272 1273 static PyObject * 1274 Overlapped_ConnectNamedPipe(OverlappedObject *self, PyObject *args) 1275 { 1276 HANDLE Pipe; 1277 BOOL ret; 1278 DWORD err; 1279 1280 if (!PyArg_ParseTuple(args, F_HANDLE, &Pipe)) 1281 return NULL; 1282 1283 if (self->type != TYPE_NONE) { 1284 PyErr_SetString(PyExc_ValueError, "operation already attempted"); 1285 return NULL; 1286 } 1287 1288 self->type = TYPE_CONNECT_NAMED_PIPE; 1289 self->handle = Pipe; 1290 1291 Py_BEGIN_ALLOW_THREADS 1292 ret = ConnectNamedPipe(Pipe, &self->overlapped); 1293 Py_END_ALLOW_THREADS 1294 1295 self->error = err = ret ? ERROR_SUCCESS : GetLastError(); 1296 switch (err) { 1297 case ERROR_PIPE_CONNECTED: 1298 mark_as_completed(&self->overlapped); 1299 Py_RETURN_TRUE; 1300 case ERROR_SUCCESS: 1301 case ERROR_IO_PENDING: 1302 Py_RETURN_FALSE; 1303 default: 1304 Overlapped_clear(self); 1305 return SetFromWindowsErr(err); 1306 } 1307 } 1308 1309 PyDoc_STRVAR( 1310 ConnectPipe_doc, 1311 "ConnectPipe(addr) -> pipe_handle\n\n" 1312 "Connect to the pipe for asynchronous I/O (overlapped)."); 1313 1314 static PyObject * 1315 ConnectPipe(OverlappedObject *self, PyObject *args) 1316 { 1317 PyObject *AddressObj; 1318 wchar_t *Address; 1319 HANDLE PipeHandle; 1320 1321 if (!PyArg_ParseTuple(args, "U", &AddressObj)) 1322 return NULL; 1323 1324 Address = PyUnicode_AsWideCharString(AddressObj, NULL); 1325 if (Address == NULL) 1326 return NULL; 1327 1328 Py_BEGIN_ALLOW_THREADS 1329 PipeHandle = CreateFileW(Address, 1330 GENERIC_READ | GENERIC_WRITE, 1331 0, NULL, OPEN_EXISTING, 1332 FILE_FLAG_OVERLAPPED, NULL); 1333 Py_END_ALLOW_THREADS 1334 1335 PyMem_Free(Address); 1336 if (PipeHandle == INVALID_HANDLE_VALUE) 1337 return SetFromWindowsErr(0); 1338 return Py_BuildValue(F_HANDLE, PipeHandle); 1339 } 1340 1341 static PyObject* 1342 Overlapped_getaddress(OverlappedObject *self) 1343 { 1344 return PyLong_FromVoidPtr(&self->overlapped); 1345 } 1346 1347 static PyObject* 1348 Overlapped_getpending(OverlappedObject *self) 1349 { 1350 return PyBool_FromLong(!HasOverlappedIoCompleted(&self->overlapped) && 1351 self->type != TYPE_NOT_STARTED); 1352 } 1353 1354 static int 1355 Overlapped_traverse(OverlappedObject *self, visitproc visit, void *arg) 1356 { 1357 switch (self->type) { 1358 case TYPE_READ: 1359 case TYPE_ACCEPT: 1360 Py_VISIT(self->allocated_buffer); 1361 break; 1362 case TYPE_WRITE: 1363 case TYPE_READINTO: 1364 if (self->user_buffer.obj) { 1365 Py_VISIT(&self->user_buffer.obj); 1366 } 1367 break; 1368 } 1369 return 0; 1370 } 1371 1372 1373 static PyMethodDef Overlapped_methods[] = { 1374 {"getresult", (PyCFunction) Overlapped_getresult, 1375 METH_VARARGS, Overlapped_getresult_doc}, 1376 {"cancel", (PyCFunction) Overlapped_cancel, 1377 METH_NOARGS, Overlapped_cancel_doc}, 1378 {"ReadFile", (PyCFunction) Overlapped_ReadFile, 1379 METH_VARARGS, Overlapped_ReadFile_doc}, 1380 {"ReadFileInto", (PyCFunction) Overlapped_ReadFileInto, 1381 METH_VARARGS, Overlapped_ReadFileInto_doc}, 1382 {"WSARecv", (PyCFunction) Overlapped_WSARecv, 1383 METH_VARARGS, Overlapped_WSARecv_doc}, 1384 {"WSARecvInto", (PyCFunction) Overlapped_WSARecvInto, 1385 METH_VARARGS, Overlapped_WSARecvInto_doc}, 1386 {"WriteFile", (PyCFunction) Overlapped_WriteFile, 1387 METH_VARARGS, Overlapped_WriteFile_doc}, 1388 {"WSASend", (PyCFunction) Overlapped_WSASend, 1389 METH_VARARGS, Overlapped_WSASend_doc}, 1390 {"AcceptEx", (PyCFunction) Overlapped_AcceptEx, 1391 METH_VARARGS, Overlapped_AcceptEx_doc}, 1392 {"ConnectEx", (PyCFunction) Overlapped_ConnectEx, 1393 METH_VARARGS, Overlapped_ConnectEx_doc}, 1394 {"DisconnectEx", (PyCFunction) Overlapped_DisconnectEx, 1395 METH_VARARGS, Overlapped_DisconnectEx_doc}, 1396 {"TransmitFile", (PyCFunction) Overlapped_TransmitFile, 1397 METH_VARARGS, Overlapped_TransmitFile_doc}, 1398 {"ConnectNamedPipe", (PyCFunction) Overlapped_ConnectNamedPipe, 1399 METH_VARARGS, Overlapped_ConnectNamedPipe_doc}, 1400 {NULL} 1401 }; 1402 1403 static PyMemberDef Overlapped_members[] = { 1404 {"error", T_ULONG, 1405 offsetof(OverlappedObject, error), 1406 READONLY, "Error from last operation"}, 1407 {"event", T_HANDLE, 1408 offsetof(OverlappedObject, overlapped) + offsetof(OVERLAPPED, hEvent), 1409 READONLY, "Overlapped event handle"}, 1410 {NULL} 1411 }; 1412 1413 static PyGetSetDef Overlapped_getsets[] = { 1414 {"address", (getter)Overlapped_getaddress, NULL, 1415 "Address of overlapped structure"}, 1416 {"pending", (getter)Overlapped_getpending, NULL, 1417 "Whether the operation is pending"}, 1418 {NULL}, 1419 }; 1420 1421 PyTypeObject OverlappedType = { 1422 PyVarObject_HEAD_INIT(NULL, 0) 1423 /* tp_name */ "_overlapped.Overlapped", 1424 /* tp_basicsize */ sizeof(OverlappedObject), 1425 /* tp_itemsize */ 0, 1426 /* tp_dealloc */ (destructor) Overlapped_dealloc, 1427 /* tp_print */ 0, 1428 /* tp_getattr */ 0, 1429 /* tp_setattr */ 0, 1430 /* tp_reserved */ 0, 1431 /* tp_repr */ 0, 1432 /* tp_as_number */ 0, 1433 /* tp_as_sequence */ 0, 1434 /* tp_as_mapping */ 0, 1435 /* tp_hash */ 0, 1436 /* tp_call */ 0, 1437 /* tp_str */ 0, 1438 /* tp_getattro */ 0, 1439 /* tp_setattro */ 0, 1440 /* tp_as_buffer */ 0, 1441 /* tp_flags */ Py_TPFLAGS_DEFAULT, 1442 /* tp_doc */ "OVERLAPPED structure wrapper", 1443 /* tp_traverse */ (traverseproc)Overlapped_traverse, 1444 /* tp_clear */ 0, 1445 /* tp_richcompare */ 0, 1446 /* tp_weaklistoffset */ 0, 1447 /* tp_iter */ 0, 1448 /* tp_iternext */ 0, 1449 /* tp_methods */ Overlapped_methods, 1450 /* tp_members */ Overlapped_members, 1451 /* tp_getset */ Overlapped_getsets, 1452 /* tp_base */ 0, 1453 /* tp_dict */ 0, 1454 /* tp_descr_get */ 0, 1455 /* tp_descr_set */ 0, 1456 /* tp_dictoffset */ 0, 1457 /* tp_init */ 0, 1458 /* tp_alloc */ 0, 1459 /* tp_new */ Overlapped_new, 1460 }; 1461 1462 static PyMethodDef overlapped_functions[] = { 1463 {"CreateIoCompletionPort", overlapped_CreateIoCompletionPort, 1464 METH_VARARGS, CreateIoCompletionPort_doc}, 1465 {"GetQueuedCompletionStatus", overlapped_GetQueuedCompletionStatus, 1466 METH_VARARGS, GetQueuedCompletionStatus_doc}, 1467 {"PostQueuedCompletionStatus", overlapped_PostQueuedCompletionStatus, 1468 METH_VARARGS, PostQueuedCompletionStatus_doc}, 1469 {"FormatMessage", overlapped_FormatMessage, 1470 METH_VARARGS, FormatMessage_doc}, 1471 {"BindLocal", overlapped_BindLocal, 1472 METH_VARARGS, BindLocal_doc}, 1473 {"RegisterWaitWithQueue", overlapped_RegisterWaitWithQueue, 1474 METH_VARARGS, RegisterWaitWithQueue_doc}, 1475 {"UnregisterWait", overlapped_UnregisterWait, 1476 METH_VARARGS, UnregisterWait_doc}, 1477 {"UnregisterWaitEx", overlapped_UnregisterWaitEx, 1478 METH_VARARGS, UnregisterWaitEx_doc}, 1479 {"CreateEvent", overlapped_CreateEvent, 1480 METH_VARARGS, CreateEvent_doc}, 1481 {"SetEvent", overlapped_SetEvent, 1482 METH_VARARGS, SetEvent_doc}, 1483 {"ResetEvent", overlapped_ResetEvent, 1484 METH_VARARGS, ResetEvent_doc}, 1485 {"ConnectPipe", 1486 (PyCFunction) ConnectPipe, 1487 METH_VARARGS, ConnectPipe_doc}, 1488 {NULL} 1489 }; 1490 1491 static struct PyModuleDef overlapped_module = { 1492 PyModuleDef_HEAD_INIT, 1493 "_overlapped", 1494 NULL, 1495 -1, 1496 overlapped_functions, 1497 NULL, 1498 NULL, 1499 NULL, 1500 NULL 1501 }; 1502 1503 #define WINAPI_CONSTANT(fmt, con) \ 1504 PyDict_SetItemString(d, #con, Py_BuildValue(fmt, con)) 1505 1506 PyMODINIT_FUNC 1507 PyInit__overlapped(void) 1508 { 1509 PyObject *m, *d; 1510 1511 /* Ensure WSAStartup() called before initializing function pointers */ 1512 m = PyImport_ImportModule("_socket"); 1513 if (!m) 1514 return NULL; 1515 Py_DECREF(m); 1516 1517 if (initialize_function_pointers() < 0) 1518 return NULL; 1519 1520 if (PyType_Ready(&OverlappedType) < 0) 1521 return NULL; 1522 1523 m = PyModule_Create(&overlapped_module); 1524 if (PyModule_AddObject(m, "Overlapped", (PyObject *)&OverlappedType) < 0) 1525 return NULL; 1526 1527 d = PyModule_GetDict(m); 1528 1529 WINAPI_CONSTANT(F_DWORD, ERROR_IO_PENDING); 1530 WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED); 1531 WINAPI_CONSTANT(F_DWORD, ERROR_OPERATION_ABORTED); 1532 WINAPI_CONSTANT(F_DWORD, ERROR_SEM_TIMEOUT); 1533 WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_BUSY); 1534 WINAPI_CONSTANT(F_DWORD, INFINITE); 1535 WINAPI_CONSTANT(F_HANDLE, INVALID_HANDLE_VALUE); 1536 WINAPI_CONSTANT(F_HANDLE, NULL); 1537 WINAPI_CONSTANT(F_DWORD, SO_UPDATE_ACCEPT_CONTEXT); 1538 WINAPI_CONSTANT(F_DWORD, SO_UPDATE_CONNECT_CONTEXT); 1539 WINAPI_CONSTANT(F_DWORD, TF_REUSE_SOCKET); 1540 1541 return m; 1542 } 1543