blob: 0aa8657898da13e29a51cb22c071341c499ac34a [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);
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
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);
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
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 }
Steve Dowercc16be82016-09-08 10:35:16 -0700993 else if (PyArg_ParseTuple(obj, "uHkk", &Host, &Port, &FlowInfo, &ScopeId))
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700994 {
995 PyErr_Clear();
996 Address->sa_family = AF_INET6;
Steve Dowercc16be82016-09-08 10:35:16 -0700997 if (WSAStringToAddressW(Host, AF_INET6, NULL, Address, &Length) < 0) {
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700998 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
1011PyDoc_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
1016static PyObject *
1017Overlapped_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
1059PyDoc_STRVAR(
1060 Overlapped_DisconnectEx_doc,
1061 "DisconnectEx(handle, flags) -> Overlapped[None]\n\n"
1062 "Start overlapped connect. client_handle should be unbound.");
1063
1064static PyObject *
1065Overlapped_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
1098PyDoc_STRVAR(
1099 Overlapped_ConnectNamedPipe_doc,
1100 "ConnectNamedPipe(handle) -> Overlapped[None]\n\n"
1101 "Start overlapped wait for a client to connect.");
1102
1103static PyObject *
1104Overlapped_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 Stinner2b77c542015-01-22 23:50:03 +01001129 Py_RETURN_TRUE;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001130 case ERROR_SUCCESS:
1131 case ERROR_IO_PENDING:
Victor Stinner2b77c542015-01-22 23:50:03 +01001132 Py_RETURN_FALSE;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001133 default:
1134 self->type = TYPE_NOT_STARTED;
1135 return SetFromWindowsErr(err);
1136 }
1137}
1138
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001139PyDoc_STRVAR(
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001140 ConnectPipe_doc,
1141 "ConnectPipe(addr) -> pipe_handle\n\n"
1142 "Connect to the pipe for asynchronous I/O (overlapped).");
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001143
1144static PyObject *
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001145ConnectPipe(OverlappedObject *self, PyObject *args)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001146{
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001147 PyObject *AddressObj;
1148 wchar_t *Address;
1149 HANDLE PipeHandle;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001150
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001151 if (!PyArg_ParseTuple(args, "U", &AddressObj))
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001152 return NULL;
1153
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001154 Address = PyUnicode_AsWideCharString(AddressObj, NULL);
1155 if (Address == NULL)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001156 return NULL;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001157
Victor Stinner498b1f62015-01-26 22:43:39 +01001158 Py_BEGIN_ALLOW_THREADS
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001159 PipeHandle = CreateFileW(Address,
1160 GENERIC_READ | GENERIC_WRITE,
1161 0, NULL, OPEN_EXISTING,
1162 FILE_FLAG_OVERLAPPED, NULL);
Victor Stinner498b1f62015-01-26 22:43:39 +01001163 Py_END_ALLOW_THREADS
1164
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001165 PyMem_Free(Address);
1166 if (PipeHandle == INVALID_HANDLE_VALUE)
1167 return SetFromWindowsErr(0);
1168 return Py_BuildValue(F_HANDLE, PipeHandle);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001169}
1170
1171static PyObject*
1172Overlapped_getaddress(OverlappedObject *self)
1173{
1174 return PyLong_FromVoidPtr(&self->overlapped);
1175}
1176
1177static PyObject*
1178Overlapped_getpending(OverlappedObject *self)
1179{
1180 return PyBool_FromLong(!HasOverlappedIoCompleted(&self->overlapped) &&
1181 self->type != TYPE_NOT_STARTED);
1182}
1183
1184static 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 Rossum27b7c7e2013-10-17 13:40:50 -07001205 {NULL}
1206};
1207
1208static 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
1218static 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
1226PyTypeObject 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
1267static 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 Rossum90fb9142013-10-30 14:44:05 -07001278 {"RegisterWaitWithQueue", overlapped_RegisterWaitWithQueue,
1279 METH_VARARGS, RegisterWaitWithQueue_doc},
1280 {"UnregisterWait", overlapped_UnregisterWait,
1281 METH_VARARGS, UnregisterWait_doc},
Victor Stinnerd0a28de2015-01-21 23:39:51 +01001282 {"UnregisterWaitEx", overlapped_UnregisterWaitEx,
1283 METH_VARARGS, UnregisterWaitEx_doc},
Guido van Rossum90fb9142013-10-30 14:44:05 -07001284 {"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 Stinner7ffa2c52015-01-22 22:55:08 +01001290 {"ConnectPipe",
1291 (PyCFunction) ConnectPipe,
1292 METH_VARARGS, ConnectPipe_doc},
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001293 {NULL}
1294};
1295
1296static 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
1311PyMODINIT_FUNC
1312PyInit__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 Stinner7ffa2c52015-01-22 22:55:08 +01001337 WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_BUSY);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001338 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}