blob: 6099d46643f74739fad40d214e8fd5994c2861ed [file] [log] [blame]
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001/*
2 * Support for overlapped IO
3 *
4 * Some code borrowed from Modules/_winapi.c of CPython
5 */
6
7/* XXX check overflow and DWORD <-> Py_ssize_t conversions
8 Check itemsize */
9
10#include "Python.h"
11#include "structmember.h"
12
13#define WINDOWS_LEAN_AND_MEAN
14#include <winsock2.h>
15#include <ws2tcpip.h>
16#include <mswsock.h>
17
18#if defined(MS_WIN32) && !defined(MS_WIN64)
19# define F_POINTER "k"
20# define T_POINTER T_ULONG
21#else
22# define F_POINTER "K"
23# define T_POINTER T_ULONGLONG
24#endif
25
Victor Stinnerccdbe802016-04-01 21:37:41 +020026/* 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 Rossum27b7c7e2013-10-17 13:40:50 -070032#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
40enum {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
44typedef 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 Stinner91445fb2014-01-30 19:06:44 +010054 /* Buffer used for reading: TYPE_READ and TYPE_ACCEPT */
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070055 PyObject *read_buffer;
Victor Stinner91445fb2014-01-30 19:06:44 +010056 /* Buffer used for writing: TYPE_WRITE */
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070057 Py_buffer write_buffer;
58 };
59} OverlappedObject;
60
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070061/*
62 * Map Windows error codes to subclasses of OSError
63 */
64
65static PyObject *
66SetFromWindowsErr(DWORD err)
67{
68 PyObject *exception_type;
69
70 if (err == 0)
71 err = GetLastError();
72 switch (err) {
73 case ERROR_CONNECTION_REFUSED:
74 exception_type = PyExc_ConnectionRefusedError;
75 break;
76 case ERROR_CONNECTION_ABORTED:
77 exception_type = PyExc_ConnectionAbortedError;
78 break;
79 default:
80 exception_type = PyExc_OSError;
81 }
82 return PyErr_SetExcFromWindowsErr(exception_type, err);
83}
84
85/*
86 * Some functions should be loaded at runtime
87 */
88
89static LPFN_ACCEPTEX Py_AcceptEx = NULL;
90static LPFN_CONNECTEX Py_ConnectEx = NULL;
91static LPFN_DISCONNECTEX Py_DisconnectEx = NULL;
92static BOOL (CALLBACK *Py_CancelIoEx)(HANDLE, LPOVERLAPPED) = NULL;
93
94#define GET_WSA_POINTER(s, x) \
95 (SOCKET_ERROR != WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, \
96 &Guid##x, sizeof(Guid##x), &Py_##x, \
97 sizeof(Py_##x), &dwBytes, NULL, NULL))
98
99static int
100initialize_function_pointers(void)
101{
102 GUID GuidAcceptEx = WSAID_ACCEPTEX;
103 GUID GuidConnectEx = WSAID_CONNECTEX;
104 GUID GuidDisconnectEx = WSAID_DISCONNECTEX;
105 HINSTANCE hKernel32;
106 SOCKET s;
107 DWORD dwBytes;
108
109 s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
110 if (s == INVALID_SOCKET) {
111 SetFromWindowsErr(WSAGetLastError());
112 return -1;
113 }
114
115 if (!GET_WSA_POINTER(s, AcceptEx) ||
116 !GET_WSA_POINTER(s, ConnectEx) ||
117 !GET_WSA_POINTER(s, DisconnectEx))
118 {
119 closesocket(s);
120 SetFromWindowsErr(WSAGetLastError());
121 return -1;
122 }
123
124 closesocket(s);
125
126 /* On WinXP we will have Py_CancelIoEx == NULL */
127 hKernel32 = GetModuleHandle("KERNEL32");
128 *(FARPROC *)&Py_CancelIoEx = GetProcAddress(hKernel32, "CancelIoEx");
129 return 0;
130}
131
132/*
133 * Completion port stuff
134 */
135
136PyDoc_STRVAR(
137 CreateIoCompletionPort_doc,
138 "CreateIoCompletionPort(handle, port, key, concurrency) -> port\n\n"
139 "Create a completion port or register a handle with a port.");
140
141static PyObject *
142overlapped_CreateIoCompletionPort(PyObject *self, PyObject *args)
143{
144 HANDLE FileHandle;
145 HANDLE ExistingCompletionPort;
146 ULONG_PTR CompletionKey;
147 DWORD NumberOfConcurrentThreads;
148 HANDLE ret;
149
150 if (!PyArg_ParseTuple(args, F_HANDLE F_HANDLE F_ULONG_PTR F_DWORD,
151 &FileHandle, &ExistingCompletionPort, &CompletionKey,
152 &NumberOfConcurrentThreads))
153 return NULL;
154
155 Py_BEGIN_ALLOW_THREADS
156 ret = CreateIoCompletionPort(FileHandle, ExistingCompletionPort,
157 CompletionKey, NumberOfConcurrentThreads);
158 Py_END_ALLOW_THREADS
159
160 if (ret == NULL)
161 return SetFromWindowsErr(0);
162 return Py_BuildValue(F_HANDLE, ret);
163}
164
165PyDoc_STRVAR(
166 GetQueuedCompletionStatus_doc,
167 "GetQueuedCompletionStatus(port, msecs) -> (err, bytes, key, address)\n\n"
168 "Get a message from completion port. Wait for up to msecs milliseconds.");
169
170static PyObject *
171overlapped_GetQueuedCompletionStatus(PyObject *self, PyObject *args)
172{
173 HANDLE CompletionPort = NULL;
174 DWORD NumberOfBytes = 0;
175 ULONG_PTR CompletionKey = 0;
176 OVERLAPPED *Overlapped = NULL;
177 DWORD Milliseconds;
178 DWORD err;
179 BOOL ret;
180
181 if (!PyArg_ParseTuple(args, F_HANDLE F_DWORD,
182 &CompletionPort, &Milliseconds))
183 return NULL;
184
185 Py_BEGIN_ALLOW_THREADS
186 ret = GetQueuedCompletionStatus(CompletionPort, &NumberOfBytes,
187 &CompletionKey, &Overlapped, Milliseconds);
188 Py_END_ALLOW_THREADS
189
190 err = ret ? ERROR_SUCCESS : GetLastError();
191 if (Overlapped == NULL) {
192 if (err == WAIT_TIMEOUT)
193 Py_RETURN_NONE;
194 else
195 return SetFromWindowsErr(err);
196 }
197 return Py_BuildValue(F_DWORD F_DWORD F_ULONG_PTR F_POINTER,
198 err, NumberOfBytes, CompletionKey, Overlapped);
199}
200
201PyDoc_STRVAR(
202 PostQueuedCompletionStatus_doc,
203 "PostQueuedCompletionStatus(port, bytes, key, address) -> None\n\n"
204 "Post a message to completion port.");
205
206static PyObject *
207overlapped_PostQueuedCompletionStatus(PyObject *self, PyObject *args)
208{
209 HANDLE CompletionPort;
210 DWORD NumberOfBytes;
211 ULONG_PTR CompletionKey;
212 OVERLAPPED *Overlapped;
213 BOOL ret;
214
215 if (!PyArg_ParseTuple(args, F_HANDLE F_DWORD F_ULONG_PTR F_POINTER,
216 &CompletionPort, &NumberOfBytes, &CompletionKey,
217 &Overlapped))
218 return NULL;
219
220 Py_BEGIN_ALLOW_THREADS
221 ret = PostQueuedCompletionStatus(CompletionPort, NumberOfBytes,
222 CompletionKey, Overlapped);
223 Py_END_ALLOW_THREADS
224
225 if (!ret)
226 return SetFromWindowsErr(0);
227 Py_RETURN_NONE;
228}
229
230/*
Guido van Rossum90fb9142013-10-30 14:44:05 -0700231 * Wait for a handle
232 */
233
234struct PostCallbackData {
235 HANDLE CompletionPort;
236 LPOVERLAPPED Overlapped;
237};
238
239static VOID CALLBACK
240PostToQueueCallback(PVOID lpParameter, BOOL TimerOrWaitFired)
241{
242 struct PostCallbackData *p = (struct PostCallbackData*) lpParameter;
243
244 PostQueuedCompletionStatus(p->CompletionPort, TimerOrWaitFired,
245 0, p->Overlapped);
246 /* ignore possible error! */
Victor Stinner6150f312016-03-16 23:25:02 +0100247 PyMem_RawFree(p);
Guido van Rossum90fb9142013-10-30 14:44:05 -0700248}
249
250PyDoc_STRVAR(
251 RegisterWaitWithQueue_doc,
252 "RegisterWaitWithQueue(Object, CompletionPort, Overlapped, Timeout)\n"
253 " -> WaitHandle\n\n"
254 "Register wait for Object; when complete CompletionPort is notified.\n");
255
256static PyObject *
257overlapped_RegisterWaitWithQueue(PyObject *self, PyObject *args)
258{
259 HANDLE NewWaitObject;
260 HANDLE Object;
261 ULONG Milliseconds;
262 struct PostCallbackData data, *pdata;
263
264 if (!PyArg_ParseTuple(args, F_HANDLE F_HANDLE F_POINTER F_DWORD,
265 &Object,
266 &data.CompletionPort,
267 &data.Overlapped,
268 &Milliseconds))
269 return NULL;
270
Victor Stinner6150f312016-03-16 23:25:02 +0100271 /* 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 Rossum90fb9142013-10-30 14:44:05 -0700275 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 Stinner6150f312016-03-16 23:25:02 +0100285 PyMem_RawFree(pdata);
Guido van Rossum90fb9142013-10-30 14:44:05 -0700286 return SetFromWindowsErr(0);
287 }
288
289 return Py_BuildValue(F_HANDLE, NewWaitObject);
290}
291
292PyDoc_STRVAR(
293 UnregisterWait_doc,
294 "UnregisterWait(WaitHandle) -> None\n\n"
295 "Unregister wait handle.\n");
296
297static PyObject *
298overlapped_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 Stinnerd0a28de2015-01-21 23:39:51 +0100315PyDoc_STRVAR(
316 UnregisterWaitEx_doc,
317 "UnregisterWaitEx(WaitHandle, Event) -> None\n\n"
318 "Unregister wait handle.\n");
319
320static PyObject *
321overlapped_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 Rossum90fb9142013-10-30 14:44:05 -0700338/*
339 * Event functions -- currently only used by tests
340 */
341
342PyDoc_STRVAR(
343 CreateEvent_doc,
344 "CreateEvent(EventAttributes, ManualReset, InitialState, Name)"
345 " -> Handle\n\n"
346 "Create an event. EventAttributes must be None.\n");
347
348static PyObject *
349overlapped_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
376PyDoc_STRVAR(
377 SetEvent_doc,
378 "SetEvent(Handle) -> None\n\n"
379 "Set event.\n");
380
381static PyObject *
382overlapped_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
399PyDoc_STRVAR(
400 ResetEvent_doc,
401 "ResetEvent(Handle) -> None\n\n"
402 "Reset event.\n");
403
404static PyObject *
405overlapped_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 Rossum27b7c7e2013-10-17 13:40:50 -0700423 * Bind socket handle to local port without doing slow getaddrinfo()
424 */
425
426PyDoc_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
432static PyObject *
433overlapped_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
470PyDoc_STRVAR(
471 FormatMessage_doc,
472 "FormatMessage(error_code) -> error_message\n\n"
473 "Return error message for an error code.");
474
475static PyObject *
476overlapped_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
510static void
511mark_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
523PyDoc_STRVAR(
524 Overlapped_doc,
525 "Overlapped object");
526
527static PyObject *
528Overlapped_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
561static void
562Overlapped_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 Rossum27b7c7e2013-10-17 13:40:50 -0700597 switch (self->type) {
Victor Stinner91445fb2014-01-30 19:06:44 +0100598 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 Rossum27b7c7e2013-10-17 13:40:50 -0700606 }
607 PyObject_Del(self);
608 SetLastError(olderr);
609}
610
611PyDoc_STRVAR(
612 Overlapped_cancel_doc,
613 "cancel() -> None\n\n"
614 "Cancel overlapped operation");
615
616static PyObject *
617Overlapped_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
640PyDoc_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
647static PyObject *
648Overlapped_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 Stinner91445fb2014-01-30 19:06:44 +0100679 if ((self->type == TYPE_READ || self->type == TYPE_ACCEPT) && self->read_buffer != NULL)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700680 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
699PyDoc_STRVAR(
700 Overlapped_ReadFile_doc,
701 "ReadFile(handle, size) -> Overlapped[message]\n\n"
702 "Start overlapped read");
703
704static PyObject *
705Overlapped_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 Stinner41063d22015-01-26 22:30:49 +0100742 return SetFromWindowsErr(err);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700743 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
753PyDoc_STRVAR(
754 Overlapped_WSARecv_doc,
755 "RecvFile(handle, size, flags) -> Overlapped[message]\n\n"
756 "Start overlapped receive");
757
758static PyObject *
759Overlapped_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 Stinner41063d22015-01-26 22:30:49 +0100801 return SetFromWindowsErr(err);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700802 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
812PyDoc_STRVAR(
813 Overlapped_WriteFile_doc,
814 "WriteFile(handle, buf) -> Overlapped[bytes_transferred]\n\n"
815 "Start overlapped write");
816
817static PyObject *
818Overlapped_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);
Oren Milmand83c23b2017-08-15 19:04:18 +0300840 PyErr_SetString(PyExc_ValueError, "buffer too large");
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700841 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
865PyDoc_STRVAR(
866 Overlapped_WSASend_doc,
867 "WSASend(handle, buf, flags) -> Overlapped[bytes_transferred]\n\n"
868 "Start overlapped send");
869
870static PyObject *
871Overlapped_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);
Oren Milmand83c23b2017-08-15 19:04:18 +0300896 PyErr_SetString(PyExc_ValueError, "buffer too large");
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700897 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
922PyDoc_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
927static PyObject *
928Overlapped_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
973static int
974parse_address(PyObject *obj, SOCKADDR *Address, int Length)
975{
Steve Dowercc16be82016-09-08 10:35:16 -0700976 Py_UNICODE *Host;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700977 unsigned short Port;
978 unsigned long FlowInfo;
979 unsigned long ScopeId;
980
981 memset(Address, 0, Length);
982
Steve Dowercc16be82016-09-08 10:35:16 -0700983 if (PyArg_ParseTuple(obj, "uH", &Host, &Port))
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700984 {
985 Address->sa_family = AF_INET;
Steve Dowercc16be82016-09-08 10:35:16 -0700986 if (WSAStringToAddressW(Host, AF_INET, NULL, Address, &Length) < 0) {
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700987 SetFromWindowsErr(WSAGetLastError());
988 return -1;
989 }
990 ((SOCKADDR_IN*)Address)->sin_port = htons(Port);
991 return Length;
992 }
Oren Milman1d1d3e92017-08-20 18:35:36 +0300993 else if (PyArg_ParseTuple(obj,
994 "uHkk;ConnectEx(): illegal address_as_bytes "
995 "argument", &Host, &Port, &FlowInfo, &ScopeId))
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700996 {
997 PyErr_Clear();
998 Address->sa_family = AF_INET6;
Steve Dowercc16be82016-09-08 10:35:16 -0700999 if (WSAStringToAddressW(Host, AF_INET6, NULL, Address, &Length) < 0) {
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001000 SetFromWindowsErr(WSAGetLastError());
1001 return -1;
1002 }
1003 ((SOCKADDR_IN6*)Address)->sin6_port = htons(Port);
1004 ((SOCKADDR_IN6*)Address)->sin6_flowinfo = FlowInfo;
1005 ((SOCKADDR_IN6*)Address)->sin6_scope_id = ScopeId;
1006 return Length;
1007 }
1008
1009 return -1;
1010}
1011
1012
1013PyDoc_STRVAR(
1014 Overlapped_ConnectEx_doc,
1015 "ConnectEx(client_handle, address_as_bytes) -> Overlapped[None]\n\n"
1016 "Start overlapped connect. client_handle should be unbound.");
1017
1018static PyObject *
1019Overlapped_ConnectEx(OverlappedObject *self, PyObject *args)
1020{
1021 SOCKET ConnectSocket;
1022 PyObject *AddressObj;
1023 char AddressBuf[sizeof(struct sockaddr_in6)];
1024 SOCKADDR *Address = (SOCKADDR*)AddressBuf;
1025 int Length;
1026 BOOL ret;
1027 DWORD err;
1028
Oren Milman1d1d3e92017-08-20 18:35:36 +03001029 if (!PyArg_ParseTuple(args, F_HANDLE "O!:ConnectEx",
1030 &ConnectSocket, &PyTuple_Type, &AddressObj))
1031 {
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001032 return NULL;
Oren Milman1d1d3e92017-08-20 18:35:36 +03001033 }
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001034
1035 if (self->type != TYPE_NONE) {
1036 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1037 return NULL;
1038 }
1039
1040 Length = sizeof(AddressBuf);
1041 Length = parse_address(AddressObj, Address, Length);
1042 if (Length < 0)
1043 return NULL;
1044
1045 self->type = TYPE_CONNECT;
1046 self->handle = (HANDLE)ConnectSocket;
1047
1048 Py_BEGIN_ALLOW_THREADS
1049 ret = Py_ConnectEx(ConnectSocket, Address, Length,
1050 NULL, 0, NULL, &self->overlapped);
1051 Py_END_ALLOW_THREADS
1052
1053 self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError();
1054 switch (err) {
1055 case ERROR_SUCCESS:
1056 case ERROR_IO_PENDING:
1057 Py_RETURN_NONE;
1058 default:
1059 self->type = TYPE_NOT_STARTED;
1060 return SetFromWindowsErr(err);
1061 }
1062}
1063
1064PyDoc_STRVAR(
1065 Overlapped_DisconnectEx_doc,
1066 "DisconnectEx(handle, flags) -> Overlapped[None]\n\n"
1067 "Start overlapped connect. client_handle should be unbound.");
1068
1069static PyObject *
1070Overlapped_DisconnectEx(OverlappedObject *self, PyObject *args)
1071{
1072 SOCKET Socket;
1073 DWORD flags;
1074 BOOL ret;
1075 DWORD err;
1076
1077 if (!PyArg_ParseTuple(args, F_HANDLE F_DWORD, &Socket, &flags))
1078 return NULL;
1079
1080 if (self->type != TYPE_NONE) {
1081 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1082 return NULL;
1083 }
1084
1085 self->type = TYPE_DISCONNECT;
1086 self->handle = (HANDLE)Socket;
1087
1088 Py_BEGIN_ALLOW_THREADS
1089 ret = Py_DisconnectEx(Socket, &self->overlapped, flags, 0);
1090 Py_END_ALLOW_THREADS
1091
1092 self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError();
1093 switch (err) {
1094 case ERROR_SUCCESS:
1095 case ERROR_IO_PENDING:
1096 Py_RETURN_NONE;
1097 default:
1098 self->type = TYPE_NOT_STARTED;
1099 return SetFromWindowsErr(err);
1100 }
1101}
1102
1103PyDoc_STRVAR(
1104 Overlapped_ConnectNamedPipe_doc,
1105 "ConnectNamedPipe(handle) -> Overlapped[None]\n\n"
1106 "Start overlapped wait for a client to connect.");
1107
1108static PyObject *
1109Overlapped_ConnectNamedPipe(OverlappedObject *self, PyObject *args)
1110{
1111 HANDLE Pipe;
1112 BOOL ret;
1113 DWORD err;
1114
1115 if (!PyArg_ParseTuple(args, F_HANDLE, &Pipe))
1116 return NULL;
1117
1118 if (self->type != TYPE_NONE) {
1119 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1120 return NULL;
1121 }
1122
1123 self->type = TYPE_CONNECT_NAMED_PIPE;
1124 self->handle = Pipe;
1125
1126 Py_BEGIN_ALLOW_THREADS
1127 ret = ConnectNamedPipe(Pipe, &self->overlapped);
1128 Py_END_ALLOW_THREADS
1129
1130 self->error = err = ret ? ERROR_SUCCESS : GetLastError();
1131 switch (err) {
1132 case ERROR_PIPE_CONNECTED:
1133 mark_as_completed(&self->overlapped);
Victor Stinner2b77c542015-01-22 23:50:03 +01001134 Py_RETURN_TRUE;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001135 case ERROR_SUCCESS:
1136 case ERROR_IO_PENDING:
Victor Stinner2b77c542015-01-22 23:50:03 +01001137 Py_RETURN_FALSE;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001138 default:
1139 self->type = TYPE_NOT_STARTED;
1140 return SetFromWindowsErr(err);
1141 }
1142}
1143
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001144PyDoc_STRVAR(
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001145 ConnectPipe_doc,
1146 "ConnectPipe(addr) -> pipe_handle\n\n"
1147 "Connect to the pipe for asynchronous I/O (overlapped).");
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001148
1149static PyObject *
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001150ConnectPipe(OverlappedObject *self, PyObject *args)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001151{
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001152 PyObject *AddressObj;
1153 wchar_t *Address;
1154 HANDLE PipeHandle;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001155
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001156 if (!PyArg_ParseTuple(args, "U", &AddressObj))
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001157 return NULL;
1158
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001159 Address = PyUnicode_AsWideCharString(AddressObj, NULL);
1160 if (Address == NULL)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001161 return NULL;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001162
Victor Stinner498b1f62015-01-26 22:43:39 +01001163 Py_BEGIN_ALLOW_THREADS
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001164 PipeHandle = CreateFileW(Address,
1165 GENERIC_READ | GENERIC_WRITE,
1166 0, NULL, OPEN_EXISTING,
1167 FILE_FLAG_OVERLAPPED, NULL);
Victor Stinner498b1f62015-01-26 22:43:39 +01001168 Py_END_ALLOW_THREADS
1169
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001170 PyMem_Free(Address);
1171 if (PipeHandle == INVALID_HANDLE_VALUE)
1172 return SetFromWindowsErr(0);
1173 return Py_BuildValue(F_HANDLE, PipeHandle);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001174}
1175
1176static PyObject*
1177Overlapped_getaddress(OverlappedObject *self)
1178{
1179 return PyLong_FromVoidPtr(&self->overlapped);
1180}
1181
1182static PyObject*
1183Overlapped_getpending(OverlappedObject *self)
1184{
1185 return PyBool_FromLong(!HasOverlappedIoCompleted(&self->overlapped) &&
1186 self->type != TYPE_NOT_STARTED);
1187}
1188
1189static PyMethodDef Overlapped_methods[] = {
1190 {"getresult", (PyCFunction) Overlapped_getresult,
1191 METH_VARARGS, Overlapped_getresult_doc},
1192 {"cancel", (PyCFunction) Overlapped_cancel,
1193 METH_NOARGS, Overlapped_cancel_doc},
1194 {"ReadFile", (PyCFunction) Overlapped_ReadFile,
1195 METH_VARARGS, Overlapped_ReadFile_doc},
1196 {"WSARecv", (PyCFunction) Overlapped_WSARecv,
1197 METH_VARARGS, Overlapped_WSARecv_doc},
1198 {"WriteFile", (PyCFunction) Overlapped_WriteFile,
1199 METH_VARARGS, Overlapped_WriteFile_doc},
1200 {"WSASend", (PyCFunction) Overlapped_WSASend,
1201 METH_VARARGS, Overlapped_WSASend_doc},
1202 {"AcceptEx", (PyCFunction) Overlapped_AcceptEx,
1203 METH_VARARGS, Overlapped_AcceptEx_doc},
1204 {"ConnectEx", (PyCFunction) Overlapped_ConnectEx,
1205 METH_VARARGS, Overlapped_ConnectEx_doc},
1206 {"DisconnectEx", (PyCFunction) Overlapped_DisconnectEx,
1207 METH_VARARGS, Overlapped_DisconnectEx_doc},
1208 {"ConnectNamedPipe", (PyCFunction) Overlapped_ConnectNamedPipe,
1209 METH_VARARGS, Overlapped_ConnectNamedPipe_doc},
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001210 {NULL}
1211};
1212
1213static PyMemberDef Overlapped_members[] = {
1214 {"error", T_ULONG,
1215 offsetof(OverlappedObject, error),
1216 READONLY, "Error from last operation"},
1217 {"event", T_HANDLE,
1218 offsetof(OverlappedObject, overlapped) + offsetof(OVERLAPPED, hEvent),
1219 READONLY, "Overlapped event handle"},
1220 {NULL}
1221};
1222
1223static PyGetSetDef Overlapped_getsets[] = {
1224 {"address", (getter)Overlapped_getaddress, NULL,
1225 "Address of overlapped structure"},
1226 {"pending", (getter)Overlapped_getpending, NULL,
1227 "Whether the operation is pending"},
1228 {NULL},
1229};
1230
1231PyTypeObject OverlappedType = {
1232 PyVarObject_HEAD_INIT(NULL, 0)
1233 /* tp_name */ "_overlapped.Overlapped",
1234 /* tp_basicsize */ sizeof(OverlappedObject),
1235 /* tp_itemsize */ 0,
1236 /* tp_dealloc */ (destructor) Overlapped_dealloc,
1237 /* tp_print */ 0,
1238 /* tp_getattr */ 0,
1239 /* tp_setattr */ 0,
1240 /* tp_reserved */ 0,
1241 /* tp_repr */ 0,
1242 /* tp_as_number */ 0,
1243 /* tp_as_sequence */ 0,
1244 /* tp_as_mapping */ 0,
1245 /* tp_hash */ 0,
1246 /* tp_call */ 0,
1247 /* tp_str */ 0,
1248 /* tp_getattro */ 0,
1249 /* tp_setattro */ 0,
1250 /* tp_as_buffer */ 0,
1251 /* tp_flags */ Py_TPFLAGS_DEFAULT,
1252 /* tp_doc */ "OVERLAPPED structure wrapper",
1253 /* tp_traverse */ 0,
1254 /* tp_clear */ 0,
1255 /* tp_richcompare */ 0,
1256 /* tp_weaklistoffset */ 0,
1257 /* tp_iter */ 0,
1258 /* tp_iternext */ 0,
1259 /* tp_methods */ Overlapped_methods,
1260 /* tp_members */ Overlapped_members,
1261 /* tp_getset */ Overlapped_getsets,
1262 /* tp_base */ 0,
1263 /* tp_dict */ 0,
1264 /* tp_descr_get */ 0,
1265 /* tp_descr_set */ 0,
1266 /* tp_dictoffset */ 0,
1267 /* tp_init */ 0,
1268 /* tp_alloc */ 0,
1269 /* tp_new */ Overlapped_new,
1270};
1271
1272static PyMethodDef overlapped_functions[] = {
1273 {"CreateIoCompletionPort", overlapped_CreateIoCompletionPort,
1274 METH_VARARGS, CreateIoCompletionPort_doc},
1275 {"GetQueuedCompletionStatus", overlapped_GetQueuedCompletionStatus,
1276 METH_VARARGS, GetQueuedCompletionStatus_doc},
1277 {"PostQueuedCompletionStatus", overlapped_PostQueuedCompletionStatus,
1278 METH_VARARGS, PostQueuedCompletionStatus_doc},
1279 {"FormatMessage", overlapped_FormatMessage,
1280 METH_VARARGS, FormatMessage_doc},
1281 {"BindLocal", overlapped_BindLocal,
1282 METH_VARARGS, BindLocal_doc},
Guido van Rossum90fb9142013-10-30 14:44:05 -07001283 {"RegisterWaitWithQueue", overlapped_RegisterWaitWithQueue,
1284 METH_VARARGS, RegisterWaitWithQueue_doc},
1285 {"UnregisterWait", overlapped_UnregisterWait,
1286 METH_VARARGS, UnregisterWait_doc},
Victor Stinnerd0a28de2015-01-21 23:39:51 +01001287 {"UnregisterWaitEx", overlapped_UnregisterWaitEx,
1288 METH_VARARGS, UnregisterWaitEx_doc},
Guido van Rossum90fb9142013-10-30 14:44:05 -07001289 {"CreateEvent", overlapped_CreateEvent,
1290 METH_VARARGS, CreateEvent_doc},
1291 {"SetEvent", overlapped_SetEvent,
1292 METH_VARARGS, SetEvent_doc},
1293 {"ResetEvent", overlapped_ResetEvent,
1294 METH_VARARGS, ResetEvent_doc},
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001295 {"ConnectPipe",
1296 (PyCFunction) ConnectPipe,
1297 METH_VARARGS, ConnectPipe_doc},
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001298 {NULL}
1299};
1300
1301static struct PyModuleDef overlapped_module = {
1302 PyModuleDef_HEAD_INIT,
1303 "_overlapped",
1304 NULL,
1305 -1,
1306 overlapped_functions,
1307 NULL,
1308 NULL,
1309 NULL,
1310 NULL
1311};
1312
1313#define WINAPI_CONSTANT(fmt, con) \
1314 PyDict_SetItemString(d, #con, Py_BuildValue(fmt, con))
1315
1316PyMODINIT_FUNC
1317PyInit__overlapped(void)
1318{
1319 PyObject *m, *d;
1320
1321 /* Ensure WSAStartup() called before initializing function pointers */
1322 m = PyImport_ImportModule("_socket");
1323 if (!m)
1324 return NULL;
1325 Py_DECREF(m);
1326
1327 if (initialize_function_pointers() < 0)
1328 return NULL;
1329
1330 if (PyType_Ready(&OverlappedType) < 0)
1331 return NULL;
1332
1333 m = PyModule_Create(&overlapped_module);
1334 if (PyModule_AddObject(m, "Overlapped", (PyObject *)&OverlappedType) < 0)
1335 return NULL;
1336
1337 d = PyModule_GetDict(m);
1338
1339 WINAPI_CONSTANT(F_DWORD, ERROR_IO_PENDING);
1340 WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED);
1341 WINAPI_CONSTANT(F_DWORD, ERROR_SEM_TIMEOUT);
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001342 WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_BUSY);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001343 WINAPI_CONSTANT(F_DWORD, INFINITE);
1344 WINAPI_CONSTANT(F_HANDLE, INVALID_HANDLE_VALUE);
1345 WINAPI_CONSTANT(F_HANDLE, NULL);
1346 WINAPI_CONSTANT(F_DWORD, SO_UPDATE_ACCEPT_CONTEXT);
1347 WINAPI_CONSTANT(F_DWORD, SO_UPDATE_CONNECT_CONTEXT);
1348 WINAPI_CONSTANT(F_DWORD, TF_REUSE_SOCKET);
1349
1350 return m;
1351}