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