| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 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 |  | 
| Victor Stinner | ccdbe80 | 2016-04-01 21:37:41 +0200 | [diff] [blame] | 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 |  | 
| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 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 { | 
| Victor Stinner | 91445fb | 2014-01-30 19:06:44 +0100 | [diff] [blame] | 54 |         /* Buffer used for reading: TYPE_READ and TYPE_ACCEPT */ | 
| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 55 |         PyObject *read_buffer; | 
| Victor Stinner | 91445fb | 2014-01-30 19:06:44 +0100 | [diff] [blame] | 56 |         /* Buffer used for writing: TYPE_WRITE */ | 
| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 57 |         Py_buffer write_buffer; | 
 | 58 |     }; | 
 | 59 | } OverlappedObject; | 
 | 60 |  | 
| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 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 | /* | 
| Guido van Rossum | 90fb914 | 2013-10-30 14:44:05 -0700 | [diff] [blame] | 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! */ | 
| Victor Stinner | 6150f31 | 2016-03-16 23:25:02 +0100 | [diff] [blame] | 247 |     PyMem_RawFree(p); | 
| Guido van Rossum | 90fb914 | 2013-10-30 14:44:05 -0700 | [diff] [blame] | 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 |  | 
| Victor Stinner | 6150f31 | 2016-03-16 23:25:02 +0100 | [diff] [blame] | 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)); | 
| Guido van Rossum | 90fb914 | 2013-10-30 14:44:05 -0700 | [diff] [blame] | 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 |     { | 
| Victor Stinner | 6150f31 | 2016-03-16 23:25:02 +0100 | [diff] [blame] | 285 |         PyMem_RawFree(pdata); | 
| Guido van Rossum | 90fb914 | 2013-10-30 14:44:05 -0700 | [diff] [blame] | 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 |  | 
| Victor Stinner | d0a28de | 2015-01-21 23:39:51 +0100 | [diff] [blame] | 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 |  | 
| Guido van Rossum | 90fb914 | 2013-10-30 14:44:05 -0700 | [diff] [blame] | 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 | /* | 
| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 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 |  | 
| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 597 |     switch (self->type) { | 
| Victor Stinner | 91445fb | 2014-01-30 19:06:44 +0100 | [diff] [blame] | 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; | 
| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 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: | 
| Victor Stinner | 91445fb | 2014-01-30 19:06:44 +0100 | [diff] [blame] | 679 |             if ((self->type == TYPE_READ || self->type == TYPE_ACCEPT) && self->read_buffer != NULL) | 
| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 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); | 
| Victor Stinner | 41063d2 | 2015-01-26 22:30:49 +0100 | [diff] [blame] | 742 |             return SetFromWindowsErr(err); | 
| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 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); | 
| Victor Stinner | 41063d2 | 2015-01-26 22:30:49 +0100 | [diff] [blame] | 801 |             return SetFromWindowsErr(err); | 
| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 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 | { | 
| Steve Dower | cc16be8 | 2016-09-08 10:35:16 -0700 | [diff] [blame] | 976 |     Py_UNICODE *Host; | 
| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 977 |     unsigned short Port; | 
 | 978 |     unsigned long FlowInfo; | 
 | 979 |     unsigned long ScopeId; | 
 | 980 |  | 
 | 981 |     memset(Address, 0, Length); | 
 | 982 |  | 
| Steve Dower | cc16be8 | 2016-09-08 10:35:16 -0700 | [diff] [blame] | 983 |     if (PyArg_ParseTuple(obj, "uH", &Host, &Port)) | 
| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 984 |     { | 
 | 985 |         Address->sa_family = AF_INET; | 
| Steve Dower | cc16be8 | 2016-09-08 10:35:16 -0700 | [diff] [blame] | 986 |         if (WSAStringToAddressW(Host, AF_INET, NULL, Address, &Length) < 0) { | 
| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 987 |             SetFromWindowsErr(WSAGetLastError()); | 
 | 988 |             return -1; | 
 | 989 |         } | 
 | 990 |         ((SOCKADDR_IN*)Address)->sin_port = htons(Port); | 
 | 991 |         return Length; | 
 | 992 |     } | 
| Steve Dower | cc16be8 | 2016-09-08 10:35:16 -0700 | [diff] [blame] | 993 |     else if (PyArg_ParseTuple(obj, "uHkk", &Host, &Port, &FlowInfo, &ScopeId)) | 
| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 994 |     { | 
 | 995 |         PyErr_Clear(); | 
 | 996 |         Address->sa_family = AF_INET6; | 
| Steve Dower | cc16be8 | 2016-09-08 10:35:16 -0700 | [diff] [blame] | 997 |         if (WSAStringToAddressW(Host, AF_INET6, NULL, Address, &Length) < 0) { | 
| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 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); | 
| Victor Stinner | 2b77c54 | 2015-01-22 23:50:03 +0100 | [diff] [blame] | 1129 |             Py_RETURN_TRUE; | 
| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 1130 |         case ERROR_SUCCESS: | 
 | 1131 |         case ERROR_IO_PENDING: | 
| Victor Stinner | 2b77c54 | 2015-01-22 23:50:03 +0100 | [diff] [blame] | 1132 |             Py_RETURN_FALSE; | 
| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 1133 |         default: | 
 | 1134 |             self->type = TYPE_NOT_STARTED; | 
 | 1135 |             return SetFromWindowsErr(err); | 
 | 1136 |     } | 
 | 1137 | } | 
 | 1138 |  | 
| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 1139 | PyDoc_STRVAR( | 
| Victor Stinner | 7ffa2c5 | 2015-01-22 22:55:08 +0100 | [diff] [blame] | 1140 |     ConnectPipe_doc, | 
 | 1141 |     "ConnectPipe(addr) -> pipe_handle\n\n" | 
 | 1142 |     "Connect to the pipe for asynchronous I/O (overlapped)."); | 
| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 1143 |  | 
 | 1144 | static PyObject * | 
| Victor Stinner | 7ffa2c5 | 2015-01-22 22:55:08 +0100 | [diff] [blame] | 1145 | ConnectPipe(OverlappedObject *self, PyObject *args) | 
| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 1146 | { | 
| Victor Stinner | 7ffa2c5 | 2015-01-22 22:55:08 +0100 | [diff] [blame] | 1147 |     PyObject *AddressObj; | 
 | 1148 |     wchar_t *Address; | 
 | 1149 |     HANDLE PipeHandle; | 
| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 1150 |  | 
| Victor Stinner | 7ffa2c5 | 2015-01-22 22:55:08 +0100 | [diff] [blame] | 1151 |     if (!PyArg_ParseTuple(args, "U",  &AddressObj)) | 
| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 1152 |         return NULL; | 
 | 1153 |  | 
| Victor Stinner | 7ffa2c5 | 2015-01-22 22:55:08 +0100 | [diff] [blame] | 1154 |     Address = PyUnicode_AsWideCharString(AddressObj, NULL); | 
 | 1155 |     if (Address == NULL) | 
| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 1156 |         return NULL; | 
| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 1157 |  | 
| Victor Stinner | 498b1f6 | 2015-01-26 22:43:39 +0100 | [diff] [blame] | 1158 |     Py_BEGIN_ALLOW_THREADS | 
| Victor Stinner | 7ffa2c5 | 2015-01-22 22:55:08 +0100 | [diff] [blame] | 1159 |     PipeHandle = CreateFileW(Address, | 
 | 1160 |                              GENERIC_READ | GENERIC_WRITE, | 
 | 1161 |                              0, NULL, OPEN_EXISTING, | 
 | 1162 |                              FILE_FLAG_OVERLAPPED, NULL); | 
| Victor Stinner | 498b1f6 | 2015-01-26 22:43:39 +0100 | [diff] [blame] | 1163 |     Py_END_ALLOW_THREADS | 
 | 1164 |  | 
| Victor Stinner | 7ffa2c5 | 2015-01-22 22:55:08 +0100 | [diff] [blame] | 1165 |     PyMem_Free(Address); | 
 | 1166 |     if (PipeHandle == INVALID_HANDLE_VALUE) | 
 | 1167 |         return SetFromWindowsErr(0); | 
 | 1168 |     return Py_BuildValue(F_HANDLE, PipeHandle); | 
| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 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}, | 
| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 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}, | 
| Guido van Rossum | 90fb914 | 2013-10-30 14:44:05 -0700 | [diff] [blame] | 1278 |     {"RegisterWaitWithQueue", overlapped_RegisterWaitWithQueue, | 
 | 1279 |      METH_VARARGS, RegisterWaitWithQueue_doc}, | 
 | 1280 |     {"UnregisterWait", overlapped_UnregisterWait, | 
 | 1281 |      METH_VARARGS, UnregisterWait_doc}, | 
| Victor Stinner | d0a28de | 2015-01-21 23:39:51 +0100 | [diff] [blame] | 1282 |     {"UnregisterWaitEx", overlapped_UnregisterWaitEx, | 
 | 1283 |      METH_VARARGS, UnregisterWaitEx_doc}, | 
| Guido van Rossum | 90fb914 | 2013-10-30 14:44:05 -0700 | [diff] [blame] | 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}, | 
| Victor Stinner | 7ffa2c5 | 2015-01-22 22:55:08 +0100 | [diff] [blame] | 1290 |     {"ConnectPipe", | 
 | 1291 |      (PyCFunction) ConnectPipe, | 
 | 1292 |      METH_VARARGS, ConnectPipe_doc}, | 
| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 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); | 
| Victor Stinner | 7ffa2c5 | 2015-01-22 22:55:08 +0100 | [diff] [blame] | 1337 |     WINAPI_CONSTANT(F_DWORD,  ERROR_PIPE_BUSY); | 
| Guido van Rossum | 27b7c7e | 2013-10-17 13:40:50 -0700 | [diff] [blame] | 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 | } |