#ifndef Py_BUILD_CORE_BUILTIN
#define Py_BUILD_CORE_MODULE …
#endif
#include "Python.h"
#include <stdbool.h>
#ifdef MS_WIN32
#include <windows.h>
#include <tchar.h>
#else
#include <dlfcn.h>
#endif
#ifdef __APPLE__
#include <mach-o/dyld.h>
#endif
#ifdef MS_WIN32
#include <malloc.h>
#endif
#include <ffi.h>
#include "ctypes.h"
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#endif
#ifdef _Py_MEMORY_SANITIZER
#include <sanitizer/msan_interface.h>
#endif
#if defined(_DEBUG) || defined(__MINGW32__)
#define DONT_USE_SEH
#endif
#include "pycore_runtime.h"
#include "pycore_global_objects.h"
#include "pycore_traceback.h"
#if defined(Py_HAVE_C_COMPLEX) && defined(Py_FFI_SUPPORT_C_COMPLEX)
#include "../_complex.h"
#endif
#include "clinic/callproc.c.h"
#define CTYPES_CAPSULE_NAME_PYMEM …
static void pymem_destructor(PyObject *ptr)
{ … }
PyObject *
_ctypes_get_errobj(ctypes_state *st, int **pspace)
{ … }
static PyObject *
get_error_internal(PyObject *self, PyObject *args, int index)
{ … }
static PyObject *
set_error_internal(PyObject *self, PyObject *args, int index)
{ … }
static PyObject *
get_errno(PyObject *self, PyObject *args)
{ … }
static PyObject *
set_errno(PyObject *self, PyObject *args)
{ … }
#ifdef MS_WIN32
static PyObject *
get_last_error(PyObject *self, PyObject *args)
{
if (PySys_Audit("ctypes.get_last_error", NULL) < 0) {
return NULL;
}
return get_error_internal(self, args, 1);
}
static PyObject *
set_last_error(PyObject *self, PyObject *args)
{
if (PySys_Audit("ctypes.set_last_error", "O", args) < 0) {
return NULL;
}
return set_error_internal(self, args, 1);
}
static WCHAR *FormatError(DWORD code)
{
WCHAR *lpMsgBuf;
DWORD n;
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';
}
return lpMsgBuf;
}
#ifndef DONT_USE_SEH
static void SetException(DWORD code, EXCEPTION_RECORD *pr)
{
if (PySys_Audit("ctypes.set_exception", "I", code) < 0) {
return;
}
switch (code) {
case EXCEPTION_ACCESS_VIOLATION:
if (pr->ExceptionInformation[0] == 0)
PyErr_Format(PyExc_OSError,
"exception: access violation reading %p",
pr->ExceptionInformation[1]);
else
PyErr_Format(PyExc_OSError,
"exception: access violation writing %p",
pr->ExceptionInformation[1]);
break;
case EXCEPTION_BREAKPOINT:
PyErr_SetString(PyExc_OSError,
"exception: breakpoint encountered");
break;
case EXCEPTION_DATATYPE_MISALIGNMENT:
PyErr_SetString(PyExc_OSError,
"exception: datatype misalignment");
break;
case EXCEPTION_SINGLE_STEP:
PyErr_SetString(PyExc_OSError,
"exception: single step");
break;
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
PyErr_SetString(PyExc_OSError,
"exception: array bounds exceeded");
break;
case EXCEPTION_FLT_DENORMAL_OPERAND:
PyErr_SetString(PyExc_OSError,
"exception: floating-point operand denormal");
break;
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
PyErr_SetString(PyExc_OSError,
"exception: float divide by zero");
break;
case EXCEPTION_FLT_INEXACT_RESULT:
PyErr_SetString(PyExc_OSError,
"exception: float inexact");
break;
case EXCEPTION_FLT_INVALID_OPERATION:
PyErr_SetString(PyExc_OSError,
"exception: float invalid operation");
break;
case EXCEPTION_FLT_OVERFLOW:
PyErr_SetString(PyExc_OSError,
"exception: float overflow");
break;
case EXCEPTION_FLT_STACK_CHECK:
PyErr_SetString(PyExc_OSError,
"exception: stack over/underflow");
break;
case EXCEPTION_STACK_OVERFLOW:
PyErr_SetString(PyExc_OSError,
"exception: stack overflow");
break;
case EXCEPTION_FLT_UNDERFLOW:
PyErr_SetString(PyExc_OSError,
"exception: float underflow");
break;
case EXCEPTION_INT_DIVIDE_BY_ZERO:
PyErr_SetString(PyExc_OSError,
"exception: integer divide by zero");
break;
case EXCEPTION_INT_OVERFLOW:
PyErr_SetString(PyExc_OSError,
"exception: integer overflow");
break;
case EXCEPTION_PRIV_INSTRUCTION:
PyErr_SetString(PyExc_OSError,
"exception: privileged instruction");
break;
case EXCEPTION_NONCONTINUABLE_EXCEPTION:
PyErr_SetString(PyExc_OSError,
"exception: nocontinuable");
break;
default:
PyErr_SetFromWindowsErr(code);
break;
}
}
static DWORD HandleException(EXCEPTION_POINTERS *ptrs,
DWORD *pdw, EXCEPTION_RECORD *record)
{
*pdw = ptrs->ExceptionRecord->ExceptionCode;
*record = *ptrs->ExceptionRecord;
if (*pdw == EXCEPTION_BREAKPOINT)
return EXCEPTION_CONTINUE_SEARCH;
return EXCEPTION_EXECUTE_HANDLER;
}
#endif
static PyObject *
check_hresult(PyObject *self, PyObject *args)
{
HRESULT hr;
if (!PyArg_ParseTuple(args, "i", &hr))
return NULL;
if (FAILED(hr))
return PyErr_SetFromWindowsErr(hr);
return PyLong_FromLong(hr);
}
#endif
PyCArgObject *
PyCArgObject_new(ctypes_state *st)
{ … }
static int
PyCArg_traverse(PyCArgObject *self, visitproc visit, void *arg)
{ … }
static int
PyCArg_clear(PyCArgObject *self)
{ … }
static void
PyCArg_dealloc(PyCArgObject *self)
{ … }
static int
is_literal_char(unsigned char c)
{ … }
static PyObject *
PyCArg_repr(PyCArgObject *self)
{ … }
static PyMemberDef PyCArgType_members[] = …;
static PyType_Slot carg_slots[] = …;
PyType_Spec carg_spec = …;
result;
struct argument { … };
static int ConvParam(ctypes_state *st,
PyObject *obj, Py_ssize_t index, struct argument *pa)
{ … }
#if defined(MS_WIN32) && !defined(_WIN32_WCE)
int can_return_struct_as_int(size_t s)
{
return s == 1 || s == 2 || s == 4;
}
int can_return_struct_as_sint64(size_t s)
{
#ifdef _M_ARM
return 0;
#else
return s == 8;
#endif
}
#endif
ffi_type *_ctypes_get_ffi_type(ctypes_state *st, PyObject *obj)
{ … }
static int _call_function_pointer(ctypes_state *st,
int flags,
PPROC pProc,
void **avalues,
ffi_type **atypes,
ffi_type *restype,
void *resmem,
int argcount,
int argtypecount)
{ … }
static PyObject *GetResult(ctypes_state *st,
PyObject *restype, void *result, PyObject *checker)
{ … }
void _ctypes_extend_error(PyObject *exc_class, const char *fmt, ...)
{ … }
#ifdef MS_WIN32
static PyObject *
GetComError(ctypes_state *st, HRESULT errcode, GUID *riid, IUnknown *pIunk)
{
HRESULT hr;
ISupportErrorInfo *psei = NULL;
IErrorInfo *pei = NULL;
BSTR descr=NULL, helpfile=NULL, source=NULL;
GUID guid;
DWORD helpcontext=0;
LPOLESTR progid;
PyObject *obj;
LPOLESTR text;
Py_BEGIN_ALLOW_THREADS
hr = pIunk->lpVtbl->QueryInterface(pIunk, &IID_ISupportErrorInfo, (void **)&psei);
if (FAILED(hr))
goto failed;
hr = psei->lpVtbl->InterfaceSupportsErrorInfo(psei, riid);
psei->lpVtbl->Release(psei);
if (FAILED(hr))
goto failed;
hr = GetErrorInfo(0, &pei);
if (hr != S_OK)
goto failed;
pei->lpVtbl->GetDescription(pei, &descr);
pei->lpVtbl->GetGUID(pei, &guid);
pei->lpVtbl->GetHelpContext(pei, &helpcontext);
pei->lpVtbl->GetHelpFile(pei, &helpfile);
pei->lpVtbl->GetSource(pei, &source);
pei->lpVtbl->Release(pei);
failed:
Py_END_ALLOW_THREADS
progid = NULL;
ProgIDFromCLSID(&guid, &progid);
text = FormatError(errcode);
obj = Py_BuildValue(
"iu(uuuiu)",
errcode,
text,
descr, source, helpfile, helpcontext,
progid);
if (obj) {
PyErr_SetObject((PyObject *)st->PyComError_Type, obj);
Py_DECREF(obj);
}
LocalFree(text);
if (descr)
SysFreeString(descr);
if (helpfile)
SysFreeString(helpfile);
if (source)
SysFreeString(source);
return NULL;
}
#endif
#if (defined(__x86_64__) && (defined(__MINGW64__) || defined(__CYGWIN__))) || \
defined(__aarch64__) || defined(__riscv)
#define CTYPES_PASS_BY_REF_HACK
#define POW2 …
#define IS_PASS_BY_REF …
#endif
PyObject *_ctypes_callproc(ctypes_state *st,
PPROC pProc,
PyObject *argtuple,
#ifdef MS_WIN32
IUnknown *pIunk,
GUID *iid,
#endif
int flags,
PyObject *argtypes,
PyObject *restype,
PyObject *checker)
{ … }
static int
_parse_voidp(PyObject *obj, void **address)
{ … }
#ifdef MS_WIN32
PyDoc_STRVAR(format_error_doc,
"FormatError([integer]) -> string\n\
\n\
Convert a win32 error code into a string. If the error code is not\n\
given, the return value of a call to GetLastError() is used.\n");
static PyObject *format_error(PyObject *self, PyObject *args)
{
PyObject *result;
wchar_t *lpMsgBuf;
DWORD code = 0;
if (!PyArg_ParseTuple(args, "|i:FormatError", &code))
return NULL;
if (code == 0)
code = GetLastError();
lpMsgBuf = FormatError(code);
if (lpMsgBuf) {
result = PyUnicode_FromWideChar(lpMsgBuf, wcslen(lpMsgBuf));
LocalFree(lpMsgBuf);
} else {
result = PyUnicode_FromString("<no description>");
}
return result;
}
PyDoc_STRVAR(load_library_doc,
"LoadLibrary(name, load_flags) -> handle\n\
\n\
Load an executable (usually a DLL), and return a handle to it.\n\
The handle may be used to locate exported functions in this\n\
module. load_flags are as defined for LoadLibraryEx in the\n\
Windows API.\n");
static PyObject *load_library(PyObject *self, PyObject *args)
{
PyObject *nameobj;
int load_flags = 0;
HMODULE hMod;
DWORD err;
if (!PyArg_ParseTuple(args, "U|i:LoadLibrary", &nameobj, &load_flags))
return NULL;
if (PySys_Audit("ctypes.dlopen", "O", nameobj) < 0) {
return NULL;
}
WCHAR *name = PyUnicode_AsWideCharString(nameobj, NULL);
if (!name)
return NULL;
Py_BEGIN_ALLOW_THREADS
hMod = LoadLibraryExW(name, NULL, (DWORD)load_flags);
err = hMod ? 0 : GetLastError();
Py_END_ALLOW_THREADS
PyMem_Free(name);
if (err == ERROR_MOD_NOT_FOUND) {
PyErr_Format(PyExc_FileNotFoundError,
("Could not find module '%.500S' (or one of its "
"dependencies). Try using the full path with "
"constructor syntax."),
nameobj);
return NULL;
} else if (err) {
return PyErr_SetFromWindowsErr(err);
}
#ifdef _WIN64
return PyLong_FromVoidPtr(hMod);
#else
return PyLong_FromLong((int)hMod);
#endif
}
PyDoc_STRVAR(free_library_doc,
"FreeLibrary(handle) -> void\n\
\n\
Free the handle of an executable previously loaded by LoadLibrary.\n");
static PyObject *free_library(PyObject *self, PyObject *args)
{
void *hMod;
BOOL result;
DWORD err;
if (!PyArg_ParseTuple(args, "O&:FreeLibrary", &_parse_voidp, &hMod))
return NULL;
Py_BEGIN_ALLOW_THREADS
result = FreeLibrary((HMODULE)hMod);
err = result ? 0 : GetLastError();
Py_END_ALLOW_THREADS
if (!result) {
return PyErr_SetFromWindowsErr(err);
}
Py_RETURN_NONE;
}
PyDoc_STRVAR(copy_com_pointer_doc,
"CopyComPointer(src, dst) -> HRESULT value\n");
static PyObject *
copy_com_pointer(PyObject *self, PyObject *args)
{
PyObject *p1, *p2, *r = NULL;
struct argument a, b;
IUnknown *src, **pdst;
if (!PyArg_ParseTuple(args, "OO:CopyComPointer", &p1, &p2))
return NULL;
a.keep = b.keep = NULL;
ctypes_state *st = get_module_state(self);
if (ConvParam(st, p1, 0, &a) < 0 || ConvParam(st, p2, 1, &b) < 0) {
goto done;
}
src = (IUnknown *)a.value.p;
pdst = (IUnknown **)b.value.p;
if (pdst == NULL)
r = PyLong_FromLong(E_POINTER);
else {
if (src)
src->lpVtbl->AddRef(src);
*pdst = src;
r = PyLong_FromLong(S_OK);
}
done:
Py_XDECREF(a.keep);
Py_XDECREF(b.keep);
return r;
}
#else
#ifdef __APPLE__
#ifdef HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH
# ifdef HAVE_BUILTIN_AVAILABLE
#define HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH_RUNTIME …
# else
#define HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH_RUNTIME …
# endif
#else
static void *libsystem_b_handle;
static bool (*_dyld_shared_cache_contains_path)(const char *path);
__attribute__((constructor)) void load_dyld_shared_cache_contains_path(void) {
libsystem_b_handle = dlopen("/usr/lib/libSystem.B.dylib", RTLD_LAZY);
if (libsystem_b_handle != NULL) {
_dyld_shared_cache_contains_path = dlsym(libsystem_b_handle, "_dyld_shared_cache_contains_path");
}
}
__attribute__((destructor)) void unload_dyld_shared_cache_contains_path(void) {
if (libsystem_b_handle != NULL) {
dlclose(libsystem_b_handle);
}
}
#define HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH_RUNTIME …
#endif
static PyObject *py_dyld_shared_cache_contains_path(PyObject *self, PyObject *args)
{
PyObject *name, *name2;
char *name_str;
if (HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH_RUNTIME) {
int r;
if (!PyArg_ParseTuple(args, "O", &name))
return NULL;
if (name == Py_None)
Py_RETURN_FALSE;
if (PyUnicode_FSConverter(name, &name2) == 0)
return NULL;
name_str = PyBytes_AS_STRING(name2);
r = _dyld_shared_cache_contains_path(name_str);
Py_DECREF(name2);
if (r) {
Py_RETURN_TRUE;
} else {
Py_RETURN_FALSE;
}
} else {
PyErr_SetString(PyExc_NotImplementedError, "_dyld_shared_cache_contains_path symbol is missing");
return NULL;
}
}
#endif
static PyObject *py_dl_open(PyObject *self, PyObject *args)
{ … }
static PyObject *py_dl_close(PyObject *self, PyObject *args)
{ … }
static PyObject *py_dl_sym(PyObject *self, PyObject *args)
{ … }
#endif
static PyObject *
call_function(PyObject *self, PyObject *args)
{ … }
static PyObject *
call_cdeclfunction(PyObject *self, PyObject *args)
{ … }
PyDoc_STRVAR(sizeof_doc,
"sizeof(C type) -> integer\n"
"sizeof(C instance) -> integer\n"
"Return the size in bytes of a C instance");
static PyObject *
sizeof_func(PyObject *self, PyObject *obj)
{ … }
PyDoc_STRVAR(alignment_doc,
"alignment(C type) -> integer\n"
"alignment(C instance) -> integer\n"
"Return the alignment requirements of a C instance");
static PyObject *
align_func(PyObject *self, PyObject *obj)
{ … }
PyDoc_STRVAR(byref_doc,
"byref(C instance[, offset=0]) -> byref-object\n"
"Return a pointer lookalike to a C instance, only usable\n"
"as function argument");
static PyObject *
byref(PyObject *self, PyObject *args)
{ … }
PyDoc_STRVAR(addressof_doc,
"addressof(C instance) -> integer\n"
"Return the address of the C instance internal buffer");
static PyObject *
addressof(PyObject *self, PyObject *obj)
{ … }
static int
converter(PyObject *obj, void **address)
{ … }
static PyObject *
My_PyObj_FromPtr(PyObject *self, PyObject *args)
{ … }
static PyObject *
My_Py_INCREF(PyObject *self, PyObject *arg)
{ … }
static PyObject *
My_Py_DECREF(PyObject *self, PyObject *arg)
{ … }
static PyObject *
resize(PyObject *self, PyObject *args)
{ … }
static PyObject *
unpickle(PyObject *self, PyObject *args)
{ … }
static PyObject *
create_pointer_type(PyObject *module, PyObject *cls)
{ … }
static PyObject *
create_pointer_inst(PyObject *module, PyObject *arg)
{ … }
static PyObject *
buffer_info(PyObject *self, PyObject *arg)
{ … }
PyMethodDef _ctypes_module_methods[] = …;