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