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