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" // PyMemberDef
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 /*[python input]
41 class OVERLAPPED_converter(CConverter):
42 type = 'OVERLAPPED *'
43 format_unit = '"F_POINTER"'
44
45 class HANDLE_converter(CConverter):
46 type = 'HANDLE'
47 format_unit = '"F_HANDLE"'
48
49 class ULONG_PTR_converter(CConverter):
50 type = 'ULONG_PTR'
51 format_unit = '"F_ULONG_PTR"'
52
53 class DWORD_converter(CConverter):
54 type = 'DWORD'
55 format_unit = 'k'
56
57 class BOOL_converter(CConverter):
58 type = 'BOOL'
59 format_unit = 'i'
60 [python start generated code]*/
61 /*[python end generated code: output=da39a3ee5e6b4b0d input=83bb8c2c2514f2a8]*/
62
63 /*[clinic input]
64 module _overlapped
65 class _overlapped.Overlapped "OverlappedObject *" "&OverlappedType"
66 [clinic start generated code]*/
67 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=92e5a799db35b96c]*/
68
69
70 enum {TYPE_NONE, TYPE_NOT_STARTED, TYPE_READ, TYPE_READINTO, TYPE_WRITE,
71 TYPE_ACCEPT, TYPE_CONNECT, TYPE_DISCONNECT, TYPE_CONNECT_NAMED_PIPE,
72 TYPE_WAIT_NAMED_PIPE_AND_CONNECT, TYPE_TRANSMIT_FILE, TYPE_READ_FROM,
73 TYPE_WRITE_TO};
74
75 typedef struct {
76 PyObject_HEAD
77 OVERLAPPED overlapped;
78 /* For convenience, we store the file handle too */
79 HANDLE handle;
80 /* Error returned by last method call */
81 DWORD error;
82 /* Type of operation */
83 DWORD type;
84 union {
85 /* Buffer allocated by us: TYPE_READ and TYPE_ACCEPT */
86 PyObject *allocated_buffer;
87 /* Buffer passed by the user: TYPE_WRITE, TYPE_WRITE_TO, and TYPE_READINTO */
88 Py_buffer user_buffer;
89
90 /* Data used for reading from a connectionless socket:
91 TYPE_READ_FROM */
92 struct {
93 // A (buffer, (host, port)) tuple
94 PyObject *result;
95 // The actual read buffer
96 PyObject *allocated_buffer;
97 struct sockaddr_in6 address;
98 int address_length;
99 } read_from;
100 };
101 } OverlappedObject;
102
103 typedef struct {
104 PyTypeObject *overlapped_type;
105 } OverlappedState;
106
107 static inline OverlappedState*
overlapped_get_state(PyObject * module)108 overlapped_get_state(PyObject *module)
109 {
110 void *state = PyModule_GetState(module);
111 assert(state != NULL);
112 return (OverlappedState *)state;
113 }
114
115
116 /*
117 * Map Windows error codes to subclasses of OSError
118 */
119
120 static PyObject *
SetFromWindowsErr(DWORD err)121 SetFromWindowsErr(DWORD err)
122 {
123 PyObject *exception_type;
124
125 if (err == 0)
126 err = GetLastError();
127 switch (err) {
128 case ERROR_CONNECTION_REFUSED:
129 exception_type = PyExc_ConnectionRefusedError;
130 break;
131 case ERROR_CONNECTION_ABORTED:
132 exception_type = PyExc_ConnectionAbortedError;
133 break;
134 default:
135 exception_type = PyExc_OSError;
136 }
137 return PyErr_SetExcFromWindowsErr(exception_type, err);
138 }
139
140 /*
141 * Some functions should be loaded at runtime
142 */
143
144 static LPFN_ACCEPTEX Py_AcceptEx = NULL;
145 static LPFN_CONNECTEX Py_ConnectEx = NULL;
146 static LPFN_DISCONNECTEX Py_DisconnectEx = NULL;
147 static LPFN_TRANSMITFILE Py_TransmitFile = NULL;
148 static BOOL (CALLBACK *Py_CancelIoEx)(HANDLE, LPOVERLAPPED) = NULL;
149
150 #define GET_WSA_POINTER(s, x) \
151 (SOCKET_ERROR != WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, \
152 &Guid##x, sizeof(Guid##x), &Py_##x, \
153 sizeof(Py_##x), &dwBytes, NULL, NULL))
154
155 static int
initialize_function_pointers(void)156 initialize_function_pointers(void)
157 {
158 GUID GuidAcceptEx = WSAID_ACCEPTEX;
159 GUID GuidConnectEx = WSAID_CONNECTEX;
160 GUID GuidDisconnectEx = WSAID_DISCONNECTEX;
161 GUID GuidTransmitFile = WSAID_TRANSMITFILE;
162 HINSTANCE hKernel32;
163 SOCKET s;
164 DWORD dwBytes;
165
166 s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
167 if (s == INVALID_SOCKET) {
168 SetFromWindowsErr(WSAGetLastError());
169 return -1;
170 }
171
172 if (!GET_WSA_POINTER(s, AcceptEx) ||
173 !GET_WSA_POINTER(s, ConnectEx) ||
174 !GET_WSA_POINTER(s, DisconnectEx) ||
175 !GET_WSA_POINTER(s, TransmitFile))
176 {
177 closesocket(s);
178 SetFromWindowsErr(WSAGetLastError());
179 return -1;
180 }
181
182 closesocket(s);
183
184 /* On WinXP we will have Py_CancelIoEx == NULL */
185 Py_BEGIN_ALLOW_THREADS
186 hKernel32 = GetModuleHandle("KERNEL32");
187 *(FARPROC *)&Py_CancelIoEx = GetProcAddress(hKernel32, "CancelIoEx");
188 Py_END_ALLOW_THREADS
189 return 0;
190 }
191
192 /*
193 * Completion port stuff
194 */
195
196 /*[clinic input]
197 _overlapped.CreateIoCompletionPort
198
199 handle as FileHandle: HANDLE
200 port as ExistingCompletionPort: HANDLE
201 key as CompletionKey: ULONG_PTR
202 concurrency as NumberOfConcurrentThreads: DWORD
203 /
204
205 Create a completion port or register a handle with a port.
206 [clinic start generated code]*/
207
208 static PyObject *
_overlapped_CreateIoCompletionPort_impl(PyObject * module,HANDLE FileHandle,HANDLE ExistingCompletionPort,ULONG_PTR CompletionKey,DWORD NumberOfConcurrentThreads)209 _overlapped_CreateIoCompletionPort_impl(PyObject *module, HANDLE FileHandle,
210 HANDLE ExistingCompletionPort,
211 ULONG_PTR CompletionKey,
212 DWORD NumberOfConcurrentThreads)
213 /*[clinic end generated code: output=24ede2b0f05e5433 input=847bae4d0efe1976]*/
214 {
215 HANDLE ret;
216
217 Py_BEGIN_ALLOW_THREADS
218 ret = CreateIoCompletionPort(FileHandle, ExistingCompletionPort,
219 CompletionKey, NumberOfConcurrentThreads);
220 Py_END_ALLOW_THREADS
221
222 if (ret == NULL)
223 return SetFromWindowsErr(0);
224 return Py_BuildValue(F_HANDLE, ret);
225 }
226
227 /*[clinic input]
228 _overlapped.GetQueuedCompletionStatus
229
230 port as CompletionPort: HANDLE
231 msecs as Milliseconds: DWORD
232 /
233
234 Get a message from completion port.
235
236 Wait for up to msecs milliseconds.
237 [clinic start generated code]*/
238
239 static PyObject *
_overlapped_GetQueuedCompletionStatus_impl(PyObject * module,HANDLE CompletionPort,DWORD Milliseconds)240 _overlapped_GetQueuedCompletionStatus_impl(PyObject *module,
241 HANDLE CompletionPort,
242 DWORD Milliseconds)
243 /*[clinic end generated code: output=68314171628dddb7 input=94a042d14c4f6410]*/
244 {
245 DWORD NumberOfBytes = 0;
246 ULONG_PTR CompletionKey = 0;
247 OVERLAPPED *Overlapped = NULL;
248 DWORD err;
249 BOOL ret;
250
251 Py_BEGIN_ALLOW_THREADS
252 ret = GetQueuedCompletionStatus(CompletionPort, &NumberOfBytes,
253 &CompletionKey, &Overlapped, Milliseconds);
254 Py_END_ALLOW_THREADS
255
256 err = ret ? ERROR_SUCCESS : GetLastError();
257 if (Overlapped == NULL) {
258 if (err == WAIT_TIMEOUT)
259 Py_RETURN_NONE;
260 else
261 return SetFromWindowsErr(err);
262 }
263 return Py_BuildValue(F_DWORD F_DWORD F_ULONG_PTR F_POINTER,
264 err, NumberOfBytes, CompletionKey, Overlapped);
265 }
266
267 /*[clinic input]
268 _overlapped.PostQueuedCompletionStatus
269
270 port as CompletionPort: HANDLE
271 bytes as NumberOfBytes: DWORD
272 key as CompletionKey: ULONG_PTR
273 address as Overlapped: OVERLAPPED
274 /
275
276 Post a message to completion port.
277 [clinic start generated code]*/
278
279 static PyObject *
_overlapped_PostQueuedCompletionStatus_impl(PyObject * module,HANDLE CompletionPort,DWORD NumberOfBytes,ULONG_PTR CompletionKey,OVERLAPPED * Overlapped)280 _overlapped_PostQueuedCompletionStatus_impl(PyObject *module,
281 HANDLE CompletionPort,
282 DWORD NumberOfBytes,
283 ULONG_PTR CompletionKey,
284 OVERLAPPED *Overlapped)
285 /*[clinic end generated code: output=93e73f2933a43e9e input=e936202d87937aca]*/
286 {
287 BOOL ret;
288
289 Py_BEGIN_ALLOW_THREADS
290 ret = PostQueuedCompletionStatus(CompletionPort, NumberOfBytes,
291 CompletionKey, Overlapped);
292 Py_END_ALLOW_THREADS
293
294 if (!ret)
295 return SetFromWindowsErr(0);
296 Py_RETURN_NONE;
297 }
298
299 /*
300 * Wait for a handle
301 */
302
303 struct PostCallbackData {
304 HANDLE CompletionPort;
305 LPOVERLAPPED Overlapped;
306 };
307
308 static VOID CALLBACK
PostToQueueCallback(PVOID lpParameter,BOOLEAN TimerOrWaitFired)309 PostToQueueCallback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
310 {
311 struct PostCallbackData *p = (struct PostCallbackData*) lpParameter;
312
313 PostQueuedCompletionStatus(p->CompletionPort, TimerOrWaitFired,
314 0, p->Overlapped);
315 /* ignore possible error! */
316 PyMem_RawFree(p);
317 }
318
319 /*[clinic input]
320 _overlapped.RegisterWaitWithQueue
321
322 Object: HANDLE
323 CompletionPort: HANDLE
324 Overlapped: OVERLAPPED
325 Timeout as Milliseconds: DWORD
326 /
327
328 Register wait for Object; when complete CompletionPort is notified.
329 [clinic start generated code]*/
330
331 static PyObject *
_overlapped_RegisterWaitWithQueue_impl(PyObject * module,HANDLE Object,HANDLE CompletionPort,OVERLAPPED * Overlapped,DWORD Milliseconds)332 _overlapped_RegisterWaitWithQueue_impl(PyObject *module, HANDLE Object,
333 HANDLE CompletionPort,
334 OVERLAPPED *Overlapped,
335 DWORD Milliseconds)
336 /*[clinic end generated code: output=c2ace732e447fe45 input=2dd4efee44abe8ee]*/
337 {
338 HANDLE NewWaitObject;
339 struct PostCallbackData data = {CompletionPort, Overlapped}, *pdata;
340
341 /* Use PyMem_RawMalloc() rather than PyMem_Malloc(), since
342 PostToQueueCallback() will call PyMem_Free() from a new C thread
343 which doesn't hold the GIL. */
344 pdata = PyMem_RawMalloc(sizeof(struct PostCallbackData));
345 if (pdata == NULL)
346 return SetFromWindowsErr(0);
347
348 *pdata = data;
349
350 if (!RegisterWaitForSingleObject(
351 &NewWaitObject, Object, PostToQueueCallback, pdata, Milliseconds,
352 WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE))
353 {
354 PyMem_RawFree(pdata);
355 return SetFromWindowsErr(0);
356 }
357
358 return Py_BuildValue(F_HANDLE, NewWaitObject);
359 }
360
361 /*[clinic input]
362 _overlapped.UnregisterWait
363
364 WaitHandle: HANDLE
365 /
366
367 Unregister wait handle.
368 [clinic start generated code]*/
369
370 static PyObject *
_overlapped_UnregisterWait_impl(PyObject * module,HANDLE WaitHandle)371 _overlapped_UnregisterWait_impl(PyObject *module, HANDLE WaitHandle)
372 /*[clinic end generated code: output=ec90cd955a9a617d input=a56709544cb2df0f]*/
373 {
374 BOOL ret;
375
376 Py_BEGIN_ALLOW_THREADS
377 ret = UnregisterWait(WaitHandle);
378 Py_END_ALLOW_THREADS
379
380 if (!ret)
381 return SetFromWindowsErr(0);
382 Py_RETURN_NONE;
383 }
384
385 /*[clinic input]
386 _overlapped.UnregisterWaitEx
387
388 WaitHandle: HANDLE
389 Event: HANDLE
390 /
391
392 Unregister wait handle.
393 [clinic start generated code]*/
394
395 static PyObject *
_overlapped_UnregisterWaitEx_impl(PyObject * module,HANDLE WaitHandle,HANDLE Event)396 _overlapped_UnregisterWaitEx_impl(PyObject *module, HANDLE WaitHandle,
397 HANDLE Event)
398 /*[clinic end generated code: output=2e3d84c1d5f65b92 input=953cddc1de50fab9]*/
399 {
400 BOOL ret;
401
402 Py_BEGIN_ALLOW_THREADS
403 ret = UnregisterWaitEx(WaitHandle, Event);
404 Py_END_ALLOW_THREADS
405
406 if (!ret)
407 return SetFromWindowsErr(0);
408 Py_RETURN_NONE;
409 }
410
411 /*
412 * Event functions -- currently only used by tests
413 */
414
415 /*[clinic input]
416 _overlapped.CreateEvent
417
418 EventAttributes: object
419 ManualReset: BOOL
420 InitialState: BOOL
421 Name: Py_UNICODE(accept={str, NoneType})
422 /
423
424 Create an event.
425
426 EventAttributes must be None.
427 [clinic start generated code]*/
428
429 static PyObject *
_overlapped_CreateEvent_impl(PyObject * module,PyObject * EventAttributes,BOOL ManualReset,BOOL InitialState,const Py_UNICODE * Name)430 _overlapped_CreateEvent_impl(PyObject *module, PyObject *EventAttributes,
431 BOOL ManualReset, BOOL InitialState,
432 const Py_UNICODE *Name)
433 /*[clinic end generated code: output=8e04f0916c17b13d input=dbc36ae14375ba24]*/
434 {
435 HANDLE Event;
436
437 if (EventAttributes != Py_None) {
438 PyErr_SetString(PyExc_ValueError, "EventAttributes must be None");
439 return NULL;
440 }
441
442 Py_BEGIN_ALLOW_THREADS
443 Event = CreateEventW(NULL, ManualReset, InitialState, Name);
444 Py_END_ALLOW_THREADS
445
446 if (Event == NULL)
447 return SetFromWindowsErr(0);
448 return Py_BuildValue(F_HANDLE, Event);
449 }
450
451 /*[clinic input]
452 _overlapped.SetEvent
453
454 Handle: HANDLE
455 /
456
457 Set event.
458 [clinic start generated code]*/
459
460 static PyObject *
_overlapped_SetEvent_impl(PyObject * module,HANDLE Handle)461 _overlapped_SetEvent_impl(PyObject *module, HANDLE Handle)
462 /*[clinic end generated code: output=5b8d974216b0e569 input=d8b0d26eb7391e80]*/
463 {
464 BOOL ret;
465
466 Py_BEGIN_ALLOW_THREADS
467 ret = SetEvent(Handle);
468 Py_END_ALLOW_THREADS
469
470 if (!ret)
471 return SetFromWindowsErr(0);
472 Py_RETURN_NONE;
473 }
474
475 /*[clinic input]
476 _overlapped.ResetEvent
477
478 Handle: HANDLE
479 /
480
481 Reset event.
482 [clinic start generated code]*/
483
484 static PyObject *
_overlapped_ResetEvent_impl(PyObject * module,HANDLE Handle)485 _overlapped_ResetEvent_impl(PyObject *module, HANDLE Handle)
486 /*[clinic end generated code: output=066537a8405cddb2 input=d4e089c9ba84ff2f]*/
487 {
488 BOOL ret;
489
490 Py_BEGIN_ALLOW_THREADS
491 ret = ResetEvent(Handle);
492 Py_END_ALLOW_THREADS
493
494 if (!ret)
495 return SetFromWindowsErr(0);
496 Py_RETURN_NONE;
497 }
498
499 /*
500 * Bind socket handle to local port without doing slow getaddrinfo()
501 */
502
503 /*[clinic input]
504 _overlapped.BindLocal
505
506 handle as Socket: HANDLE
507 family as Family: int
508 /
509
510 Bind a socket handle to an arbitrary local port.
511
512 family should be AF_INET or AF_INET6.
513 [clinic start generated code]*/
514
515 static PyObject *
_overlapped_BindLocal_impl(PyObject * module,HANDLE Socket,int Family)516 _overlapped_BindLocal_impl(PyObject *module, HANDLE Socket, int Family)
517 /*[clinic end generated code: output=edb93862697aed9c input=a0e7b5c2f541170c]*/
518 {
519 BOOL ret;
520
521 if (Family == AF_INET) {
522 struct sockaddr_in addr;
523 memset(&addr, 0, sizeof(addr));
524 addr.sin_family = AF_INET;
525 addr.sin_port = 0;
526 addr.sin_addr.S_un.S_addr = INADDR_ANY;
527 ret = bind((SOCKET)Socket, (SOCKADDR*)&addr, sizeof(addr))
528 != SOCKET_ERROR;
529 } else if (Family == AF_INET6) {
530 struct sockaddr_in6 addr;
531 memset(&addr, 0, sizeof(addr));
532 addr.sin6_family = AF_INET6;
533 addr.sin6_port = 0;
534 addr.sin6_addr = in6addr_any;
535 ret = bind((SOCKET)Socket, (SOCKADDR*)&addr, sizeof(addr))
536 != SOCKET_ERROR;
537 } else {
538 PyErr_SetString(PyExc_ValueError, "expected tuple of length 2 or 4");
539 return NULL;
540 }
541
542 if (!ret)
543 return SetFromWindowsErr(WSAGetLastError());
544 Py_RETURN_NONE;
545 }
546
547 /*
548 * Windows equivalent of os.strerror() -- compare _ctypes/callproc.c
549 */
550
551 /*[clinic input]
552 _overlapped.FormatMessage
553
554 error_code as code: DWORD
555 /
556
557 Return error message for an error code.
558 [clinic start generated code]*/
559
560 static PyObject *
_overlapped_FormatMessage_impl(PyObject * module,DWORD code)561 _overlapped_FormatMessage_impl(PyObject *module, DWORD code)
562 /*[clinic end generated code: output=02c964ff22407c6b input=644bb5b80326179e]*/
563 {
564 DWORD n;
565 WCHAR *lpMsgBuf;
566 PyObject *res;
567
568 n = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
569 FORMAT_MESSAGE_FROM_SYSTEM |
570 FORMAT_MESSAGE_IGNORE_INSERTS,
571 NULL,
572 code,
573 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
574 (LPWSTR) &lpMsgBuf,
575 0,
576 NULL);
577 if (n) {
578 while (iswspace(lpMsgBuf[n-1]))
579 --n;
580 lpMsgBuf[n] = L'\0';
581 res = Py_BuildValue("u", lpMsgBuf);
582 } else {
583 res = PyUnicode_FromFormat("unknown error code %u", code);
584 }
585 LocalFree(lpMsgBuf);
586 return res;
587 }
588
589
590 /*
591 * Mark operation as completed - used when reading produces ERROR_BROKEN_PIPE
592 */
593
594 static void
mark_as_completed(OVERLAPPED * ov)595 mark_as_completed(OVERLAPPED *ov)
596 {
597 ov->Internal = 0;
598 if (ov->hEvent != NULL)
599 SetEvent(ov->hEvent);
600 }
601
602 /*
603 * A Python object wrapping an OVERLAPPED structure and other useful data
604 * for overlapped I/O
605 */
606
607 /*[clinic input]
608 @classmethod
609 _overlapped.Overlapped.__new__
610
611 event: HANDLE(c_default='INVALID_HANDLE_VALUE') = _overlapped.INVALID_HANDLE_VALUE
612
613 OVERLAPPED structure wrapper.
614 [clinic start generated code]*/
615
616 static PyObject *
_overlapped_Overlapped_impl(PyTypeObject * type,HANDLE event)617 _overlapped_Overlapped_impl(PyTypeObject *type, HANDLE event)
618 /*[clinic end generated code: output=6da60504a18eb421 input=26b8a7429e629e95]*/
619 {
620 OverlappedObject *self;
621
622 if (event == INVALID_HANDLE_VALUE) {
623 event = CreateEvent(NULL, TRUE, FALSE, NULL);
624 if (event == NULL)
625 return SetFromWindowsErr(0);
626 }
627
628 self = PyObject_New(OverlappedObject, type);
629 if (self == NULL) {
630 if (event != NULL)
631 CloseHandle(event);
632 return NULL;
633 }
634
635 self->handle = NULL;
636 self->error = 0;
637 self->type = TYPE_NONE;
638 self->allocated_buffer = NULL;
639 memset(&self->overlapped, 0, sizeof(OVERLAPPED));
640 memset(&self->user_buffer, 0, sizeof(Py_buffer));
641 if (event)
642 self->overlapped.hEvent = event;
643 return (PyObject *)self;
644 }
645
646
647 /* Note (bpo-32710): OverlappedType.tp_clear is not defined to not release
648 buffers while overlapped are still running, to prevent a crash. */
649 static int
Overlapped_clear(OverlappedObject * self)650 Overlapped_clear(OverlappedObject *self)
651 {
652 switch (self->type) {
653 case TYPE_READ:
654 case TYPE_ACCEPT: {
655 Py_CLEAR(self->allocated_buffer);
656 break;
657 }
658 case TYPE_READ_FROM: {
659 // An initial call to WSARecvFrom will only allocate the buffer.
660 // The result tuple of (message, address) is only
661 // allocated _after_ a message has been received.
662 if(self->read_from.result) {
663 // We've received a message, free the result tuple.
664 Py_CLEAR(self->read_from.result);
665 }
666 if(self->read_from.allocated_buffer) {
667 Py_CLEAR(self->read_from.allocated_buffer);
668 }
669 break;
670 }
671 case TYPE_WRITE:
672 case TYPE_WRITE_TO:
673 case TYPE_READINTO: {
674 if (self->user_buffer.obj) {
675 PyBuffer_Release(&self->user_buffer);
676 }
677 break;
678 }
679 }
680 self->type = TYPE_NOT_STARTED;
681 return 0;
682 }
683
684 static void
Overlapped_dealloc(OverlappedObject * self)685 Overlapped_dealloc(OverlappedObject *self)
686 {
687 DWORD bytes;
688 DWORD olderr = GetLastError();
689 BOOL wait = FALSE;
690 BOOL ret;
691
692 if (!HasOverlappedIoCompleted(&self->overlapped) &&
693 self->type != TYPE_NOT_STARTED)
694 {
695 if (Py_CancelIoEx && Py_CancelIoEx(self->handle, &self->overlapped))
696 wait = TRUE;
697
698 Py_BEGIN_ALLOW_THREADS
699 ret = GetOverlappedResult(self->handle, &self->overlapped,
700 &bytes, wait);
701 Py_END_ALLOW_THREADS
702
703 switch (ret ? ERROR_SUCCESS : GetLastError()) {
704 case ERROR_SUCCESS:
705 case ERROR_NOT_FOUND:
706 case ERROR_OPERATION_ABORTED:
707 break;
708 default:
709 PyErr_Format(
710 PyExc_RuntimeError,
711 "%R still has pending operation at "
712 "deallocation, the process may crash", self);
713 PyErr_WriteUnraisable(NULL);
714 }
715 }
716
717 if (self->overlapped.hEvent != NULL) {
718 CloseHandle(self->overlapped.hEvent);
719 }
720
721 Overlapped_clear(self);
722 SetLastError(olderr);
723
724 PyTypeObject *tp = Py_TYPE(self);
725 PyObject_Free(self);
726 Py_DECREF(tp);
727 }
728
729
730 /* Convert IPv4 sockaddr to a Python str. */
731
732 static PyObject *
make_ipv4_addr(const struct sockaddr_in * addr)733 make_ipv4_addr(const struct sockaddr_in *addr)
734 {
735 char buf[INET_ADDRSTRLEN];
736 if (inet_ntop(AF_INET, &addr->sin_addr, buf, sizeof(buf)) == NULL) {
737 PyErr_SetFromErrno(PyExc_OSError);
738 return NULL;
739 }
740 return PyUnicode_FromString(buf);
741 }
742
743 /* Convert IPv6 sockaddr to a Python str. */
744
745 static PyObject *
make_ipv6_addr(const struct sockaddr_in6 * addr)746 make_ipv6_addr(const struct sockaddr_in6 *addr)
747 {
748 char buf[INET6_ADDRSTRLEN];
749 if (inet_ntop(AF_INET6, &addr->sin6_addr, buf, sizeof(buf)) == NULL) {
750 PyErr_SetFromErrno(PyExc_OSError);
751 return NULL;
752 }
753 return PyUnicode_FromString(buf);
754 }
755
756 static PyObject*
unparse_address(LPSOCKADDR Address,DWORD Length)757 unparse_address(LPSOCKADDR Address, DWORD Length)
758 {
759 /* The function is adopted from mocketmodule.c makesockaddr()*/
760
761 switch(Address->sa_family) {
762 case AF_INET: {
763 const struct sockaddr_in *a = (const struct sockaddr_in *)Address;
764 PyObject *addrobj = make_ipv4_addr(a);
765 PyObject *ret = NULL;
766 if (addrobj) {
767 ret = Py_BuildValue("Oi", addrobj, ntohs(a->sin_port));
768 Py_DECREF(addrobj);
769 }
770 return ret;
771 }
772 case AF_INET6: {
773 const struct sockaddr_in6 *a = (const struct sockaddr_in6 *)Address;
774 PyObject *addrobj = make_ipv6_addr(a);
775 PyObject *ret = NULL;
776 if (addrobj) {
777 ret = Py_BuildValue("OiII",
778 addrobj,
779 ntohs(a->sin6_port),
780 ntohl(a->sin6_flowinfo),
781 a->sin6_scope_id);
782 Py_DECREF(addrobj);
783 }
784 return ret;
785 }
786 default: {
787 PyErr_SetString(PyExc_ValueError, "recvfrom returned unsupported address family");
788 return NULL;
789 }
790 }
791 }
792
793 /*[clinic input]
794 _overlapped.Overlapped.cancel
795
796 Cancel overlapped operation.
797 [clinic start generated code]*/
798
799 static PyObject *
_overlapped_Overlapped_cancel_impl(OverlappedObject * self)800 _overlapped_Overlapped_cancel_impl(OverlappedObject *self)
801 /*[clinic end generated code: output=54ad7aeece89901c input=80eb67c7b57dbcf1]*/
802 {
803 BOOL ret = TRUE;
804
805 if (self->type == TYPE_NOT_STARTED
806 || self->type == TYPE_WAIT_NAMED_PIPE_AND_CONNECT)
807 Py_RETURN_NONE;
808
809 if (!HasOverlappedIoCompleted(&self->overlapped)) {
810 Py_BEGIN_ALLOW_THREADS
811 if (Py_CancelIoEx)
812 ret = Py_CancelIoEx(self->handle, &self->overlapped);
813 else
814 ret = CancelIo(self->handle);
815 Py_END_ALLOW_THREADS
816 }
817
818 /* CancelIoEx returns ERROR_NOT_FOUND if the I/O completed in-between */
819 if (!ret && GetLastError() != ERROR_NOT_FOUND)
820 return SetFromWindowsErr(0);
821 Py_RETURN_NONE;
822 }
823
824 /*[clinic input]
825 _overlapped.Overlapped.getresult
826
827 wait: BOOL(c_default='FALSE') = False
828 /
829
830 Retrieve result of operation.
831
832 If wait is true then it blocks until the operation is finished. If wait
833 is false and the operation is still pending then an error is raised.
834 [clinic start generated code]*/
835
836 static PyObject *
_overlapped_Overlapped_getresult_impl(OverlappedObject * self,BOOL wait)837 _overlapped_Overlapped_getresult_impl(OverlappedObject *self, BOOL wait)
838 /*[clinic end generated code: output=8c9bd04d08994f6c input=aa5b03e9897ca074]*/
839 {
840 DWORD transferred = 0;
841 BOOL ret;
842 DWORD err;
843 PyObject *addr;
844
845 if (self->type == TYPE_NONE) {
846 PyErr_SetString(PyExc_ValueError, "operation not yet attempted");
847 return NULL;
848 }
849
850 if (self->type == TYPE_NOT_STARTED) {
851 PyErr_SetString(PyExc_ValueError, "operation failed to start");
852 return NULL;
853 }
854
855 Py_BEGIN_ALLOW_THREADS
856 ret = GetOverlappedResult(self->handle, &self->overlapped, &transferred,
857 wait);
858 Py_END_ALLOW_THREADS
859
860 self->error = err = ret ? ERROR_SUCCESS : GetLastError();
861 switch (err) {
862 case ERROR_SUCCESS:
863 case ERROR_MORE_DATA:
864 break;
865 case ERROR_BROKEN_PIPE:
866 if (self->type == TYPE_READ || self->type == TYPE_READINTO) {
867 break;
868 }
869 else if (self->type == TYPE_READ_FROM &&
870 (self->read_from.result != NULL ||
871 self->read_from.allocated_buffer != NULL))
872 {
873 break;
874 }
875 /* fall through */
876 default:
877 return SetFromWindowsErr(err);
878 }
879
880 switch (self->type) {
881 case TYPE_READ:
882 assert(PyBytes_CheckExact(self->allocated_buffer));
883 if (transferred != PyBytes_GET_SIZE(self->allocated_buffer) &&
884 _PyBytes_Resize(&self->allocated_buffer, transferred))
885 return NULL;
886
887 Py_INCREF(self->allocated_buffer);
888 return self->allocated_buffer;
889 case TYPE_READ_FROM:
890 assert(PyBytes_CheckExact(self->read_from.allocated_buffer));
891
892 if (transferred != PyBytes_GET_SIZE(
893 self->read_from.allocated_buffer) &&
894 _PyBytes_Resize(&self->read_from.allocated_buffer, transferred))
895 {
896 return NULL;
897 }
898
899 // unparse the address
900 addr = unparse_address((SOCKADDR*)&self->read_from.address,
901 self->read_from.address_length);
902
903 if (addr == NULL) {
904 return NULL;
905 }
906
907 // The result is a two item tuple: (message, address)
908 self->read_from.result = PyTuple_New(2);
909 if (self->read_from.result == NULL) {
910 Py_CLEAR(addr);
911 return NULL;
912 }
913
914 // first item: message
915 Py_INCREF(self->read_from.allocated_buffer);
916 PyTuple_SET_ITEM(self->read_from.result, 0,
917 self->read_from.allocated_buffer);
918 // second item: address
919 PyTuple_SET_ITEM(self->read_from.result, 1, addr);
920
921 Py_INCREF(self->read_from.result);
922 return self->read_from.result;
923 default:
924 return PyLong_FromUnsignedLong((unsigned long) transferred);
925 }
926 }
927
928 static PyObject *
do_ReadFile(OverlappedObject * self,HANDLE handle,char * bufstart,DWORD buflen)929 do_ReadFile(OverlappedObject *self, HANDLE handle,
930 char *bufstart, DWORD buflen)
931 {
932 DWORD nread;
933 int ret;
934 DWORD err;
935
936 Py_BEGIN_ALLOW_THREADS
937 ret = ReadFile(handle, bufstart, buflen, &nread,
938 &self->overlapped);
939 Py_END_ALLOW_THREADS
940
941 self->error = err = ret ? ERROR_SUCCESS : GetLastError();
942 switch (err) {
943 case ERROR_BROKEN_PIPE:
944 mark_as_completed(&self->overlapped);
945 return SetFromWindowsErr(err);
946 case ERROR_SUCCESS:
947 case ERROR_MORE_DATA:
948 case ERROR_IO_PENDING:
949 Py_RETURN_NONE;
950 default:
951 Overlapped_clear(self);
952 return SetFromWindowsErr(err);
953 }
954 }
955
956 /*[clinic input]
957 _overlapped.Overlapped.ReadFile
958
959 handle: HANDLE
960 size: DWORD
961 /
962
963 Start overlapped read.
964 [clinic start generated code]*/
965
966 static PyObject *
_overlapped_Overlapped_ReadFile_impl(OverlappedObject * self,HANDLE handle,DWORD size)967 _overlapped_Overlapped_ReadFile_impl(OverlappedObject *self, HANDLE handle,
968 DWORD size)
969 /*[clinic end generated code: output=4c8557e16941e4ae input=98c495baa0342425]*/
970 {
971 PyObject *buf;
972
973 if (self->type != TYPE_NONE) {
974 PyErr_SetString(PyExc_ValueError, "operation already attempted");
975 return NULL;
976 }
977
978 #if SIZEOF_SIZE_T <= SIZEOF_LONG
979 size = Py_MIN(size, (DWORD)PY_SSIZE_T_MAX);
980 #endif
981 buf = PyBytes_FromStringAndSize(NULL, Py_MAX(size, 1));
982 if (buf == NULL)
983 return NULL;
984
985 self->type = TYPE_READ;
986 self->handle = handle;
987 self->allocated_buffer = buf;
988
989 return do_ReadFile(self, handle, PyBytes_AS_STRING(buf), size);
990 }
991
992 /*[clinic input]
993 _overlapped.Overlapped.ReadFileInto
994
995 handle: HANDLE
996 buf as bufobj: object
997 /
998
999 Start overlapped receive.
1000 [clinic start generated code]*/
1001
1002 static PyObject *
_overlapped_Overlapped_ReadFileInto_impl(OverlappedObject * self,HANDLE handle,PyObject * bufobj)1003 _overlapped_Overlapped_ReadFileInto_impl(OverlappedObject *self,
1004 HANDLE handle, PyObject *bufobj)
1005 /*[clinic end generated code: output=1e9e712e742e5b2a input=16f6cc268d1d0387]*/
1006 {
1007 if (self->type != TYPE_NONE) {
1008 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1009 return NULL;
1010 }
1011
1012 if (!PyArg_Parse(bufobj, "y*", &self->user_buffer))
1013 return NULL;
1014
1015 #if SIZEOF_SIZE_T > SIZEOF_LONG
1016 if (self->user_buffer.len > (Py_ssize_t)ULONG_MAX) {
1017 PyBuffer_Release(&self->user_buffer);
1018 PyErr_SetString(PyExc_ValueError, "buffer too large");
1019 return NULL;
1020 }
1021 #endif
1022
1023 self->type = TYPE_READINTO;
1024 self->handle = handle;
1025
1026 return do_ReadFile(self, handle, self->user_buffer.buf,
1027 (DWORD)self->user_buffer.len);
1028 }
1029
1030 static PyObject *
do_WSARecv(OverlappedObject * self,HANDLE handle,char * bufstart,DWORD buflen,DWORD flags)1031 do_WSARecv(OverlappedObject *self, HANDLE handle,
1032 char *bufstart, DWORD buflen, DWORD flags)
1033 {
1034 DWORD nread;
1035 WSABUF wsabuf;
1036 int ret;
1037 DWORD err;
1038
1039 wsabuf.buf = bufstart;
1040 wsabuf.len = buflen;
1041
1042 Py_BEGIN_ALLOW_THREADS
1043 ret = WSARecv((SOCKET)handle, &wsabuf, 1, &nread, &flags,
1044 &self->overlapped, NULL);
1045 Py_END_ALLOW_THREADS
1046
1047 self->error = err = (ret < 0 ? WSAGetLastError() : ERROR_SUCCESS);
1048 switch (err) {
1049 case ERROR_BROKEN_PIPE:
1050 mark_as_completed(&self->overlapped);
1051 return SetFromWindowsErr(err);
1052 case ERROR_SUCCESS:
1053 case ERROR_MORE_DATA:
1054 case ERROR_IO_PENDING:
1055 Py_RETURN_NONE;
1056 default:
1057 Overlapped_clear(self);
1058 return SetFromWindowsErr(err);
1059 }
1060 }
1061
1062 /*[clinic input]
1063 _overlapped.Overlapped.WSARecv
1064
1065 handle: HANDLE
1066 size: DWORD
1067 flags: DWORD = 0
1068 /
1069
1070 Start overlapped receive.
1071 [clinic start generated code]*/
1072
1073 static PyObject *
_overlapped_Overlapped_WSARecv_impl(OverlappedObject * self,HANDLE handle,DWORD size,DWORD flags)1074 _overlapped_Overlapped_WSARecv_impl(OverlappedObject *self, HANDLE handle,
1075 DWORD size, DWORD flags)
1076 /*[clinic end generated code: output=3a5e9c61ff040906 input=8c04e506cc3d741a]*/
1077 {
1078 PyObject *buf;
1079
1080 if (self->type != TYPE_NONE) {
1081 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1082 return NULL;
1083 }
1084
1085 #if SIZEOF_SIZE_T <= SIZEOF_LONG
1086 size = Py_MIN(size, (DWORD)PY_SSIZE_T_MAX);
1087 #endif
1088 buf = PyBytes_FromStringAndSize(NULL, Py_MAX(size, 1));
1089 if (buf == NULL)
1090 return NULL;
1091
1092 self->type = TYPE_READ;
1093 self->handle = handle;
1094 self->allocated_buffer = buf;
1095
1096 return do_WSARecv(self, handle, PyBytes_AS_STRING(buf), size, flags);
1097 }
1098
1099 /*[clinic input]
1100 _overlapped.Overlapped.WSARecvInto
1101
1102 handle: HANDLE
1103 buf as bufobj: object
1104 flags: DWORD
1105 /
1106
1107 Start overlapped receive.
1108 [clinic start generated code]*/
1109
1110 static PyObject *
_overlapped_Overlapped_WSARecvInto_impl(OverlappedObject * self,HANDLE handle,PyObject * bufobj,DWORD flags)1111 _overlapped_Overlapped_WSARecvInto_impl(OverlappedObject *self,
1112 HANDLE handle, PyObject *bufobj,
1113 DWORD flags)
1114 /*[clinic end generated code: output=9a438abc436fe87c input=4f87c38fc381d525]*/
1115 {
1116 if (self->type != TYPE_NONE) {
1117 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1118 return NULL;
1119 }
1120
1121 if (!PyArg_Parse(bufobj, "y*", &self->user_buffer))
1122 return NULL;
1123
1124 #if SIZEOF_SIZE_T > SIZEOF_LONG
1125 if (self->user_buffer.len > (Py_ssize_t)ULONG_MAX) {
1126 PyBuffer_Release(&self->user_buffer);
1127 PyErr_SetString(PyExc_ValueError, "buffer too large");
1128 return NULL;
1129 }
1130 #endif
1131
1132 self->type = TYPE_READINTO;
1133 self->handle = handle;
1134
1135 return do_WSARecv(self, handle, self->user_buffer.buf,
1136 (DWORD)self->user_buffer.len, flags);
1137 }
1138
1139 /*[clinic input]
1140 _overlapped.Overlapped.WriteFile
1141
1142 handle: HANDLE
1143 buf as bufobj: object
1144 /
1145
1146 Start overlapped write.
1147 [clinic start generated code]*/
1148
1149 static PyObject *
_overlapped_Overlapped_WriteFile_impl(OverlappedObject * self,HANDLE handle,PyObject * bufobj)1150 _overlapped_Overlapped_WriteFile_impl(OverlappedObject *self, HANDLE handle,
1151 PyObject *bufobj)
1152 /*[clinic end generated code: output=c376230b6120d877 input=b8d9a7608d8a1e72]*/
1153 {
1154 DWORD written;
1155 BOOL ret;
1156 DWORD err;
1157
1158 if (self->type != TYPE_NONE) {
1159 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1160 return NULL;
1161 }
1162
1163 if (!PyArg_Parse(bufobj, "y*", &self->user_buffer))
1164 return NULL;
1165
1166 #if SIZEOF_SIZE_T > SIZEOF_LONG
1167 if (self->user_buffer.len > (Py_ssize_t)ULONG_MAX) {
1168 PyBuffer_Release(&self->user_buffer);
1169 PyErr_SetString(PyExc_ValueError, "buffer too large");
1170 return NULL;
1171 }
1172 #endif
1173
1174 self->type = TYPE_WRITE;
1175 self->handle = handle;
1176
1177 Py_BEGIN_ALLOW_THREADS
1178 ret = WriteFile(handle, self->user_buffer.buf,
1179 (DWORD)self->user_buffer.len,
1180 &written, &self->overlapped);
1181 Py_END_ALLOW_THREADS
1182
1183 self->error = err = ret ? ERROR_SUCCESS : GetLastError();
1184 switch (err) {
1185 case ERROR_SUCCESS:
1186 case ERROR_IO_PENDING:
1187 Py_RETURN_NONE;
1188 default:
1189 Overlapped_clear(self);
1190 return SetFromWindowsErr(err);
1191 }
1192 }
1193
1194 /*[clinic input]
1195 _overlapped.Overlapped.WSASend
1196
1197 handle: HANDLE
1198 buf as bufobj: object
1199 flags: DWORD
1200 /
1201
1202 Start overlapped send.
1203 [clinic start generated code]*/
1204
1205 static PyObject *
_overlapped_Overlapped_WSASend_impl(OverlappedObject * self,HANDLE handle,PyObject * bufobj,DWORD flags)1206 _overlapped_Overlapped_WSASend_impl(OverlappedObject *self, HANDLE handle,
1207 PyObject *bufobj, DWORD flags)
1208 /*[clinic end generated code: output=316031c7467040cc input=932e7cba6d18f708]*/
1209 {
1210 DWORD written;
1211 WSABUF wsabuf;
1212 int ret;
1213 DWORD err;
1214
1215 if (self->type != TYPE_NONE) {
1216 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1217 return NULL;
1218 }
1219
1220 if (!PyArg_Parse(bufobj, "y*", &self->user_buffer))
1221 return NULL;
1222
1223 #if SIZEOF_SIZE_T > SIZEOF_LONG
1224 if (self->user_buffer.len > (Py_ssize_t)ULONG_MAX) {
1225 PyBuffer_Release(&self->user_buffer);
1226 PyErr_SetString(PyExc_ValueError, "buffer too large");
1227 return NULL;
1228 }
1229 #endif
1230
1231 self->type = TYPE_WRITE;
1232 self->handle = handle;
1233 wsabuf.len = (DWORD)self->user_buffer.len;
1234 wsabuf.buf = self->user_buffer.buf;
1235
1236 Py_BEGIN_ALLOW_THREADS
1237 ret = WSASend((SOCKET)handle, &wsabuf, 1, &written, flags,
1238 &self->overlapped, NULL);
1239 Py_END_ALLOW_THREADS
1240
1241 self->error = err = (ret < 0 ? WSAGetLastError() : ERROR_SUCCESS);
1242 switch (err) {
1243 case ERROR_SUCCESS:
1244 case ERROR_IO_PENDING:
1245 Py_RETURN_NONE;
1246 default:
1247 Overlapped_clear(self);
1248 return SetFromWindowsErr(err);
1249 }
1250 }
1251
1252 /*[clinic input]
1253 _overlapped.Overlapped.AcceptEx
1254
1255 listen_handle as ListenSocket: HANDLE
1256 accept_handle as AcceptSocket: HANDLE
1257 /
1258
1259 Start overlapped wait for client to connect.
1260 [clinic start generated code]*/
1261
1262 static PyObject *
_overlapped_Overlapped_AcceptEx_impl(OverlappedObject * self,HANDLE ListenSocket,HANDLE AcceptSocket)1263 _overlapped_Overlapped_AcceptEx_impl(OverlappedObject *self,
1264 HANDLE ListenSocket,
1265 HANDLE AcceptSocket)
1266 /*[clinic end generated code: output=9a7381d4232af889 input=b83473224fc3a1c5]*/
1267 {
1268 DWORD BytesReceived;
1269 DWORD size;
1270 PyObject *buf;
1271 BOOL ret;
1272 DWORD err;
1273
1274 if (self->type != TYPE_NONE) {
1275 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1276 return NULL;
1277 }
1278
1279 size = sizeof(struct sockaddr_in6) + 16;
1280 buf = PyBytes_FromStringAndSize(NULL, size*2);
1281 if (!buf)
1282 return NULL;
1283
1284 self->type = TYPE_ACCEPT;
1285 self->handle = ListenSocket;
1286 self->allocated_buffer = buf;
1287
1288 Py_BEGIN_ALLOW_THREADS
1289 ret = Py_AcceptEx((SOCKET)ListenSocket, (SOCKET)AcceptSocket,
1290 PyBytes_AS_STRING(buf), 0, size, size, &BytesReceived,
1291 &self->overlapped);
1292 Py_END_ALLOW_THREADS
1293
1294 self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError();
1295 switch (err) {
1296 case ERROR_SUCCESS:
1297 case ERROR_IO_PENDING:
1298 Py_RETURN_NONE;
1299 default:
1300 Overlapped_clear(self);
1301 return SetFromWindowsErr(err);
1302 }
1303 }
1304
1305
1306 static int
parse_address(PyObject * obj,SOCKADDR * Address,int Length)1307 parse_address(PyObject *obj, SOCKADDR *Address, int Length)
1308 {
1309 PyObject *Host_obj;
1310 Py_UNICODE *Host;
1311 unsigned short Port;
1312 unsigned long FlowInfo;
1313 unsigned long ScopeId;
1314
1315 memset(Address, 0, Length);
1316
1317 switch (PyTuple_GET_SIZE(obj)) {
1318 case 2: {
1319 if (!PyArg_ParseTuple(obj, "UH", &Host_obj, &Port)) {
1320 return -1;
1321 }
1322 #if USE_UNICODE_WCHAR_CACHE
1323 Host = (wchar_t *)_PyUnicode_AsUnicode(Host_obj);
1324 #else /* USE_UNICODE_WCHAR_CACHE */
1325 Host = PyUnicode_AsWideCharString(Host_obj, NULL);
1326 #endif /* USE_UNICODE_WCHAR_CACHE */
1327 if (Host == NULL) {
1328 return -1;
1329 }
1330 Address->sa_family = AF_INET;
1331 if (WSAStringToAddressW(Host, AF_INET, NULL, Address, &Length) < 0) {
1332 SetFromWindowsErr(WSAGetLastError());
1333 Length = -1;
1334 }
1335 else {
1336 ((SOCKADDR_IN*)Address)->sin_port = htons(Port);
1337 }
1338 #if !USE_UNICODE_WCHAR_CACHE
1339 PyMem_Free(Host);
1340 #endif /* USE_UNICODE_WCHAR_CACHE */
1341 return Length;
1342 }
1343 case 4: {
1344 if (!PyArg_ParseTuple(obj,
1345 "UHkk;ConnectEx(): illegal address_as_bytes argument",
1346 &Host_obj, &Port, &FlowInfo, &ScopeId))
1347 {
1348 return -1;
1349 }
1350 #if USE_UNICODE_WCHAR_CACHE
1351 Host = (wchar_t *)_PyUnicode_AsUnicode(Host_obj);
1352 #else /* USE_UNICODE_WCHAR_CACHE */
1353 Host = PyUnicode_AsWideCharString(Host_obj, NULL);
1354 #endif /* USE_UNICODE_WCHAR_CACHE */
1355 if (Host == NULL) {
1356 return -1;
1357 }
1358 Address->sa_family = AF_INET6;
1359 if (WSAStringToAddressW(Host, AF_INET6, NULL, Address, &Length) < 0) {
1360 SetFromWindowsErr(WSAGetLastError());
1361 Length = -1;
1362 }
1363 else {
1364 ((SOCKADDR_IN6*)Address)->sin6_port = htons(Port);
1365 ((SOCKADDR_IN6*)Address)->sin6_flowinfo = FlowInfo;
1366 ((SOCKADDR_IN6*)Address)->sin6_scope_id = ScopeId;
1367 }
1368 #if !USE_UNICODE_WCHAR_CACHE
1369 PyMem_Free(Host);
1370 #endif /* USE_UNICODE_WCHAR_CACHE */
1371 return Length;
1372 }
1373 default:
1374 PyErr_SetString(PyExc_ValueError, "illegal address_as_bytes argument");
1375 return -1;
1376 }
1377 }
1378
1379 /*[clinic input]
1380 _overlapped.Overlapped.ConnectEx
1381
1382 client_handle as ConnectSocket: HANDLE
1383 address_as_bytes as AddressObj: object(subclass_of='&PyTuple_Type')
1384 /
1385
1386 Start overlapped connect.
1387
1388 client_handle should be unbound.
1389 [clinic start generated code]*/
1390
1391 static PyObject *
_overlapped_Overlapped_ConnectEx_impl(OverlappedObject * self,HANDLE ConnectSocket,PyObject * AddressObj)1392 _overlapped_Overlapped_ConnectEx_impl(OverlappedObject *self,
1393 HANDLE ConnectSocket,
1394 PyObject *AddressObj)
1395 /*[clinic end generated code: output=5aebbbdb4f022833 input=d6bbd2d84b156fc1]*/
1396 {
1397 char AddressBuf[sizeof(struct sockaddr_in6)];
1398 SOCKADDR *Address = (SOCKADDR*)AddressBuf;
1399 int Length;
1400 BOOL ret;
1401 DWORD err;
1402
1403 if (self->type != TYPE_NONE) {
1404 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1405 return NULL;
1406 }
1407
1408 Length = sizeof(AddressBuf);
1409 Length = parse_address(AddressObj, Address, Length);
1410 if (Length < 0)
1411 return NULL;
1412
1413 self->type = TYPE_CONNECT;
1414 self->handle = ConnectSocket;
1415
1416 Py_BEGIN_ALLOW_THREADS
1417 ret = Py_ConnectEx((SOCKET)ConnectSocket, Address, Length,
1418 NULL, 0, NULL, &self->overlapped);
1419 Py_END_ALLOW_THREADS
1420
1421 self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError();
1422 switch (err) {
1423 case ERROR_SUCCESS:
1424 case ERROR_IO_PENDING:
1425 Py_RETURN_NONE;
1426 default:
1427 Overlapped_clear(self);
1428 return SetFromWindowsErr(err);
1429 }
1430 }
1431
1432 /*[clinic input]
1433 _overlapped.Overlapped.DisconnectEx
1434
1435 handle as Socket: HANDLE
1436 flags: DWORD
1437 /
1438
1439 [clinic start generated code]*/
1440
1441 static PyObject *
_overlapped_Overlapped_DisconnectEx_impl(OverlappedObject * self,HANDLE Socket,DWORD flags)1442 _overlapped_Overlapped_DisconnectEx_impl(OverlappedObject *self,
1443 HANDLE Socket, DWORD flags)
1444 /*[clinic end generated code: output=8d64ddb8c93c2126 input=680845cdcdf820eb]*/
1445 {
1446 BOOL ret;
1447 DWORD err;
1448
1449 if (self->type != TYPE_NONE) {
1450 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1451 return NULL;
1452 }
1453
1454 self->type = TYPE_DISCONNECT;
1455 self->handle = Socket;
1456
1457 Py_BEGIN_ALLOW_THREADS
1458 ret = Py_DisconnectEx((SOCKET)Socket, &self->overlapped, flags, 0);
1459 Py_END_ALLOW_THREADS
1460
1461 self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError();
1462 switch (err) {
1463 case ERROR_SUCCESS:
1464 case ERROR_IO_PENDING:
1465 Py_RETURN_NONE;
1466 default:
1467 Overlapped_clear(self);
1468 return SetFromWindowsErr(err);
1469 }
1470 }
1471
1472 /*[clinic input]
1473 _overlapped.Overlapped.TransmitFile
1474
1475 socket as Socket: HANDLE
1476 file as File: HANDLE
1477 offset: DWORD
1478 offset_high: DWORD
1479 count_to_write: DWORD
1480 count_per_send: DWORD
1481 flags: DWORD
1482 /
1483
1484 Transmit file data over a connected socket.
1485 [clinic start generated code]*/
1486
1487 static PyObject *
_overlapped_Overlapped_TransmitFile_impl(OverlappedObject * self,HANDLE Socket,HANDLE File,DWORD offset,DWORD offset_high,DWORD count_to_write,DWORD count_per_send,DWORD flags)1488 _overlapped_Overlapped_TransmitFile_impl(OverlappedObject *self,
1489 HANDLE Socket, HANDLE File,
1490 DWORD offset, DWORD offset_high,
1491 DWORD count_to_write,
1492 DWORD count_per_send, DWORD flags)
1493 /*[clinic end generated code: output=03f3ca5512e678fd input=7e6f97b391f60e8c]*/
1494 {
1495 BOOL ret;
1496 DWORD err;
1497
1498 if (self->type != TYPE_NONE) {
1499 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1500 return NULL;
1501 }
1502
1503 self->type = TYPE_TRANSMIT_FILE;
1504 self->handle = Socket;
1505 self->overlapped.Offset = offset;
1506 self->overlapped.OffsetHigh = offset_high;
1507
1508 Py_BEGIN_ALLOW_THREADS
1509 ret = Py_TransmitFile((SOCKET)Socket, File, count_to_write,
1510 count_per_send, &self->overlapped, NULL, flags);
1511 Py_END_ALLOW_THREADS
1512
1513 self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError();
1514 switch (err) {
1515 case ERROR_SUCCESS:
1516 case ERROR_IO_PENDING:
1517 Py_RETURN_NONE;
1518 default:
1519 Overlapped_clear(self);
1520 return SetFromWindowsErr(err);
1521 }
1522 }
1523
1524 /*[clinic input]
1525 _overlapped.Overlapped.ConnectNamedPipe
1526
1527 handle as Pipe: HANDLE
1528 /
1529
1530 Start overlapped wait for a client to connect.
1531 [clinic start generated code]*/
1532
1533 static PyObject *
_overlapped_Overlapped_ConnectNamedPipe_impl(OverlappedObject * self,HANDLE Pipe)1534 _overlapped_Overlapped_ConnectNamedPipe_impl(OverlappedObject *self,
1535 HANDLE Pipe)
1536 /*[clinic end generated code: output=3e69adfe55818abe input=8b0d4cef8a72f7bc]*/
1537 {
1538 BOOL ret;
1539 DWORD err;
1540
1541 if (self->type != TYPE_NONE) {
1542 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1543 return NULL;
1544 }
1545
1546 self->type = TYPE_CONNECT_NAMED_PIPE;
1547 self->handle = Pipe;
1548
1549 Py_BEGIN_ALLOW_THREADS
1550 ret = ConnectNamedPipe(Pipe, &self->overlapped);
1551 Py_END_ALLOW_THREADS
1552
1553 self->error = err = ret ? ERROR_SUCCESS : GetLastError();
1554 switch (err) {
1555 case ERROR_PIPE_CONNECTED:
1556 mark_as_completed(&self->overlapped);
1557 Py_RETURN_TRUE;
1558 case ERROR_SUCCESS:
1559 case ERROR_IO_PENDING:
1560 Py_RETURN_FALSE;
1561 default:
1562 Overlapped_clear(self);
1563 return SetFromWindowsErr(err);
1564 }
1565 }
1566
1567 /*[clinic input]
1568 _overlapped.Overlapped.ConnectPipe
1569
1570 addr as Address: Py_UNICODE
1571 /
1572
1573 Connect to the pipe for asynchronous I/O (overlapped).
1574 [clinic start generated code]*/
1575
1576 static PyObject *
_overlapped_Overlapped_ConnectPipe_impl(OverlappedObject * self,const Py_UNICODE * Address)1577 _overlapped_Overlapped_ConnectPipe_impl(OverlappedObject *self,
1578 const Py_UNICODE *Address)
1579 /*[clinic end generated code: output=3cc9661667d459d4 input=167c06a274efcefc]*/
1580 {
1581 HANDLE PipeHandle;
1582
1583 Py_BEGIN_ALLOW_THREADS
1584 PipeHandle = CreateFileW(Address,
1585 GENERIC_READ | GENERIC_WRITE,
1586 0, NULL, OPEN_EXISTING,
1587 FILE_FLAG_OVERLAPPED, NULL);
1588 Py_END_ALLOW_THREADS
1589
1590 if (PipeHandle == INVALID_HANDLE_VALUE)
1591 return SetFromWindowsErr(0);
1592 return Py_BuildValue(F_HANDLE, PipeHandle);
1593 }
1594
1595 static PyObject*
Overlapped_getaddress(OverlappedObject * self)1596 Overlapped_getaddress(OverlappedObject *self)
1597 {
1598 return PyLong_FromVoidPtr(&self->overlapped);
1599 }
1600
1601 static PyObject*
Overlapped_getpending(OverlappedObject * self)1602 Overlapped_getpending(OverlappedObject *self)
1603 {
1604 return PyBool_FromLong(!HasOverlappedIoCompleted(&self->overlapped) &&
1605 self->type != TYPE_NOT_STARTED);
1606 }
1607
1608 static int
Overlapped_traverse(OverlappedObject * self,visitproc visit,void * arg)1609 Overlapped_traverse(OverlappedObject *self, visitproc visit, void *arg)
1610 {
1611 switch (self->type) {
1612 case TYPE_READ:
1613 case TYPE_ACCEPT:
1614 Py_VISIT(self->allocated_buffer);
1615 break;
1616 case TYPE_WRITE:
1617 case TYPE_WRITE_TO:
1618 case TYPE_READINTO:
1619 if (self->user_buffer.obj) {
1620 Py_VISIT(&self->user_buffer.obj);
1621 }
1622 break;
1623 case TYPE_READ_FROM:
1624 Py_VISIT(self->read_from.result);
1625 Py_VISIT(self->read_from.allocated_buffer);
1626 }
1627 return 0;
1628 }
1629
1630 // UDP functions
1631
1632 /*
1633 * Note: WSAConnect does not support Overlapped I/O so this function should
1634 * _only_ be used for connectionless sockets (UDP).
1635 */
1636
1637 /*[clinic input]
1638 _overlapped.WSAConnect
1639
1640 client_handle as ConnectSocket: HANDLE
1641 address_as_bytes as AddressObj: object
1642 /
1643
1644 Bind a remote address to a connectionless (UDP) socket.
1645 [clinic start generated code]*/
1646
1647 static PyObject *
_overlapped_WSAConnect_impl(PyObject * module,HANDLE ConnectSocket,PyObject * AddressObj)1648 _overlapped_WSAConnect_impl(PyObject *module, HANDLE ConnectSocket,
1649 PyObject *AddressObj)
1650 /*[clinic end generated code: output=ea0b4391e94dad63 input=169f8075e9ae7fa4]*/
1651 {
1652 char AddressBuf[sizeof(struct sockaddr_in6)];
1653 SOCKADDR *Address = (SOCKADDR*)AddressBuf;
1654 int Length;
1655 int err;
1656
1657 Length = sizeof(AddressBuf);
1658 Length = parse_address(AddressObj, Address, Length);
1659 if (Length < 0) {
1660 return NULL;
1661 }
1662
1663 Py_BEGIN_ALLOW_THREADS
1664 // WSAConnect does not support overlapped I/O so this call will
1665 // successfully complete immediately.
1666 err = WSAConnect((SOCKET)ConnectSocket, Address, Length,
1667 NULL, NULL, NULL, NULL);
1668 Py_END_ALLOW_THREADS
1669
1670 if (err == 0) {
1671 Py_RETURN_NONE;
1672 }
1673 else {
1674 return SetFromWindowsErr(WSAGetLastError());
1675 }
1676 }
1677
1678 /*[clinic input]
1679 _overlapped.Overlapped.WSASendTo
1680
1681 handle: HANDLE
1682 buf as bufobj: object
1683 flags: DWORD
1684 address_as_bytes as AddressObj: object
1685 /
1686
1687 Start overlapped sendto over a connectionless (UDP) socket.
1688 [clinic start generated code]*/
1689
1690 static PyObject *
_overlapped_Overlapped_WSASendTo_impl(OverlappedObject * self,HANDLE handle,PyObject * bufobj,DWORD flags,PyObject * AddressObj)1691 _overlapped_Overlapped_WSASendTo_impl(OverlappedObject *self, HANDLE handle,
1692 PyObject *bufobj, DWORD flags,
1693 PyObject *AddressObj)
1694 /*[clinic end generated code: output=fe0ff55eb60d65e1 input=f709e6ecebd9bc18]*/
1695 {
1696 char AddressBuf[sizeof(struct sockaddr_in6)];
1697 SOCKADDR *Address = (SOCKADDR*)AddressBuf;
1698 int AddressLength;
1699 DWORD written;
1700 WSABUF wsabuf;
1701 int ret;
1702 DWORD err;
1703
1704 // Parse the "to" address
1705 AddressLength = sizeof(AddressBuf);
1706 AddressLength = parse_address(AddressObj, Address, AddressLength);
1707 if (AddressLength < 0) {
1708 return NULL;
1709 }
1710
1711 if (self->type != TYPE_NONE) {
1712 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1713 return NULL;
1714 }
1715
1716 if (!PyArg_Parse(bufobj, "y*", &self->user_buffer)) {
1717 return NULL;
1718 }
1719
1720 #if SIZEOF_SIZE_T > SIZEOF_LONG
1721 if (self->user_buffer.len > (Py_ssize_t)ULONG_MAX) {
1722 PyBuffer_Release(&self->user_buffer);
1723 PyErr_SetString(PyExc_ValueError, "buffer too large");
1724 return NULL;
1725 }
1726 #endif
1727
1728 self->type = TYPE_WRITE_TO;
1729 self->handle = handle;
1730 wsabuf.len = (DWORD)self->user_buffer.len;
1731 wsabuf.buf = self->user_buffer.buf;
1732
1733 Py_BEGIN_ALLOW_THREADS
1734 ret = WSASendTo((SOCKET)handle, &wsabuf, 1, &written, flags,
1735 Address, AddressLength, &self->overlapped, NULL);
1736 Py_END_ALLOW_THREADS
1737
1738 self->error = err = (ret == SOCKET_ERROR ? WSAGetLastError() :
1739 ERROR_SUCCESS);
1740
1741 switch(err) {
1742 case ERROR_SUCCESS:
1743 case ERROR_IO_PENDING:
1744 Py_RETURN_NONE;
1745 default:
1746 self->type = TYPE_NOT_STARTED;
1747 return SetFromWindowsErr(err);
1748 }
1749 }
1750
1751
1752
1753 PyDoc_STRVAR(
1754 Overlapped_WSARecvFrom_doc,
1755 "RecvFile(handle, size, flags) -> Overlapped[(message, (host, port))]\n\n"
1756 "Start overlapped receive");
1757
1758 /*[clinic input]
1759 _overlapped.Overlapped.WSARecvFrom
1760
1761 handle: HANDLE
1762 size: DWORD
1763 flags: DWORD = 0
1764 /
1765
1766 Start overlapped receive.
1767 [clinic start generated code]*/
1768
1769 static PyObject *
_overlapped_Overlapped_WSARecvFrom_impl(OverlappedObject * self,HANDLE handle,DWORD size,DWORD flags)1770 _overlapped_Overlapped_WSARecvFrom_impl(OverlappedObject *self,
1771 HANDLE handle, DWORD size,
1772 DWORD flags)
1773 /*[clinic end generated code: output=13832a2025b86860 input=1b2663fa130e0286]*/
1774 {
1775 DWORD nread;
1776 PyObject *buf;
1777 WSABUF wsabuf;
1778 int ret;
1779 DWORD err;
1780
1781 if (self->type != TYPE_NONE) {
1782 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1783 return NULL;
1784 }
1785
1786 #if SIZEOF_SIZE_T <= SIZEOF_LONG
1787 size = Py_MIN(size, (DWORD)PY_SSIZE_T_MAX);
1788 #endif
1789 buf = PyBytes_FromStringAndSize(NULL, Py_MAX(size, 1));
1790 if (buf == NULL) {
1791 return NULL;
1792 }
1793
1794 wsabuf.len = size;
1795 wsabuf.buf = PyBytes_AS_STRING(buf);
1796
1797 self->type = TYPE_READ_FROM;
1798 self->handle = handle;
1799 self->read_from.allocated_buffer = buf;
1800 memset(&self->read_from.address, 0, sizeof(self->read_from.address));
1801 self->read_from.address_length = sizeof(self->read_from.address);
1802
1803 Py_BEGIN_ALLOW_THREADS
1804 ret = WSARecvFrom((SOCKET)handle, &wsabuf, 1, &nread, &flags,
1805 (SOCKADDR*)&self->read_from.address,
1806 &self->read_from.address_length,
1807 &self->overlapped, NULL);
1808 Py_END_ALLOW_THREADS
1809
1810 self->error = err = (ret < 0 ? WSAGetLastError() : ERROR_SUCCESS);
1811
1812 switch(err) {
1813 case ERROR_BROKEN_PIPE:
1814 mark_as_completed(&self->overlapped);
1815 return SetFromWindowsErr(err);
1816 case ERROR_SUCCESS:
1817 case ERROR_MORE_DATA:
1818 case ERROR_IO_PENDING:
1819 Py_RETURN_NONE;
1820 default:
1821 self->type = TYPE_NOT_STARTED;
1822 return SetFromWindowsErr(err);
1823 }
1824 }
1825
1826 #include "clinic/overlapped.c.h"
1827
1828 static PyMethodDef Overlapped_methods[] = {
1829 _OVERLAPPED_OVERLAPPED_GETRESULT_METHODDEF
1830 _OVERLAPPED_OVERLAPPED_CANCEL_METHODDEF
1831 _OVERLAPPED_OVERLAPPED_READFILE_METHODDEF
1832 _OVERLAPPED_OVERLAPPED_READFILEINTO_METHODDEF
1833 _OVERLAPPED_OVERLAPPED_WSARECV_METHODDEF
1834 _OVERLAPPED_OVERLAPPED_WSARECVINTO_METHODDEF
1835 _OVERLAPPED_OVERLAPPED_WRITEFILE_METHODDEF
1836 _OVERLAPPED_OVERLAPPED_WSASEND_METHODDEF
1837 _OVERLAPPED_OVERLAPPED_ACCEPTEX_METHODDEF
1838 _OVERLAPPED_OVERLAPPED_CONNECTEX_METHODDEF
1839 _OVERLAPPED_OVERLAPPED_DISCONNECTEX_METHODDEF
1840 _OVERLAPPED_OVERLAPPED_TRANSMITFILE_METHODDEF
1841 _OVERLAPPED_OVERLAPPED_CONNECTNAMEDPIPE_METHODDEF
1842 _OVERLAPPED_OVERLAPPED_WSARECVFROM_METHODDEF
1843 _OVERLAPPED_OVERLAPPED_WSASENDTO_METHODDEF
1844 {NULL}
1845 };
1846
1847 static PyMemberDef Overlapped_members[] = {
1848 {"error", T_ULONG,
1849 offsetof(OverlappedObject, error),
1850 READONLY, "Error from last operation"},
1851 {"event", T_HANDLE,
1852 offsetof(OverlappedObject, overlapped) + offsetof(OVERLAPPED, hEvent),
1853 READONLY, "Overlapped event handle"},
1854 {NULL}
1855 };
1856
1857 static PyGetSetDef Overlapped_getsets[] = {
1858 {"address", (getter)Overlapped_getaddress, NULL,
1859 "Address of overlapped structure"},
1860 {"pending", (getter)Overlapped_getpending, NULL,
1861 "Whether the operation is pending"},
1862 {NULL},
1863 };
1864
1865 static PyType_Slot overlapped_type_slots[] = {
1866 {Py_tp_dealloc, Overlapped_dealloc},
1867 {Py_tp_doc, (char *)_overlapped_Overlapped__doc__},
1868 {Py_tp_traverse, Overlapped_traverse},
1869 {Py_tp_methods, Overlapped_methods},
1870 {Py_tp_members, Overlapped_members},
1871 {Py_tp_getset, Overlapped_getsets},
1872 {Py_tp_new, _overlapped_Overlapped},
1873 {0,0}
1874 };
1875
1876 static PyType_Spec overlapped_type_spec = {
1877 .name = "_overlapped.Overlapped",
1878 .basicsize = sizeof(OverlappedObject),
1879 .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE),
1880 .slots = overlapped_type_slots
1881 };
1882
1883 static PyMethodDef overlapped_functions[] = {
1884 _OVERLAPPED_CREATEIOCOMPLETIONPORT_METHODDEF
1885 _OVERLAPPED_GETQUEUEDCOMPLETIONSTATUS_METHODDEF
1886 _OVERLAPPED_POSTQUEUEDCOMPLETIONSTATUS_METHODDEF
1887 _OVERLAPPED_FORMATMESSAGE_METHODDEF
1888 _OVERLAPPED_BINDLOCAL_METHODDEF
1889 _OVERLAPPED_REGISTERWAITWITHQUEUE_METHODDEF
1890 _OVERLAPPED_UNREGISTERWAIT_METHODDEF
1891 _OVERLAPPED_UNREGISTERWAITEX_METHODDEF
1892 _OVERLAPPED_CREATEEVENT_METHODDEF
1893 _OVERLAPPED_SETEVENT_METHODDEF
1894 _OVERLAPPED_RESETEVENT_METHODDEF
1895 _OVERLAPPED_OVERLAPPED_CONNECTPIPE_METHODDEF
1896 _OVERLAPPED_WSACONNECT_METHODDEF
1897 {NULL}
1898 };
1899
1900 static int
overlapped_traverse(PyObject * module,visitproc visit,void * arg)1901 overlapped_traverse(PyObject *module, visitproc visit, void *arg)
1902 {
1903 OverlappedState *state = overlapped_get_state(module);
1904 Py_VISIT(state->overlapped_type);
1905 return 0;
1906 }
1907
1908 static int
overlapped_clear(PyObject * module)1909 overlapped_clear(PyObject *module)
1910 {
1911 OverlappedState *state = overlapped_get_state(module);
1912 Py_CLEAR(state->overlapped_type);
1913 return 0;
1914 }
1915
1916 static void
overlapped_free(void * module)1917 overlapped_free(void *module)
1918 {
1919 overlapped_clear((PyObject *)module);
1920 }
1921
1922 #define WINAPI_CONSTANT(fmt, con) \
1923 do { \
1924 PyObject *value = Py_BuildValue(fmt, con); \
1925 if (value == NULL) { \
1926 return -1; \
1927 } \
1928 if (PyModule_AddObject(module, #con, value) < 0 ) { \
1929 Py_DECREF(value); \
1930 return -1; \
1931 } \
1932 } while (0)
1933
1934 static int
overlapped_exec(PyObject * module)1935 overlapped_exec(PyObject *module)
1936 {
1937 /* Ensure WSAStartup() called before initializing function pointers */
1938 PyObject *socket_module = PyImport_ImportModule("_socket");
1939 if (!socket_module) {
1940 return -1;
1941 }
1942
1943 Py_DECREF(socket_module);
1944
1945 if (initialize_function_pointers() < 0) {
1946 return -1;
1947 }
1948
1949 OverlappedState *st = overlapped_get_state(module);
1950 st->overlapped_type = (PyTypeObject *)PyType_FromModuleAndSpec(
1951 module, &overlapped_type_spec, NULL);
1952 if (st->overlapped_type == NULL) {
1953 return -1;
1954 }
1955
1956 if (PyModule_AddType(module, st->overlapped_type) < 0) {
1957 return -1;
1958 }
1959
1960 WINAPI_CONSTANT(F_DWORD, ERROR_IO_PENDING);
1961 WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED);
1962 WINAPI_CONSTANT(F_DWORD, ERROR_OPERATION_ABORTED);
1963 WINAPI_CONSTANT(F_DWORD, ERROR_SEM_TIMEOUT);
1964 WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_BUSY);
1965 WINAPI_CONSTANT(F_DWORD, INFINITE);
1966 WINAPI_CONSTANT(F_HANDLE, INVALID_HANDLE_VALUE);
1967 WINAPI_CONSTANT(F_HANDLE, NULL);
1968 WINAPI_CONSTANT(F_DWORD, SO_UPDATE_ACCEPT_CONTEXT);
1969 WINAPI_CONSTANT(F_DWORD, SO_UPDATE_CONNECT_CONTEXT);
1970 WINAPI_CONSTANT(F_DWORD, TF_REUSE_SOCKET);
1971
1972 return 0;
1973 }
1974
1975 static PyModuleDef_Slot overlapped_slots[] = {
1976 {Py_mod_exec, overlapped_exec},
1977 {0, NULL}
1978 };
1979
1980 static struct PyModuleDef overlapped_module = {
1981 PyModuleDef_HEAD_INIT,
1982 .m_name = "_overlapped",
1983 .m_size = sizeof(OverlappedState),
1984 .m_methods = overlapped_functions,
1985 .m_slots = overlapped_slots,
1986 .m_traverse = overlapped_traverse,
1987 .m_clear = overlapped_clear,
1988 .m_free = overlapped_free
1989 };
1990
1991 PyMODINIT_FUNC
PyInit__overlapped(void)1992 PyInit__overlapped(void)
1993 {
1994 return PyModuleDef_Init(&overlapped_module);
1995 }
1996