Skip to content

Commit

Permalink
Moved kernel32 calls to _winapi.
Browse files Browse the repository at this point in the history
  • Loading branch information
applio committed Feb 20, 2019
1 parent 868b83d commit 9d83b06
Show file tree
Hide file tree
Showing 3 changed files with 295 additions and 71 deletions.
77 changes: 8 additions & 69 deletions Lib/multiprocessing/shared_memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,69 +27,10 @@

if os.name == "nt":
import _winapi
import ctypes
from ctypes import wintypes

kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)

class MEMORY_BASIC_INFORMATION(ctypes.Structure):
_fields_ = (
('BaseAddress', ctypes.c_void_p),
('AllocationBase', ctypes.c_void_p),
('AllocationProtect', wintypes.DWORD),
('RegionSize', ctypes.c_size_t),
('State', wintypes.DWORD),
('Protect', wintypes.DWORD),
('Type', wintypes.DWORD)
)

PMEMORY_BASIC_INFORMATION = ctypes.POINTER(MEMORY_BASIC_INFORMATION)
PAGE_READONLY = 0x02
PAGE_EXECUTE_READWRITE = 0x04
INVALID_HANDLE_VALUE = -1
ERROR_ALREADY_EXISTS = 183

def _errcheck_bool(result, func, args):
if not result:
raise ctypes.WinError(ctypes.get_last_error())
return args

kernel32.VirtualQuery.errcheck = _errcheck_bool
kernel32.VirtualQuery.restype = ctypes.c_size_t
kernel32.VirtualQuery.argtypes = (
wintypes.LPCVOID,
PMEMORY_BASIC_INFORMATION,
ctypes.c_size_t
)

kernel32.OpenFileMappingW.errcheck = _errcheck_bool
kernel32.OpenFileMappingW.restype = wintypes.HANDLE
kernel32.OpenFileMappingW.argtypes = (
wintypes.DWORD,
wintypes.BOOL,
wintypes.LPCWSTR
)

kernel32.CreateFileMappingW.errcheck = _errcheck_bool
kernel32.CreateFileMappingW.restype = wintypes.HANDLE
kernel32.CreateFileMappingW.argtypes = (
wintypes.HANDLE,
wintypes.LPCVOID,
wintypes.DWORD,
wintypes.DWORD,
wintypes.DWORD,
wintypes.LPCWSTR
)

kernel32.MapViewOfFile.errcheck = _errcheck_bool
kernel32.MapViewOfFile.restype = wintypes.LPVOID
kernel32.MapViewOfFile.argtypes = (
wintypes.HANDLE,
wintypes.DWORD,
wintypes.DWORD,
wintypes.DWORD,
ctypes.c_size_t
)


class WindowsNamedSharedMemory:
Expand All @@ -102,31 +43,29 @@ def __init__(self, name, flags=None, mode=384, size=0, read_only=False):
# Attempt to dynamically determine the existing named shared
# memory block's size which is likely a multiple of mmap.PAGESIZE.
try:
h_map = kernel32.OpenFileMappingW(PAGE_READONLY, False, name)
h_map = _winapi.OpenFileMappingW(PAGE_READONLY, False, name)
except OSError:
raise FileNotFoundError(name)
try:
p_buf = kernel32.MapViewOfFile(h_map, PAGE_READONLY, 0, 0, 0)
p_buf = _winapi.MapViewOfFile(h_map, PAGE_READONLY, 0, 0, 0)
finally:
_winapi.CloseHandle(h_map)
mbi = MEMORY_BASIC_INFORMATION()
kernel32.VirtualQuery(p_buf, ctypes.byref(mbi), mmap.PAGESIZE)
size = mbi.RegionSize
size = _winapi.VirtualQuerySize(p_buf)

if flags == O_CREX:
# Create and reserve shared memory block with this name until
# it can be attached to by mmap.
h_map = kernel32.CreateFileMappingW(
h_map = _winapi.CreateFileMappingW(
INVALID_HANDLE_VALUE,
None,
_winapi.NULL,
PAGE_EXECUTE_READWRITE,
size >> 32,
(size >> 32) & 0xFFFFFFFF,
size & 0xFFFFFFFF,
name
)
try:
last_error_code = ctypes.get_last_error()
if last_error_code == ERROR_ALREADY_EXISTS:
last_error_code = _winapi.GetLastError()
if last_error_code == _winapi.ERROR_ALREADY_EXISTS:
raise FileExistsError(f"File exists: {name!r}")
self._mmap = mmap.mmap(-1, size, tagname=name)
finally:
Expand Down
135 changes: 134 additions & 1 deletion Modules/_winapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ def create_converter(type_, format_unit):
create_converter('HANDLE', '" F_HANDLE "')
create_converter('HMODULE', '" F_HANDLE "')
create_converter('LPSECURITY_ATTRIBUTES', '" F_POINTER "')
create_converter('LPCVOID', '" F_POINTER "')
create_converter('BOOL', 'i') # F_BOOL used previously (always 'i')
create_converter('DWORD', 'k') # F_DWORD is always "k" (which is much shorter)
Expand Down Expand Up @@ -186,8 +187,17 @@ class DWORD_return_converter(CReturnConverter):
self.err_occurred_if("_return_value == PY_DWORD_MAX", data)
data.return_conversion.append(
'return_value = Py_BuildValue("k", _return_value);\n')
class LPVOID_return_converter(CReturnConverter):
type = 'LPVOID'
def render(self, function, data):
self.declare(data)
self.err_occurred_if("_return_value == NULL", data)
data.return_conversion.append(
'return_value = HANDLE_TO_PYNUM(_return_value);\n')
[python start generated code]*/
/*[python end generated code: output=da39a3ee5e6b4b0d input=27456f8555228b62]*/
/*[python end generated code: output=da39a3ee5e6b4b0d input=79464c61a31ae932]*/

#include "clinic/_winapi.c.h"

Expand Down Expand Up @@ -464,6 +474,41 @@ _winapi_CreateFile_impl(PyObject *module, LPCTSTR file_name,
return handle;
}

/*[clinic input]
_winapi.CreateFileMappingW -> HANDLE
file_handle: HANDLE
security_attributes: LPSECURITY_ATTRIBUTES
protect: DWORD
max_size_high: DWORD
max_size_low: DWORD
name: LPCWSTR
/
[clinic start generated code]*/

static HANDLE
_winapi_CreateFileMappingW_impl(PyObject *module, HANDLE file_handle,
LPSECURITY_ATTRIBUTES security_attributes,
DWORD protect, DWORD max_size_high,
DWORD max_size_low, LPCWSTR name)
/*[clinic end generated code: output=c6b017501c929de1 input=35cadabe53b3b4da]*/
{
HANDLE handle;

Py_BEGIN_ALLOW_THREADS
handle = CreateFileMappingW(file_handle, security_attributes,
protect, max_size_high, max_size_low,
name);
Py_END_ALLOW_THREADS

if (handle == NULL) {
PyErr_SetFromWindowsErr(0);
handle = INVALID_HANDLE_VALUE;
}

return handle;
}

/*[clinic input]
_winapi.CreateJunction
Expand Down Expand Up @@ -1295,6 +1340,64 @@ _winapi_GetVersion_impl(PyObject *module)

#pragma warning(pop)

/*[clinic input]
_winapi.MapViewOfFile -> LPVOID
file_map: HANDLE
desired_access: DWORD
file_offset_high: DWORD
file_offset_low: DWORD
number_bytes: size_t
/
[clinic start generated code]*/

static LPVOID
_winapi_MapViewOfFile_impl(PyObject *module, HANDLE file_map,
DWORD desired_access, DWORD file_offset_high,
DWORD file_offset_low, size_t number_bytes)
/*[clinic end generated code: output=f23b1ee4823663e3 input=177471073be1a103]*/
{
LPVOID address;

Py_BEGIN_ALLOW_THREADS
address = MapViewOfFile(file_map, desired_access, file_offset_high,
file_offset_low, number_bytes);
Py_END_ALLOW_THREADS

if (address == NULL)
PyErr_SetFromWindowsErr(0);

return address;
}

/*[clinic input]
_winapi.OpenFileMappingW -> HANDLE
desired_access: DWORD
inherit_handle: BOOL
name: LPCWSTR
/
[clinic start generated code]*/

static HANDLE
_winapi_OpenFileMappingW_impl(PyObject *module, DWORD desired_access,
BOOL inherit_handle, LPCWSTR name)
/*[clinic end generated code: output=ad829d0e68cac379 input=68fa4e0f2d5d5c42]*/
{
HANDLE handle;

Py_BEGIN_ALLOW_THREADS
handle = OpenFileMappingW(desired_access, inherit_handle, name);
Py_END_ALLOW_THREADS

if (handle == NULL) {
PyErr_SetFromWindowsErr(0);
handle = INVALID_HANDLE_VALUE;
}

return handle;
}

/*[clinic input]
_winapi.OpenProcess -> HANDLE
Expand Down Expand Up @@ -1490,6 +1593,32 @@ _winapi_TerminateProcess_impl(PyObject *module, HANDLE handle,
Py_RETURN_NONE;
}

/*[clinic input]
_winapi.VirtualQuerySize -> size_t
address: LPCVOID
/
[clinic start generated code]*/

static size_t
_winapi_VirtualQuerySize_impl(PyObject *module, LPCVOID address)
/*[clinic end generated code: output=40c8e0ff5ec964df input=6b784a69755d0bb6]*/
{
SIZE_T size_of_buf;
MEMORY_BASIC_INFORMATION mem_basic_info;
SIZE_T region_size;

Py_BEGIN_ALLOW_THREADS
size_of_buf = VirtualQuery(address, &mem_basic_info, sizeof(mem_basic_info));
Py_END_ALLOW_THREADS

if (size_of_buf == 0)
PyErr_SetFromWindowsErr(0);

region_size = mem_basic_info.RegionSize;
return region_size;
}

/*[clinic input]
_winapi.WaitNamedPipe
Expand Down Expand Up @@ -1719,6 +1848,7 @@ static PyMethodDef winapi_functions[] = {
_WINAPI_CLOSEHANDLE_METHODDEF
_WINAPI_CONNECTNAMEDPIPE_METHODDEF
_WINAPI_CREATEFILE_METHODDEF
_WINAPI_CREATEFILEMAPPINGW_METHODDEF
_WINAPI_CREATENAMEDPIPE_METHODDEF
_WINAPI_CREATEPIPE_METHODDEF
_WINAPI_CREATEPROCESS_METHODDEF
Expand All @@ -1731,11 +1861,14 @@ static PyMethodDef winapi_functions[] = {
_WINAPI_GETMODULEFILENAME_METHODDEF
_WINAPI_GETSTDHANDLE_METHODDEF
_WINAPI_GETVERSION_METHODDEF
_WINAPI_MAPVIEWOFFILE_METHODDEF
_WINAPI_OPENFILEMAPPINGW_METHODDEF
_WINAPI_OPENPROCESS_METHODDEF
_WINAPI_PEEKNAMEDPIPE_METHODDEF
_WINAPI_READFILE_METHODDEF
_WINAPI_SETNAMEDPIPEHANDLESTATE_METHODDEF
_WINAPI_TERMINATEPROCESS_METHODDEF
_WINAPI_VIRTUALQUERYSIZE_METHODDEF
_WINAPI_WAITNAMEDPIPE_METHODDEF
_WINAPI_WAITFORMULTIPLEOBJECTS_METHODDEF
_WINAPI_WAITFORSINGLEOBJECT_METHODDEF
Expand Down
Loading

0 comments on commit 9d83b06

Please sign in to comment.