LCOV - code coverage report
Current view: | top level - Modules/_ctypes - callproc.c (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 30 | 531 | 5.6 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 3 | 35 | 8.6 %
|  |  | Branches: | 11 | 295 | 3.7 %

               Branch data     Line data    Source code
           1                 :            : /*
           2                 :            :  * History: First version dated from 3/97, derived from my SCMLIB version
           3                 :            :  * for win16.
           4                 :            :  */
           5                 :            : /*
           6                 :            :  * Related Work:
           7                 :            :  *      - calldll       http://www.nightmare.com/software.html
           8                 :            :  *      - libffi        http://sourceware.cygnus.com/libffi/
           9                 :            :  *      - ffcall        http://clisp.cons.org/~haible/packages-ffcall.html
          10                 :            :  *   and, of course, Don Beaudry's MESS package, but this is more ctypes
          11                 :            :  *   related.
          12                 :            :  */
          13                 :            :
          14                 :            :
          15                 :            : /*
          16                 :            :   How are functions called, and how are parameters converted to C ?
          17                 :            :
          18                 :            :   1. _ctypes.c::PyCFuncPtr_call receives an argument tuple 'inargs' and a
          19                 :            :   keyword dictionary 'kwds'.
          20                 :            :
          21                 :            :   2. After several checks, _build_callargs() is called which returns another
          22                 :            :   tuple 'callargs'.  This may be the same tuple as 'inargs', a slice of
          23                 :            :   'inargs', or a completely fresh tuple, depending on several things (is it a
          24                 :            :   COM method?, are 'paramflags' available?).
          25                 :            :
          26                 :            :   3. _build_callargs also calculates bitarrays containing indexes into
          27                 :            :   the callargs tuple, specifying how to build the return value(s) of
          28                 :            :   the function.
          29                 :            :
          30                 :            :   4. _ctypes_callproc is then called with the 'callargs' tuple.  _ctypes_callproc first
          31                 :            :   allocates two arrays.  The first is an array of 'struct argument' items, the
          32                 :            :   second array has 'void *' entries.
          33                 :            :
          34                 :            :   5. If 'converters' are present (converters is a sequence of argtypes'
          35                 :            :   from_param methods), for each item in 'callargs' converter is called and the
          36                 :            :   result passed to ConvParam.  If 'converters' are not present, each argument
          37                 :            :   is directly passed to ConvParm.
          38                 :            :
          39                 :            :   6. For each arg, ConvParam stores the contained C data (or a pointer to it,
          40                 :            :   for structures) into the 'struct argument' array.
          41                 :            :
          42                 :            :   7. Finally, a loop fills the 'void *' array so that each item points to the
          43                 :            :   data contained in or pointed to by the 'struct argument' array.
          44                 :            :
          45                 :            :   8. The 'void *' argument array is what _call_function_pointer
          46                 :            :   expects. _call_function_pointer then has very little to do - only some
          47                 :            :   libffi specific stuff, then it calls ffi_call.
          48                 :            :
          49                 :            :   So, there are 4 data structures holding processed arguments:
          50                 :            :   - the inargs tuple (in PyCFuncPtr_call)
          51                 :            :   - the callargs tuple (in PyCFuncPtr_call)
          52                 :            :   - the 'struct arguments' array
          53                 :            :   - the 'void *' array
          54                 :            :
          55                 :            :  */
          56                 :            :
          57                 :            : #ifndef Py_BUILD_CORE_BUILTIN
          58                 :            : #  define Py_BUILD_CORE_MODULE 1
          59                 :            : #endif
          60                 :            :
          61                 :            : #include "Python.h"
          62                 :            : #include "structmember.h"         // PyMemberDef
          63                 :            :
          64                 :            : #include <stdbool.h>
          65                 :            :
          66                 :            : #ifdef MS_WIN32
          67                 :            : #include <windows.h>
          68                 :            : #include <tchar.h>
          69                 :            : #else
          70                 :            : #include <dlfcn.h>
          71                 :            : #endif
          72                 :            :
          73                 :            : #ifdef __APPLE__
          74                 :            : #include <mach-o/dyld.h>
          75                 :            : #endif
          76                 :            :
          77                 :            : #ifdef MS_WIN32
          78                 :            : #include <malloc.h>
          79                 :            : #endif
          80                 :            :
          81                 :            : #include <ffi.h>
          82                 :            : #include "ctypes.h"
          83                 :            : #ifdef HAVE_ALLOCA_H
          84                 :            : /* AIX needs alloca.h for alloca() */
          85                 :            : #include <alloca.h>
          86                 :            : #endif
          87                 :            :
          88                 :            : #ifdef _Py_MEMORY_SANITIZER
          89                 :            : #include <sanitizer/msan_interface.h>
          90                 :            : #endif
          91                 :            :
          92                 :            : #if defined(_DEBUG) || defined(__MINGW32__)
          93                 :            : /* Don't use structured exception handling on Windows if this is defined.
          94                 :            :    MingW, AFAIK, doesn't support it.
          95                 :            : */
          96                 :            : #define DONT_USE_SEH
          97                 :            : #endif
          98                 :            :
          99                 :            : #include "pycore_runtime.h"         // _PyRuntime
         100                 :            : #include "pycore_global_objects.h"  // _Py_ID()
         101                 :            :
         102                 :            : #define CTYPES_CAPSULE_NAME_PYMEM "_ctypes pymem"
         103                 :            :
         104                 :            :
         105                 :          0 : static void pymem_destructor(PyObject *ptr)
         106                 :            : {
         107                 :          0 :     void *p = PyCapsule_GetPointer(ptr, CTYPES_CAPSULE_NAME_PYMEM);
         108         [ #  # ]:          0 :     if (p) {
         109                 :          0 :         PyMem_Free(p);
         110                 :            :     }
         111                 :          0 : }
         112                 :            :
         113                 :            : /*
         114                 :            :   ctypes maintains thread-local storage that has space for two error numbers:
         115                 :            :   private copies of the system 'errno' value and, on Windows, the system error code
         116                 :            :   accessed by the GetLastError() and SetLastError() api functions.
         117                 :            :
         118                 :            :   Foreign functions created with CDLL(..., use_errno=True), when called, swap
         119                 :            :   the system 'errno' value with the private copy just before the actual
         120                 :            :   function call, and swapped again immediately afterwards.  The 'use_errno'
         121                 :            :   parameter defaults to False, in this case 'ctypes_errno' is not touched.
         122                 :            :
         123                 :            :   On Windows, foreign functions created with CDLL(..., use_last_error=True) or
         124                 :            :   WinDLL(..., use_last_error=True) swap the system LastError value with the
         125                 :            :   ctypes private copy.
         126                 :            :
         127                 :            :   The values are also swapped immediately before and after ctypes callback
         128                 :            :   functions are called, if the callbacks are constructed using the new
         129                 :            :   optional use_errno parameter set to True: CFUNCTYPE(..., use_errno=TRUE) or
         130                 :            :   WINFUNCTYPE(..., use_errno=True).
         131                 :            :
         132                 :            :   New ctypes functions are provided to access the ctypes private copies from
         133                 :            :   Python:
         134                 :            :
         135                 :            :   - ctypes.set_errno(value) and ctypes.set_last_error(value) store 'value' in
         136                 :            :     the private copy and returns the previous value.
         137                 :            :
         138                 :            :   - ctypes.get_errno() and ctypes.get_last_error() returns the current ctypes
         139                 :            :     private copies value.
         140                 :            : */
         141                 :            :
         142                 :            : /*
         143                 :            :   This function creates and returns a thread-local Python object that has
         144                 :            :   space to store two integer error numbers; once created the Python object is
         145                 :            :   kept alive in the thread state dictionary as long as the thread itself.
         146                 :            : */
         147                 :            : PyObject *
         148                 :          0 : _ctypes_get_errobj(int **pspace)
         149                 :            : {
         150                 :          0 :     PyObject *dict = PyThreadState_GetDict();
         151                 :            :     PyObject *errobj;
         152                 :            :     static PyObject *error_object_name;
         153         [ #  # ]:          0 :     if (dict == NULL) {
         154                 :          0 :         PyErr_SetString(PyExc_RuntimeError,
         155                 :            :                         "cannot get thread state");
         156                 :          0 :         return NULL;
         157                 :            :     }
         158         [ #  # ]:          0 :     if (error_object_name == NULL) {
         159                 :          0 :         error_object_name = PyUnicode_InternFromString("ctypes.error_object");
         160         [ #  # ]:          0 :         if (error_object_name == NULL)
         161                 :          0 :             return NULL;
         162                 :            :     }
         163                 :          0 :     errobj = PyDict_GetItemWithError(dict, error_object_name);
         164         [ #  # ]:          0 :     if (errobj) {
         165         [ #  # ]:          0 :         if (!PyCapsule_IsValid(errobj, CTYPES_CAPSULE_NAME_PYMEM)) {
         166                 :          0 :             PyErr_SetString(PyExc_RuntimeError,
         167                 :            :                 "ctypes.error_object is an invalid capsule");
         168                 :          0 :             return NULL;
         169                 :            :         }
         170                 :          0 :         Py_INCREF(errobj);
         171                 :            :     }
         172         [ #  # ]:          0 :     else if (!PyErr_Occurred()) {
         173                 :          0 :         void *space = PyMem_Calloc(2, sizeof(int));
         174         [ #  # ]:          0 :         if (space == NULL)
         175                 :          0 :             return NULL;
         176                 :          0 :         errobj = PyCapsule_New(space, CTYPES_CAPSULE_NAME_PYMEM, pymem_destructor);
         177         [ #  # ]:          0 :         if (errobj == NULL) {
         178                 :          0 :             PyMem_Free(space);
         179                 :          0 :             return NULL;
         180                 :            :         }
         181         [ #  # ]:          0 :         if (-1 == PyDict_SetItem(dict, error_object_name,
         182                 :            :                                  errobj)) {
         183                 :          0 :             Py_DECREF(errobj);
         184                 :          0 :             return NULL;
         185                 :            :         }
         186                 :            :     }
         187                 :            :     else {
         188                 :          0 :         return NULL;
         189                 :            :     }
         190                 :          0 :     *pspace = (int *)PyCapsule_GetPointer(errobj, CTYPES_CAPSULE_NAME_PYMEM);
         191                 :          0 :     return errobj;
         192                 :            : }
         193                 :            :
         194                 :            : static PyObject *
         195                 :          0 : get_error_internal(PyObject *self, PyObject *args, int index)
         196                 :            : {
         197                 :            :     int *space;
         198                 :          0 :     PyObject *errobj = _ctypes_get_errobj(&space);
         199                 :            :     PyObject *result;
         200                 :            :
         201         [ #  # ]:          0 :     if (errobj == NULL)
         202                 :          0 :         return NULL;
         203                 :          0 :     result = PyLong_FromLong(space[index]);
         204                 :          0 :     Py_DECREF(errobj);
         205                 :          0 :     return result;
         206                 :            : }
         207                 :            :
         208                 :            : static PyObject *
         209                 :          0 : set_error_internal(PyObject *self, PyObject *args, int index)
         210                 :            : {
         211                 :            :     int new_errno, old_errno;
         212                 :            :     PyObject *errobj;
         213                 :            :     int *space;
         214                 :            :
         215         [ #  # ]:          0 :     if (!PyArg_ParseTuple(args, "i", &new_errno)) {
         216                 :          0 :         return NULL;
         217                 :            :     }
         218                 :          0 :     errobj = _ctypes_get_errobj(&space);
         219         [ #  # ]:          0 :     if (errobj == NULL)
         220                 :          0 :         return NULL;
         221                 :          0 :     old_errno = space[index];
         222                 :          0 :     space[index] = new_errno;
         223                 :          0 :     Py_DECREF(errobj);
         224                 :          0 :     return PyLong_FromLong(old_errno);
         225                 :            : }
         226                 :            :
         227                 :            : static PyObject *
         228                 :          0 : get_errno(PyObject *self, PyObject *args)
         229                 :            : {
         230         [ #  # ]:          0 :     if (PySys_Audit("ctypes.get_errno", NULL) < 0) {
         231                 :          0 :         return NULL;
         232                 :            :     }
         233                 :          0 :     return get_error_internal(self, args, 0);
         234                 :            : }
         235                 :            :
         236                 :            : static PyObject *
         237                 :          0 : set_errno(PyObject *self, PyObject *args)
         238                 :            : {
         239         [ #  # ]:          0 :     if (PySys_Audit("ctypes.set_errno", "O", args) < 0) {
         240                 :          0 :         return NULL;
         241                 :            :     }
         242                 :          0 :     return set_error_internal(self, args, 0);
         243                 :            : }
         244                 :            :
         245                 :            : #ifdef MS_WIN32
         246                 :            :
         247                 :            : static PyObject *
         248                 :            : get_last_error(PyObject *self, PyObject *args)
         249                 :            : {
         250                 :            :     if (PySys_Audit("ctypes.get_last_error", NULL) < 0) {
         251                 :            :         return NULL;
         252                 :            :     }
         253                 :            :     return get_error_internal(self, args, 1);
         254                 :            : }
         255                 :            :
         256                 :            : static PyObject *
         257                 :            : set_last_error(PyObject *self, PyObject *args)
         258                 :            : {
         259                 :            :     if (PySys_Audit("ctypes.set_last_error", "O", args) < 0) {
         260                 :            :         return NULL;
         261                 :            :     }
         262                 :            :     return set_error_internal(self, args, 1);
         263                 :            : }
         264                 :            :
         265                 :            : static WCHAR *FormatError(DWORD code)
         266                 :            : {
         267                 :            :     WCHAR *lpMsgBuf;
         268                 :            :     DWORD n;
         269                 :            :     n = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
         270                 :            :                        FORMAT_MESSAGE_FROM_SYSTEM |
         271                 :            :                        FORMAT_MESSAGE_IGNORE_INSERTS,
         272                 :            :                        NULL,
         273                 :            :                        code,
         274                 :            :                        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
         275                 :            :                (LPWSTR) &lpMsgBuf,
         276                 :            :                0,
         277                 :            :                NULL);
         278                 :            :     if (n) {
         279                 :            :         while (iswspace(lpMsgBuf[n-1]))
         280                 :            :             --n;
         281                 :            :         lpMsgBuf[n] = L'\0'; /* rstrip() */
         282                 :            :     }
         283                 :            :     return lpMsgBuf;
         284                 :            : }
         285                 :            :
         286                 :            : #ifndef DONT_USE_SEH
         287                 :            : static void SetException(DWORD code, EXCEPTION_RECORD *pr)
         288                 :            : {
         289                 :            :     if (PySys_Audit("ctypes.set_exception", "I", code) < 0) {
         290                 :            :         /* An exception was set by the audit hook */
         291                 :            :         return;
         292                 :            :     }
         293                 :            :
         294                 :            :     /* The 'code' is a normal win32 error code so it could be handled by
         295                 :            :     PyErr_SetFromWindowsErr(). However, for some errors, we have additional
         296                 :            :     information not included in the error code. We handle those here and
         297                 :            :     delegate all others to the generic function. */
         298                 :            :     switch (code) {
         299                 :            :     case EXCEPTION_ACCESS_VIOLATION:
         300                 :            :         /* The thread attempted to read from or write
         301                 :            :            to a virtual address for which it does not
         302                 :            :            have the appropriate access. */
         303                 :            :         if (pr->ExceptionInformation[0] == 0)
         304                 :            :             PyErr_Format(PyExc_OSError,
         305                 :            :                          "exception: access violation reading %p",
         306                 :            :                          pr->ExceptionInformation[1]);
         307                 :            :         else
         308                 :            :             PyErr_Format(PyExc_OSError,
         309                 :            :                          "exception: access violation writing %p",
         310                 :            :                          pr->ExceptionInformation[1]);
         311                 :            :         break;
         312                 :            :
         313                 :            :     case EXCEPTION_BREAKPOINT:
         314                 :            :         /* A breakpoint was encountered. */
         315                 :            :         PyErr_SetString(PyExc_OSError,
         316                 :            :                         "exception: breakpoint encountered");
         317                 :            :         break;
         318                 :            :
         319                 :            :     case EXCEPTION_DATATYPE_MISALIGNMENT:
         320                 :            :         /* The thread attempted to read or write data that is
         321                 :            :            misaligned on hardware that does not provide
         322                 :            :            alignment. For example, 16-bit values must be
         323                 :            :            aligned on 2-byte boundaries, 32-bit values on
         324                 :            :            4-byte boundaries, and so on. */
         325                 :            :         PyErr_SetString(PyExc_OSError,
         326                 :            :                         "exception: datatype misalignment");
         327                 :            :         break;
         328                 :            :
         329                 :            :     case EXCEPTION_SINGLE_STEP:
         330                 :            :         /* A trace trap or other single-instruction mechanism
         331                 :            :            signaled that one instruction has been executed. */
         332                 :            :         PyErr_SetString(PyExc_OSError,
         333                 :            :                         "exception: single step");
         334                 :            :         break;
         335                 :            :
         336                 :            :     case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
         337                 :            :         /* The thread attempted to access an array element
         338                 :            :            that is out of bounds, and the underlying hardware
         339                 :            :            supports bounds checking. */
         340                 :            :         PyErr_SetString(PyExc_OSError,
         341                 :            :                         "exception: array bounds exceeded");
         342                 :            :         break;
         343                 :            :
         344                 :            :     case EXCEPTION_FLT_DENORMAL_OPERAND:
         345                 :            :         /* One of the operands in a floating-point operation
         346                 :            :            is denormal. A denormal value is one that is too
         347                 :            :            small to represent as a standard floating-point
         348                 :            :            value. */
         349                 :            :         PyErr_SetString(PyExc_OSError,
         350                 :            :                         "exception: floating-point operand denormal");
         351                 :            :         break;
         352                 :            :
         353                 :            :     case EXCEPTION_FLT_DIVIDE_BY_ZERO:
         354                 :            :         /* The thread attempted to divide a floating-point
         355                 :            :            value by a floating-point divisor of zero. */
         356                 :            :         PyErr_SetString(PyExc_OSError,
         357                 :            :                         "exception: float divide by zero");
         358                 :            :         break;
         359                 :            :
         360                 :            :     case EXCEPTION_FLT_INEXACT_RESULT:
         361                 :            :         /* The result of a floating-point operation cannot be
         362                 :            :            represented exactly as a decimal fraction. */
         363                 :            :         PyErr_SetString(PyExc_OSError,
         364                 :            :                         "exception: float inexact");
         365                 :            :         break;
         366                 :            :
         367                 :            :     case EXCEPTION_FLT_INVALID_OPERATION:
         368                 :            :         /* This exception represents any floating-point
         369                 :            :            exception not included in this list. */
         370                 :            :         PyErr_SetString(PyExc_OSError,
         371                 :            :                         "exception: float invalid operation");
         372                 :            :         break;
         373                 :            :
         374                 :            :     case EXCEPTION_FLT_OVERFLOW:
         375                 :            :         /* The exponent of a floating-point operation is
         376                 :            :            greater than the magnitude allowed by the
         377                 :            :            corresponding type. */
         378                 :            :         PyErr_SetString(PyExc_OSError,
         379                 :            :                         "exception: float overflow");
         380                 :            :         break;
         381                 :            :
         382                 :            :     case EXCEPTION_FLT_STACK_CHECK:
         383                 :            :         /* The stack overflowed or underflowed as the result
         384                 :            :            of a floating-point operation. */
         385                 :            :         PyErr_SetString(PyExc_OSError,
         386                 :            :                         "exception: stack over/underflow");
         387                 :            :         break;
         388                 :            :
         389                 :            :     case EXCEPTION_STACK_OVERFLOW:
         390                 :            :         /* The stack overflowed or underflowed as the result
         391                 :            :            of a floating-point operation. */
         392                 :            :         PyErr_SetString(PyExc_OSError,
         393                 :            :                         "exception: stack overflow");
         394                 :            :         break;
         395                 :            :
         396                 :            :     case EXCEPTION_FLT_UNDERFLOW:
         397                 :            :         /* The exponent of a floating-point operation is less
         398                 :            :            than the magnitude allowed by the corresponding
         399                 :            :            type. */
         400                 :            :         PyErr_SetString(PyExc_OSError,
         401                 :            :                         "exception: float underflow");
         402                 :            :         break;
         403                 :            :
         404                 :            :     case EXCEPTION_INT_DIVIDE_BY_ZERO:
         405                 :            :         /* The thread attempted to divide an integer value by
         406                 :            :            an integer divisor of zero. */
         407                 :            :         PyErr_SetString(PyExc_OSError,
         408                 :            :                         "exception: integer divide by zero");
         409                 :            :         break;
         410                 :            :
         411                 :            :     case EXCEPTION_INT_OVERFLOW:
         412                 :            :         /* The result of an integer operation caused a carry
         413                 :            :            out of the most significant bit of the result. */
         414                 :            :         PyErr_SetString(PyExc_OSError,
         415                 :            :                         "exception: integer overflow");
         416                 :            :         break;
         417                 :            :
         418                 :            :     case EXCEPTION_PRIV_INSTRUCTION:
         419                 :            :         /* The thread attempted to execute an instruction
         420                 :            :            whose operation is not allowed in the current
         421                 :            :            machine mode. */
         422                 :            :         PyErr_SetString(PyExc_OSError,
         423                 :            :                         "exception: privileged instruction");
         424                 :            :         break;
         425                 :            :
         426                 :            :     case EXCEPTION_NONCONTINUABLE_EXCEPTION:
         427                 :            :         /* The thread attempted to continue execution after a
         428                 :            :            noncontinuable exception occurred. */
         429                 :            :         PyErr_SetString(PyExc_OSError,
         430                 :            :                         "exception: nocontinuable");
         431                 :            :         break;
         432                 :            :
         433                 :            :     default:
         434                 :            :         PyErr_SetFromWindowsErr(code);
         435                 :            :         break;
         436                 :            :     }
         437                 :            : }
         438                 :            :
         439                 :            : static DWORD HandleException(EXCEPTION_POINTERS *ptrs,
         440                 :            :                              DWORD *pdw, EXCEPTION_RECORD *record)
         441                 :            : {
         442                 :            :     *pdw = ptrs->ExceptionRecord->ExceptionCode;
         443                 :            :     *record = *ptrs->ExceptionRecord;
         444                 :            :     /* We don't want to catch breakpoint exceptions, they are used to attach
         445                 :            :      * a debugger to the process.
         446                 :            :      */
         447                 :            :     if (*pdw == EXCEPTION_BREAKPOINT)
         448                 :            :         return EXCEPTION_CONTINUE_SEARCH;
         449                 :            :     return EXCEPTION_EXECUTE_HANDLER;
         450                 :            : }
         451                 :            : #endif
         452                 :            :
         453                 :            : static PyObject *
         454                 :            : check_hresult(PyObject *self, PyObject *args)
         455                 :            : {
         456                 :            :     HRESULT hr;
         457                 :            :     if (!PyArg_ParseTuple(args, "i", &hr))
         458                 :            :         return NULL;
         459                 :            :     if (FAILED(hr))
         460                 :            :         return PyErr_SetFromWindowsErr(hr);
         461                 :            :     return PyLong_FromLong(hr);
         462                 :            : }
         463                 :            :
         464                 :            : #endif
         465                 :            :
         466                 :            : /**************************************************************/
         467                 :            :
         468                 :            : PyCArgObject *
         469                 :          0 : PyCArgObject_new(void)
         470                 :            : {
         471                 :            :     PyCArgObject *p;
         472                 :          0 :     p = PyObject_New(PyCArgObject, &PyCArg_Type);
         473         [ #  # ]:          0 :     if (p == NULL)
         474                 :          0 :         return NULL;
         475                 :          0 :     p->pffi_type = NULL;
         476                 :          0 :     p->tag = '\0';
         477                 :          0 :     p->obj = NULL;
         478                 :          0 :     memset(&p->value, 0, sizeof(p->value));
         479                 :          0 :     return p;
         480                 :            : }
         481                 :            :
         482                 :            : static void
         483                 :          0 : PyCArg_dealloc(PyCArgObject *self)
         484                 :            : {
         485                 :          0 :     Py_XDECREF(self->obj);
         486                 :          0 :     PyObject_Free(self);
         487                 :          0 : }
         488                 :            :
         489                 :            : static int
         490                 :          0 : is_literal_char(unsigned char c)
         491                 :            : {
         492   [ #  #  #  #  :          0 :     return c < 128 && _PyUnicode_IsPrintable(c) && c != '\\' && c != '\'';
                 #  #  #  # ]
         493                 :            : }
         494                 :            :
         495                 :            : static PyObject *
         496                 :          0 : PyCArg_repr(PyCArgObject *self)
         497                 :            : {
         498   [ #  #  #  #  :          0 :     switch(self->tag) {
                 #  #  #  #
                          # ]
         499                 :          0 :     case 'b':
         500                 :            :     case 'B':
         501                 :          0 :         return PyUnicode_FromFormat("<cparam '%c' (%d)>",
         502                 :          0 :             self->tag, self->value.b);
         503                 :          0 :     case 'h':
         504                 :            :     case 'H':
         505                 :          0 :         return PyUnicode_FromFormat("<cparam '%c' (%d)>",
         506                 :          0 :             self->tag, self->value.h);
         507                 :          0 :     case 'i':
         508                 :            :     case 'I':
         509                 :          0 :         return PyUnicode_FromFormat("<cparam '%c' (%d)>",
         510                 :          0 :             self->tag, self->value.i);
         511                 :          0 :     case 'l':
         512                 :            :     case 'L':
         513                 :          0 :         return PyUnicode_FromFormat("<cparam '%c' (%ld)>",
         514                 :          0 :             self->tag, self->value.l);
         515                 :            :
         516                 :          0 :     case 'q':
         517                 :            :     case 'Q':
         518                 :          0 :         return PyUnicode_FromFormat("<cparam '%c' (%lld)>",
         519                 :          0 :             self->tag, self->value.q);
         520                 :          0 :     case 'd':
         521                 :            :     case 'f': {
         522         [ #  # ]:          0 :         PyObject *f = PyFloat_FromDouble((self->tag == 'f') ? self->value.f : self->value.d);
         523         [ #  # ]:          0 :         if (f == NULL) {
         524                 :          0 :             return NULL;
         525                 :            :         }
         526                 :          0 :         PyObject *result = PyUnicode_FromFormat("<cparam '%c' (%R)>", self->tag, f);
         527                 :          0 :         Py_DECREF(f);
         528                 :          0 :         return result;
         529                 :            :     }
         530                 :          0 :     case 'c':
         531         [ #  # ]:          0 :         if (is_literal_char((unsigned char)self->value.c)) {
         532                 :          0 :             return PyUnicode_FromFormat("<cparam '%c' ('%c')>",
         533                 :          0 :                 self->tag, self->value.c);
         534                 :            :         }
         535                 :            :         else {
         536                 :          0 :             return PyUnicode_FromFormat("<cparam '%c' ('\\x%02x')>",
         537                 :          0 :                 self->tag, (unsigned char)self->value.c);
         538                 :            :         }
         539                 :            :
         540                 :            : /* Hm, are these 'z' and 'Z' codes useful at all?
         541                 :            :    Shouldn't they be replaced by the functionality of create_string_buffer()
         542                 :            :    and c_wstring() ?
         543                 :            : */
         544                 :          0 :     case 'z':
         545                 :            :     case 'Z':
         546                 :            :     case 'P':
         547                 :          0 :         return PyUnicode_FromFormat("<cparam '%c' (%p)>",
         548                 :          0 :             self->tag, self->value.p);
         549                 :            :         break;
         550                 :            :
         551                 :          0 :     default:
         552         [ #  # ]:          0 :         if (is_literal_char((unsigned char)self->tag)) {
         553                 :          0 :             return PyUnicode_FromFormat("<cparam '%c' at %p>",
         554                 :          0 :                 (unsigned char)self->tag, (void *)self);
         555                 :            :         }
         556                 :            :         else {
         557                 :          0 :             return PyUnicode_FromFormat("<cparam 0x%02x at %p>",
         558                 :          0 :                 (unsigned char)self->tag, (void *)self);
         559                 :            :         }
         560                 :            :     }
         561                 :            : }
         562                 :            :
         563                 :            : static PyMemberDef PyCArgType_members[] = {
         564                 :            :     { "_obj", T_OBJECT,
         565                 :            :       offsetof(PyCArgObject, obj), READONLY,
         566                 :            :       "the wrapped object" },
         567                 :            :     { NULL },
         568                 :            : };
         569                 :            :
         570                 :            : PyTypeObject PyCArg_Type = {
         571                 :            :     PyVarObject_HEAD_INIT(NULL, 0)
         572                 :            :     "CArgObject",
         573                 :            :     sizeof(PyCArgObject),
         574                 :            :     0,
         575                 :            :     (destructor)PyCArg_dealloc,                 /* tp_dealloc */
         576                 :            :     0,                                          /* tp_vectorcall_offset */
         577                 :            :     0,                                          /* tp_getattr */
         578                 :            :     0,                                          /* tp_setattr */
         579                 :            :     0,                                          /* tp_as_async */
         580                 :            :     (reprfunc)PyCArg_repr,                      /* tp_repr */
         581                 :            :     0,                                          /* tp_as_number */
         582                 :            :     0,                                          /* tp_as_sequence */
         583                 :            :     0,                                          /* tp_as_mapping */
         584                 :            :     0,                                          /* tp_hash */
         585                 :            :     0,                                          /* tp_call */
         586                 :            :     0,                                          /* tp_str */
         587                 :            :     0,                                          /* tp_getattro */
         588                 :            :     0,                                          /* tp_setattro */
         589                 :            :     0,                                          /* tp_as_buffer */
         590                 :            :     Py_TPFLAGS_DEFAULT,                         /* tp_flags */
         591                 :            :     0,                                          /* tp_doc */
         592                 :            :     0,                                          /* tp_traverse */
         593                 :            :     0,                                          /* tp_clear */
         594                 :            :     0,                                          /* tp_richcompare */
         595                 :            :     0,                                          /* tp_weaklistoffset */
         596                 :            :     0,                                          /* tp_iter */
         597                 :            :     0,                                          /* tp_iternext */
         598                 :            :     0,                                          /* tp_methods */
         599                 :            :     PyCArgType_members,                         /* tp_members */
         600                 :            : };
         601                 :            :
         602                 :            : /****************************************************************/
         603                 :            : /*
         604                 :            :  * Convert a PyObject * into a parameter suitable to pass to an
         605                 :            :  * C function call.
         606                 :            :  *
         607                 :            :  * 1. Python integers are converted to C int and passed by value.
         608                 :            :  *    Py_None is converted to a C NULL pointer.
         609                 :            :  *
         610                 :            :  * 2. 3-tuples are expected to have a format character in the first
         611                 :            :  *    item, which must be 'i', 'f', 'd', 'q', or 'P'.
         612                 :            :  *    The second item will have to be an integer, float, double, long long
         613                 :            :  *    or integer (denoting an address void *), will be converted to the
         614                 :            :  *    corresponding C data type and passed by value.
         615                 :            :  *
         616                 :            :  * 3. Other Python objects are tested for an '_as_parameter_' attribute.
         617                 :            :  *    The value of this attribute must be an integer which will be passed
         618                 :            :  *    by value, or a 2-tuple or 3-tuple which will be used according
         619                 :            :  *    to point 2 above. The third item (if any), is ignored. It is normally
         620                 :            :  *    used to keep the object alive where this parameter refers to.
         621                 :            :  *    XXX This convention is dangerous - you can construct arbitrary tuples
         622                 :            :  *    in Python and pass them. Would it be safer to use a custom container
         623                 :            :  *    datatype instead of a tuple?
         624                 :            :  *
         625                 :            :  * 4. Other Python objects cannot be passed as parameters - an exception is raised.
         626                 :            :  *
         627                 :            :  * 5. ConvParam will store the converted result in a struct containing format
         628                 :            :  *    and value.
         629                 :            :  */
         630                 :            :
         631                 :            : union result {
         632                 :            :     char c;
         633                 :            :     char b;
         634                 :            :     short h;
         635                 :            :     int i;
         636                 :            :     long l;
         637                 :            :     long long q;
         638                 :            :     long double D;
         639                 :            :     double d;
         640                 :            :     float f;
         641                 :            :     void *p;
         642                 :            : };
         643                 :            :
         644                 :            : struct argument {
         645                 :            :     ffi_type *ffi_type;
         646                 :            :     PyObject *keep;
         647                 :            :     union result value;
         648                 :            : };
         649                 :            :
         650                 :            : /*
         651                 :            :  * Convert a single Python object into a PyCArgObject and return it.
         652                 :            :  */
         653                 :          0 : static int ConvParam(PyObject *obj, Py_ssize_t index, struct argument *pa)
         654                 :            : {
         655                 :            :     StgDictObject *dict;
         656                 :          0 :     pa->keep = NULL; /* so we cannot forget it later */
         657                 :            :
         658                 :          0 :     dict = PyObject_stgdict(obj);
         659         [ #  # ]:          0 :     if (dict) {
         660                 :            :         PyCArgObject *carg;
         661                 :            :         assert(dict->paramfunc);
         662                 :            :         /* If it has an stgdict, it is a CDataObject */
         663                 :          0 :         carg = dict->paramfunc((CDataObject *)obj);
         664         [ #  # ]:          0 :         if (carg == NULL)
         665                 :          0 :             return -1;
         666                 :          0 :         pa->ffi_type = carg->pffi_type;
         667                 :          0 :         memcpy(&pa->value, &carg->value, sizeof(pa->value));
         668                 :          0 :         pa->keep = (PyObject *)carg;
         669                 :          0 :         return 0;
         670                 :            :     }
         671                 :            :
         672         [ #  # ]:          0 :     if (PyCArg_CheckExact(obj)) {
         673                 :          0 :         PyCArgObject *carg = (PyCArgObject *)obj;
         674                 :          0 :         pa->ffi_type = carg->pffi_type;
         675                 :          0 :         pa->keep = Py_NewRef(obj);
         676                 :          0 :         memcpy(&pa->value, &carg->value, sizeof(pa->value));
         677                 :          0 :         return 0;
         678                 :            :     }
         679                 :            :
         680                 :            :     /* check for None, integer, string or unicode and use directly if successful */
         681         [ #  # ]:          0 :     if (obj == Py_None) {
         682                 :          0 :         pa->ffi_type = &ffi_type_pointer;
         683                 :          0 :         pa->value.p = NULL;
         684                 :          0 :         return 0;
         685                 :            :     }
         686                 :            :
         687         [ #  # ]:          0 :     if (PyLong_Check(obj)) {
         688                 :          0 :         pa->ffi_type = &ffi_type_sint;
         689                 :          0 :         pa->value.i = (long)PyLong_AsUnsignedLong(obj);
         690   [ #  #  #  # ]:          0 :         if (pa->value.i == -1 && PyErr_Occurred()) {
         691                 :          0 :             PyErr_Clear();
         692                 :          0 :             pa->value.i = PyLong_AsLong(obj);
         693   [ #  #  #  # ]:          0 :             if (pa->value.i == -1 && PyErr_Occurred()) {
         694                 :          0 :                 PyErr_SetString(PyExc_OverflowError,
         695                 :            :                                 "int too long to convert");
         696                 :          0 :                 return -1;
         697                 :            :             }
         698                 :            :         }
         699                 :          0 :         return 0;
         700                 :            :     }
         701                 :            :
         702         [ #  # ]:          0 :     if (PyBytes_Check(obj)) {
         703                 :          0 :         pa->ffi_type = &ffi_type_pointer;
         704                 :          0 :         pa->value.p = PyBytes_AsString(obj);
         705                 :          0 :         pa->keep = Py_NewRef(obj);
         706                 :          0 :         return 0;
         707                 :            :     }
         708                 :            :
         709         [ #  # ]:          0 :     if (PyUnicode_Check(obj)) {
         710                 :          0 :         pa->ffi_type = &ffi_type_pointer;
         711                 :          0 :         pa->value.p = PyUnicode_AsWideCharString(obj, NULL);
         712         [ #  # ]:          0 :         if (pa->value.p == NULL)
         713                 :          0 :             return -1;
         714                 :          0 :         pa->keep = PyCapsule_New(pa->value.p, CTYPES_CAPSULE_NAME_PYMEM, pymem_destructor);
         715         [ #  # ]:          0 :         if (!pa->keep) {
         716                 :          0 :             PyMem_Free(pa->value.p);
         717                 :          0 :             return -1;
         718                 :            :         }
         719                 :          0 :         return 0;
         720                 :            :     }
         721                 :            :
         722                 :            :     {
         723                 :            :         PyObject *arg;
         724         [ #  # ]:          0 :         if (_PyObject_LookupAttr(obj, &_Py_ID(_as_parameter_), &arg) < 0) {
         725                 :          0 :             return -1;
         726                 :            :         }
         727                 :            :         /* Which types should we exactly allow here?
         728                 :            :            integers are required for using Python classes
         729                 :            :            as parameters (they have to expose the '_as_parameter_'
         730                 :            :            attribute)
         731                 :            :         */
         732         [ #  # ]:          0 :         if (arg) {
         733                 :            :             int result;
         734                 :          0 :             result = ConvParam(arg, index, pa);
         735                 :          0 :             Py_DECREF(arg);
         736                 :          0 :             return result;
         737                 :            :         }
         738                 :          0 :         PyErr_Format(PyExc_TypeError,
         739                 :            :                      "Don't know how to convert parameter %d",
         740                 :            :                      Py_SAFE_DOWNCAST(index, Py_ssize_t, int));
         741                 :          0 :         return -1;
         742                 :            :     }
         743                 :            : }
         744                 :            :
         745                 :            : #if defined(MS_WIN32) && !defined(_WIN32_WCE)
         746                 :            : /*
         747                 :            : Per: https://msdn.microsoft.com/en-us/library/7572ztz4.aspx
         748                 :            : To be returned by value in RAX, user-defined types must have a length
         749                 :            : of 1, 2, 4, 8, 16, 32, or 64 bits
         750                 :            : */
         751                 :            : int can_return_struct_as_int(size_t s)
         752                 :            : {
         753                 :            :     return s == 1 || s == 2 || s == 4;
         754                 :            : }
         755                 :            :
         756                 :            : int can_return_struct_as_sint64(size_t s)
         757                 :            : {
         758                 :            : #ifdef _M_ARM
         759                 :            :     // 8 byte structs cannot be returned in a register on ARM32
         760                 :            :     return 0;
         761                 :            : #else
         762                 :            :     return s == 8;
         763                 :            : #endif
         764                 :            : }
         765                 :            : #endif
         766                 :            :
         767                 :            :
         768                 :          0 : ffi_type *_ctypes_get_ffi_type(PyObject *obj)
         769                 :            : {
         770                 :            :     StgDictObject *dict;
         771         [ #  # ]:          0 :     if (obj == NULL)
         772                 :          0 :         return &ffi_type_sint;
         773                 :          0 :     dict = PyType_stgdict(obj);
         774         [ #  # ]:          0 :     if (dict == NULL)
         775                 :          0 :         return &ffi_type_sint;
         776                 :            : #if defined(MS_WIN32) && !defined(_WIN32_WCE)
         777                 :            :     /* This little trick works correctly with MSVC.
         778                 :            :        It returns small structures in registers
         779                 :            :     */
         780                 :            :     if (dict->ffi_type_pointer.type == FFI_TYPE_STRUCT) {
         781                 :            :         if (can_return_struct_as_int(dict->ffi_type_pointer.size))
         782                 :            :             return &ffi_type_sint32;
         783                 :            :         else if (can_return_struct_as_sint64 (dict->ffi_type_pointer.size))
         784                 :            :             return &ffi_type_sint64;
         785                 :            :     }
         786                 :            : #endif
         787                 :          0 :     return &dict->ffi_type_pointer;
         788                 :            : }
         789                 :            :
         790                 :            :
         791                 :            : /*
         792                 :            :  * libffi uses:
         793                 :            :  *
         794                 :            :  * ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi,
         795                 :            :  *                         unsigned int nargs,
         796                 :            :  *                         ffi_type *rtype,
         797                 :            :  *                         ffi_type **atypes);
         798                 :            :  *
         799                 :            :  * and then
         800                 :            :  *
         801                 :            :  * void ffi_call(ffi_cif *cif, void *fn, void *rvalue, void **avalues);
         802                 :            :  */
         803                 :          0 : static int _call_function_pointer(int flags,
         804                 :            :                                   PPROC pProc,
         805                 :            :                                   void **avalues,
         806                 :            :                                   ffi_type **atypes,
         807                 :            :                                   ffi_type *restype,
         808                 :            :                                   void *resmem,
         809                 :            :                                   int argcount,
         810                 :            :                                   int argtypecount)
         811                 :            : {
         812                 :          0 :     PyThreadState *_save = NULL; /* For Py_BLOCK_THREADS and Py_UNBLOCK_THREADS */
         813                 :          0 :     PyObject *error_object = NULL;
         814                 :            :     int *space;
         815                 :            :     ffi_cif cif;
         816                 :            :     int cc;
         817                 :            : #if defined(MS_WIN32) && !defined(DONT_USE_SEH)
         818                 :            :     DWORD dwExceptionCode = 0;
         819                 :            :     EXCEPTION_RECORD record;
         820                 :            : #endif
         821                 :            :     /* XXX check before here */
         822         [ #  # ]:          0 :     if (restype == NULL) {
         823                 :          0 :         PyErr_SetString(PyExc_RuntimeError,
         824                 :            :                         "No ffi_type for result");
         825                 :          0 :         return -1;
         826                 :            :     }
         827                 :            :
         828                 :          0 :     cc = FFI_DEFAULT_ABI;
         829                 :            : #if defined(MS_WIN32) && !defined(MS_WIN64) && !defined(_WIN32_WCE) && !defined(_M_ARM)
         830                 :            :     if ((flags & FUNCFLAG_CDECL) == 0)
         831                 :            :         cc = FFI_STDCALL;
         832                 :            : #endif
         833                 :            :
         834                 :            : #   ifdef USING_APPLE_OS_LIBFFI
         835                 :            : #    ifdef HAVE_BUILTIN_AVAILABLE
         836                 :            : #      define HAVE_FFI_PREP_CIF_VAR_RUNTIME __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)
         837                 :            : #    else
         838                 :            : #      define HAVE_FFI_PREP_CIF_VAR_RUNTIME (ffi_prep_cif_var != NULL)
         839                 :            : #    endif
         840                 :            : #   elif HAVE_FFI_PREP_CIF_VAR
         841                 :            : #      define HAVE_FFI_PREP_CIF_VAR_RUNTIME true
         842                 :            : #   else
         843                 :            : #      define HAVE_FFI_PREP_CIF_VAR_RUNTIME false
         844                 :            : #   endif
         845                 :            :
         846                 :            :     /* Even on Apple-arm64 the calling convention for variadic functions coincides
         847                 :            :      * with the standard calling convention in the case that the function called
         848                 :            :      * only with its fixed arguments.   Thus, we do not need a special flag to be
         849                 :            :      * set on variadic functions.   We treat a function as variadic if it is called
         850                 :            :      * with a nonzero number of variadic arguments */
         851   [ #  #  #  # ]:          0 :     bool is_variadic = (argtypecount != 0 && argcount > argtypecount);
         852                 :            :     (void) is_variadic;
         853                 :            :
         854                 :            : #if defined(__APPLE__) && defined(__arm64__)
         855                 :            :     if (is_variadic) {
         856                 :            :         if (HAVE_FFI_PREP_CIF_VAR_RUNTIME) {
         857                 :            :         } else {
         858                 :            :             PyErr_SetString(PyExc_NotImplementedError, "ffi_prep_cif_var() is missing");
         859                 :            :             return -1;
         860                 :            :         }
         861                 :            :     }
         862                 :            : #endif
         863                 :            :
         864                 :            : #if HAVE_FFI_PREP_CIF_VAR
         865         [ #  # ]:          0 :     if (is_variadic) {
         866                 :            :         if (HAVE_FFI_PREP_CIF_VAR_RUNTIME) {
         867         [ #  # ]:          0 :             if (FFI_OK != ffi_prep_cif_var(&cif,
         868                 :            :                                         cc,
         869                 :            :                                         argtypecount,
         870                 :            :                                         argcount,
         871                 :            :                                         restype,
         872                 :            :                                         atypes)) {
         873                 :          0 :                 PyErr_SetString(PyExc_RuntimeError,
         874                 :            :                                 "ffi_prep_cif_var failed");
         875                 :          0 :                 return -1;
         876                 :            :             }
         877                 :            :         } else {
         878                 :            :             if (FFI_OK != ffi_prep_cif(&cif,
         879                 :            :                                        cc,
         880                 :            :                                        argcount,
         881                 :            :                                        restype,
         882                 :            :                                        atypes)) {
         883                 :            :                 PyErr_SetString(PyExc_RuntimeError,
         884                 :            :                                 "ffi_prep_cif failed");
         885                 :            :                 return -1;
         886                 :            :             }
         887                 :            :         }
         888                 :            :     } else
         889                 :            : #endif
         890                 :            :
         891                 :            :     {
         892         [ #  # ]:          0 :         if (FFI_OK != ffi_prep_cif(&cif,
         893                 :            :                                    cc,
         894                 :            :                                    argcount,
         895                 :            :                                    restype,
         896                 :            :                                    atypes)) {
         897                 :          0 :             PyErr_SetString(PyExc_RuntimeError,
         898                 :            :                             "ffi_prep_cif failed");
         899                 :          0 :             return -1;
         900                 :            :         }
         901                 :            :     }
         902                 :            :
         903         [ #  # ]:          0 :     if (flags & (FUNCFLAG_USE_ERRNO | FUNCFLAG_USE_LASTERROR)) {
         904                 :          0 :         error_object = _ctypes_get_errobj(&space);
         905         [ #  # ]:          0 :         if (error_object == NULL)
         906                 :          0 :             return -1;
         907                 :            :     }
         908         [ #  # ]:          0 :     if ((flags & FUNCFLAG_PYTHONAPI) == 0)
         909                 :          0 :         Py_UNBLOCK_THREADS
         910         [ #  # ]:          0 :     if (flags & FUNCFLAG_USE_ERRNO) {
         911                 :          0 :         int temp = space[0];
         912                 :          0 :         space[0] = errno;
         913                 :          0 :         errno = temp;
         914                 :            :     }
         915                 :            : #ifdef MS_WIN32
         916                 :            :     if (flags & FUNCFLAG_USE_LASTERROR) {
         917                 :            :         int temp = space[1];
         918                 :            :         space[1] = GetLastError();
         919                 :            :         SetLastError(temp);
         920                 :            :     }
         921                 :            : #ifndef DONT_USE_SEH
         922                 :            :     __try {
         923                 :            : #endif
         924                 :            : #endif
         925                 :          0 :                 ffi_call(&cif, (void *)pProc, resmem, avalues);
         926                 :            : #ifdef MS_WIN32
         927                 :            : #ifndef DONT_USE_SEH
         928                 :            :     }
         929                 :            :     __except (HandleException(GetExceptionInformation(),
         930                 :            :                               &dwExceptionCode, &record)) {
         931                 :            :         ;
         932                 :            :     }
         933                 :            : #endif
         934                 :            :     if (flags & FUNCFLAG_USE_LASTERROR) {
         935                 :            :         int temp = space[1];
         936                 :            :         space[1] = GetLastError();
         937                 :            :         SetLastError(temp);
         938                 :            :     }
         939                 :            : #endif
         940         [ #  # ]:          0 :     if (flags & FUNCFLAG_USE_ERRNO) {
         941                 :          0 :         int temp = space[0];
         942                 :          0 :         space[0] = errno;
         943                 :          0 :         errno = temp;
         944                 :            :     }
         945         [ #  # ]:          0 :     if ((flags & FUNCFLAG_PYTHONAPI) == 0)
         946                 :          0 :         Py_BLOCK_THREADS
         947                 :          0 :     Py_XDECREF(error_object);
         948                 :            : #ifdef MS_WIN32
         949                 :            : #ifndef DONT_USE_SEH
         950                 :            :     if (dwExceptionCode) {
         951                 :            :         SetException(dwExceptionCode, &record);
         952                 :            :         return -1;
         953                 :            :     }
         954                 :            : #endif
         955                 :            : #endif
         956   [ #  #  #  # ]:          0 :     if ((flags & FUNCFLAG_PYTHONAPI) && PyErr_Occurred())
         957                 :          0 :         return -1;
         958                 :          0 :     return 0;
         959                 :            : }
         960                 :            :
         961                 :            : /*
         962                 :            :  * Convert the C value in result into a Python object, depending on restype.
         963                 :            :  *
         964                 :            :  * - If restype is NULL, return a Python integer.
         965                 :            :  * - If restype is None, return None.
         966                 :            :  * - If restype is a simple ctypes type (c_int, c_void_p), call the type's getfunc,
         967                 :            :  *   pass the result to checker and return the result.
         968                 :            :  * - If restype is another ctypes type, return an instance of that.
         969                 :            :  * - Otherwise, call restype and return the result.
         970                 :            :  */
         971                 :          0 : static PyObject *GetResult(PyObject *restype, void *result, PyObject *checker)
         972                 :            : {
         973                 :            :     StgDictObject *dict;
         974                 :            :     PyObject *retval, *v;
         975                 :            :
         976         [ #  # ]:          0 :     if (restype == NULL)
         977                 :          0 :         return PyLong_FromLong(*(int *)result);
         978                 :            :
         979         [ #  # ]:          0 :     if (restype == Py_None) {
         980                 :          0 :         Py_RETURN_NONE;
         981                 :            :     }
         982                 :            :
         983                 :          0 :     dict = PyType_stgdict(restype);
         984         [ #  # ]:          0 :     if (dict == NULL)
         985                 :          0 :         return PyObject_CallFunction(restype, "i", *(int *)result);
         986                 :            :
         987   [ #  #  #  # ]:          0 :     if (dict->getfunc && !_ctypes_simple_instance(restype)) {
         988                 :          0 :         retval = dict->getfunc(result, dict->size);
         989                 :            :         /* If restype is py_object (detected by comparing getfunc with
         990                 :            :            O_get), we have to call Py_DECREF because O_get has already
         991                 :            :            called Py_INCREF.
         992                 :            :         */
         993         [ #  # ]:          0 :         if (dict->getfunc == _ctypes_get_fielddesc("O")->getfunc) {
         994                 :          0 :             Py_DECREF(retval);
         995                 :            :         }
         996                 :            :     } else
         997                 :          0 :         retval = PyCData_FromBaseObj(restype, NULL, 0, result);
         998                 :            :
         999   [ #  #  #  # ]:          0 :     if (!checker || !retval)
        1000                 :          0 :         return retval;
        1001                 :            :
        1002                 :          0 :     v = PyObject_CallOneArg(checker, retval);
        1003         [ #  # ]:          0 :     if (v == NULL)
        1004                 :          0 :         _PyTraceback_Add("GetResult", "_ctypes/callproc.c", __LINE__-2);
        1005                 :          0 :     Py_DECREF(retval);
        1006                 :          0 :     return v;
        1007                 :            : }
        1008                 :            :
        1009                 :            : /*
        1010                 :            :  * Raise a new exception 'exc_class', adding additional text to the original
        1011                 :            :  * exception string.
        1012                 :            :  */
        1013                 :          0 : void _ctypes_extend_error(PyObject *exc_class, const char *fmt, ...)
        1014                 :            : {
        1015                 :            :     va_list vargs;
        1016                 :            :
        1017                 :          0 :     va_start(vargs, fmt);
        1018                 :          0 :     PyObject *s = PyUnicode_FromFormatV(fmt, vargs);
        1019                 :          0 :     va_end(vargs);
        1020         [ #  # ]:          0 :     if (s == NULL) {
        1021                 :          0 :         return;
        1022                 :            :     }
        1023                 :            :
        1024                 :            :     assert(PyErr_Occurred());
        1025                 :          0 :     PyObject *exc = PyErr_GetRaisedException();
        1026                 :            :     assert(exc != NULL);
        1027                 :          0 :     PyObject *cls_str = PyType_GetName(Py_TYPE(exc));
        1028         [ #  # ]:          0 :     if (cls_str) {
        1029                 :          0 :         PyUnicode_AppendAndDel(&s, cls_str);
        1030                 :          0 :         PyUnicode_AppendAndDel(&s, PyUnicode_FromString(": "));
        1031         [ #  # ]:          0 :         if (s == NULL) {
        1032                 :          0 :             goto error;
        1033                 :            :         }
        1034                 :            :     }
        1035                 :            :     else {
        1036                 :          0 :         PyErr_Clear();
        1037                 :            :     }
        1038                 :            :
        1039                 :          0 :     PyObject *msg_str = PyObject_Str(exc);
        1040         [ #  # ]:          0 :     if (msg_str) {
        1041                 :          0 :         PyUnicode_AppendAndDel(&s, msg_str);
        1042                 :            :     }
        1043                 :            :     else {
        1044                 :          0 :         PyErr_Clear();
        1045                 :          0 :         PyUnicode_AppendAndDel(&s, PyUnicode_FromString("???"));
        1046                 :            :     }
        1047         [ #  # ]:          0 :     if (s == NULL) {
        1048                 :          0 :         goto error;
        1049                 :            :     }
        1050                 :          0 :     PyErr_SetObject(exc_class, s);
        1051                 :          0 : error:
        1052                 :          0 :     Py_XDECREF(exc);
        1053                 :          0 :     Py_XDECREF(s);
        1054                 :            : }
        1055                 :            :
        1056                 :            :
        1057                 :            : #ifdef MS_WIN32
        1058                 :            :
        1059                 :            : static PyObject *
        1060                 :            : GetComError(HRESULT errcode, GUID *riid, IUnknown *pIunk)
        1061                 :            : {
        1062                 :            :     HRESULT hr;
        1063                 :            :     ISupportErrorInfo *psei = NULL;
        1064                 :            :     IErrorInfo *pei = NULL;
        1065                 :            :     BSTR descr=NULL, helpfile=NULL, source=NULL;
        1066                 :            :     GUID guid;
        1067                 :            :     DWORD helpcontext=0;
        1068                 :            :     LPOLESTR progid;
        1069                 :            :     PyObject *obj;
        1070                 :            :     LPOLESTR text;
        1071                 :            :
        1072                 :            :     /* We absolutely have to release the GIL during COM method calls,
        1073                 :            :        otherwise we may get a deadlock!
        1074                 :            :     */
        1075                 :            :     Py_BEGIN_ALLOW_THREADS
        1076                 :            :
        1077                 :            :     hr = pIunk->lpVtbl->QueryInterface(pIunk, &IID_ISupportErrorInfo, (void **)&psei);
        1078                 :            :     if (FAILED(hr))
        1079                 :            :         goto failed;
        1080                 :            :
        1081                 :            :     hr = psei->lpVtbl->InterfaceSupportsErrorInfo(psei, riid);
        1082                 :            :     psei->lpVtbl->Release(psei);
        1083                 :            :     if (FAILED(hr))
        1084                 :            :         goto failed;
        1085                 :            :
        1086                 :            :     hr = GetErrorInfo(0, &pei);
        1087                 :            :     if (hr != S_OK)
        1088                 :            :         goto failed;
        1089                 :            :
        1090                 :            :     pei->lpVtbl->GetDescription(pei, &descr);
        1091                 :            :     pei->lpVtbl->GetGUID(pei, &guid);
        1092                 :            :     pei->lpVtbl->GetHelpContext(pei, &helpcontext);
        1093                 :            :     pei->lpVtbl->GetHelpFile(pei, &helpfile);
        1094                 :            :     pei->lpVtbl->GetSource(pei, &source);
        1095                 :            :
        1096                 :            :     pei->lpVtbl->Release(pei);
        1097                 :            :
        1098                 :            :   failed:
        1099                 :            :     Py_END_ALLOW_THREADS
        1100                 :            :
        1101                 :            :     progid = NULL;
        1102                 :            :     ProgIDFromCLSID(&guid, &progid);
        1103                 :            :
        1104                 :            :     text = FormatError(errcode);
        1105                 :            :     obj = Py_BuildValue(
        1106                 :            :         "iu(uuuiu)",
        1107                 :            :         errcode,
        1108                 :            :         text,
        1109                 :            :         descr, source, helpfile, helpcontext,
        1110                 :            :         progid);
        1111                 :            :     if (obj) {
        1112                 :            :         PyErr_SetObject(ComError, obj);
        1113                 :            :         Py_DECREF(obj);
        1114                 :            :     }
        1115                 :            :     LocalFree(text);
        1116                 :            :
        1117                 :            :     if (descr)
        1118                 :            :         SysFreeString(descr);
        1119                 :            :     if (helpfile)
        1120                 :            :         SysFreeString(helpfile);
        1121                 :            :     if (source)
        1122                 :            :         SysFreeString(source);
        1123                 :            :
        1124                 :            :     return NULL;
        1125                 :            : }
        1126                 :            : #endif
        1127                 :            :
        1128                 :            : #if (defined(__x86_64__) && (defined(__MINGW64__) || defined(__CYGWIN__))) || \
        1129                 :            :     defined(__aarch64__) || defined(__riscv)
        1130                 :            : #define CTYPES_PASS_BY_REF_HACK
        1131                 :            : #define POW2(x) (((x & ~(x - 1)) == x) ? x : 0)
        1132                 :            : #define IS_PASS_BY_REF(x) (x > 8 || !POW2(x))
        1133                 :            : #endif
        1134                 :            :
        1135                 :            : /*
        1136                 :            :  * Requirements, must be ensured by the caller:
        1137                 :            :  * - argtuple is tuple of arguments
        1138                 :            :  * - argtypes is either NULL, or a tuple of the same size as argtuple
        1139                 :            :  *
        1140                 :            :  * - XXX various requirements for restype, not yet collected
        1141                 :            :  */
        1142                 :          0 : PyObject *_ctypes_callproc(PPROC pProc,
        1143                 :            :                     PyObject *argtuple,
        1144                 :            : #ifdef MS_WIN32
        1145                 :            :                     IUnknown *pIunk,
        1146                 :            :                     GUID *iid,
        1147                 :            : #endif
        1148                 :            :                     int flags,
        1149                 :            :                     PyObject *argtypes, /* misleading name: This is a tuple of
        1150                 :            :                                            methods, not types: the .from_param
        1151                 :            :                                            class methods of the types */
        1152                 :            :             PyObject *restype,
        1153                 :            :             PyObject *checker)
        1154                 :            : {
        1155                 :            :     Py_ssize_t i, n, argcount, argtype_count;
        1156                 :            :     void *resbuf;
        1157                 :            :     struct argument *args, *pa;
        1158                 :            :     ffi_type **atypes;
        1159                 :            :     ffi_type *rtype;
        1160                 :            :     void **avalues;
        1161                 :          0 :     PyObject *retval = NULL;
        1162                 :            :
        1163                 :          0 :     n = argcount = PyTuple_GET_SIZE(argtuple);
        1164                 :            : #ifdef MS_WIN32
        1165                 :            :     /* an optional COM object this pointer */
        1166                 :            :     if (pIunk)
        1167                 :            :         ++argcount;
        1168                 :            : #endif
        1169                 :            :
        1170         [ #  # ]:          0 :     if (argcount > CTYPES_MAX_ARGCOUNT)
        1171                 :            :     {
        1172                 :          0 :         PyErr_Format(PyExc_ArgError, "too many arguments (%zi), maximum is %i",
        1173                 :            :                      argcount, CTYPES_MAX_ARGCOUNT);
        1174                 :          0 :         return NULL;
        1175                 :            :     }
        1176                 :            :
        1177                 :          0 :     args = alloca(sizeof(struct argument) * argcount);
        1178                 :          0 :     memset(args, 0, sizeof(struct argument) * argcount);
        1179         [ #  # ]:          0 :     argtype_count = argtypes ? PyTuple_GET_SIZE(argtypes) : 0;
        1180                 :            : #ifdef MS_WIN32
        1181                 :            :     if (pIunk) {
        1182                 :            :         args[0].ffi_type = &ffi_type_pointer;
        1183                 :            :         args[0].value.p = pIunk;
        1184                 :            :         pa = &args[1];
        1185                 :            :     } else
        1186                 :            : #endif
        1187                 :          0 :         pa = &args[0];
        1188                 :            :
        1189                 :            :     /* Convert the arguments */
        1190         [ #  # ]:          0 :     for (i = 0; i < n; ++i, ++pa) {
        1191                 :            :         PyObject *converter;
        1192                 :            :         PyObject *arg;
        1193                 :            :         int err;
        1194                 :            :
        1195                 :          0 :         arg = PyTuple_GET_ITEM(argtuple, i);            /* borrowed ref */
        1196                 :            :         /* For cdecl functions, we allow more actual arguments
        1197                 :            :            than the length of the argtypes tuple.
        1198                 :            :            This is checked in _ctypes::PyCFuncPtr_Call
        1199                 :            :         */
        1200   [ #  #  #  # ]:          0 :         if (argtypes && argtype_count > i) {
        1201                 :            :             PyObject *v;
        1202                 :          0 :             converter = PyTuple_GET_ITEM(argtypes, i);
        1203                 :          0 :             v = PyObject_CallOneArg(converter, arg);
        1204         [ #  # ]:          0 :             if (v == NULL) {
        1205                 :          0 :                 _ctypes_extend_error(PyExc_ArgError, "argument %zd: ", i+1);
        1206                 :          0 :                 goto cleanup;
        1207                 :            :             }
        1208                 :            :
        1209                 :          0 :             err = ConvParam(v, i+1, pa);
        1210                 :          0 :             Py_DECREF(v);
        1211         [ #  # ]:          0 :             if (-1 == err) {
        1212                 :          0 :                 _ctypes_extend_error(PyExc_ArgError, "argument %zd: ", i+1);
        1213                 :          0 :                 goto cleanup;
        1214                 :            :             }
        1215                 :            :         } else {
        1216                 :          0 :             err = ConvParam(arg, i+1, pa);
        1217         [ #  # ]:          0 :             if (-1 == err) {
        1218                 :          0 :                 _ctypes_extend_error(PyExc_ArgError, "argument %zd: ", i+1);
        1219                 :          0 :                 goto cleanup; /* leaking ? */
        1220                 :            :             }
        1221                 :            :         }
        1222                 :            :     }
        1223                 :            :
        1224         [ #  # ]:          0 :     if (restype == Py_None) {
        1225                 :          0 :         rtype = &ffi_type_void;
        1226                 :            :     } else {
        1227                 :          0 :         rtype = _ctypes_get_ffi_type(restype);
        1228                 :            :     }
        1229                 :            :
        1230                 :          0 :     resbuf = alloca(max(rtype->size, sizeof(ffi_arg)));
        1231                 :            :
        1232                 :            : #ifdef _Py_MEMORY_SANITIZER
        1233                 :            :     /* ffi_call actually initializes resbuf, but from asm, which
        1234                 :            :      * MemorySanitizer can't detect. Avoid false positives from MSan. */
        1235                 :            :     if (resbuf != NULL) {
        1236                 :            :         __msan_unpoison(resbuf, max(rtype->size, sizeof(ffi_arg)));
        1237                 :            :     }
        1238                 :            : #endif
        1239                 :          0 :     avalues = (void **)alloca(sizeof(void *) * argcount);
        1240                 :          0 :     atypes = (ffi_type **)alloca(sizeof(ffi_type *) * argcount);
        1241   [ #  #  #  #  :          0 :     if (!resbuf || !avalues || !atypes) {
                       #  # ]
        1242                 :          0 :         PyErr_NoMemory();
        1243                 :          0 :         goto cleanup;
        1244                 :            :     }
        1245         [ #  # ]:          0 :     for (i = 0; i < argcount; ++i) {
        1246                 :          0 :         atypes[i] = args[i].ffi_type;
        1247                 :            : #ifdef CTYPES_PASS_BY_REF_HACK
        1248                 :            :         size_t size = atypes[i]->size;
        1249                 :            :         if (IS_PASS_BY_REF(size)) {
        1250                 :            :             void *tmp = alloca(size);
        1251                 :            :             if (atypes[i]->type == FFI_TYPE_STRUCT)
        1252                 :            :                 memcpy(tmp, args[i].value.p, size);
        1253                 :            :             else
        1254                 :            :                 memcpy(tmp, (void*)&args[i].value, size);
        1255                 :            :
        1256                 :            :             avalues[i] = tmp;
        1257                 :            :         }
        1258                 :            :         else
        1259                 :            : #endif
        1260         [ #  # ]:          0 :         if (atypes[i]->type == FFI_TYPE_STRUCT)
        1261                 :          0 :             avalues[i] = (void *)args[i].value.p;
        1262                 :            :         else
        1263                 :          0 :             avalues[i] = (void *)&args[i].value;
        1264                 :            :     }
        1265                 :            :
        1266         [ #  # ]:          0 :     if (-1 == _call_function_pointer(flags, pProc, avalues, atypes,
        1267                 :            :                                      rtype, resbuf,
        1268                 :            :                                      Py_SAFE_DOWNCAST(argcount, Py_ssize_t, int),
        1269                 :            :                                      Py_SAFE_DOWNCAST(argtype_count, Py_ssize_t, int)))
        1270                 :          0 :         goto cleanup;
        1271                 :            :
        1272                 :            : #ifdef WORDS_BIGENDIAN
        1273                 :            :     /* libffi returns the result in a buffer with sizeof(ffi_arg). This
        1274                 :            :        causes problems on big endian machines, since the result buffer
        1275                 :            :        address cannot simply be used as result pointer, instead we must
        1276                 :            :        adjust the pointer value:
        1277                 :            :      */
        1278                 :            :     /*
        1279                 :            :       XXX I should find out and clarify why this is needed at all,
        1280                 :            :       especially why adjusting for ffi_type_float must be avoided on
        1281                 :            :       64-bit platforms.
        1282                 :            :      */
        1283                 :            :     if (rtype->type != FFI_TYPE_FLOAT
        1284                 :            :         && rtype->type != FFI_TYPE_STRUCT
        1285                 :            :         && rtype->size < sizeof(ffi_arg))
        1286                 :            :     {
        1287                 :            :         resbuf = (char *)resbuf + sizeof(ffi_arg) - rtype->size;
        1288                 :            :     }
        1289                 :            : #endif
        1290                 :            :
        1291                 :            : #ifdef MS_WIN32
        1292                 :            :     if (iid && pIunk) {
        1293                 :            :         if (*(int *)resbuf & 0x80000000)
        1294                 :            :             retval = GetComError(*(HRESULT *)resbuf, iid, pIunk);
        1295                 :            :         else
        1296                 :            :             retval = PyLong_FromLong(*(int *)resbuf);
        1297                 :            :     } else if (flags & FUNCFLAG_HRESULT) {
        1298                 :            :         if (*(int *)resbuf & 0x80000000)
        1299                 :            :             retval = PyErr_SetFromWindowsErr(*(int *)resbuf);
        1300                 :            :         else
        1301                 :            :             retval = PyLong_FromLong(*(int *)resbuf);
        1302                 :            :     } else
        1303                 :            : #endif
        1304                 :          0 :         retval = GetResult(restype, resbuf, checker);
        1305                 :          0 :   cleanup:
        1306         [ #  # ]:          0 :     for (i = 0; i < argcount; ++i)
        1307                 :          0 :         Py_XDECREF(args[i].keep);
        1308                 :          0 :     return retval;
        1309                 :            : }
        1310                 :            :
        1311                 :            : static int
        1312                 :          0 : _parse_voidp(PyObject *obj, void **address)
        1313                 :            : {
        1314                 :          0 :     *address = PyLong_AsVoidPtr(obj);
        1315         [ #  # ]:          0 :     if (*address == NULL)
        1316                 :          0 :         return 0;
        1317                 :          0 :     return 1;
        1318                 :            : }
        1319                 :            :
        1320                 :            : #ifdef MS_WIN32
        1321                 :            :
        1322                 :            : PyDoc_STRVAR(format_error_doc,
        1323                 :            : "FormatError([integer]) -> string\n\
        1324                 :            : \n\
        1325                 :            : Convert a win32 error code into a string. If the error code is not\n\
        1326                 :            : given, the return value of a call to GetLastError() is used.\n");
        1327                 :            : static PyObject *format_error(PyObject *self, PyObject *args)
        1328                 :            : {
        1329                 :            :     PyObject *result;
        1330                 :            :     wchar_t *lpMsgBuf;
        1331                 :            :     DWORD code = 0;
        1332                 :            :     if (!PyArg_ParseTuple(args, "|i:FormatError", &code))
        1333                 :            :         return NULL;
        1334                 :            :     if (code == 0)
        1335                 :            :         code = GetLastError();
        1336                 :            :     lpMsgBuf = FormatError(code);
        1337                 :            :     if (lpMsgBuf) {
        1338                 :            :         result = PyUnicode_FromWideChar(lpMsgBuf, wcslen(lpMsgBuf));
        1339                 :            :         LocalFree(lpMsgBuf);
        1340                 :            :     } else {
        1341                 :            :         result = PyUnicode_FromString("<no description>");
        1342                 :            :     }
        1343                 :            :     return result;
        1344                 :            : }
        1345                 :            :
        1346                 :            : PyDoc_STRVAR(load_library_doc,
        1347                 :            : "LoadLibrary(name, load_flags) -> handle\n\
        1348                 :            : \n\
        1349                 :            : Load an executable (usually a DLL), and return a handle to it.\n\
        1350                 :            : The handle may be used to locate exported functions in this\n\
        1351                 :            : module. load_flags are as defined for LoadLibraryEx in the\n\
        1352                 :            : Windows API.\n");
        1353                 :            : static PyObject *load_library(PyObject *self, PyObject *args)
        1354                 :            : {
        1355                 :            :     PyObject *nameobj;
        1356                 :            :     int load_flags = 0;
        1357                 :            :     HMODULE hMod;
        1358                 :            :     DWORD err;
        1359                 :            :
        1360                 :            :     if (!PyArg_ParseTuple(args, "U|i:LoadLibrary", &nameobj, &load_flags))
        1361                 :            :         return NULL;
        1362                 :            :
        1363                 :            :     if (PySys_Audit("ctypes.dlopen", "O", nameobj) < 0) {
        1364                 :            :         return NULL;
        1365                 :            :     }
        1366                 :            :
        1367                 :            :     WCHAR *name = PyUnicode_AsWideCharString(nameobj, NULL);
        1368                 :            :     if (!name)
        1369                 :            :         return NULL;
        1370                 :            :
        1371                 :            :     Py_BEGIN_ALLOW_THREADS
        1372                 :            :     /* bpo-36085: Limit DLL search directories to avoid pre-loading
        1373                 :            :      * attacks and enable use of the AddDllDirectory function.
        1374                 :            :      */
        1375                 :            :     hMod = LoadLibraryExW(name, NULL, (DWORD)load_flags);
        1376                 :            :     err = hMod ? 0 : GetLastError();
        1377                 :            :     Py_END_ALLOW_THREADS
        1378                 :            :
        1379                 :            :     PyMem_Free(name);
        1380                 :            :     if (err == ERROR_MOD_NOT_FOUND) {
        1381                 :            :         PyErr_Format(PyExc_FileNotFoundError,
        1382                 :            :                      ("Could not find module '%.500S' (or one of its "
        1383                 :            :                       "dependencies). Try using the full path with "
        1384                 :            :                       "constructor syntax."),
        1385                 :            :                      nameobj);
        1386                 :            :         return NULL;
        1387                 :            :     } else if (err) {
        1388                 :            :         return PyErr_SetFromWindowsErr(err);
        1389                 :            :     }
        1390                 :            : #ifdef _WIN64
        1391                 :            :     return PyLong_FromVoidPtr(hMod);
        1392                 :            : #else
        1393                 :            :     return Py_BuildValue("i", hMod);
        1394                 :            : #endif
        1395                 :            : }
        1396                 :            :
        1397                 :            : PyDoc_STRVAR(free_library_doc,
        1398                 :            : "FreeLibrary(handle) -> void\n\
        1399                 :            : \n\
        1400                 :            : Free the handle of an executable previously loaded by LoadLibrary.\n");
        1401                 :            : static PyObject *free_library(PyObject *self, PyObject *args)
        1402                 :            : {
        1403                 :            :     void *hMod;
        1404                 :            :     BOOL result;
        1405                 :            :     DWORD err;
        1406                 :            :     if (!PyArg_ParseTuple(args, "O&:FreeLibrary", &_parse_voidp, &hMod))
        1407                 :            :         return NULL;
        1408                 :            :
        1409                 :            :     Py_BEGIN_ALLOW_THREADS
        1410                 :            :     result = FreeLibrary((HMODULE)hMod);
        1411                 :            :     err = result ? 0 : GetLastError();
        1412                 :            :     Py_END_ALLOW_THREADS
        1413                 :            :
        1414                 :            :     if (!result) {
        1415                 :            :         return PyErr_SetFromWindowsErr(err);
        1416                 :            :     }
        1417                 :            :     Py_RETURN_NONE;
        1418                 :            : }
        1419                 :            :
        1420                 :            : PyDoc_STRVAR(copy_com_pointer_doc,
        1421                 :            : "CopyComPointer(src, dst) -> HRESULT value\n");
        1422                 :            :
        1423                 :            : static PyObject *
        1424                 :            : copy_com_pointer(PyObject *self, PyObject *args)
        1425                 :            : {
        1426                 :            :     PyObject *p1, *p2, *r = NULL;
        1427                 :            :     struct argument a, b;
        1428                 :            :     IUnknown *src, **pdst;
        1429                 :            :     if (!PyArg_ParseTuple(args, "OO:CopyComPointer", &p1, &p2))
        1430                 :            :         return NULL;
        1431                 :            :     a.keep = b.keep = NULL;
        1432                 :            :
        1433                 :            :     if (-1 == ConvParam(p1, 0, &a) || -1 == ConvParam(p2, 1, &b))
        1434                 :            :         goto done;
        1435                 :            :     src = (IUnknown *)a.value.p;
        1436                 :            :     pdst = (IUnknown **)b.value.p;
        1437                 :            :
        1438                 :            :     if (pdst == NULL)
        1439                 :            :         r = PyLong_FromLong(E_POINTER);
        1440                 :            :     else {
        1441                 :            :         if (src)
        1442                 :            :             src->lpVtbl->AddRef(src);
        1443                 :            :         *pdst = src;
        1444                 :            :         r = PyLong_FromLong(S_OK);
        1445                 :            :     }
        1446                 :            :   done:
        1447                 :            :     Py_XDECREF(a.keep);
        1448                 :            :     Py_XDECREF(b.keep);
        1449                 :            :     return r;
        1450                 :            : }
        1451                 :            : #else
        1452                 :            : #ifdef __APPLE__
        1453                 :            : #ifdef HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH
        1454                 :            : #  ifdef HAVE_BUILTIN_AVAILABLE
        1455                 :            : #    define HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH_RUNTIME \
        1456                 :            :         __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
        1457                 :            : #  else
        1458                 :            : #    define HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH_RUNTIME \
        1459                 :            :          (_dyld_shared_cache_contains_path != NULL)
        1460                 :            : #  endif
        1461                 :            : #else
        1462                 :            : // Support the deprecated case of compiling on an older macOS version
        1463                 :            : static void *libsystem_b_handle;
        1464                 :            : static bool (*_dyld_shared_cache_contains_path)(const char *path);
        1465                 :            :
        1466                 :            : __attribute__((constructor)) void load_dyld_shared_cache_contains_path(void) {
        1467                 :            :     libsystem_b_handle = dlopen("/usr/lib/libSystem.B.dylib", RTLD_LAZY);
        1468                 :            :     if (libsystem_b_handle != NULL) {
        1469                 :            :         _dyld_shared_cache_contains_path = dlsym(libsystem_b_handle, "_dyld_shared_cache_contains_path");
        1470                 :            :     }
        1471                 :            : }
        1472                 :            :
        1473                 :            : __attribute__((destructor)) void unload_dyld_shared_cache_contains_path(void) {
        1474                 :            :     if (libsystem_b_handle != NULL) {
        1475                 :            :         dlclose(libsystem_b_handle);
        1476                 :            :     }
        1477                 :            : }
        1478                 :            : #define HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH_RUNTIME \
        1479                 :            :     _dyld_shared_cache_contains_path != NULL
        1480                 :            : #endif
        1481                 :            :
        1482                 :            : static PyObject *py_dyld_shared_cache_contains_path(PyObject *self, PyObject *args)
        1483                 :            : {
        1484                 :            :      PyObject *name, *name2;
        1485                 :            :      char *name_str;
        1486                 :            :
        1487                 :            :      if (HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH_RUNTIME) {
        1488                 :            :          int r;
        1489                 :            :
        1490                 :            :          if (!PyArg_ParseTuple(args, "O", &name))
        1491                 :            :              return NULL;
        1492                 :            :
        1493                 :            :          if (name == Py_None)
        1494                 :            :              Py_RETURN_FALSE;
        1495                 :            :
        1496                 :            :          if (PyUnicode_FSConverter(name, &name2) == 0)
        1497                 :            :              return NULL;
        1498                 :            :          name_str = PyBytes_AS_STRING(name2);
        1499                 :            :
        1500                 :            :          r = _dyld_shared_cache_contains_path(name_str);
        1501                 :            :          Py_DECREF(name2);
        1502                 :            :
        1503                 :            :          if (r) {
        1504                 :            :              Py_RETURN_TRUE;
        1505                 :            :          } else {
        1506                 :            :              Py_RETURN_FALSE;
        1507                 :            :          }
        1508                 :            :
        1509                 :            :      } else {
        1510                 :            :          PyErr_SetString(PyExc_NotImplementedError, "_dyld_shared_cache_contains_path symbol is missing");
        1511                 :            :          return NULL;
        1512                 :            :      }
        1513                 :            :
        1514                 :            :  }
        1515                 :            : #endif
        1516                 :            :
        1517                 :          1 : static PyObject *py_dl_open(PyObject *self, PyObject *args)
        1518                 :            : {
        1519                 :            :     PyObject *name, *name2;
        1520                 :            :     const char *name_str;
        1521                 :            :     void * handle;
        1522                 :            : #if HAVE_DECL_RTLD_LOCAL
        1523                 :          1 :     int mode = RTLD_NOW | RTLD_LOCAL;
        1524                 :            : #else
        1525                 :            :     /* cygwin doesn't define RTLD_LOCAL */
        1526                 :            :     int mode = RTLD_NOW;
        1527                 :            : #endif
        1528         [ -  + ]:          1 :     if (!PyArg_ParseTuple(args, "O|i:dlopen", &name, &mode))
        1529                 :          0 :         return NULL;
        1530                 :          1 :     mode |= RTLD_NOW;
        1531         [ -  + ]:          1 :     if (name != Py_None) {
        1532         [ #  # ]:          0 :         if (PyUnicode_FSConverter(name, &name2) == 0)
        1533                 :          0 :             return NULL;
        1534                 :          0 :         name_str = PyBytes_AS_STRING(name2);
        1535                 :            :     } else {
        1536                 :          1 :         name_str = NULL;
        1537                 :          1 :         name2 = NULL;
        1538                 :            :     }
        1539         [ -  + ]:          1 :     if (PySys_Audit("ctypes.dlopen", "O", name) < 0) {
        1540                 :          0 :         return NULL;
        1541                 :            :     }
        1542                 :          1 :     handle = dlopen(name_str, mode);
        1543                 :          1 :     Py_XDECREF(name2);
        1544         [ -  + ]:          1 :     if (!handle) {
        1545                 :          0 :         const char *errmsg = dlerror();
        1546         [ #  # ]:          0 :         if (!errmsg)
        1547                 :          0 :             errmsg = "dlopen() error";
        1548                 :          0 :         PyErr_SetString(PyExc_OSError,
        1549                 :            :                                errmsg);
        1550                 :          0 :         return NULL;
        1551                 :            :     }
        1552                 :          1 :     return PyLong_FromVoidPtr(handle);
        1553                 :            : }
        1554                 :            :
        1555                 :          0 : static PyObject *py_dl_close(PyObject *self, PyObject *args)
        1556                 :            : {
        1557                 :            :     void *handle;
        1558                 :            :
        1559         [ #  # ]:          0 :     if (!PyArg_ParseTuple(args, "O&:dlclose", &_parse_voidp, &handle))
        1560                 :          0 :         return NULL;
        1561         [ #  # ]:          0 :     if (dlclose(handle)) {
        1562                 :          0 :         PyErr_SetString(PyExc_OSError,
        1563                 :          0 :                                dlerror());
        1564                 :          0 :         return NULL;
        1565                 :            :     }
        1566                 :          0 :     Py_RETURN_NONE;
        1567                 :            : }
        1568                 :            :
        1569                 :          0 : static PyObject *py_dl_sym(PyObject *self, PyObject *args)
        1570                 :            : {
        1571                 :            :     char *name;
        1572                 :            :     void *handle;
        1573                 :            :     void *ptr;
        1574                 :            :
        1575         [ #  # ]:          0 :     if (!PyArg_ParseTuple(args, "O&s:dlsym",
        1576                 :            :                           &_parse_voidp, &handle, &name))
        1577                 :          0 :         return NULL;
        1578         [ #  # ]:          0 :     if (PySys_Audit("ctypes.dlsym/handle", "O", args) < 0) {
        1579                 :          0 :         return NULL;
        1580                 :            :     }
        1581                 :          0 :     ptr = dlsym((void*)handle, name);
        1582         [ #  # ]:          0 :     if (!ptr) {
        1583                 :          0 :         PyErr_SetString(PyExc_OSError,
        1584                 :          0 :                                dlerror());
        1585                 :          0 :         return NULL;
        1586                 :            :     }
        1587                 :          0 :     return PyLong_FromVoidPtr(ptr);
        1588                 :            : }
        1589                 :            : #endif
        1590                 :            :
        1591                 :            : /*
        1592                 :            :  * Only for debugging so far: So that we can call CFunction instances
        1593                 :            :  *
        1594                 :            :  * XXX Needs to accept more arguments: flags, argtypes, restype
        1595                 :            :  */
        1596                 :            : static PyObject *
        1597                 :          0 : call_function(PyObject *self, PyObject *args)
        1598                 :            : {
        1599                 :            :     void *func;
        1600                 :            :     PyObject *arguments;
        1601                 :            :     PyObject *result;
        1602                 :            :
        1603         [ #  # ]:          0 :     if (!PyArg_ParseTuple(args,
        1604                 :            :                           "O&O!",
        1605                 :            :                           &_parse_voidp, &func,
        1606                 :            :                           &PyTuple_Type, &arguments))
        1607                 :          0 :         return NULL;
        1608         [ #  # ]:          0 :     if (PySys_Audit("ctypes.call_function", "nO",
        1609                 :            :                     (Py_ssize_t)func, arguments) < 0) {
        1610                 :          0 :         return NULL;
        1611                 :            :     }
        1612                 :            :
        1613                 :          0 :     result =  _ctypes_callproc((PPROC)func,
        1614                 :            :                         arguments,
        1615                 :            : #ifdef MS_WIN32
        1616                 :            :                         NULL,
        1617                 :            :                         NULL,
        1618                 :            : #endif
        1619                 :            :                         0, /* flags */
        1620                 :            :                 NULL, /* self->argtypes */
        1621                 :            :                 NULL, /* self->restype */
        1622                 :            :                 NULL); /* checker */
        1623                 :          0 :     return result;
        1624                 :            : }
        1625                 :            :
        1626                 :            : /*
        1627                 :            :  * Only for debugging so far: So that we can call CFunction instances
        1628                 :            :  *
        1629                 :            :  * XXX Needs to accept more arguments: flags, argtypes, restype
        1630                 :            :  */
        1631                 :            : static PyObject *
        1632                 :          0 : call_cdeclfunction(PyObject *self, PyObject *args)
        1633                 :            : {
        1634                 :            :     void *func;
        1635                 :            :     PyObject *arguments;
        1636                 :            :     PyObject *result;
        1637                 :            :
        1638         [ #  # ]:          0 :     if (!PyArg_ParseTuple(args,
        1639                 :            :                           "O&O!",
        1640                 :            :                           &_parse_voidp, &func,
        1641                 :            :                           &PyTuple_Type, &arguments))
        1642                 :          0 :         return NULL;
        1643         [ #  # ]:          0 :     if (PySys_Audit("ctypes.call_function", "nO",
        1644                 :            :                     (Py_ssize_t)func, arguments) < 0) {
        1645                 :          0 :         return NULL;
        1646                 :            :     }
        1647                 :            :
        1648                 :          0 :     result =  _ctypes_callproc((PPROC)func,
        1649                 :            :                         arguments,
        1650                 :            : #ifdef MS_WIN32
        1651                 :            :                         NULL,
        1652                 :            :                         NULL,
        1653                 :            : #endif
        1654                 :            :                         FUNCFLAG_CDECL, /* flags */
        1655                 :            :                         NULL, /* self->argtypes */
        1656                 :            :                         NULL, /* self->restype */
        1657                 :            :                         NULL); /* checker */
        1658                 :          0 :     return result;
        1659                 :            : }
        1660                 :            :
        1661                 :            : /*****************************************************************
        1662                 :            :  * functions
        1663                 :            :  */
        1664                 :            : PyDoc_STRVAR(sizeof_doc,
        1665                 :            : "sizeof(C type) -> integer\n"
        1666                 :            : "sizeof(C instance) -> integer\n"
        1667                 :            : "Return the size in bytes of a C instance");
        1668                 :            :
        1669                 :            : static PyObject *
        1670                 :         38 : sizeof_func(PyObject *self, PyObject *obj)
        1671                 :            : {
        1672                 :            :     StgDictObject *dict;
        1673                 :            :
        1674                 :         38 :     dict = PyType_stgdict(obj);
        1675         [ +  - ]:         38 :     if (dict)
        1676                 :         38 :         return PyLong_FromSsize_t(dict->size);
        1677                 :            :
        1678         [ #  # ]:          0 :     if (CDataObject_Check(obj))
        1679                 :          0 :         return PyLong_FromSsize_t(((CDataObject *)obj)->b_size);
        1680                 :          0 :     PyErr_SetString(PyExc_TypeError,
        1681                 :            :                     "this type has no size");
        1682                 :          0 :     return NULL;
        1683                 :            : }
        1684                 :            :
        1685                 :            : PyDoc_STRVAR(alignment_doc,
        1686                 :            : "alignment(C type) -> integer\n"
        1687                 :            : "alignment(C instance) -> integer\n"
        1688                 :            : "Return the alignment requirements of a C instance");
        1689                 :            :
        1690                 :            : static PyObject *
        1691                 :          0 : align_func(PyObject *self, PyObject *obj)
        1692                 :            : {
        1693                 :            :     StgDictObject *dict;
        1694                 :            :
        1695                 :          0 :     dict = PyType_stgdict(obj);
        1696         [ #  # ]:          0 :     if (dict)
        1697                 :          0 :         return PyLong_FromSsize_t(dict->align);
        1698                 :            :
        1699                 :          0 :     dict = PyObject_stgdict(obj);
        1700         [ #  # ]:          0 :     if (dict)
        1701                 :          0 :         return PyLong_FromSsize_t(dict->align);
        1702                 :            :
        1703                 :          0 :     PyErr_SetString(PyExc_TypeError,
        1704                 :            :                     "no alignment info");
        1705                 :          0 :     return NULL;
        1706                 :            : }
        1707                 :            :
        1708                 :            : PyDoc_STRVAR(byref_doc,
        1709                 :            : "byref(C instance[, offset=0]) -> byref-object\n"
        1710                 :            : "Return a pointer lookalike to a C instance, only usable\n"
        1711                 :            : "as function argument");
        1712                 :            :
        1713                 :            : /*
        1714                 :            :  * We must return something which can be converted to a parameter,
        1715                 :            :  * but still has a reference to self.
        1716                 :            :  */
        1717                 :            : static PyObject *
        1718                 :          0 : byref(PyObject *self, PyObject *args)
        1719                 :            : {
        1720                 :            :     PyCArgObject *parg;
        1721                 :            :     PyObject *obj;
        1722                 :          0 :     PyObject *pyoffset = NULL;
        1723                 :          0 :     Py_ssize_t offset = 0;
        1724                 :            :
        1725         [ #  # ]:          0 :     if (!PyArg_UnpackTuple(args, "byref", 1, 2,
        1726                 :            :                            &obj, &pyoffset))
        1727                 :          0 :         return NULL;
        1728         [ #  # ]:          0 :     if (pyoffset) {
        1729                 :          0 :         offset = PyNumber_AsSsize_t(pyoffset, NULL);
        1730   [ #  #  #  # ]:          0 :         if (offset == -1 && PyErr_Occurred())
        1731                 :          0 :             return NULL;
        1732                 :            :     }
        1733         [ #  # ]:          0 :     if (!CDataObject_Check(obj)) {
        1734                 :          0 :         PyErr_Format(PyExc_TypeError,
        1735                 :            :                      "byref() argument must be a ctypes instance, not '%s'",
        1736                 :          0 :                      Py_TYPE(obj)->tp_name);
        1737                 :          0 :         return NULL;
        1738                 :            :     }
        1739                 :            :
        1740                 :          0 :     parg = PyCArgObject_new();
        1741         [ #  # ]:          0 :     if (parg == NULL)
        1742                 :          0 :         return NULL;
        1743                 :            :
        1744                 :          0 :     parg->tag = 'P';
        1745                 :          0 :     parg->pffi_type = &ffi_type_pointer;
        1746                 :          0 :     parg->obj = Py_NewRef(obj);
        1747                 :          0 :     parg->value.p = (char *)((CDataObject *)obj)->b_ptr + offset;
        1748                 :          0 :     return (PyObject *)parg;
        1749                 :            : }
        1750                 :            :
        1751                 :            : PyDoc_STRVAR(addressof_doc,
        1752                 :            : "addressof(C instance) -> integer\n"
        1753                 :            : "Return the address of the C instance internal buffer");
        1754                 :            :
        1755                 :            : static PyObject *
        1756                 :          0 : addressof(PyObject *self, PyObject *obj)
        1757                 :            : {
        1758         [ #  # ]:          0 :     if (!CDataObject_Check(obj)) {
        1759                 :          0 :         PyErr_SetString(PyExc_TypeError,
        1760                 :            :                         "invalid type");
        1761                 :          0 :         return NULL;
        1762                 :            :     }
        1763         [ #  # ]:          0 :     if (PySys_Audit("ctypes.addressof", "(O)", obj) < 0) {
        1764                 :          0 :         return NULL;
        1765                 :            :     }
        1766                 :          0 :     return PyLong_FromVoidPtr(((CDataObject *)obj)->b_ptr);
        1767                 :            : }
        1768                 :            :
        1769                 :            : static int
        1770                 :          0 : converter(PyObject *obj, void **address)
        1771                 :            : {
        1772                 :          0 :     *address = PyLong_AsVoidPtr(obj);
        1773                 :          0 :     return *address != NULL;
        1774                 :            : }
        1775                 :            :
        1776                 :            : static PyObject *
        1777                 :          0 : My_PyObj_FromPtr(PyObject *self, PyObject *args)
        1778                 :            : {
        1779                 :            :     PyObject *ob;
        1780         [ #  # ]:          0 :     if (!PyArg_ParseTuple(args, "O&:PyObj_FromPtr", converter, &ob)) {
        1781                 :          0 :         return NULL;
        1782                 :            :     }
        1783         [ #  # ]:          0 :     if (PySys_Audit("ctypes.PyObj_FromPtr", "(O)", ob) < 0) {
        1784                 :          0 :         return NULL;
        1785                 :            :     }
        1786                 :          0 :     return Py_NewRef(ob);
        1787                 :            : }
        1788                 :            :
        1789                 :            : static PyObject *
        1790                 :          0 : My_Py_INCREF(PyObject *self, PyObject *arg)
        1791                 :            : {
        1792                 :          0 :     Py_INCREF(arg); /* that's what this function is for */
        1793                 :          0 :     Py_INCREF(arg); /* that for returning it */
        1794                 :          0 :     return arg;
        1795                 :            : }
        1796                 :            :
        1797                 :            : static PyObject *
        1798                 :          0 : My_Py_DECREF(PyObject *self, PyObject *arg)
        1799                 :            : {
        1800                 :          0 :     Py_DECREF(arg); /* that's what this function is for */
        1801                 :          0 :     Py_INCREF(arg); /* that's for returning it */
        1802                 :          0 :     return arg;
        1803                 :            : }
        1804                 :            :
        1805                 :            : static PyObject *
        1806                 :          0 : resize(PyObject *self, PyObject *args)
        1807                 :            : {
        1808                 :            :     CDataObject *obj;
        1809                 :            :     StgDictObject *dict;
        1810                 :            :     Py_ssize_t size;
        1811                 :            :
        1812         [ #  # ]:          0 :     if (!PyArg_ParseTuple(args,
        1813                 :            :                           "On:resize",
        1814                 :            :                           &obj, &size))
        1815                 :          0 :         return NULL;
        1816                 :            :
        1817                 :          0 :     dict = PyObject_stgdict((PyObject *)obj);
        1818         [ #  # ]:          0 :     if (dict == NULL) {
        1819                 :          0 :         PyErr_SetString(PyExc_TypeError,
        1820                 :            :                         "excepted ctypes instance");
        1821                 :          0 :         return NULL;
        1822                 :            :     }
        1823         [ #  # ]:          0 :     if (size < dict->size) {
        1824                 :          0 :         PyErr_Format(PyExc_ValueError,
        1825                 :            :                      "minimum size is %zd",
        1826                 :            :                      dict->size);
        1827                 :          0 :         return NULL;
        1828                 :            :     }
        1829         [ #  # ]:          0 :     if (obj->b_needsfree == 0) {
        1830                 :          0 :         PyErr_Format(PyExc_ValueError,
        1831                 :            :                      "Memory cannot be resized because this object doesn't own it");
        1832                 :          0 :         return NULL;
        1833                 :            :     }
        1834         [ #  # ]:          0 :     if ((size_t)size <= sizeof(obj->b_value)) {
        1835                 :            :         /* internal default buffer is large enough */
        1836                 :          0 :         obj->b_size = size;
        1837                 :          0 :         goto done;
        1838                 :            :     }
        1839         [ #  # ]:          0 :     if (!_CDataObject_HasExternalBuffer(obj)) {
        1840                 :            :         /* We are currently using the objects default buffer, but it
        1841                 :            :            isn't large enough any more. */
        1842                 :          0 :         void *ptr = PyMem_Calloc(1, size);
        1843         [ #  # ]:          0 :         if (ptr == NULL)
        1844                 :          0 :             return PyErr_NoMemory();
        1845                 :          0 :         memmove(ptr, obj->b_ptr, obj->b_size);
        1846                 :          0 :         obj->b_ptr = ptr;
        1847                 :          0 :         obj->b_size = size;
        1848                 :            :     } else {
        1849                 :          0 :         void * ptr = PyMem_Realloc(obj->b_ptr, size);
        1850         [ #  # ]:          0 :         if (ptr == NULL)
        1851                 :          0 :             return PyErr_NoMemory();
        1852                 :          0 :         obj->b_ptr = ptr;
        1853                 :          0 :         obj->b_size = size;
        1854                 :            :     }
        1855                 :          0 :   done:
        1856                 :          0 :     Py_RETURN_NONE;
        1857                 :            : }
        1858                 :            :
        1859                 :            : static PyObject *
        1860                 :          0 : unpickle(PyObject *self, PyObject *args)
        1861                 :            : {
        1862                 :            :     PyObject *typ, *state, *meth, *obj, *result;
        1863                 :            :
        1864         [ #  # ]:          0 :     if (!PyArg_ParseTuple(args, "OO!", &typ, &PyTuple_Type, &state))
        1865                 :          0 :         return NULL;
        1866                 :          0 :     obj = PyObject_CallMethodOneArg(typ, &_Py_ID(__new__), typ);
        1867         [ #  # ]:          0 :     if (obj == NULL)
        1868                 :          0 :         return NULL;
        1869                 :            :
        1870                 :          0 :     meth = PyObject_GetAttr(obj, &_Py_ID(__setstate__));
        1871         [ #  # ]:          0 :     if (meth == NULL) {
        1872                 :          0 :         goto error;
        1873                 :            :     }
        1874                 :            :
        1875                 :          0 :     result = PyObject_Call(meth, state, NULL);
        1876                 :          0 :     Py_DECREF(meth);
        1877         [ #  # ]:          0 :     if (result == NULL) {
        1878                 :          0 :         goto error;
        1879                 :            :     }
        1880                 :          0 :     Py_DECREF(result);
        1881                 :            :
        1882                 :          0 :     return obj;
        1883                 :            :
        1884                 :          0 : error:
        1885                 :          0 :     Py_DECREF(obj);
        1886                 :          0 :     return NULL;
        1887                 :            : }
        1888                 :            :
        1889                 :            : static PyObject *
        1890                 :          4 : POINTER(PyObject *self, PyObject *cls)
        1891                 :            : {
        1892                 :            :     PyObject *result;
        1893                 :            :     PyTypeObject *typ;
        1894                 :            :     PyObject *key;
        1895                 :            :
        1896                 :          4 :     result = PyDict_GetItemWithError(_ctypes_ptrtype_cache, cls);
        1897         [ -  + ]:          4 :     if (result) {
        1898                 :          0 :         return Py_NewRef(result);
        1899                 :            :     }
        1900         [ -  + ]:          4 :     else if (PyErr_Occurred()) {
        1901                 :          0 :         return NULL;
        1902                 :            :     }
        1903         [ -  + ]:          4 :     if (PyUnicode_CheckExact(cls)) {
        1904                 :          0 :         PyObject *name = PyUnicode_FromFormat("LP_%U", cls);
        1905                 :          0 :         result = PyObject_CallFunction((PyObject *)Py_TYPE(&PyCPointer_Type),
        1906                 :            :                                        "N(O){}",
        1907                 :            :                                        name,
        1908                 :            :                                        &PyCPointer_Type);
        1909         [ #  # ]:          0 :         if (result == NULL)
        1910                 :          0 :             return result;
        1911                 :          0 :         key = PyLong_FromVoidPtr(result);
        1912         [ #  # ]:          0 :         if (key == NULL) {
        1913                 :          0 :             Py_DECREF(result);
        1914                 :          0 :             return NULL;
        1915                 :            :         }
        1916         [ +  - ]:          4 :     } else if (PyType_Check(cls)) {
        1917                 :          4 :         typ = (PyTypeObject *)cls;
        1918                 :          4 :         PyObject *name = PyUnicode_FromFormat("LP_%s", typ->tp_name);
        1919                 :          4 :         result = PyObject_CallFunction((PyObject *)Py_TYPE(&PyCPointer_Type),
        1920                 :            :                                        "N(O){sO}",
        1921                 :            :                                        name,
        1922                 :            :                                        &PyCPointer_Type,
        1923                 :            :                                        "_type_", cls);
        1924         [ -  + ]:          4 :         if (result == NULL)
        1925                 :          0 :             return result;
        1926                 :          4 :         key = Py_NewRef(cls);
        1927                 :            :     } else {
        1928                 :          0 :         PyErr_SetString(PyExc_TypeError, "must be a ctypes type");
        1929                 :          0 :         return NULL;
        1930                 :            :     }
        1931         [ -  + ]:          4 :     if (-1 == PyDict_SetItem(_ctypes_ptrtype_cache, key, result)) {
        1932                 :          0 :         Py_DECREF(result);
        1933                 :          0 :         Py_DECREF(key);
        1934                 :          0 :         return NULL;
        1935                 :            :     }
        1936                 :          4 :     Py_DECREF(key);
        1937                 :          4 :     return result;
        1938                 :            : }
        1939                 :            :
        1940                 :            : static PyObject *
        1941                 :          0 : pointer(PyObject *self, PyObject *arg)
        1942                 :            : {
        1943                 :            :     PyObject *result;
        1944                 :            :     PyObject *typ;
        1945                 :            :
        1946                 :          0 :     typ = PyDict_GetItemWithError(_ctypes_ptrtype_cache, (PyObject *)Py_TYPE(arg));
        1947         [ #  # ]:          0 :     if (typ) {
        1948                 :          0 :         return PyObject_CallOneArg(typ, arg);
        1949                 :            :     }
        1950         [ #  # ]:          0 :     else if (PyErr_Occurred()) {
        1951                 :          0 :         return NULL;
        1952                 :            :     }
        1953                 :          0 :     typ = POINTER(NULL, (PyObject *)Py_TYPE(arg));
        1954         [ #  # ]:          0 :     if (typ == NULL)
        1955                 :          0 :         return NULL;
        1956                 :          0 :     result = PyObject_CallOneArg(typ, arg);
        1957                 :          0 :     Py_DECREF(typ);
        1958                 :          0 :     return result;
        1959                 :            : }
        1960                 :            :
        1961                 :            : static PyObject *
        1962                 :          0 : buffer_info(PyObject *self, PyObject *arg)
        1963                 :            : {
        1964                 :          0 :     StgDictObject *dict = PyType_stgdict(arg);
        1965                 :            :     PyObject *shape;
        1966                 :            :     Py_ssize_t i;
        1967                 :            :
        1968         [ #  # ]:          0 :     if (dict == NULL)
        1969                 :          0 :         dict = PyObject_stgdict(arg);
        1970         [ #  # ]:          0 :     if (dict == NULL) {
        1971                 :          0 :         PyErr_SetString(PyExc_TypeError,
        1972                 :            :                         "not a ctypes type or object");
        1973                 :          0 :         return NULL;
        1974                 :            :     }
        1975                 :          0 :     shape = PyTuple_New(dict->ndim);
        1976         [ #  # ]:          0 :     if (shape == NULL)
        1977                 :          0 :         return NULL;
        1978         [ #  # ]:          0 :     for (i = 0; i < (int)dict->ndim; ++i)
        1979                 :          0 :         PyTuple_SET_ITEM(shape, i, PyLong_FromSsize_t(dict->shape[i]));
        1980                 :            :
        1981         [ #  # ]:          0 :     if (PyErr_Occurred()) {
        1982                 :          0 :         Py_DECREF(shape);
        1983                 :          0 :         return NULL;
        1984                 :            :     }
        1985                 :          0 :     return Py_BuildValue("siN", dict->format, dict->ndim, shape);
        1986                 :            : }
        1987                 :            :
        1988                 :            :
        1989                 :            :
        1990                 :            : PyMethodDef _ctypes_module_methods[] = {
        1991                 :            :     {"get_errno", get_errno, METH_NOARGS},
        1992                 :            :     {"set_errno", set_errno, METH_VARARGS},
        1993                 :            :     {"POINTER", POINTER, METH_O },
        1994                 :            :     {"pointer", pointer, METH_O },
        1995                 :            :     {"_unpickle", unpickle, METH_VARARGS },
        1996                 :            :     {"buffer_info", buffer_info, METH_O, "Return buffer interface information"},
        1997                 :            :     {"resize", resize, METH_VARARGS, "Resize the memory buffer of a ctypes instance"},
        1998                 :            : #ifdef MS_WIN32
        1999                 :            :     {"get_last_error", get_last_error, METH_NOARGS},
        2000                 :            :     {"set_last_error", set_last_error, METH_VARARGS},
        2001                 :            :     {"CopyComPointer", copy_com_pointer, METH_VARARGS, copy_com_pointer_doc},
        2002                 :            :     {"FormatError", format_error, METH_VARARGS, format_error_doc},
        2003                 :            :     {"LoadLibrary", load_library, METH_VARARGS, load_library_doc},
        2004                 :            :     {"FreeLibrary", free_library, METH_VARARGS, free_library_doc},
        2005                 :            :     {"_check_HRESULT", check_hresult, METH_VARARGS},
        2006                 :            : #else
        2007                 :            :     {"dlopen", py_dl_open, METH_VARARGS,
        2008                 :            :      "dlopen(name, flag={RTLD_GLOBAL|RTLD_LOCAL}) open a shared library"},
        2009                 :            :     {"dlclose", py_dl_close, METH_VARARGS, "dlclose a library"},
        2010                 :            :     {"dlsym", py_dl_sym, METH_VARARGS, "find symbol in shared library"},
        2011                 :            : #endif
        2012                 :            : #ifdef __APPLE__
        2013                 :            :      {"_dyld_shared_cache_contains_path", py_dyld_shared_cache_contains_path, METH_VARARGS, "check if path is in the shared cache"},
        2014                 :            : #endif
        2015                 :            :     {"alignment", align_func, METH_O, alignment_doc},
        2016                 :            :     {"sizeof", sizeof_func, METH_O, sizeof_doc},
        2017                 :            :     {"byref", byref, METH_VARARGS, byref_doc},
        2018                 :            :     {"addressof", addressof, METH_O, addressof_doc},
        2019                 :            :     {"call_function", call_function, METH_VARARGS },
        2020                 :            :     {"call_cdeclfunction", call_cdeclfunction, METH_VARARGS },
        2021                 :            :     {"PyObj_FromPtr", My_PyObj_FromPtr, METH_VARARGS },
        2022                 :            :     {"Py_INCREF", My_Py_INCREF, METH_O },
        2023                 :            :     {"Py_DECREF", My_Py_DECREF, METH_O },
        2024                 :            :     {NULL,      NULL}        /* Sentinel */
        2025                 :            : };
        2026                 :            :
        2027                 :            : /*
        2028                 :            :  Local Variables:
        2029                 :            :  compile-command: "cd .. && python setup.py -q build -g && python setup.py -q build install --home ~"
        2030                 :            :  End:
        2031                 :            : */

Generated by: LCOV version 1.14