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