blob: ef77c8875aa39ec69fbfa47eb05259ae53e8f7dd [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! */
241 PyMem_Free(p);
242}
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
265 pdata = PyMem_Malloc(sizeof(struct PostCallbackData));
266 if (pdata == NULL)
267 return SetFromWindowsErr(0);
268
269 *pdata = data;
270
271 if (!RegisterWaitForSingleObject(
272 &NewWaitObject, Object, (WAITORTIMERCALLBACK)PostToQueueCallback,
273 pdata, Milliseconds,
274 WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE))
275 {
276 PyMem_Free(pdata);
277 return SetFromWindowsErr(0);
278 }
279
280 return Py_BuildValue(F_HANDLE, NewWaitObject);
281}
282
283PyDoc_STRVAR(
284 UnregisterWait_doc,
285 "UnregisterWait(WaitHandle) -> None\n\n"
286 "Unregister wait handle.\n");
287
288static PyObject *
289overlapped_UnregisterWait(PyObject *self, PyObject *args)
290{
291 HANDLE WaitHandle;
292 BOOL ret;
293
294 if (!PyArg_ParseTuple(args, F_HANDLE, &WaitHandle))
295 return NULL;
296
297 Py_BEGIN_ALLOW_THREADS
298 ret = UnregisterWait(WaitHandle);
299 Py_END_ALLOW_THREADS
300
301 if (!ret)
302 return SetFromWindowsErr(0);
303 Py_RETURN_NONE;
304}
305
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100306PyDoc_STRVAR(
307 UnregisterWaitEx_doc,
308 "UnregisterWaitEx(WaitHandle, Event) -> None\n\n"
309 "Unregister wait handle.\n");
310
311static PyObject *
312overlapped_UnregisterWaitEx(PyObject *self, PyObject *args)
313{
314 HANDLE WaitHandle, Event;
315 BOOL ret;
316
317 if (!PyArg_ParseTuple(args, F_HANDLE F_HANDLE, &WaitHandle, &Event))
318 return NULL;
319
320 Py_BEGIN_ALLOW_THREADS
321 ret = UnregisterWaitEx(WaitHandle, Event);
322 Py_END_ALLOW_THREADS
323
324 if (!ret)
325 return SetFromWindowsErr(0);
326 Py_RETURN_NONE;
327}
328
Guido van Rossum90fb9142013-10-30 14:44:05 -0700329/*
330 * Event functions -- currently only used by tests
331 */
332
333PyDoc_STRVAR(
334 CreateEvent_doc,
335 "CreateEvent(EventAttributes, ManualReset, InitialState, Name)"
336 " -> Handle\n\n"
337 "Create an event. EventAttributes must be None.\n");
338
339static PyObject *
340overlapped_CreateEvent(PyObject *self, PyObject *args)
341{
342 PyObject *EventAttributes;
343 BOOL ManualReset;
344 BOOL InitialState;
345 Py_UNICODE *Name;
346 HANDLE Event;
347
348 if (!PyArg_ParseTuple(args, "O" F_BOOL F_BOOL "Z",
349 &EventAttributes, &ManualReset,
350 &InitialState, &Name))
351 return NULL;
352
353 if (EventAttributes != Py_None) {
354 PyErr_SetString(PyExc_ValueError, "EventAttributes must be None");
355 return NULL;
356 }
357
358 Py_BEGIN_ALLOW_THREADS
359 Event = CreateEventW(NULL, ManualReset, InitialState, Name);
360 Py_END_ALLOW_THREADS
361
362 if (Event == NULL)
363 return SetFromWindowsErr(0);
364 return Py_BuildValue(F_HANDLE, Event);
365}
366
367PyDoc_STRVAR(
368 SetEvent_doc,
369 "SetEvent(Handle) -> None\n\n"
370 "Set event.\n");
371
372static PyObject *
373overlapped_SetEvent(PyObject *self, PyObject *args)
374{
375 HANDLE Handle;
376 BOOL ret;
377
378 if (!PyArg_ParseTuple(args, F_HANDLE, &Handle))
379 return NULL;
380
381 Py_BEGIN_ALLOW_THREADS
382 ret = SetEvent(Handle);
383 Py_END_ALLOW_THREADS
384
385 if (!ret)
386 return SetFromWindowsErr(0);
387 Py_RETURN_NONE;
388}
389
390PyDoc_STRVAR(
391 ResetEvent_doc,
392 "ResetEvent(Handle) -> None\n\n"
393 "Reset event.\n");
394
395static PyObject *
396overlapped_ResetEvent(PyObject *self, PyObject *args)
397{
398 HANDLE Handle;
399 BOOL ret;
400
401 if (!PyArg_ParseTuple(args, F_HANDLE, &Handle))
402 return NULL;
403
404 Py_BEGIN_ALLOW_THREADS
405 ret = ResetEvent(Handle);
406 Py_END_ALLOW_THREADS
407
408 if (!ret)
409 return SetFromWindowsErr(0);
410 Py_RETURN_NONE;
411}
412
413/*
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700414 * Bind socket handle to local port without doing slow getaddrinfo()
415 */
416
417PyDoc_STRVAR(
418 BindLocal_doc,
419 "BindLocal(handle, family) -> None\n\n"
420 "Bind a socket handle to an arbitrary local port.\n"
421 "family should AF_INET or AF_INET6.\n");
422
423static PyObject *
424overlapped_BindLocal(PyObject *self, PyObject *args)
425{
426 SOCKET Socket;
427 int Family;
428 BOOL ret;
429
430 if (!PyArg_ParseTuple(args, F_HANDLE "i", &Socket, &Family))
431 return NULL;
432
433 if (Family == AF_INET) {
434 struct sockaddr_in addr;
435 memset(&addr, 0, sizeof(addr));
436 addr.sin_family = AF_INET;
437 addr.sin_port = 0;
438 addr.sin_addr.S_un.S_addr = INADDR_ANY;
439 ret = bind(Socket, (SOCKADDR*)&addr, sizeof(addr)) != SOCKET_ERROR;
440 } else if (Family == AF_INET6) {
441 struct sockaddr_in6 addr;
442 memset(&addr, 0, sizeof(addr));
443 addr.sin6_family = AF_INET6;
444 addr.sin6_port = 0;
445 addr.sin6_addr = in6addr_any;
446 ret = bind(Socket, (SOCKADDR*)&addr, sizeof(addr)) != SOCKET_ERROR;
447 } else {
448 PyErr_SetString(PyExc_ValueError, "expected tuple of length 2 or 4");
449 return NULL;
450 }
451
452 if (!ret)
453 return SetFromWindowsErr(WSAGetLastError());
454 Py_RETURN_NONE;
455}
456
457/*
458 * Windows equivalent of os.strerror() -- compare _ctypes/callproc.c
459 */
460
461PyDoc_STRVAR(
462 FormatMessage_doc,
463 "FormatMessage(error_code) -> error_message\n\n"
464 "Return error message for an error code.");
465
466static PyObject *
467overlapped_FormatMessage(PyObject *ignore, PyObject *args)
468{
469 DWORD code, n;
470 WCHAR *lpMsgBuf;
471 PyObject *res;
472
473 if (!PyArg_ParseTuple(args, F_DWORD, &code))
474 return NULL;
475
476 n = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
477 FORMAT_MESSAGE_FROM_SYSTEM,
478 NULL,
479 code,
480 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
481 (LPWSTR) &lpMsgBuf,
482 0,
483 NULL);
484 if (n) {
485 while (iswspace(lpMsgBuf[n-1]))
486 --n;
487 lpMsgBuf[n] = L'\0';
488 res = Py_BuildValue("u", lpMsgBuf);
489 } else {
490 res = PyUnicode_FromFormat("unknown error code %u", code);
491 }
492 LocalFree(lpMsgBuf);
493 return res;
494}
495
496
497/*
498 * Mark operation as completed - used when reading produces ERROR_BROKEN_PIPE
499 */
500
501static void
502mark_as_completed(OVERLAPPED *ov)
503{
504 ov->Internal = 0;
505 if (ov->hEvent != NULL)
506 SetEvent(ov->hEvent);
507}
508
509/*
510 * A Python object wrapping an OVERLAPPED structure and other useful data
511 * for overlapped I/O
512 */
513
514PyDoc_STRVAR(
515 Overlapped_doc,
516 "Overlapped object");
517
518static PyObject *
519Overlapped_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
520{
521 OverlappedObject *self;
522 HANDLE event = INVALID_HANDLE_VALUE;
523 static char *kwlist[] = {"event", NULL};
524
525 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|" F_HANDLE, kwlist, &event))
526 return NULL;
527
528 if (event == INVALID_HANDLE_VALUE) {
529 event = CreateEvent(NULL, TRUE, FALSE, NULL);
530 if (event == NULL)
531 return SetFromWindowsErr(0);
532 }
533
534 self = PyObject_New(OverlappedObject, type);
535 if (self == NULL) {
536 if (event != NULL)
537 CloseHandle(event);
538 return NULL;
539 }
540
541 self->handle = NULL;
542 self->error = 0;
543 self->type = TYPE_NONE;
544 self->read_buffer = NULL;
545 memset(&self->overlapped, 0, sizeof(OVERLAPPED));
546 memset(&self->write_buffer, 0, sizeof(Py_buffer));
547 if (event)
548 self->overlapped.hEvent = event;
549 return (PyObject *)self;
550}
551
552static void
553Overlapped_dealloc(OverlappedObject *self)
554{
555 DWORD bytes;
556 DWORD olderr = GetLastError();
557 BOOL wait = FALSE;
558 BOOL ret;
559
560 if (!HasOverlappedIoCompleted(&self->overlapped) &&
561 self->type != TYPE_NOT_STARTED)
562 {
563 if (Py_CancelIoEx && Py_CancelIoEx(self->handle, &self->overlapped))
564 wait = TRUE;
565
566 Py_BEGIN_ALLOW_THREADS
567 ret = GetOverlappedResult(self->handle, &self->overlapped,
568 &bytes, wait);
569 Py_END_ALLOW_THREADS
570
571 switch (ret ? ERROR_SUCCESS : GetLastError()) {
572 case ERROR_SUCCESS:
573 case ERROR_NOT_FOUND:
574 case ERROR_OPERATION_ABORTED:
575 break;
576 default:
577 PyErr_Format(
578 PyExc_RuntimeError,
579 "%R still has pending operation at "
580 "deallocation, the process may crash", self);
581 PyErr_WriteUnraisable(NULL);
582 }
583 }
584
585 if (self->overlapped.hEvent != NULL)
586 CloseHandle(self->overlapped.hEvent);
587
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700588 switch (self->type) {
Victor Stinner91445fb2014-01-30 19:06:44 +0100589 case TYPE_READ:
590 case TYPE_ACCEPT:
591 Py_CLEAR(self->read_buffer);
592 break;
593 case TYPE_WRITE:
594 if (self->write_buffer.obj)
595 PyBuffer_Release(&self->write_buffer);
596 break;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700597 }
598 PyObject_Del(self);
599 SetLastError(olderr);
600}
601
602PyDoc_STRVAR(
603 Overlapped_cancel_doc,
604 "cancel() -> None\n\n"
605 "Cancel overlapped operation");
606
607static PyObject *
608Overlapped_cancel(OverlappedObject *self)
609{
610 BOOL ret = TRUE;
611
612 if (self->type == TYPE_NOT_STARTED
613 || self->type == TYPE_WAIT_NAMED_PIPE_AND_CONNECT)
614 Py_RETURN_NONE;
615
616 if (!HasOverlappedIoCompleted(&self->overlapped)) {
617 Py_BEGIN_ALLOW_THREADS
618 if (Py_CancelIoEx)
619 ret = Py_CancelIoEx(self->handle, &self->overlapped);
620 else
621 ret = CancelIo(self->handle);
622 Py_END_ALLOW_THREADS
623 }
624
625 /* CancelIoEx returns ERROR_NOT_FOUND if the I/O completed in-between */
626 if (!ret && GetLastError() != ERROR_NOT_FOUND)
627 return SetFromWindowsErr(0);
628 Py_RETURN_NONE;
629}
630
631PyDoc_STRVAR(
632 Overlapped_getresult_doc,
633 "getresult(wait=False) -> result\n\n"
634 "Retrieve result of operation. If wait is true then it blocks\n"
635 "until the operation is finished. If wait is false and the\n"
636 "operation is still pending then an error is raised.");
637
638static PyObject *
639Overlapped_getresult(OverlappedObject *self, PyObject *args)
640{
641 BOOL wait = FALSE;
642 DWORD transferred = 0;
643 BOOL ret;
644 DWORD err;
645
646 if (!PyArg_ParseTuple(args, "|" F_BOOL, &wait))
647 return NULL;
648
649 if (self->type == TYPE_NONE) {
650 PyErr_SetString(PyExc_ValueError, "operation not yet attempted");
651 return NULL;
652 }
653
654 if (self->type == TYPE_NOT_STARTED) {
655 PyErr_SetString(PyExc_ValueError, "operation failed to start");
656 return NULL;
657 }
658
659 Py_BEGIN_ALLOW_THREADS
660 ret = GetOverlappedResult(self->handle, &self->overlapped, &transferred,
661 wait);
662 Py_END_ALLOW_THREADS
663
664 self->error = err = ret ? ERROR_SUCCESS : GetLastError();
665 switch (err) {
666 case ERROR_SUCCESS:
667 case ERROR_MORE_DATA:
668 break;
669 case ERROR_BROKEN_PIPE:
Victor Stinner91445fb2014-01-30 19:06:44 +0100670 if ((self->type == TYPE_READ || self->type == TYPE_ACCEPT) && self->read_buffer != NULL)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700671 break;
672 /* fall through */
673 default:
674 return SetFromWindowsErr(err);
675 }
676
677 switch (self->type) {
678 case TYPE_READ:
679 assert(PyBytes_CheckExact(self->read_buffer));
680 if (transferred != PyBytes_GET_SIZE(self->read_buffer) &&
681 _PyBytes_Resize(&self->read_buffer, transferred))
682 return NULL;
683 Py_INCREF(self->read_buffer);
684 return self->read_buffer;
685 default:
686 return PyLong_FromUnsignedLong((unsigned long) transferred);
687 }
688}
689
690PyDoc_STRVAR(
691 Overlapped_ReadFile_doc,
692 "ReadFile(handle, size) -> Overlapped[message]\n\n"
693 "Start overlapped read");
694
695static PyObject *
696Overlapped_ReadFile(OverlappedObject *self, PyObject *args)
697{
698 HANDLE handle;
699 DWORD size;
700 DWORD nread;
701 PyObject *buf;
702 BOOL ret;
703 DWORD err;
704
705 if (!PyArg_ParseTuple(args, F_HANDLE F_DWORD, &handle, &size))
706 return NULL;
707
708 if (self->type != TYPE_NONE) {
709 PyErr_SetString(PyExc_ValueError, "operation already attempted");
710 return NULL;
711 }
712
713#if SIZEOF_SIZE_T <= SIZEOF_LONG
714 size = Py_MIN(size, (DWORD)PY_SSIZE_T_MAX);
715#endif
716 buf = PyBytes_FromStringAndSize(NULL, Py_MAX(size, 1));
717 if (buf == NULL)
718 return NULL;
719
720 self->type = TYPE_READ;
721 self->handle = handle;
722 self->read_buffer = buf;
723
724 Py_BEGIN_ALLOW_THREADS
725 ret = ReadFile(handle, PyBytes_AS_STRING(buf), size, &nread,
726 &self->overlapped);
727 Py_END_ALLOW_THREADS
728
729 self->error = err = ret ? ERROR_SUCCESS : GetLastError();
730 switch (err) {
731 case ERROR_BROKEN_PIPE:
732 mark_as_completed(&self->overlapped);
Victor Stinner41063d22015-01-26 22:30:49 +0100733 return SetFromWindowsErr(err);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700734 case ERROR_SUCCESS:
735 case ERROR_MORE_DATA:
736 case ERROR_IO_PENDING:
737 Py_RETURN_NONE;
738 default:
739 self->type = TYPE_NOT_STARTED;
740 return SetFromWindowsErr(err);
741 }
742}
743
744PyDoc_STRVAR(
745 Overlapped_WSARecv_doc,
746 "RecvFile(handle, size, flags) -> Overlapped[message]\n\n"
747 "Start overlapped receive");
748
749static PyObject *
750Overlapped_WSARecv(OverlappedObject *self, PyObject *args)
751{
752 HANDLE handle;
753 DWORD size;
754 DWORD flags = 0;
755 DWORD nread;
756 PyObject *buf;
757 WSABUF wsabuf;
758 int ret;
759 DWORD err;
760
761 if (!PyArg_ParseTuple(args, F_HANDLE F_DWORD "|" F_DWORD,
762 &handle, &size, &flags))
763 return NULL;
764
765 if (self->type != TYPE_NONE) {
766 PyErr_SetString(PyExc_ValueError, "operation already attempted");
767 return NULL;
768 }
769
770#if SIZEOF_SIZE_T <= SIZEOF_LONG
771 size = Py_MIN(size, (DWORD)PY_SSIZE_T_MAX);
772#endif
773 buf = PyBytes_FromStringAndSize(NULL, Py_MAX(size, 1));
774 if (buf == NULL)
775 return NULL;
776
777 self->type = TYPE_READ;
778 self->handle = handle;
779 self->read_buffer = buf;
780 wsabuf.len = size;
781 wsabuf.buf = PyBytes_AS_STRING(buf);
782
783 Py_BEGIN_ALLOW_THREADS
784 ret = WSARecv((SOCKET)handle, &wsabuf, 1, &nread, &flags,
785 &self->overlapped, NULL);
786 Py_END_ALLOW_THREADS
787
788 self->error = err = (ret < 0 ? WSAGetLastError() : ERROR_SUCCESS);
789 switch (err) {
790 case ERROR_BROKEN_PIPE:
791 mark_as_completed(&self->overlapped);
Victor Stinner41063d22015-01-26 22:30:49 +0100792 return SetFromWindowsErr(err);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700793 case ERROR_SUCCESS:
794 case ERROR_MORE_DATA:
795 case ERROR_IO_PENDING:
796 Py_RETURN_NONE;
797 default:
798 self->type = TYPE_NOT_STARTED;
799 return SetFromWindowsErr(err);
800 }
801}
802
803PyDoc_STRVAR(
804 Overlapped_WriteFile_doc,
805 "WriteFile(handle, buf) -> Overlapped[bytes_transferred]\n\n"
806 "Start overlapped write");
807
808static PyObject *
809Overlapped_WriteFile(OverlappedObject *self, PyObject *args)
810{
811 HANDLE handle;
812 PyObject *bufobj;
813 DWORD written;
814 BOOL ret;
815 DWORD err;
816
817 if (!PyArg_ParseTuple(args, F_HANDLE "O", &handle, &bufobj))
818 return NULL;
819
820 if (self->type != TYPE_NONE) {
821 PyErr_SetString(PyExc_ValueError, "operation already attempted");
822 return NULL;
823 }
824
825 if (!PyArg_Parse(bufobj, "y*", &self->write_buffer))
826 return NULL;
827
828#if SIZEOF_SIZE_T > SIZEOF_LONG
829 if (self->write_buffer.len > (Py_ssize_t)ULONG_MAX) {
830 PyBuffer_Release(&self->write_buffer);
831 PyErr_SetString(PyExc_ValueError, "buffer to large");
832 return NULL;
833 }
834#endif
835
836 self->type = TYPE_WRITE;
837 self->handle = handle;
838
839 Py_BEGIN_ALLOW_THREADS
840 ret = WriteFile(handle, self->write_buffer.buf,
841 (DWORD)self->write_buffer.len,
842 &written, &self->overlapped);
843 Py_END_ALLOW_THREADS
844
845 self->error = err = ret ? ERROR_SUCCESS : GetLastError();
846 switch (err) {
847 case ERROR_SUCCESS:
848 case ERROR_IO_PENDING:
849 Py_RETURN_NONE;
850 default:
851 self->type = TYPE_NOT_STARTED;
852 return SetFromWindowsErr(err);
853 }
854}
855
856PyDoc_STRVAR(
857 Overlapped_WSASend_doc,
858 "WSASend(handle, buf, flags) -> Overlapped[bytes_transferred]\n\n"
859 "Start overlapped send");
860
861static PyObject *
862Overlapped_WSASend(OverlappedObject *self, PyObject *args)
863{
864 HANDLE handle;
865 PyObject *bufobj;
866 DWORD flags;
867 DWORD written;
868 WSABUF wsabuf;
869 int ret;
870 DWORD err;
871
872 if (!PyArg_ParseTuple(args, F_HANDLE "O" F_DWORD,
873 &handle, &bufobj, &flags))
874 return NULL;
875
876 if (self->type != TYPE_NONE) {
877 PyErr_SetString(PyExc_ValueError, "operation already attempted");
878 return NULL;
879 }
880
881 if (!PyArg_Parse(bufobj, "y*", &self->write_buffer))
882 return NULL;
883
884#if SIZEOF_SIZE_T > SIZEOF_LONG
885 if (self->write_buffer.len > (Py_ssize_t)ULONG_MAX) {
886 PyBuffer_Release(&self->write_buffer);
887 PyErr_SetString(PyExc_ValueError, "buffer to large");
888 return NULL;
889 }
890#endif
891
892 self->type = TYPE_WRITE;
893 self->handle = handle;
894 wsabuf.len = (DWORD)self->write_buffer.len;
895 wsabuf.buf = self->write_buffer.buf;
896
897 Py_BEGIN_ALLOW_THREADS
898 ret = WSASend((SOCKET)handle, &wsabuf, 1, &written, flags,
899 &self->overlapped, NULL);
900 Py_END_ALLOW_THREADS
901
902 self->error = err = (ret < 0 ? WSAGetLastError() : ERROR_SUCCESS);
903 switch (err) {
904 case ERROR_SUCCESS:
905 case ERROR_IO_PENDING:
906 Py_RETURN_NONE;
907 default:
908 self->type = TYPE_NOT_STARTED;
909 return SetFromWindowsErr(err);
910 }
911}
912
913PyDoc_STRVAR(
914 Overlapped_AcceptEx_doc,
915 "AcceptEx(listen_handle, accept_handle) -> Overlapped[address_as_bytes]\n\n"
916 "Start overlapped wait for client to connect");
917
918static PyObject *
919Overlapped_AcceptEx(OverlappedObject *self, PyObject *args)
920{
921 SOCKET ListenSocket;
922 SOCKET AcceptSocket;
923 DWORD BytesReceived;
924 DWORD size;
925 PyObject *buf;
926 BOOL ret;
927 DWORD err;
928
929 if (!PyArg_ParseTuple(args, F_HANDLE F_HANDLE,
930 &ListenSocket, &AcceptSocket))
931 return NULL;
932
933 if (self->type != TYPE_NONE) {
934 PyErr_SetString(PyExc_ValueError, "operation already attempted");
935 return NULL;
936 }
937
938 size = sizeof(struct sockaddr_in6) + 16;
939 buf = PyBytes_FromStringAndSize(NULL, size*2);
940 if (!buf)
941 return NULL;
942
943 self->type = TYPE_ACCEPT;
944 self->handle = (HANDLE)ListenSocket;
945 self->read_buffer = buf;
946
947 Py_BEGIN_ALLOW_THREADS
948 ret = Py_AcceptEx(ListenSocket, AcceptSocket, PyBytes_AS_STRING(buf),
949 0, size, size, &BytesReceived, &self->overlapped);
950 Py_END_ALLOW_THREADS
951
952 self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError();
953 switch (err) {
954 case ERROR_SUCCESS:
955 case ERROR_IO_PENDING:
956 Py_RETURN_NONE;
957 default:
958 self->type = TYPE_NOT_STARTED;
959 return SetFromWindowsErr(err);
960 }
961}
962
963
964static int
965parse_address(PyObject *obj, SOCKADDR *Address, int Length)
966{
967 char *Host;
968 unsigned short Port;
969 unsigned long FlowInfo;
970 unsigned long ScopeId;
971
972 memset(Address, 0, Length);
973
974 if (PyArg_ParseTuple(obj, "sH", &Host, &Port))
975 {
976 Address->sa_family = AF_INET;
977 if (WSAStringToAddressA(Host, AF_INET, NULL, Address, &Length) < 0) {
978 SetFromWindowsErr(WSAGetLastError());
979 return -1;
980 }
981 ((SOCKADDR_IN*)Address)->sin_port = htons(Port);
982 return Length;
983 }
984 else if (PyArg_ParseTuple(obj, "sHkk", &Host, &Port, &FlowInfo, &ScopeId))
985 {
986 PyErr_Clear();
987 Address->sa_family = AF_INET6;
988 if (WSAStringToAddressA(Host, AF_INET6, NULL, Address, &Length) < 0) {
989 SetFromWindowsErr(WSAGetLastError());
990 return -1;
991 }
992 ((SOCKADDR_IN6*)Address)->sin6_port = htons(Port);
993 ((SOCKADDR_IN6*)Address)->sin6_flowinfo = FlowInfo;
994 ((SOCKADDR_IN6*)Address)->sin6_scope_id = ScopeId;
995 return Length;
996 }
997
998 return -1;
999}
1000
1001
1002PyDoc_STRVAR(
1003 Overlapped_ConnectEx_doc,
1004 "ConnectEx(client_handle, address_as_bytes) -> Overlapped[None]\n\n"
1005 "Start overlapped connect. client_handle should be unbound.");
1006
1007static PyObject *
1008Overlapped_ConnectEx(OverlappedObject *self, PyObject *args)
1009{
1010 SOCKET ConnectSocket;
1011 PyObject *AddressObj;
1012 char AddressBuf[sizeof(struct sockaddr_in6)];
1013 SOCKADDR *Address = (SOCKADDR*)AddressBuf;
1014 int Length;
1015 BOOL ret;
1016 DWORD err;
1017
1018 if (!PyArg_ParseTuple(args, F_HANDLE "O", &ConnectSocket, &AddressObj))
1019 return NULL;
1020
1021 if (self->type != TYPE_NONE) {
1022 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1023 return NULL;
1024 }
1025
1026 Length = sizeof(AddressBuf);
1027 Length = parse_address(AddressObj, Address, Length);
1028 if (Length < 0)
1029 return NULL;
1030
1031 self->type = TYPE_CONNECT;
1032 self->handle = (HANDLE)ConnectSocket;
1033
1034 Py_BEGIN_ALLOW_THREADS
1035 ret = Py_ConnectEx(ConnectSocket, Address, Length,
1036 NULL, 0, NULL, &self->overlapped);
1037 Py_END_ALLOW_THREADS
1038
1039 self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError();
1040 switch (err) {
1041 case ERROR_SUCCESS:
1042 case ERROR_IO_PENDING:
1043 Py_RETURN_NONE;
1044 default:
1045 self->type = TYPE_NOT_STARTED;
1046 return SetFromWindowsErr(err);
1047 }
1048}
1049
1050PyDoc_STRVAR(
1051 Overlapped_DisconnectEx_doc,
1052 "DisconnectEx(handle, flags) -> Overlapped[None]\n\n"
1053 "Start overlapped connect. client_handle should be unbound.");
1054
1055static PyObject *
1056Overlapped_DisconnectEx(OverlappedObject *self, PyObject *args)
1057{
1058 SOCKET Socket;
1059 DWORD flags;
1060 BOOL ret;
1061 DWORD err;
1062
1063 if (!PyArg_ParseTuple(args, F_HANDLE F_DWORD, &Socket, &flags))
1064 return NULL;
1065
1066 if (self->type != TYPE_NONE) {
1067 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1068 return NULL;
1069 }
1070
1071 self->type = TYPE_DISCONNECT;
1072 self->handle = (HANDLE)Socket;
1073
1074 Py_BEGIN_ALLOW_THREADS
1075 ret = Py_DisconnectEx(Socket, &self->overlapped, flags, 0);
1076 Py_END_ALLOW_THREADS
1077
1078 self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError();
1079 switch (err) {
1080 case ERROR_SUCCESS:
1081 case ERROR_IO_PENDING:
1082 Py_RETURN_NONE;
1083 default:
1084 self->type = TYPE_NOT_STARTED;
1085 return SetFromWindowsErr(err);
1086 }
1087}
1088
1089PyDoc_STRVAR(
1090 Overlapped_ConnectNamedPipe_doc,
1091 "ConnectNamedPipe(handle) -> Overlapped[None]\n\n"
1092 "Start overlapped wait for a client to connect.");
1093
1094static PyObject *
1095Overlapped_ConnectNamedPipe(OverlappedObject *self, PyObject *args)
1096{
1097 HANDLE Pipe;
1098 BOOL ret;
1099 DWORD err;
1100
1101 if (!PyArg_ParseTuple(args, F_HANDLE, &Pipe))
1102 return NULL;
1103
1104 if (self->type != TYPE_NONE) {
1105 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1106 return NULL;
1107 }
1108
1109 self->type = TYPE_CONNECT_NAMED_PIPE;
1110 self->handle = Pipe;
1111
1112 Py_BEGIN_ALLOW_THREADS
1113 ret = ConnectNamedPipe(Pipe, &self->overlapped);
1114 Py_END_ALLOW_THREADS
1115
1116 self->error = err = ret ? ERROR_SUCCESS : GetLastError();
1117 switch (err) {
1118 case ERROR_PIPE_CONNECTED:
1119 mark_as_completed(&self->overlapped);
Victor Stinner2b77c542015-01-22 23:50:03 +01001120 Py_RETURN_TRUE;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001121 case ERROR_SUCCESS:
1122 case ERROR_IO_PENDING:
Victor Stinner2b77c542015-01-22 23:50:03 +01001123 Py_RETURN_FALSE;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001124 default:
1125 self->type = TYPE_NOT_STARTED;
1126 return SetFromWindowsErr(err);
1127 }
1128}
1129
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001130PyDoc_STRVAR(
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001131 ConnectPipe_doc,
1132 "ConnectPipe(addr) -> pipe_handle\n\n"
1133 "Connect to the pipe for asynchronous I/O (overlapped).");
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001134
1135static PyObject *
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001136ConnectPipe(OverlappedObject *self, PyObject *args)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001137{
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001138 PyObject *AddressObj;
1139 wchar_t *Address;
1140 HANDLE PipeHandle;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001141
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001142 if (!PyArg_ParseTuple(args, "U", &AddressObj))
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001143 return NULL;
1144
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001145 Address = PyUnicode_AsWideCharString(AddressObj, NULL);
1146 if (Address == NULL)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001147 return NULL;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001148
Victor Stinner498b1f62015-01-26 22:43:39 +01001149 Py_BEGIN_ALLOW_THREADS
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001150 PipeHandle = CreateFileW(Address,
1151 GENERIC_READ | GENERIC_WRITE,
1152 0, NULL, OPEN_EXISTING,
1153 FILE_FLAG_OVERLAPPED, NULL);
Victor Stinner498b1f62015-01-26 22:43:39 +01001154 Py_END_ALLOW_THREADS
1155
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001156 PyMem_Free(Address);
1157 if (PipeHandle == INVALID_HANDLE_VALUE)
1158 return SetFromWindowsErr(0);
1159 return Py_BuildValue(F_HANDLE, PipeHandle);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001160}
1161
1162static PyObject*
1163Overlapped_getaddress(OverlappedObject *self)
1164{
1165 return PyLong_FromVoidPtr(&self->overlapped);
1166}
1167
1168static PyObject*
1169Overlapped_getpending(OverlappedObject *self)
1170{
1171 return PyBool_FromLong(!HasOverlappedIoCompleted(&self->overlapped) &&
1172 self->type != TYPE_NOT_STARTED);
1173}
1174
1175static PyMethodDef Overlapped_methods[] = {
1176 {"getresult", (PyCFunction) Overlapped_getresult,
1177 METH_VARARGS, Overlapped_getresult_doc},
1178 {"cancel", (PyCFunction) Overlapped_cancel,
1179 METH_NOARGS, Overlapped_cancel_doc},
1180 {"ReadFile", (PyCFunction) Overlapped_ReadFile,
1181 METH_VARARGS, Overlapped_ReadFile_doc},
1182 {"WSARecv", (PyCFunction) Overlapped_WSARecv,
1183 METH_VARARGS, Overlapped_WSARecv_doc},
1184 {"WriteFile", (PyCFunction) Overlapped_WriteFile,
1185 METH_VARARGS, Overlapped_WriteFile_doc},
1186 {"WSASend", (PyCFunction) Overlapped_WSASend,
1187 METH_VARARGS, Overlapped_WSASend_doc},
1188 {"AcceptEx", (PyCFunction) Overlapped_AcceptEx,
1189 METH_VARARGS, Overlapped_AcceptEx_doc},
1190 {"ConnectEx", (PyCFunction) Overlapped_ConnectEx,
1191 METH_VARARGS, Overlapped_ConnectEx_doc},
1192 {"DisconnectEx", (PyCFunction) Overlapped_DisconnectEx,
1193 METH_VARARGS, Overlapped_DisconnectEx_doc},
1194 {"ConnectNamedPipe", (PyCFunction) Overlapped_ConnectNamedPipe,
1195 METH_VARARGS, Overlapped_ConnectNamedPipe_doc},
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001196 {NULL}
1197};
1198
1199static PyMemberDef Overlapped_members[] = {
1200 {"error", T_ULONG,
1201 offsetof(OverlappedObject, error),
1202 READONLY, "Error from last operation"},
1203 {"event", T_HANDLE,
1204 offsetof(OverlappedObject, overlapped) + offsetof(OVERLAPPED, hEvent),
1205 READONLY, "Overlapped event handle"},
1206 {NULL}
1207};
1208
1209static PyGetSetDef Overlapped_getsets[] = {
1210 {"address", (getter)Overlapped_getaddress, NULL,
1211 "Address of overlapped structure"},
1212 {"pending", (getter)Overlapped_getpending, NULL,
1213 "Whether the operation is pending"},
1214 {NULL},
1215};
1216
1217PyTypeObject OverlappedType = {
1218 PyVarObject_HEAD_INIT(NULL, 0)
1219 /* tp_name */ "_overlapped.Overlapped",
1220 /* tp_basicsize */ sizeof(OverlappedObject),
1221 /* tp_itemsize */ 0,
1222 /* tp_dealloc */ (destructor) Overlapped_dealloc,
1223 /* tp_print */ 0,
1224 /* tp_getattr */ 0,
1225 /* tp_setattr */ 0,
1226 /* tp_reserved */ 0,
1227 /* tp_repr */ 0,
1228 /* tp_as_number */ 0,
1229 /* tp_as_sequence */ 0,
1230 /* tp_as_mapping */ 0,
1231 /* tp_hash */ 0,
1232 /* tp_call */ 0,
1233 /* tp_str */ 0,
1234 /* tp_getattro */ 0,
1235 /* tp_setattro */ 0,
1236 /* tp_as_buffer */ 0,
1237 /* tp_flags */ Py_TPFLAGS_DEFAULT,
1238 /* tp_doc */ "OVERLAPPED structure wrapper",
1239 /* tp_traverse */ 0,
1240 /* tp_clear */ 0,
1241 /* tp_richcompare */ 0,
1242 /* tp_weaklistoffset */ 0,
1243 /* tp_iter */ 0,
1244 /* tp_iternext */ 0,
1245 /* tp_methods */ Overlapped_methods,
1246 /* tp_members */ Overlapped_members,
1247 /* tp_getset */ Overlapped_getsets,
1248 /* tp_base */ 0,
1249 /* tp_dict */ 0,
1250 /* tp_descr_get */ 0,
1251 /* tp_descr_set */ 0,
1252 /* tp_dictoffset */ 0,
1253 /* tp_init */ 0,
1254 /* tp_alloc */ 0,
1255 /* tp_new */ Overlapped_new,
1256};
1257
1258static PyMethodDef overlapped_functions[] = {
1259 {"CreateIoCompletionPort", overlapped_CreateIoCompletionPort,
1260 METH_VARARGS, CreateIoCompletionPort_doc},
1261 {"GetQueuedCompletionStatus", overlapped_GetQueuedCompletionStatus,
1262 METH_VARARGS, GetQueuedCompletionStatus_doc},
1263 {"PostQueuedCompletionStatus", overlapped_PostQueuedCompletionStatus,
1264 METH_VARARGS, PostQueuedCompletionStatus_doc},
1265 {"FormatMessage", overlapped_FormatMessage,
1266 METH_VARARGS, FormatMessage_doc},
1267 {"BindLocal", overlapped_BindLocal,
1268 METH_VARARGS, BindLocal_doc},
Guido van Rossum90fb9142013-10-30 14:44:05 -07001269 {"RegisterWaitWithQueue", overlapped_RegisterWaitWithQueue,
1270 METH_VARARGS, RegisterWaitWithQueue_doc},
1271 {"UnregisterWait", overlapped_UnregisterWait,
1272 METH_VARARGS, UnregisterWait_doc},
Victor Stinnerd0a28de2015-01-21 23:39:51 +01001273 {"UnregisterWaitEx", overlapped_UnregisterWaitEx,
1274 METH_VARARGS, UnregisterWaitEx_doc},
Guido van Rossum90fb9142013-10-30 14:44:05 -07001275 {"CreateEvent", overlapped_CreateEvent,
1276 METH_VARARGS, CreateEvent_doc},
1277 {"SetEvent", overlapped_SetEvent,
1278 METH_VARARGS, SetEvent_doc},
1279 {"ResetEvent", overlapped_ResetEvent,
1280 METH_VARARGS, ResetEvent_doc},
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001281 {"ConnectPipe",
1282 (PyCFunction) ConnectPipe,
1283 METH_VARARGS, ConnectPipe_doc},
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001284 {NULL}
1285};
1286
1287static struct PyModuleDef overlapped_module = {
1288 PyModuleDef_HEAD_INIT,
1289 "_overlapped",
1290 NULL,
1291 -1,
1292 overlapped_functions,
1293 NULL,
1294 NULL,
1295 NULL,
1296 NULL
1297};
1298
1299#define WINAPI_CONSTANT(fmt, con) \
1300 PyDict_SetItemString(d, #con, Py_BuildValue(fmt, con))
1301
1302PyMODINIT_FUNC
1303PyInit__overlapped(void)
1304{
1305 PyObject *m, *d;
1306
1307 /* Ensure WSAStartup() called before initializing function pointers */
1308 m = PyImport_ImportModule("_socket");
1309 if (!m)
1310 return NULL;
1311 Py_DECREF(m);
1312
1313 if (initialize_function_pointers() < 0)
1314 return NULL;
1315
1316 if (PyType_Ready(&OverlappedType) < 0)
1317 return NULL;
1318
1319 m = PyModule_Create(&overlapped_module);
1320 if (PyModule_AddObject(m, "Overlapped", (PyObject *)&OverlappedType) < 0)
1321 return NULL;
1322
1323 d = PyModule_GetDict(m);
1324
1325 WINAPI_CONSTANT(F_DWORD, ERROR_IO_PENDING);
1326 WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED);
1327 WINAPI_CONSTANT(F_DWORD, ERROR_SEM_TIMEOUT);
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001328 WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_BUSY);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001329 WINAPI_CONSTANT(F_DWORD, INFINITE);
1330 WINAPI_CONSTANT(F_HANDLE, INVALID_HANDLE_VALUE);
1331 WINAPI_CONSTANT(F_HANDLE, NULL);
1332 WINAPI_CONSTANT(F_DWORD, SO_UPDATE_ACCEPT_CONTEXT);
1333 WINAPI_CONSTANT(F_DWORD, SO_UPDATE_CONNECT_CONTEXT);
1334 WINAPI_CONSTANT(F_DWORD, TF_REUSE_SOCKET);
1335
1336 return m;
1337}