aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/Modules/overlapped.c
diff options
context:
space:
mode:
authorAlexSm <alex@ydb.tech>2024-03-05 10:40:59 +0100
committerGitHub <noreply@github.com>2024-03-05 12:40:59 +0300
commit1ac13c847b5358faba44dbb638a828e24369467b (patch)
tree07672b4dd3604ad3dee540a02c6494cb7d10dc3d /contrib/tools/python3/Modules/overlapped.c
parentffcca3e7f7958ddc6487b91d3df8c01054bd0638 (diff)
downloadydb-1ac13c847b5358faba44dbb638a828e24369467b.tar.gz
Library import 16 (#2433)
Co-authored-by: robot-piglet <robot-piglet@yandex-team.com> Co-authored-by: deshevoy <deshevoy@yandex-team.com> Co-authored-by: robot-contrib <robot-contrib@yandex-team.com> Co-authored-by: thegeorg <thegeorg@yandex-team.com> Co-authored-by: robot-ya-builder <robot-ya-builder@yandex-team.com> Co-authored-by: svidyuk <svidyuk@yandex-team.com> Co-authored-by: shadchin <shadchin@yandex-team.com> Co-authored-by: robot-ratatosk <robot-ratatosk@yandex-team.com> Co-authored-by: innokentii <innokentii@yandex-team.com> Co-authored-by: arkady-e1ppa <arkady-e1ppa@yandex-team.com> Co-authored-by: snermolaev <snermolaev@yandex-team.com> Co-authored-by: dimdim11 <dimdim11@yandex-team.com> Co-authored-by: kickbutt <kickbutt@yandex-team.com> Co-authored-by: abdullinsaid <abdullinsaid@yandex-team.com> Co-authored-by: korsunandrei <korsunandrei@yandex-team.com> Co-authored-by: petrk <petrk@yandex-team.com> Co-authored-by: miroslav2 <miroslav2@yandex-team.com> Co-authored-by: serjflint <serjflint@yandex-team.com> Co-authored-by: akhropov <akhropov@yandex-team.com> Co-authored-by: prettyboy <prettyboy@yandex-team.com> Co-authored-by: ilikepugs <ilikepugs@yandex-team.com> Co-authored-by: hiddenpath <hiddenpath@yandex-team.com> Co-authored-by: mikhnenko <mikhnenko@yandex-team.com> Co-authored-by: spreis <spreis@yandex-team.com> Co-authored-by: andreyshspb <andreyshspb@yandex-team.com> Co-authored-by: dimaandreev <dimaandreev@yandex-team.com> Co-authored-by: rashid <rashid@yandex-team.com> Co-authored-by: robot-ydb-importer <robot-ydb-importer@yandex-team.com> Co-authored-by: r-vetrov <r-vetrov@yandex-team.com> Co-authored-by: ypodlesov <ypodlesov@yandex-team.com> Co-authored-by: zaverden <zaverden@yandex-team.com> Co-authored-by: vpozdyayev <vpozdyayev@yandex-team.com> Co-authored-by: robot-cozmo <robot-cozmo@yandex-team.com> Co-authored-by: v-korovin <v-korovin@yandex-team.com> Co-authored-by: arikon <arikon@yandex-team.com> Co-authored-by: khoden <khoden@yandex-team.com> Co-authored-by: psydmm <psydmm@yandex-team.com> Co-authored-by: robot-javacom <robot-javacom@yandex-team.com> Co-authored-by: dtorilov <dtorilov@yandex-team.com> Co-authored-by: sennikovmv <sennikovmv@yandex-team.com> Co-authored-by: hcpp <hcpp@ydb.tech>
Diffstat (limited to 'contrib/tools/python3/Modules/overlapped.c')
-rw-r--r--contrib/tools/python3/Modules/overlapped.c2069
1 files changed, 2069 insertions, 0 deletions
diff --git a/contrib/tools/python3/Modules/overlapped.c b/contrib/tools/python3/Modules/overlapped.c
new file mode 100644
index 0000000000..afdd78d1bc
--- /dev/null
+++ b/contrib/tools/python3/Modules/overlapped.c
@@ -0,0 +1,2069 @@
+/*
+ * Support for overlapped IO
+ *
+ * Some code borrowed from Modules/_winapi.c of CPython
+ */
+
+/* XXX check overflow and DWORD <-> Py_ssize_t conversions
+ Check itemsize */
+
+#include "Python.h"
+#include "structmember.h" // PyMemberDef
+
+#define WINDOWS_LEAN_AND_MEAN
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <mswsock.h>
+
+#if defined(MS_WIN32) && !defined(MS_WIN64)
+# define F_POINTER "k"
+# define T_POINTER T_ULONG
+#else
+# define F_POINTER "K"
+# define T_POINTER T_ULONGLONG
+#endif
+
+#define F_HANDLE F_POINTER
+#define F_ULONG_PTR F_POINTER
+#define F_DWORD "k"
+#define F_BOOL "i"
+#define F_UINT "I"
+
+#define T_HANDLE T_POINTER
+
+/*[python input]
+class pointer_converter(CConverter):
+ format_unit = '"F_POINTER"'
+
+ def parse_arg(self, argname, displayname):
+ return """
+ {paramname} = PyLong_AsVoidPtr({argname});
+ if (!{paramname} && PyErr_Occurred()) {{{{
+ goto exit;
+ }}}}
+ """.format(argname=argname, paramname=self.parser_name)
+
+class OVERLAPPED_converter(pointer_converter):
+ type = 'OVERLAPPED *'
+
+class HANDLE_converter(pointer_converter):
+ type = 'HANDLE'
+
+class ULONG_PTR_converter(pointer_converter):
+ type = 'ULONG_PTR'
+
+ def parse_arg(self, argname, displayname):
+ return """
+ {paramname} = (uintptr_t)PyLong_AsVoidPtr({argname});
+ if (!{paramname} && PyErr_Occurred()) {{{{
+ goto exit;
+ }}}}
+ """.format(argname=argname, paramname=self.parser_name)
+
+class DWORD_converter(unsigned_long_converter):
+ type = 'DWORD'
+
+class BOOL_converter(int_converter):
+ type = 'BOOL'
+[python start generated code]*/
+/*[python end generated code: output=da39a3ee5e6b4b0d input=8a07ea3018f4cec8]*/
+
+/*[clinic input]
+module _overlapped
+class _overlapped.Overlapped "OverlappedObject *" "&OverlappedType"
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=92e5a799db35b96c]*/
+
+
+enum {TYPE_NONE, TYPE_NOT_STARTED, TYPE_READ, TYPE_READINTO, TYPE_WRITE,
+ TYPE_ACCEPT, TYPE_CONNECT, TYPE_DISCONNECT, TYPE_CONNECT_NAMED_PIPE,
+ TYPE_WAIT_NAMED_PIPE_AND_CONNECT, TYPE_TRANSMIT_FILE, TYPE_READ_FROM,
+ TYPE_WRITE_TO, TYPE_READ_FROM_INTO};
+
+typedef struct {
+ PyObject_HEAD
+ OVERLAPPED overlapped;
+ /* For convenience, we store the file handle too */
+ HANDLE handle;
+ /* Error returned by last method call */
+ DWORD error;
+ /* Type of operation */
+ DWORD type;
+ union {
+ /* Buffer allocated by us: TYPE_READ and TYPE_ACCEPT */
+ PyObject *allocated_buffer;
+ /* Buffer passed by the user: TYPE_WRITE, TYPE_WRITE_TO, and TYPE_READINTO */
+ Py_buffer user_buffer;
+
+ /* Data used for reading from a connectionless socket:
+ TYPE_READ_FROM */
+ struct {
+ // A (buffer, (host, port)) tuple
+ PyObject *result;
+ // The actual read buffer
+ PyObject *allocated_buffer;
+ struct sockaddr_in6 address;
+ int address_length;
+ } read_from;
+
+ /* Data used for reading from a connectionless socket:
+ TYPE_READ_FROM_INTO */
+ struct {
+ // A (number of bytes read, (host, port)) tuple
+ PyObject* result;
+ /* Buffer passed by the user */
+ Py_buffer user_buffer;
+ struct sockaddr_in6 address;
+ int address_length;
+ } read_from_into;
+ };
+} OverlappedObject;
+
+
+static inline void
+steal_buffer(Py_buffer * dst, Py_buffer * src)
+{
+ memcpy(dst, src, sizeof(Py_buffer));
+ memset(src, 0, sizeof(Py_buffer));
+}
+
+/*
+ * Map Windows error codes to subclasses of OSError
+ */
+
+static PyObject *
+SetFromWindowsErr(DWORD err)
+{
+ PyObject *exception_type;
+
+ if (err == 0)
+ err = GetLastError();
+ switch (err) {
+ case ERROR_CONNECTION_REFUSED:
+ exception_type = PyExc_ConnectionRefusedError;
+ break;
+ case ERROR_CONNECTION_ABORTED:
+ exception_type = PyExc_ConnectionAbortedError;
+ break;
+ default:
+ exception_type = PyExc_OSError;
+ }
+ return PyErr_SetExcFromWindowsErr(exception_type, err);
+}
+
+/*
+ * Some functions should be loaded at runtime
+ */
+
+static LPFN_ACCEPTEX Py_AcceptEx = NULL;
+static LPFN_CONNECTEX Py_ConnectEx = NULL;
+static LPFN_DISCONNECTEX Py_DisconnectEx = NULL;
+static LPFN_TRANSMITFILE Py_TransmitFile = NULL;
+
+#define GET_WSA_POINTER(s, x) \
+ (SOCKET_ERROR != WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, \
+ &Guid##x, sizeof(Guid##x), &Py_##x, \
+ sizeof(Py_##x), &dwBytes, NULL, NULL))
+
+static int
+initialize_function_pointers(void)
+{
+ GUID GuidAcceptEx = WSAID_ACCEPTEX;
+ GUID GuidConnectEx = WSAID_CONNECTEX;
+ GUID GuidDisconnectEx = WSAID_DISCONNECTEX;
+ GUID GuidTransmitFile = WSAID_TRANSMITFILE;
+ SOCKET s;
+ DWORD dwBytes;
+
+ if (Py_AcceptEx != NULL &&
+ Py_ConnectEx != NULL &&
+ Py_DisconnectEx != NULL &&
+ Py_TransmitFile != NULL)
+ {
+ // All function pointers are initialized already
+ // by previous module import
+ return 0;
+ }
+
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (s == INVALID_SOCKET) {
+ SetFromWindowsErr(WSAGetLastError());
+ return -1;
+ }
+
+ if (!GET_WSA_POINTER(s, AcceptEx) ||
+ !GET_WSA_POINTER(s, ConnectEx) ||
+ !GET_WSA_POINTER(s, DisconnectEx) ||
+ !GET_WSA_POINTER(s, TransmitFile))
+ {
+ closesocket(s);
+ SetFromWindowsErr(WSAGetLastError());
+ return -1;
+ }
+
+ closesocket(s);
+ return 0;
+}
+
+/*
+ * Completion port stuff
+ */
+
+/*[clinic input]
+_overlapped.CreateIoCompletionPort
+
+ handle as FileHandle: HANDLE
+ port as ExistingCompletionPort: HANDLE
+ key as CompletionKey: ULONG_PTR
+ concurrency as NumberOfConcurrentThreads: DWORD
+ /
+
+Create a completion port or register a handle with a port.
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_CreateIoCompletionPort_impl(PyObject *module, HANDLE FileHandle,
+ HANDLE ExistingCompletionPort,
+ ULONG_PTR CompletionKey,
+ DWORD NumberOfConcurrentThreads)
+/*[clinic end generated code: output=24ede2b0f05e5433 input=847bae4d0efe1976]*/
+{
+ HANDLE ret;
+
+ Py_BEGIN_ALLOW_THREADS
+ ret = CreateIoCompletionPort(FileHandle, ExistingCompletionPort,
+ CompletionKey, NumberOfConcurrentThreads);
+ Py_END_ALLOW_THREADS
+
+ if (ret == NULL)
+ return SetFromWindowsErr(0);
+ return Py_BuildValue(F_HANDLE, ret);
+}
+
+/*[clinic input]
+_overlapped.GetQueuedCompletionStatus
+
+ port as CompletionPort: HANDLE
+ msecs as Milliseconds: DWORD
+ /
+
+Get a message from completion port.
+
+Wait for up to msecs milliseconds.
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_GetQueuedCompletionStatus_impl(PyObject *module,
+ HANDLE CompletionPort,
+ DWORD Milliseconds)
+/*[clinic end generated code: output=68314171628dddb7 input=94a042d14c4f6410]*/
+{
+ DWORD NumberOfBytes = 0;
+ ULONG_PTR CompletionKey = 0;
+ OVERLAPPED *Overlapped = NULL;
+ DWORD err;
+ BOOL ret;
+
+ Py_BEGIN_ALLOW_THREADS
+ ret = GetQueuedCompletionStatus(CompletionPort, &NumberOfBytes,
+ &CompletionKey, &Overlapped, Milliseconds);
+ Py_END_ALLOW_THREADS
+
+ err = ret ? ERROR_SUCCESS : GetLastError();
+ if (Overlapped == NULL) {
+ if (err == WAIT_TIMEOUT)
+ Py_RETURN_NONE;
+ else
+ return SetFromWindowsErr(err);
+ }
+ return Py_BuildValue(F_DWORD F_DWORD F_ULONG_PTR F_POINTER,
+ err, NumberOfBytes, CompletionKey, Overlapped);
+}
+
+/*[clinic input]
+_overlapped.PostQueuedCompletionStatus
+
+ port as CompletionPort: HANDLE
+ bytes as NumberOfBytes: DWORD
+ key as CompletionKey: ULONG_PTR
+ address as Overlapped: OVERLAPPED
+ /
+
+Post a message to completion port.
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_PostQueuedCompletionStatus_impl(PyObject *module,
+ HANDLE CompletionPort,
+ DWORD NumberOfBytes,
+ ULONG_PTR CompletionKey,
+ OVERLAPPED *Overlapped)
+/*[clinic end generated code: output=93e73f2933a43e9e input=e936202d87937aca]*/
+{
+ BOOL ret;
+
+ Py_BEGIN_ALLOW_THREADS
+ ret = PostQueuedCompletionStatus(CompletionPort, NumberOfBytes,
+ CompletionKey, Overlapped);
+ Py_END_ALLOW_THREADS
+
+ if (!ret)
+ return SetFromWindowsErr(0);
+ Py_RETURN_NONE;
+}
+
+/*
+ * Wait for a handle
+ */
+
+struct PostCallbackData {
+ HANDLE CompletionPort;
+ LPOVERLAPPED Overlapped;
+};
+
+static VOID CALLBACK
+PostToQueueCallback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
+{
+ struct PostCallbackData *p = (struct PostCallbackData*) lpParameter;
+
+ PostQueuedCompletionStatus(p->CompletionPort, TimerOrWaitFired,
+ 0, p->Overlapped);
+ /* ignore possible error! */
+ PyMem_RawFree(p);
+}
+
+/*[clinic input]
+_overlapped.RegisterWaitWithQueue
+
+ Object: HANDLE
+ CompletionPort: HANDLE
+ Overlapped: OVERLAPPED
+ Timeout as Milliseconds: DWORD
+ /
+
+Register wait for Object; when complete CompletionPort is notified.
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_RegisterWaitWithQueue_impl(PyObject *module, HANDLE Object,
+ HANDLE CompletionPort,
+ OVERLAPPED *Overlapped,
+ DWORD Milliseconds)
+/*[clinic end generated code: output=c2ace732e447fe45 input=2dd4efee44abe8ee]*/
+{
+ HANDLE NewWaitObject;
+ struct PostCallbackData data = {CompletionPort, Overlapped}, *pdata;
+
+ /* Use PyMem_RawMalloc() rather than PyMem_Malloc(), since
+ PostToQueueCallback() will call PyMem_Free() from a new C thread
+ which doesn't hold the GIL. */
+ pdata = PyMem_RawMalloc(sizeof(struct PostCallbackData));
+ if (pdata == NULL)
+ return SetFromWindowsErr(0);
+
+ *pdata = data;
+
+ if (!RegisterWaitForSingleObject(
+ &NewWaitObject, Object, PostToQueueCallback, pdata, Milliseconds,
+ WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE))
+ {
+ SetFromWindowsErr(0);
+ PyMem_RawFree(pdata);
+ return NULL;
+ }
+
+ return Py_BuildValue(F_HANDLE, NewWaitObject);
+}
+
+/*[clinic input]
+_overlapped.UnregisterWait
+
+ WaitHandle: HANDLE
+ /
+
+Unregister wait handle.
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_UnregisterWait_impl(PyObject *module, HANDLE WaitHandle)
+/*[clinic end generated code: output=ec90cd955a9a617d input=a56709544cb2df0f]*/
+{
+ BOOL ret;
+
+ Py_BEGIN_ALLOW_THREADS
+ ret = UnregisterWait(WaitHandle);
+ Py_END_ALLOW_THREADS
+
+ if (!ret)
+ return SetFromWindowsErr(0);
+ Py_RETURN_NONE;
+}
+
+/*[clinic input]
+_overlapped.UnregisterWaitEx
+
+ WaitHandle: HANDLE
+ Event: HANDLE
+ /
+
+Unregister wait handle.
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_UnregisterWaitEx_impl(PyObject *module, HANDLE WaitHandle,
+ HANDLE Event)
+/*[clinic end generated code: output=2e3d84c1d5f65b92 input=953cddc1de50fab9]*/
+{
+ BOOL ret;
+
+ Py_BEGIN_ALLOW_THREADS
+ ret = UnregisterWaitEx(WaitHandle, Event);
+ Py_END_ALLOW_THREADS
+
+ if (!ret)
+ return SetFromWindowsErr(0);
+ Py_RETURN_NONE;
+}
+
+/*
+ * Event functions -- currently only used by tests
+ */
+
+/*[clinic input]
+_overlapped.CreateEvent
+
+ EventAttributes: object
+ ManualReset: BOOL
+ InitialState: BOOL
+ Name: Py_UNICODE(accept={str, NoneType})
+ /
+
+Create an event.
+
+EventAttributes must be None.
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_CreateEvent_impl(PyObject *module, PyObject *EventAttributes,
+ BOOL ManualReset, BOOL InitialState,
+ const Py_UNICODE *Name)
+/*[clinic end generated code: output=8e04f0916c17b13d input=dbc36ae14375ba24]*/
+{
+ HANDLE Event;
+
+ if (EventAttributes != Py_None) {
+ PyErr_SetString(PyExc_ValueError, "EventAttributes must be None");
+ return NULL;
+ }
+
+ Py_BEGIN_ALLOW_THREADS
+ Event = CreateEventW(NULL, ManualReset, InitialState, Name);
+ Py_END_ALLOW_THREADS
+
+ if (Event == NULL)
+ return SetFromWindowsErr(0);
+ return Py_BuildValue(F_HANDLE, Event);
+}
+
+/*[clinic input]
+_overlapped.SetEvent
+
+ Handle: HANDLE
+ /
+
+Set event.
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_SetEvent_impl(PyObject *module, HANDLE Handle)
+/*[clinic end generated code: output=5b8d974216b0e569 input=d8b0d26eb7391e80]*/
+{
+ BOOL ret;
+
+ Py_BEGIN_ALLOW_THREADS
+ ret = SetEvent(Handle);
+ Py_END_ALLOW_THREADS
+
+ if (!ret)
+ return SetFromWindowsErr(0);
+ Py_RETURN_NONE;
+}
+
+/*[clinic input]
+_overlapped.ResetEvent
+
+ Handle: HANDLE
+ /
+
+Reset event.
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_ResetEvent_impl(PyObject *module, HANDLE Handle)
+/*[clinic end generated code: output=066537a8405cddb2 input=d4e089c9ba84ff2f]*/
+{
+ BOOL ret;
+
+ Py_BEGIN_ALLOW_THREADS
+ ret = ResetEvent(Handle);
+ Py_END_ALLOW_THREADS
+
+ if (!ret)
+ return SetFromWindowsErr(0);
+ Py_RETURN_NONE;
+}
+
+/*
+ * Bind socket handle to local port without doing slow getaddrinfo()
+ */
+
+/*[clinic input]
+_overlapped.BindLocal
+
+ handle as Socket: HANDLE
+ family as Family: int
+ /
+
+Bind a socket handle to an arbitrary local port.
+
+family should be AF_INET or AF_INET6.
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_BindLocal_impl(PyObject *module, HANDLE Socket, int Family)
+/*[clinic end generated code: output=edb93862697aed9c input=a0e7b5c2f541170c]*/
+{
+ BOOL ret;
+
+ if (Family == AF_INET) {
+ struct sockaddr_in addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = 0;
+ addr.sin_addr.S_un.S_addr = INADDR_ANY;
+ ret = bind((SOCKET)Socket, (SOCKADDR*)&addr, sizeof(addr))
+ != SOCKET_ERROR;
+ } else if (Family == AF_INET6) {
+ struct sockaddr_in6 addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin6_family = AF_INET6;
+ addr.sin6_port = 0;
+ addr.sin6_addr = in6addr_any;
+ ret = bind((SOCKET)Socket, (SOCKADDR*)&addr, sizeof(addr))
+ != SOCKET_ERROR;
+ } else {
+ PyErr_SetString(PyExc_ValueError, "expected tuple of length 2 or 4");
+ return NULL;
+ }
+
+ if (!ret)
+ return SetFromWindowsErr(WSAGetLastError());
+ Py_RETURN_NONE;
+}
+
+/*
+ * Windows equivalent of os.strerror() -- compare _ctypes/callproc.c
+ */
+
+/*[clinic input]
+_overlapped.FormatMessage
+
+ error_code as code: DWORD
+ /
+
+Return error message for an error code.
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_FormatMessage_impl(PyObject *module, DWORD code)
+/*[clinic end generated code: output=02c964ff22407c6b input=644bb5b80326179e]*/
+{
+ DWORD n;
+ WCHAR *lpMsgBuf;
+ PyObject *res;
+
+ n = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ code,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPWSTR) &lpMsgBuf,
+ 0,
+ NULL);
+ if (n) {
+ while (iswspace(lpMsgBuf[n-1]))
+ --n;
+ lpMsgBuf[n] = L'\0';
+ res = Py_BuildValue("u", lpMsgBuf);
+ } else {
+ res = PyUnicode_FromFormat("unknown error code %u", code);
+ }
+ LocalFree(lpMsgBuf);
+ return res;
+}
+
+
+/*
+ * Mark operation as completed - used when reading produces ERROR_BROKEN_PIPE
+ */
+
+static inline void
+mark_as_completed(OVERLAPPED *ov)
+{
+ ov->Internal = 0;
+ if (ov->hEvent != NULL)
+ SetEvent(ov->hEvent);
+}
+
+/*
+ * A Python object wrapping an OVERLAPPED structure and other useful data
+ * for overlapped I/O
+ */
+
+/*[clinic input]
+@classmethod
+_overlapped.Overlapped.__new__
+
+ event: HANDLE(c_default='INVALID_HANDLE_VALUE') = _overlapped.INVALID_HANDLE_VALUE
+
+OVERLAPPED structure wrapper.
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_Overlapped_impl(PyTypeObject *type, HANDLE event)
+/*[clinic end generated code: output=6da60504a18eb421 input=26b8a7429e629e95]*/
+{
+ OverlappedObject *self;
+
+ if (event == INVALID_HANDLE_VALUE) {
+ event = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (event == NULL)
+ return SetFromWindowsErr(0);
+ }
+
+ self = PyObject_New(OverlappedObject, type);
+ if (self == NULL) {
+ if (event != NULL)
+ CloseHandle(event);
+ return NULL;
+ }
+
+ self->handle = NULL;
+ self->error = 0;
+ self->type = TYPE_NONE;
+ self->allocated_buffer = NULL;
+ memset(&self->overlapped, 0, sizeof(OVERLAPPED));
+ memset(&self->user_buffer, 0, sizeof(Py_buffer));
+ if (event)
+ self->overlapped.hEvent = event;
+ return (PyObject *)self;
+}
+
+
+/* Note (bpo-32710): OverlappedType.tp_clear is not defined to not release
+ buffers while overlapped are still running, to prevent a crash. */
+static int
+Overlapped_clear(OverlappedObject *self)
+{
+ switch (self->type) {
+ case TYPE_READ:
+ case TYPE_ACCEPT: {
+ Py_CLEAR(self->allocated_buffer);
+ break;
+ }
+ case TYPE_READ_FROM: {
+ // An initial call to WSARecvFrom will only allocate the buffer.
+ // The result tuple of (message, address) is only
+ // allocated _after_ a message has been received.
+ if(self->read_from.result) {
+ // We've received a message, free the result tuple.
+ Py_CLEAR(self->read_from.result);
+ }
+ if(self->read_from.allocated_buffer) {
+ Py_CLEAR(self->read_from.allocated_buffer);
+ }
+ break;
+ }
+ case TYPE_READ_FROM_INTO: {
+ if (self->read_from_into.result) {
+ // We've received a message, free the result tuple.
+ Py_CLEAR(self->read_from_into.result);
+ }
+ if (self->read_from_into.user_buffer.obj) {
+ PyBuffer_Release(&self->read_from_into.user_buffer);
+ }
+ break;
+ }
+ case TYPE_WRITE:
+ case TYPE_WRITE_TO:
+ case TYPE_READINTO: {
+ if (self->user_buffer.obj) {
+ PyBuffer_Release(&self->user_buffer);
+ }
+ break;
+ }
+ }
+ self->type = TYPE_NOT_STARTED;
+ return 0;
+}
+
+static void
+Overlapped_dealloc(OverlappedObject *self)
+{
+ DWORD bytes;
+ DWORD olderr = GetLastError();
+ BOOL wait = FALSE;
+ BOOL ret;
+
+ if (!HasOverlappedIoCompleted(&self->overlapped) &&
+ self->type != TYPE_NOT_STARTED)
+ {
+ Py_BEGIN_ALLOW_THREADS
+ if (CancelIoEx(self->handle, &self->overlapped))
+ wait = TRUE;
+
+ ret = GetOverlappedResult(self->handle, &self->overlapped,
+ &bytes, wait);
+ Py_END_ALLOW_THREADS
+
+ switch (ret ? ERROR_SUCCESS : GetLastError()) {
+ case ERROR_SUCCESS:
+ case ERROR_NOT_FOUND:
+ case ERROR_OPERATION_ABORTED:
+ break;
+ default:
+ PyErr_Format(
+ PyExc_RuntimeError,
+ "%R still has pending operation at "
+ "deallocation, the process may crash", self);
+ PyErr_WriteUnraisable(NULL);
+ }
+ }
+
+ if (self->overlapped.hEvent != NULL) {
+ CloseHandle(self->overlapped.hEvent);
+ }
+
+ Overlapped_clear(self);
+ SetLastError(olderr);
+
+ PyTypeObject *tp = Py_TYPE(self);
+ PyObject_Free(self);
+ Py_DECREF(tp);
+}
+
+
+/* Convert IPv4 sockaddr to a Python str. */
+
+static PyObject *
+make_ipv4_addr(const struct sockaddr_in *addr)
+{
+ char buf[INET_ADDRSTRLEN];
+ if (inet_ntop(AF_INET, &addr->sin_addr, buf, sizeof(buf)) == NULL) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return NULL;
+ }
+ return PyUnicode_FromString(buf);
+}
+
+/* Convert IPv6 sockaddr to a Python str. */
+
+static PyObject *
+make_ipv6_addr(const struct sockaddr_in6 *addr)
+{
+ char buf[INET6_ADDRSTRLEN];
+ if (inet_ntop(AF_INET6, &addr->sin6_addr, buf, sizeof(buf)) == NULL) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return NULL;
+ }
+ return PyUnicode_FromString(buf);
+}
+
+static PyObject*
+unparse_address(LPSOCKADDR Address, DWORD Length)
+{
+ /* The function is adopted from mocketmodule.c makesockaddr()*/
+
+ switch(Address->sa_family) {
+ case AF_INET: {
+ const struct sockaddr_in *a = (const struct sockaddr_in *)Address;
+ PyObject *addrobj = make_ipv4_addr(a);
+ PyObject *ret = NULL;
+ if (addrobj) {
+ ret = Py_BuildValue("Oi", addrobj, ntohs(a->sin_port));
+ Py_DECREF(addrobj);
+ }
+ return ret;
+ }
+ case AF_INET6: {
+ const struct sockaddr_in6 *a = (const struct sockaddr_in6 *)Address;
+ PyObject *addrobj = make_ipv6_addr(a);
+ PyObject *ret = NULL;
+ if (addrobj) {
+ ret = Py_BuildValue("OiII",
+ addrobj,
+ ntohs(a->sin6_port),
+ ntohl(a->sin6_flowinfo),
+ a->sin6_scope_id);
+ Py_DECREF(addrobj);
+ }
+ return ret;
+ }
+ default: {
+ PyErr_SetString(PyExc_ValueError, "recvfrom returned unsupported address family");
+ return NULL;
+ }
+ }
+}
+
+/*[clinic input]
+_overlapped.Overlapped.cancel
+
+Cancel overlapped operation.
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_Overlapped_cancel_impl(OverlappedObject *self)
+/*[clinic end generated code: output=54ad7aeece89901c input=80eb67c7b57dbcf1]*/
+{
+ BOOL ret = TRUE;
+
+ if (self->type == TYPE_NOT_STARTED
+ || self->type == TYPE_WAIT_NAMED_PIPE_AND_CONNECT)
+ Py_RETURN_NONE;
+
+ if (!HasOverlappedIoCompleted(&self->overlapped)) {
+ Py_BEGIN_ALLOW_THREADS
+ ret = CancelIoEx(self->handle, &self->overlapped);
+ Py_END_ALLOW_THREADS
+ }
+
+ /* CancelIoEx returns ERROR_NOT_FOUND if the I/O completed in-between */
+ if (!ret && GetLastError() != ERROR_NOT_FOUND)
+ return SetFromWindowsErr(0);
+ Py_RETURN_NONE;
+}
+
+/*[clinic input]
+_overlapped.Overlapped.getresult
+
+ wait: BOOL(c_default='FALSE') = False
+ /
+
+Retrieve result of operation.
+
+If wait is true then it blocks until the operation is finished. If wait
+is false and the operation is still pending then an error is raised.
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_Overlapped_getresult_impl(OverlappedObject *self, BOOL wait)
+/*[clinic end generated code: output=8c9bd04d08994f6c input=aa5b03e9897ca074]*/
+{
+ DWORD transferred = 0;
+ BOOL ret;
+ DWORD err;
+ PyObject *addr;
+
+ if (self->type == TYPE_NONE) {
+ PyErr_SetString(PyExc_ValueError, "operation not yet attempted");
+ return NULL;
+ }
+
+ if (self->type == TYPE_NOT_STARTED) {
+ PyErr_SetString(PyExc_ValueError, "operation failed to start");
+ return NULL;
+ }
+
+ Py_BEGIN_ALLOW_THREADS
+ ret = GetOverlappedResult(self->handle, &self->overlapped, &transferred,
+ wait);
+ Py_END_ALLOW_THREADS
+
+ self->error = err = ret ? ERROR_SUCCESS : GetLastError();
+ switch (err) {
+ case ERROR_SUCCESS:
+ case ERROR_MORE_DATA:
+ break;
+ case ERROR_BROKEN_PIPE:
+ if (self->type == TYPE_READ || self->type == TYPE_READINTO) {
+ break;
+ }
+ else if (self->type == TYPE_READ_FROM &&
+ (self->read_from.result != NULL ||
+ self->read_from.allocated_buffer != NULL))
+ {
+ break;
+ }
+ else if (self->type == TYPE_READ_FROM_INTO &&
+ self->read_from_into.result != NULL)
+ {
+ break;
+ }
+ /* fall through */
+ default:
+ return SetFromWindowsErr(err);
+ }
+
+ switch (self->type) {
+ case TYPE_READ:
+ assert(PyBytes_CheckExact(self->allocated_buffer));
+ if (transferred != PyBytes_GET_SIZE(self->allocated_buffer) &&
+ _PyBytes_Resize(&self->allocated_buffer, transferred))
+ return NULL;
+
+ return Py_NewRef(self->allocated_buffer);
+ case TYPE_READ_FROM:
+ assert(PyBytes_CheckExact(self->read_from.allocated_buffer));
+
+ if (transferred != PyBytes_GET_SIZE(
+ self->read_from.allocated_buffer) &&
+ _PyBytes_Resize(&self->read_from.allocated_buffer, transferred))
+ {
+ return NULL;
+ }
+
+ // unparse the address
+ addr = unparse_address((SOCKADDR*)&self->read_from.address,
+ self->read_from.address_length);
+
+ if (addr == NULL) {
+ return NULL;
+ }
+
+ // The result is a two item tuple: (message, address)
+ self->read_from.result = PyTuple_New(2);
+ if (self->read_from.result == NULL) {
+ Py_CLEAR(addr);
+ return NULL;
+ }
+
+ // first item: message
+ PyTuple_SET_ITEM(self->read_from.result, 0,
+ Py_NewRef(self->read_from.allocated_buffer));
+ // second item: address
+ PyTuple_SET_ITEM(self->read_from.result, 1, addr);
+
+ return Py_NewRef(self->read_from.result);
+ case TYPE_READ_FROM_INTO:
+ // unparse the address
+ addr = unparse_address((SOCKADDR*)&self->read_from_into.address,
+ self->read_from_into.address_length);
+
+ if (addr == NULL) {
+ return NULL;
+ }
+
+ // The result is a two item tuple: (number of bytes read, address)
+ self->read_from_into.result = PyTuple_New(2);
+ if (self->read_from_into.result == NULL) {
+ Py_CLEAR(addr);
+ return NULL;
+ }
+
+ // first item: number of bytes read
+ PyTuple_SET_ITEM(self->read_from_into.result, 0,
+ PyLong_FromUnsignedLong((unsigned long)transferred));
+ // second item: address
+ PyTuple_SET_ITEM(self->read_from_into.result, 1, addr);
+
+ return Py_NewRef(self->read_from_into.result);
+ default:
+ return PyLong_FromUnsignedLong((unsigned long) transferred);
+ }
+}
+
+static PyObject *
+do_ReadFile(OverlappedObject *self, HANDLE handle,
+ char *bufstart, DWORD buflen)
+{
+ DWORD nread;
+ int ret;
+ DWORD err;
+
+ Py_BEGIN_ALLOW_THREADS
+ ret = ReadFile(handle, bufstart, buflen, &nread,
+ &self->overlapped);
+ Py_END_ALLOW_THREADS
+
+ self->error = err = ret ? ERROR_SUCCESS : GetLastError();
+ switch (err) {
+ case ERROR_BROKEN_PIPE:
+ mark_as_completed(&self->overlapped);
+ return SetFromWindowsErr(err);
+ case ERROR_SUCCESS:
+ case ERROR_MORE_DATA:
+ case ERROR_IO_PENDING:
+ Py_RETURN_NONE;
+ default:
+ Overlapped_clear(self);
+ return SetFromWindowsErr(err);
+ }
+}
+
+/*[clinic input]
+_overlapped.Overlapped.ReadFile
+
+ handle: HANDLE
+ size: DWORD
+ /
+
+Start overlapped read.
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_Overlapped_ReadFile_impl(OverlappedObject *self, HANDLE handle,
+ DWORD size)
+/*[clinic end generated code: output=4c8557e16941e4ae input=98c495baa0342425]*/
+{
+ PyObject *buf;
+
+ if (self->type != TYPE_NONE) {
+ PyErr_SetString(PyExc_ValueError, "operation already attempted");
+ return NULL;
+ }
+
+#if SIZEOF_SIZE_T <= SIZEOF_LONG
+ size = Py_MIN(size, (DWORD)PY_SSIZE_T_MAX);
+#endif
+ buf = PyBytes_FromStringAndSize(NULL, Py_MAX(size, 1));
+ if (buf == NULL)
+ return NULL;
+
+ self->type = TYPE_READ;
+ self->handle = handle;
+ self->allocated_buffer = buf;
+
+ return do_ReadFile(self, handle, PyBytes_AS_STRING(buf), size);
+}
+
+/*[clinic input]
+_overlapped.Overlapped.ReadFileInto
+
+ handle: HANDLE
+ buf as bufobj: Py_buffer
+ /
+
+Start overlapped receive.
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_Overlapped_ReadFileInto_impl(OverlappedObject *self,
+ HANDLE handle, Py_buffer *bufobj)
+/*[clinic end generated code: output=8754744506023071 input=4f037ba09939e32d]*/
+{
+ if (self->type != TYPE_NONE) {
+ PyErr_SetString(PyExc_ValueError, "operation already attempted");
+ return NULL;
+ }
+
+#if SIZEOF_SIZE_T > SIZEOF_LONG
+ if (bufobj->len > (Py_ssize_t)ULONG_MAX) {
+ PyErr_SetString(PyExc_ValueError, "buffer too large");
+ return NULL;
+ }
+#endif
+ steal_buffer(&self->user_buffer, bufobj);
+
+ self->type = TYPE_READINTO;
+ self->handle = handle;
+
+ return do_ReadFile(self, handle, self->user_buffer.buf,
+ (DWORD)self->user_buffer.len);
+}
+
+static PyObject *
+do_WSARecv(OverlappedObject *self, HANDLE handle,
+ char *bufstart, DWORD buflen, DWORD flags)
+{
+ DWORD nread;
+ WSABUF wsabuf;
+ int ret;
+ DWORD err;
+
+ wsabuf.buf = bufstart;
+ wsabuf.len = buflen;
+
+ Py_BEGIN_ALLOW_THREADS
+ ret = WSARecv((SOCKET)handle, &wsabuf, 1, &nread, &flags,
+ &self->overlapped, NULL);
+ Py_END_ALLOW_THREADS
+
+ self->error = err = (ret < 0 ? WSAGetLastError() : ERROR_SUCCESS);
+ switch (err) {
+ case ERROR_BROKEN_PIPE:
+ mark_as_completed(&self->overlapped);
+ return SetFromWindowsErr(err);
+ case ERROR_SUCCESS:
+ case ERROR_MORE_DATA:
+ case ERROR_IO_PENDING:
+ Py_RETURN_NONE;
+ default:
+ Overlapped_clear(self);
+ return SetFromWindowsErr(err);
+ }
+}
+
+
+/*[clinic input]
+_overlapped.Overlapped.WSARecv
+
+ handle: HANDLE
+ size: DWORD
+ flags: DWORD = 0
+ /
+
+Start overlapped receive.
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_Overlapped_WSARecv_impl(OverlappedObject *self, HANDLE handle,
+ DWORD size, DWORD flags)
+/*[clinic end generated code: output=3a5e9c61ff040906 input=8c04e506cc3d741a]*/
+{
+ PyObject *buf;
+
+ if (self->type != TYPE_NONE) {
+ PyErr_SetString(PyExc_ValueError, "operation already attempted");
+ return NULL;
+ }
+
+#if SIZEOF_SIZE_T <= SIZEOF_LONG
+ size = Py_MIN(size, (DWORD)PY_SSIZE_T_MAX);
+#endif
+ buf = PyBytes_FromStringAndSize(NULL, Py_MAX(size, 1));
+ if (buf == NULL)
+ return NULL;
+
+ self->type = TYPE_READ;
+ self->handle = handle;
+ self->allocated_buffer = buf;
+
+ return do_WSARecv(self, handle, PyBytes_AS_STRING(buf), size, flags);
+}
+
+/*[clinic input]
+_overlapped.Overlapped.WSARecvInto
+
+ handle: HANDLE
+ buf as bufobj: Py_buffer
+ flags: DWORD
+ /
+
+Start overlapped receive.
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_Overlapped_WSARecvInto_impl(OverlappedObject *self,
+ HANDLE handle, Py_buffer *bufobj,
+ DWORD flags)
+/*[clinic end generated code: output=59ae7688786cf86b input=73e7fa00db633edd]*/
+{
+ if (self->type != TYPE_NONE) {
+ PyErr_SetString(PyExc_ValueError, "operation already attempted");
+ return NULL;
+ }
+
+#if SIZEOF_SIZE_T > SIZEOF_LONG
+ if (bufobj->len > (Py_ssize_t)ULONG_MAX) {
+ PyErr_SetString(PyExc_ValueError, "buffer too large");
+ return NULL;
+ }
+#endif
+ steal_buffer(&self->user_buffer, bufobj);
+
+ self->type = TYPE_READINTO;
+ self->handle = handle;
+
+ return do_WSARecv(self, handle, self->user_buffer.buf,
+ (DWORD)self->user_buffer.len, flags);
+}
+
+/*[clinic input]
+_overlapped.Overlapped.WriteFile
+
+ handle: HANDLE
+ buf as bufobj: Py_buffer
+ /
+
+Start overlapped write.
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_Overlapped_WriteFile_impl(OverlappedObject *self, HANDLE handle,
+ Py_buffer *bufobj)
+/*[clinic end generated code: output=fa5d5880a1bf04b1 input=ac54424c362abfc1]*/
+{
+ DWORD written;
+ BOOL ret;
+ DWORD err;
+
+ if (self->type != TYPE_NONE) {
+ PyErr_SetString(PyExc_ValueError, "operation already attempted");
+ return NULL;
+ }
+
+#if SIZEOF_SIZE_T > SIZEOF_LONG
+ if (bufobj->len > (Py_ssize_t)ULONG_MAX) {
+ PyErr_SetString(PyExc_ValueError, "buffer too large");
+ return NULL;
+ }
+#endif
+ steal_buffer(&self->user_buffer, bufobj);
+
+ self->type = TYPE_WRITE;
+ self->handle = handle;
+
+ Py_BEGIN_ALLOW_THREADS
+ ret = WriteFile(handle, self->user_buffer.buf,
+ (DWORD)self->user_buffer.len,
+ &written, &self->overlapped);
+ Py_END_ALLOW_THREADS
+
+ self->error = err = ret ? ERROR_SUCCESS : GetLastError();
+ switch (err) {
+ case ERROR_SUCCESS:
+ case ERROR_IO_PENDING:
+ Py_RETURN_NONE;
+ default:
+ Overlapped_clear(self);
+ return SetFromWindowsErr(err);
+ }
+}
+
+/*[clinic input]
+_overlapped.Overlapped.WSASend
+
+ handle: HANDLE
+ buf as bufobj: Py_buffer
+ flags: DWORD
+ /
+
+Start overlapped send.
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_Overlapped_WSASend_impl(OverlappedObject *self, HANDLE handle,
+ Py_buffer *bufobj, DWORD flags)
+/*[clinic end generated code: output=3baaa6e1f7fe229e input=c4167420ba2f93d8]*/
+{
+ DWORD written;
+ WSABUF wsabuf;
+ int ret;
+ DWORD err;
+
+ if (self->type != TYPE_NONE) {
+ PyErr_SetString(PyExc_ValueError, "operation already attempted");
+ return NULL;
+ }
+
+#if SIZEOF_SIZE_T > SIZEOF_LONG
+ if (bufobj->len > (Py_ssize_t)ULONG_MAX) {
+ PyErr_SetString(PyExc_ValueError, "buffer too large");
+ return NULL;
+ }
+#endif
+ steal_buffer(&self->user_buffer, bufobj);
+
+ self->type = TYPE_WRITE;
+ self->handle = handle;
+ wsabuf.len = (DWORD)self->user_buffer.len;
+ wsabuf.buf = self->user_buffer.buf;
+
+ Py_BEGIN_ALLOW_THREADS
+ ret = WSASend((SOCKET)handle, &wsabuf, 1, &written, flags,
+ &self->overlapped, NULL);
+ Py_END_ALLOW_THREADS
+
+ self->error = err = (ret < 0 ? WSAGetLastError() : ERROR_SUCCESS);
+ switch (err) {
+ case ERROR_SUCCESS:
+ case ERROR_IO_PENDING:
+ Py_RETURN_NONE;
+ default:
+ Overlapped_clear(self);
+ return SetFromWindowsErr(err);
+ }
+}
+
+/*[clinic input]
+_overlapped.Overlapped.AcceptEx
+
+ listen_handle as ListenSocket: HANDLE
+ accept_handle as AcceptSocket: HANDLE
+ /
+
+Start overlapped wait for client to connect.
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_Overlapped_AcceptEx_impl(OverlappedObject *self,
+ HANDLE ListenSocket,
+ HANDLE AcceptSocket)
+/*[clinic end generated code: output=9a7381d4232af889 input=b83473224fc3a1c5]*/
+{
+ DWORD BytesReceived;
+ DWORD size;
+ PyObject *buf;
+ BOOL ret;
+ DWORD err;
+
+ if (self->type != TYPE_NONE) {
+ PyErr_SetString(PyExc_ValueError, "operation already attempted");
+ return NULL;
+ }
+
+ size = sizeof(struct sockaddr_in6) + 16;
+ buf = PyBytes_FromStringAndSize(NULL, size*2);
+ if (!buf)
+ return NULL;
+
+ self->type = TYPE_ACCEPT;
+ self->handle = ListenSocket;
+ self->allocated_buffer = buf;
+
+ Py_BEGIN_ALLOW_THREADS
+ ret = Py_AcceptEx((SOCKET)ListenSocket, (SOCKET)AcceptSocket,
+ PyBytes_AS_STRING(buf), 0, size, size, &BytesReceived,
+ &self->overlapped);
+ Py_END_ALLOW_THREADS
+
+ self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError();
+ switch (err) {
+ case ERROR_SUCCESS:
+ case ERROR_IO_PENDING:
+ Py_RETURN_NONE;
+ default:
+ Overlapped_clear(self);
+ return SetFromWindowsErr(err);
+ }
+}
+
+
+static int
+parse_address(PyObject *obj, SOCKADDR *Address, int Length)
+{
+ PyObject *Host_obj;
+ wchar_t *Host;
+ unsigned short Port;
+ unsigned long FlowInfo;
+ unsigned long ScopeId;
+
+ memset(Address, 0, Length);
+
+ switch (PyTuple_GET_SIZE(obj)) {
+ case 2: {
+ if (!PyArg_ParseTuple(obj, "UH", &Host_obj, &Port)) {
+ return -1;
+ }
+ Host = PyUnicode_AsWideCharString(Host_obj, NULL);
+ if (Host == NULL) {
+ return -1;
+ }
+ Address->sa_family = AF_INET;
+ if (WSAStringToAddressW(Host, AF_INET, NULL, Address, &Length) < 0) {
+ SetFromWindowsErr(WSAGetLastError());
+ Length = -1;
+ }
+ else {
+ ((SOCKADDR_IN*)Address)->sin_port = htons(Port);
+ }
+ PyMem_Free(Host);
+ return Length;
+ }
+ case 4: {
+ if (!PyArg_ParseTuple(obj,
+ "UHkk;ConnectEx(): illegal address_as_bytes argument",
+ &Host_obj, &Port, &FlowInfo, &ScopeId))
+ {
+ return -1;
+ }
+ Host = PyUnicode_AsWideCharString(Host_obj, NULL);
+ if (Host == NULL) {
+ return -1;
+ }
+ Address->sa_family = AF_INET6;
+ if (WSAStringToAddressW(Host, AF_INET6, NULL, Address, &Length) < 0) {
+ SetFromWindowsErr(WSAGetLastError());
+ Length = -1;
+ }
+ else {
+ ((SOCKADDR_IN6*)Address)->sin6_port = htons(Port);
+ ((SOCKADDR_IN6*)Address)->sin6_flowinfo = FlowInfo;
+ ((SOCKADDR_IN6*)Address)->sin6_scope_id = ScopeId;
+ }
+ PyMem_Free(Host);
+ return Length;
+ }
+ default:
+ PyErr_SetString(PyExc_ValueError, "illegal address_as_bytes argument");
+ return -1;
+ }
+}
+
+/*[clinic input]
+_overlapped.Overlapped.ConnectEx
+
+ client_handle as ConnectSocket: HANDLE
+ address_as_bytes as AddressObj: object(subclass_of='&PyTuple_Type')
+ /
+
+Start overlapped connect.
+
+client_handle should be unbound.
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_Overlapped_ConnectEx_impl(OverlappedObject *self,
+ HANDLE ConnectSocket,
+ PyObject *AddressObj)
+/*[clinic end generated code: output=5aebbbdb4f022833 input=d6bbd2d84b156fc1]*/
+{
+ char AddressBuf[sizeof(struct sockaddr_in6)];
+ SOCKADDR *Address = (SOCKADDR*)AddressBuf;
+ int Length;
+ BOOL ret;
+ DWORD err;
+
+ if (self->type != TYPE_NONE) {
+ PyErr_SetString(PyExc_ValueError, "operation already attempted");
+ return NULL;
+ }
+
+ Length = sizeof(AddressBuf);
+ Length = parse_address(AddressObj, Address, Length);
+ if (Length < 0)
+ return NULL;
+
+ self->type = TYPE_CONNECT;
+ self->handle = ConnectSocket;
+
+ Py_BEGIN_ALLOW_THREADS
+ ret = Py_ConnectEx((SOCKET)ConnectSocket, Address, Length,
+ NULL, 0, NULL, &self->overlapped);
+ Py_END_ALLOW_THREADS
+
+ self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError();
+ switch (err) {
+ case ERROR_SUCCESS:
+ case ERROR_IO_PENDING:
+ Py_RETURN_NONE;
+ default:
+ Overlapped_clear(self);
+ return SetFromWindowsErr(err);
+ }
+}
+
+/*[clinic input]
+_overlapped.Overlapped.DisconnectEx
+
+ handle as Socket: HANDLE
+ flags: DWORD
+ /
+
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_Overlapped_DisconnectEx_impl(OverlappedObject *self,
+ HANDLE Socket, DWORD flags)
+/*[clinic end generated code: output=8d64ddb8c93c2126 input=680845cdcdf820eb]*/
+{
+ BOOL ret;
+ DWORD err;
+
+ if (self->type != TYPE_NONE) {
+ PyErr_SetString(PyExc_ValueError, "operation already attempted");
+ return NULL;
+ }
+
+ self->type = TYPE_DISCONNECT;
+ self->handle = Socket;
+
+ Py_BEGIN_ALLOW_THREADS
+ ret = Py_DisconnectEx((SOCKET)Socket, &self->overlapped, flags, 0);
+ Py_END_ALLOW_THREADS
+
+ self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError();
+ switch (err) {
+ case ERROR_SUCCESS:
+ case ERROR_IO_PENDING:
+ Py_RETURN_NONE;
+ default:
+ Overlapped_clear(self);
+ return SetFromWindowsErr(err);
+ }
+}
+
+/*[clinic input]
+_overlapped.Overlapped.TransmitFile
+
+ socket as Socket: HANDLE
+ file as File: HANDLE
+ offset: DWORD
+ offset_high: DWORD
+ count_to_write: DWORD
+ count_per_send: DWORD
+ flags: DWORD
+ /
+
+Transmit file data over a connected socket.
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_Overlapped_TransmitFile_impl(OverlappedObject *self,
+ HANDLE Socket, HANDLE File,
+ DWORD offset, DWORD offset_high,
+ DWORD count_to_write,
+ DWORD count_per_send, DWORD flags)
+/*[clinic end generated code: output=03f3ca5512e678fd input=7e6f97b391f60e8c]*/
+{
+ BOOL ret;
+ DWORD err;
+
+ if (self->type != TYPE_NONE) {
+ PyErr_SetString(PyExc_ValueError, "operation already attempted");
+ return NULL;
+ }
+
+ self->type = TYPE_TRANSMIT_FILE;
+ self->handle = Socket;
+ self->overlapped.Offset = offset;
+ self->overlapped.OffsetHigh = offset_high;
+
+ Py_BEGIN_ALLOW_THREADS
+ ret = Py_TransmitFile((SOCKET)Socket, File, count_to_write,
+ count_per_send, &self->overlapped, NULL, flags);
+ Py_END_ALLOW_THREADS
+
+ self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError();
+ switch (err) {
+ case ERROR_SUCCESS:
+ case ERROR_IO_PENDING:
+ Py_RETURN_NONE;
+ default:
+ Overlapped_clear(self);
+ return SetFromWindowsErr(err);
+ }
+}
+
+/*[clinic input]
+_overlapped.Overlapped.ConnectNamedPipe
+
+ handle as Pipe: HANDLE
+ /
+
+Start overlapped wait for a client to connect.
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_Overlapped_ConnectNamedPipe_impl(OverlappedObject *self,
+ HANDLE Pipe)
+/*[clinic end generated code: output=3e69adfe55818abe input=8b0d4cef8a72f7bc]*/
+{
+ BOOL ret;
+ DWORD err;
+
+ if (self->type != TYPE_NONE) {
+ PyErr_SetString(PyExc_ValueError, "operation already attempted");
+ return NULL;
+ }
+
+ self->type = TYPE_CONNECT_NAMED_PIPE;
+ self->handle = Pipe;
+
+ Py_BEGIN_ALLOW_THREADS
+ ret = ConnectNamedPipe(Pipe, &self->overlapped);
+ Py_END_ALLOW_THREADS
+
+ self->error = err = ret ? ERROR_SUCCESS : GetLastError();
+ switch (err) {
+ case ERROR_PIPE_CONNECTED:
+ mark_as_completed(&self->overlapped);
+ Py_RETURN_TRUE;
+ case ERROR_SUCCESS:
+ case ERROR_IO_PENDING:
+ Py_RETURN_FALSE;
+ default:
+ Overlapped_clear(self);
+ return SetFromWindowsErr(err);
+ }
+}
+
+/*[clinic input]
+_overlapped.Overlapped.ConnectPipe
+
+ addr as Address: Py_UNICODE
+ /
+
+Connect to the pipe for asynchronous I/O (overlapped).
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_Overlapped_ConnectPipe_impl(OverlappedObject *self,
+ const Py_UNICODE *Address)
+/*[clinic end generated code: output=3cc9661667d459d4 input=167c06a274efcefc]*/
+{
+ HANDLE PipeHandle;
+
+ Py_BEGIN_ALLOW_THREADS
+ PipeHandle = CreateFileW(Address,
+ GENERIC_READ | GENERIC_WRITE,
+ 0, NULL, OPEN_EXISTING,
+ FILE_FLAG_OVERLAPPED, NULL);
+ Py_END_ALLOW_THREADS
+
+ if (PipeHandle == INVALID_HANDLE_VALUE)
+ return SetFromWindowsErr(0);
+ return Py_BuildValue(F_HANDLE, PipeHandle);
+}
+
+static PyObject*
+Overlapped_getaddress(OverlappedObject *self)
+{
+ return PyLong_FromVoidPtr(&self->overlapped);
+}
+
+static PyObject*
+Overlapped_getpending(OverlappedObject *self)
+{
+ return PyBool_FromLong(!HasOverlappedIoCompleted(&self->overlapped) &&
+ self->type != TYPE_NOT_STARTED);
+}
+
+static int
+Overlapped_traverse(OverlappedObject *self, visitproc visit, void *arg)
+{
+ switch (self->type) {
+ case TYPE_READ:
+ case TYPE_ACCEPT:
+ Py_VISIT(self->allocated_buffer);
+ break;
+ case TYPE_WRITE:
+ case TYPE_WRITE_TO:
+ case TYPE_READINTO:
+ if (self->user_buffer.obj) {
+ Py_VISIT(&self->user_buffer.obj);
+ }
+ break;
+ case TYPE_READ_FROM:
+ Py_VISIT(self->read_from.result);
+ Py_VISIT(self->read_from.allocated_buffer);
+ break;
+ case TYPE_READ_FROM_INTO:
+ Py_VISIT(self->read_from_into.result);
+ if (self->read_from_into.user_buffer.obj) {
+ Py_VISIT(&self->read_from_into.user_buffer.obj);
+ }
+ break;
+ }
+ return 0;
+}
+
+// UDP functions
+
+/*
+ * Note: WSAConnect does not support Overlapped I/O so this function should
+ * _only_ be used for connectionless sockets (UDP).
+ */
+
+/*[clinic input]
+_overlapped.WSAConnect
+
+ client_handle as ConnectSocket: HANDLE
+ address_as_bytes as AddressObj: object(subclass_of='&PyTuple_Type')
+ /
+
+Bind a remote address to a connectionless (UDP) socket.
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_WSAConnect_impl(PyObject *module, HANDLE ConnectSocket,
+ PyObject *AddressObj)
+/*[clinic end generated code: output=ea0b4391e94dad63 input=7cf65313d49c015a]*/
+{
+ char AddressBuf[sizeof(struct sockaddr_in6)];
+ SOCKADDR *Address = (SOCKADDR*)AddressBuf;
+ int Length;
+ int err;
+
+ Length = sizeof(AddressBuf);
+ Length = parse_address(AddressObj, Address, Length);
+ if (Length < 0) {
+ return NULL;
+ }
+
+ Py_BEGIN_ALLOW_THREADS
+ // WSAConnect does not support overlapped I/O so this call will
+ // successfully complete immediately.
+ err = WSAConnect((SOCKET)ConnectSocket, Address, Length,
+ NULL, NULL, NULL, NULL);
+ Py_END_ALLOW_THREADS
+
+ if (err == 0) {
+ Py_RETURN_NONE;
+ }
+ else {
+ return SetFromWindowsErr(WSAGetLastError());
+ }
+}
+
+/*[clinic input]
+_overlapped.Overlapped.WSASendTo
+
+ handle: HANDLE
+ buf as bufobj: Py_buffer
+ flags: DWORD
+ address_as_bytes as AddressObj: object(subclass_of='&PyTuple_Type')
+ /
+
+Start overlapped sendto over a connectionless (UDP) socket.
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_Overlapped_WSASendTo_impl(OverlappedObject *self, HANDLE handle,
+ Py_buffer *bufobj, DWORD flags,
+ PyObject *AddressObj)
+/*[clinic end generated code: output=3cdedc4cfaeb70cd input=31f44cd4ab92fc33]*/
+{
+ char AddressBuf[sizeof(struct sockaddr_in6)];
+ SOCKADDR *Address = (SOCKADDR*)AddressBuf;
+ int AddressLength;
+ DWORD written;
+ WSABUF wsabuf;
+ int ret;
+ DWORD err;
+
+ // Parse the "to" address
+ AddressLength = sizeof(AddressBuf);
+ AddressLength = parse_address(AddressObj, Address, AddressLength);
+ if (AddressLength < 0) {
+ return NULL;
+ }
+
+ if (self->type != TYPE_NONE) {
+ PyErr_SetString(PyExc_ValueError, "operation already attempted");
+ return NULL;
+ }
+
+#if SIZEOF_SIZE_T > SIZEOF_LONG
+ if (bufobj->len > (Py_ssize_t)ULONG_MAX) {
+ PyErr_SetString(PyExc_ValueError, "buffer too large");
+ return NULL;
+ }
+#endif
+ steal_buffer(&self->user_buffer, bufobj);
+
+ self->type = TYPE_WRITE_TO;
+ self->handle = handle;
+ wsabuf.len = (DWORD)self->user_buffer.len;
+ wsabuf.buf = self->user_buffer.buf;
+
+ Py_BEGIN_ALLOW_THREADS
+ ret = WSASendTo((SOCKET)handle, &wsabuf, 1, &written, flags,
+ Address, AddressLength, &self->overlapped, NULL);
+ Py_END_ALLOW_THREADS
+
+ self->error = err = (ret == SOCKET_ERROR ? WSAGetLastError() :
+ ERROR_SUCCESS);
+
+ switch(err) {
+ case ERROR_SUCCESS:
+ case ERROR_IO_PENDING:
+ Py_RETURN_NONE;
+ default:
+ self->type = TYPE_NOT_STARTED;
+ return SetFromWindowsErr(err);
+ }
+}
+
+
+
+PyDoc_STRVAR(
+ Overlapped_WSARecvFrom_doc,
+ "RecvFile(handle, size, flags) -> Overlapped[(message, (host, port))]\n\n"
+ "Start overlapped receive");
+
+/*[clinic input]
+_overlapped.Overlapped.WSARecvFrom
+
+ handle: HANDLE
+ size: DWORD
+ flags: DWORD = 0
+ /
+
+Start overlapped receive.
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_Overlapped_WSARecvFrom_impl(OverlappedObject *self,
+ HANDLE handle, DWORD size,
+ DWORD flags)
+/*[clinic end generated code: output=13832a2025b86860 input=1b2663fa130e0286]*/
+{
+ PyObject *buf;
+ DWORD nread;
+ WSABUF wsabuf;
+ int ret;
+ DWORD err;
+
+ if (self->type != TYPE_NONE) {
+ PyErr_SetString(PyExc_ValueError, "operation already attempted");
+ return NULL;
+ }
+
+#if SIZEOF_SIZE_T <= SIZEOF_LONG
+ size = Py_MIN(size, (DWORD)PY_SSIZE_T_MAX);
+#endif
+ buf = PyBytes_FromStringAndSize(NULL, Py_MAX(size, 1));
+ if (buf == NULL) {
+ return NULL;
+ }
+
+ wsabuf.buf = PyBytes_AS_STRING(buf);
+ wsabuf.len = size;
+
+ self->type = TYPE_READ_FROM;
+ self->handle = handle;
+ self->read_from.allocated_buffer = buf;
+ memset(&self->read_from.address, 0, sizeof(self->read_from.address));
+ self->read_from.address_length = sizeof(self->read_from.address);
+
+ Py_BEGIN_ALLOW_THREADS
+ ret = WSARecvFrom((SOCKET)handle, &wsabuf, 1, &nread, &flags,
+ (SOCKADDR*)&self->read_from.address,
+ &self->read_from.address_length,
+ &self->overlapped, NULL);
+ Py_END_ALLOW_THREADS
+
+ self->error = err = (ret < 0 ? WSAGetLastError() : ERROR_SUCCESS);
+ switch (err) {
+ case ERROR_BROKEN_PIPE:
+ mark_as_completed(&self->overlapped);
+ return SetFromWindowsErr(err);
+ case ERROR_SUCCESS:
+ case ERROR_MORE_DATA:
+ case ERROR_IO_PENDING:
+ Py_RETURN_NONE;
+ default:
+ self->type = TYPE_NOT_STARTED;
+ return SetFromWindowsErr(err);
+ }
+}
+
+
+/*[clinic input]
+_overlapped.Overlapped.WSARecvFromInto
+
+ handle: HANDLE
+ buf as bufobj: Py_buffer
+ size: DWORD
+ flags: DWORD = 0
+ /
+
+Start overlapped receive.
+[clinic start generated code]*/
+
+static PyObject *
+_overlapped_Overlapped_WSARecvFromInto_impl(OverlappedObject *self,
+ HANDLE handle, Py_buffer *bufobj,
+ DWORD size, DWORD flags)
+/*[clinic end generated code: output=30c7ea171a691757 input=4be4b08d03531e76]*/
+{
+ DWORD nread;
+ WSABUF wsabuf;
+ int ret;
+ DWORD err;
+
+ if (self->type != TYPE_NONE) {
+ PyErr_SetString(PyExc_ValueError, "operation already attempted");
+ return NULL;
+ }
+
+#if SIZEOF_SIZE_T > SIZEOF_LONG
+ if (bufobj->len > (Py_ssize_t)ULONG_MAX) {
+ PyErr_SetString(PyExc_ValueError, "buffer too large");
+ return NULL;
+ }
+#endif
+
+ wsabuf.buf = bufobj->buf;
+ wsabuf.len = size;
+
+ self->type = TYPE_READ_FROM_INTO;
+ self->handle = handle;
+ steal_buffer(&self->read_from_into.user_buffer, bufobj);
+ memset(&self->read_from_into.address, 0, sizeof(self->read_from_into.address));
+ self->read_from_into.address_length = sizeof(self->read_from_into.address);
+
+ Py_BEGIN_ALLOW_THREADS
+ ret = WSARecvFrom((SOCKET)handle, &wsabuf, 1, &nread, &flags,
+ (SOCKADDR*)&self->read_from_into.address,
+ &self->read_from_into.address_length,
+ &self->overlapped, NULL);
+ Py_END_ALLOW_THREADS
+
+ self->error = err = (ret < 0 ? WSAGetLastError() : ERROR_SUCCESS);
+ switch (err) {
+ case ERROR_BROKEN_PIPE:
+ mark_as_completed(&self->overlapped);
+ return SetFromWindowsErr(err);
+ case ERROR_SUCCESS:
+ case ERROR_MORE_DATA:
+ case ERROR_IO_PENDING:
+ Py_RETURN_NONE;
+ default:
+ self->type = TYPE_NOT_STARTED;
+ return SetFromWindowsErr(err);
+ }
+}
+
+
+#include "clinic/overlapped.c.h"
+
+static PyMethodDef Overlapped_methods[] = {
+ _OVERLAPPED_OVERLAPPED_GETRESULT_METHODDEF
+ _OVERLAPPED_OVERLAPPED_CANCEL_METHODDEF
+ _OVERLAPPED_OVERLAPPED_READFILE_METHODDEF
+ _OVERLAPPED_OVERLAPPED_READFILEINTO_METHODDEF
+ _OVERLAPPED_OVERLAPPED_WSARECV_METHODDEF
+ _OVERLAPPED_OVERLAPPED_WSARECVINTO_METHODDEF
+ _OVERLAPPED_OVERLAPPED_WSARECVFROM_METHODDEF
+ _OVERLAPPED_OVERLAPPED_WSARECVFROMINTO_METHODDEF
+ _OVERLAPPED_OVERLAPPED_WRITEFILE_METHODDEF
+ _OVERLAPPED_OVERLAPPED_WSASEND_METHODDEF
+ _OVERLAPPED_OVERLAPPED_ACCEPTEX_METHODDEF
+ _OVERLAPPED_OVERLAPPED_CONNECTEX_METHODDEF
+ _OVERLAPPED_OVERLAPPED_DISCONNECTEX_METHODDEF
+ _OVERLAPPED_OVERLAPPED_TRANSMITFILE_METHODDEF
+ _OVERLAPPED_OVERLAPPED_CONNECTNAMEDPIPE_METHODDEF
+ _OVERLAPPED_OVERLAPPED_WSARECVFROM_METHODDEF
+ _OVERLAPPED_OVERLAPPED_WSASENDTO_METHODDEF
+ {NULL}
+};
+
+static PyMemberDef Overlapped_members[] = {
+ {"error", T_ULONG,
+ offsetof(OverlappedObject, error),
+ READONLY, "Error from last operation"},
+ {"event", T_HANDLE,
+ offsetof(OverlappedObject, overlapped) + offsetof(OVERLAPPED, hEvent),
+ READONLY, "Overlapped event handle"},
+ {NULL}
+};
+
+static PyGetSetDef Overlapped_getsets[] = {
+ {"address", (getter)Overlapped_getaddress, NULL,
+ "Address of overlapped structure"},
+ {"pending", (getter)Overlapped_getpending, NULL,
+ "Whether the operation is pending"},
+ {NULL},
+};
+
+static PyType_Slot overlapped_type_slots[] = {
+ {Py_tp_dealloc, Overlapped_dealloc},
+ {Py_tp_doc, (char *)_overlapped_Overlapped__doc__},
+ {Py_tp_traverse, Overlapped_traverse},
+ {Py_tp_methods, Overlapped_methods},
+ {Py_tp_members, Overlapped_members},
+ {Py_tp_getset, Overlapped_getsets},
+ {Py_tp_new, _overlapped_Overlapped},
+ {0,0}
+};
+
+static PyType_Spec overlapped_type_spec = {
+ .name = "_overlapped.Overlapped",
+ .basicsize = sizeof(OverlappedObject),
+ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE),
+ .slots = overlapped_type_slots
+};
+
+static PyMethodDef overlapped_functions[] = {
+ _OVERLAPPED_CREATEIOCOMPLETIONPORT_METHODDEF
+ _OVERLAPPED_GETQUEUEDCOMPLETIONSTATUS_METHODDEF
+ _OVERLAPPED_POSTQUEUEDCOMPLETIONSTATUS_METHODDEF
+ _OVERLAPPED_FORMATMESSAGE_METHODDEF
+ _OVERLAPPED_BINDLOCAL_METHODDEF
+ _OVERLAPPED_REGISTERWAITWITHQUEUE_METHODDEF
+ _OVERLAPPED_UNREGISTERWAIT_METHODDEF
+ _OVERLAPPED_UNREGISTERWAITEX_METHODDEF
+ _OVERLAPPED_CREATEEVENT_METHODDEF
+ _OVERLAPPED_SETEVENT_METHODDEF
+ _OVERLAPPED_RESETEVENT_METHODDEF
+ _OVERLAPPED_OVERLAPPED_CONNECTPIPE_METHODDEF
+ _OVERLAPPED_WSACONNECT_METHODDEF
+ {NULL}
+};
+
+#define WINAPI_CONSTANT(fmt, con) \
+ do { \
+ PyObject *value = Py_BuildValue(fmt, con); \
+ if (value == NULL) { \
+ return -1; \
+ } \
+ if (PyModule_AddObject(module, #con, value) < 0 ) { \
+ Py_DECREF(value); \
+ return -1; \
+ } \
+ } while (0)
+
+static int
+overlapped_exec(PyObject *module)
+{
+ /* Ensure WSAStartup() called before initializing function pointers */
+ PyObject *socket_module = PyImport_ImportModule("_socket");
+ if (!socket_module) {
+ return -1;
+ }
+
+ Py_DECREF(socket_module);
+
+ if (initialize_function_pointers() < 0) {
+ return -1;
+ }
+
+ PyTypeObject *overlapped_type = (PyTypeObject *)PyType_FromModuleAndSpec(
+ module, &overlapped_type_spec, NULL);
+ if (overlapped_type == NULL) {
+ return -1;
+ }
+
+ int rc = PyModule_AddType(module, overlapped_type);
+ Py_DECREF(overlapped_type);
+ if (rc < 0) {
+ return -1;
+ }
+
+ WINAPI_CONSTANT(F_DWORD, ERROR_IO_PENDING);
+ WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED);
+ WINAPI_CONSTANT(F_DWORD, ERROR_OPERATION_ABORTED);
+ WINAPI_CONSTANT(F_DWORD, ERROR_SEM_TIMEOUT);
+ WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_BUSY);
+ WINAPI_CONSTANT(F_DWORD, INFINITE);
+ WINAPI_CONSTANT(F_HANDLE, INVALID_HANDLE_VALUE);
+ WINAPI_CONSTANT(F_HANDLE, NULL);
+ WINAPI_CONSTANT(F_DWORD, SO_UPDATE_ACCEPT_CONTEXT);
+ WINAPI_CONSTANT(F_DWORD, SO_UPDATE_CONNECT_CONTEXT);
+ WINAPI_CONSTANT(F_DWORD, TF_REUSE_SOCKET);
+
+ return 0;
+}
+
+static PyModuleDef_Slot overlapped_slots[] = {
+ {Py_mod_exec, overlapped_exec},
+ {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
+ {0, NULL}
+};
+
+static struct PyModuleDef overlapped_module = {
+ .m_base = PyModuleDef_HEAD_INIT,
+ .m_name = "_overlapped",
+ .m_methods = overlapped_functions,
+ .m_slots = overlapped_slots,
+};
+
+PyMODINIT_FUNC
+PyInit__overlapped(void)
+{
+ return PyModuleDef_Init(&overlapped_module);
+}