Issue #11750: The Windows API functions scattered in the _subprocess and
_multiprocessing.win32 modules now live in a single module "_winapi".
Patch by sbt.
diff --git a/Modules/_multiprocessing/multiprocessing.c b/Modules/_multiprocessing/multiprocessing.c
index d370f9a..6e39a23 100644
--- a/Modules/_multiprocessing/multiprocessing.c
+++ b/Modules/_multiprocessing/multiprocessing.c
@@ -9,8 +9,6 @@
 #include "multiprocessing.h"
 
 
-PyObject *create_win32_namespace(void);
-
 PyObject *ProcessError, *BufferTooShort;
 
 /*
@@ -66,6 +64,72 @@
                          PyLong_FromVoidPtr(buffer), buffer_len);
 }
 
+#ifdef MS_WINDOWS
+static PyObject *
+multiprocessing_closesocket(PyObject *self, PyObject *args)
+{
+    HANDLE handle;
+    int ret;
+
+    if (!PyArg_ParseTuple(args, F_HANDLE ":closesocket" , &handle))
+        return NULL;
+
+    Py_BEGIN_ALLOW_THREADS
+    ret = closesocket((SOCKET) handle);
+    Py_END_ALLOW_THREADS
+
+    if (ret)
+        return PyErr_SetExcFromWindowsErr(PyExc_IOError, WSAGetLastError());
+    Py_RETURN_NONE;
+}
+
+static PyObject *
+multiprocessing_recv(PyObject *self, PyObject *args)
+{
+    HANDLE handle;
+    int size, nread;
+    PyObject *buf;
+
+    if (!PyArg_ParseTuple(args, F_HANDLE "i:recv" , &handle, &size))
+        return NULL;
+
+    buf = PyBytes_FromStringAndSize(NULL, size);
+    if (!buf)
+        return NULL;
+
+    Py_BEGIN_ALLOW_THREADS
+    nread = recv((SOCKET) handle, PyBytes_AS_STRING(buf), size, 0);
+    Py_END_ALLOW_THREADS
+
+    if (nread < 0) {
+        Py_DECREF(buf);
+        return PyErr_SetExcFromWindowsErr(PyExc_IOError, WSAGetLastError());
+    }
+    _PyBytes_Resize(&buf, nread);
+    return buf;
+}
+
+static PyObject *
+multiprocessing_send(PyObject *self, PyObject *args)
+{
+    HANDLE handle;
+    Py_buffer buf;
+    int ret;
+
+    if (!PyArg_ParseTuple(args, F_HANDLE "y*:send" , &handle, &buf))
+        return NULL;
+
+    Py_BEGIN_ALLOW_THREADS
+    ret = send((SOCKET) handle, buf.buf, buf.len, 0);
+    Py_END_ALLOW_THREADS
+
+    PyBuffer_Release(&buf);
+    if (ret < 0)
+        return PyErr_SetExcFromWindowsErr(PyExc_IOError, WSAGetLastError());
+    return PyLong_FromLong(ret);
+}
+
+#endif
 
 /*
  * Function table
@@ -75,6 +139,11 @@
     {"address_of_buffer", multiprocessing_address_of_buffer, METH_O,
      "address_of_buffer(obj) -> int\n"
      "Return address of obj assuming obj supports buffer inteface"},
+#ifdef MS_WINDOWS
+    {"closesocket", multiprocessing_closesocket, METH_VARARGS, ""},
+    {"recv", multiprocessing_recv, METH_VARARGS, ""},
+    {"send", multiprocessing_send, METH_VARARGS, ""},
+#endif
     {NULL}
 };
 
@@ -135,14 +204,6 @@
     PyModule_AddObject(module, "SemLock", (PyObject*)&SemLockType);
 #endif
 
-#ifdef MS_WINDOWS
-    /* Initialize win32 class and add to multiprocessing */
-    temp = create_win32_namespace();
-    if (!temp)
-        return NULL;
-    PyModule_AddObject(module, "win32", temp);
-#endif
-
     /* Add configuration macros */
     temp = PyDict_New();
     if (!temp)
@@ -152,7 +213,7 @@
     value = Py_BuildValue("i", name);                             \
     if (value == NULL) { Py_DECREF(temp); return NULL; }          \
     if (PyDict_SetItemString(temp, #name, value) < 0) {           \
-        Py_DECREF(temp); Py_DECREF(value); return NULL; }                 \
+        Py_DECREF(temp); Py_DECREF(value); return NULL; }         \
     Py_DECREF(value)
 
 #if defined(HAVE_SEM_OPEN) && !defined(POSIX_SEMAPHORES_NOT_ENABLED)