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