LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/python3/Modules/_ctypes - callproc.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 497 0.0 %
Date: 2012-12-17 Functions: 0 34 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10