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