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