From: Roger U. <ru...@us...> - 2007-02-17 07:30:24
|
Update of /cvsroot/pywin32/pywin32/win32/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv22320/win32/src Modified Files: PyWinTypes.h PyWinTypesmodule.cpp Log Message: Add functions to convert void pointers and resource ids Index: PyWinTypesmodule.cpp =================================================================== RCS file: /cvsroot/pywin32/pywin32/win32/src/PyWinTypesmodule.cpp,v retrieving revision 1.24 retrieving revision 1.25 diff -C2 -d -r1.24 -r1.25 *** PyWinTypesmodule.cpp 4 Feb 2007 22:11:11 -0000 1.24 --- PyWinTypesmodule.cpp 17 Feb 2007 07:30:16 -0000 1.25 *************** *** 285,289 **** } /* strip trailing cr/lf */ ! int end = _tcslen(buf)-1; if (end>1 && (buf[end-1]==_T('\n') || buf[end-1]==_T('\r'))) buf[end-1] = _T('\0'); --- 285,289 ---- } /* strip trailing cr/lf */ ! size_t end = _tcslen(buf)-1; if (end>1 && (buf[end-1]==_T('\n') || buf[end-1]==_T('\r'))) buf[end-1] = _T('\0'); *************** *** 516,519 **** --- 516,617 ---- } + /* + PyLong_AsVoidPtr is unsuitable for use in many places due to the following issues: + + 1. It fails to convert some types. On 32-bit, it calls PyLong_AsLong + which doesn't check if the type has number methods defined (tp_as_number). + This causes it to fail for PyHANDLE's. + However, it doesn't even fail consistently since on 64-bit it uses + PyLong_AsLongLong which does check tp_as_number. + + 2. When it fails to convert an object (even one for which it should succeed!) + it uses PyErr_BadInternalCall which returns a vague and misleading error. + + 3. The documentation says it's only guaranteed to work for objects created using + PyLong_FromVoidPtr. However, there's no way to call this from the + interpreter which means that places which can also accept a plain number + as well as an address have no way to ensure that both will be converted + consistently. Additionally, PyLong_FromVoidPtr just returns a python int or + long so there is actually no way to verify that an object was created using + that function and can be converted back to a usable address. + + From the response to this bug report: + http://sourceforge.net/tracker/?func=detail&atid=105470&aid=1630863&group_id=5470 + apparently if you want any reasonable or consistent behaviour from this function + you're expected to perform the type checking yourself first. + And if you have to do all that, why use the damn function at all ? + Accordingly, here is our own version. + */ + BOOL PyWinLong_AsVoidPtr(PyObject *ob, void **pptr) + { + #ifdef _WIN64 + *pptr=(void *)PyLong_AsLongLong(ob); + #else + *pptr=(void *)PyInt_AsLong(ob); + #endif + if (*pptr==(void *)-1 && PyErr_Occurred()){ + PyErr_Format(PyExc_TypeError,"Unable to convert %s to pointer-sized value", ob->ob_type->tp_name); + return FALSE; + } + return TRUE; + } + + PyObject *PyWinLong_FromVoidPtr(void *ptr) + { + #ifdef _WIN64 + return PyLong_FromLongLong((LONG_PTR)ptr); + #else + return PyInt_FromLong((LONG_PTR)ptr); + #endif + } + + + // @object PyResourceId|Identifies a resource or function in a module. + // This can be a WORD-sized integer value (0-65536), or string/unicode + // depending on whether the *A or *W API function is to be called. + // Class atoms as used with <om win32gui.CreateWindow> are also treated + // as resource ids since they can also be represented by a name or WORD id. + // When passing resource names and types as strings, they are usually formatted + // as a pound sign followed by decimal form of the id. ('#42' for example) + BOOL PyWinObject_AsResourceIdA(PyObject *ob, char **presource_id) + { + // Plain character conversion + if (PyWinObject_AsString(ob, presource_id)) + return TRUE; + PyErr_Clear(); + if (PyWinLong_AsVoidPtr(ob, (void **)presource_id) && IS_INTRESOURCE(*presource_id)) + return TRUE; + *presource_id=NULL; + PyErr_SetString(PyExc_TypeError, "Resource id/name must be string or int in the range 0-65536"); + return FALSE; + } + + BOOL PyWinObject_AsResourceIdW(PyObject *ob, WCHAR **presource_id) + { + // Unicode version of above + if (PyWinObject_AsWCHAR(ob, presource_id)) + return TRUE; + PyErr_Clear(); + if (PyWinLong_AsVoidPtr(ob, (void **)presource_id) && IS_INTRESOURCE(*presource_id)) + return TRUE; + *presource_id=NULL; + PyErr_SetString(PyExc_TypeError, "Resource id/name must be unicode or int in the range 0-65536"); + return FALSE; + } + + // PyWinObject_FreeString is overloaded to accept either char * or WCHAR * + void PyWinObject_FreeResourceId(char *resource_id) + { + if ((resource_id!=NULL) && !IS_INTRESOURCE(resource_id)) + PyWinObject_FreeString(resource_id); + } + + void PyWinObject_FreeResourceId(WCHAR *resource_id) + { + if ((resource_id!=NULL) && !IS_INTRESOURCE(resource_id)) + PyWinObject_FreeString(resource_id); + } + + /* List of functions exported by this module */ // @module pywintypes|A module which supports common Windows types. Index: PyWinTypes.h =================================================================== RCS file: /cvsroot/pywin32/pywin32/win32/src/PyWinTypes.h,v retrieving revision 1.32 retrieving revision 1.33 diff -C2 -d -r1.32 -r1.33 *** PyWinTypes.h 11 Jan 2007 13:13:48 -0000 1.32 --- PyWinTypes.h 17 Feb 2007 07:30:16 -0000 1.33 *************** *** 326,329 **** --- 326,344 ---- PYWINTYPES_EXPORT BOOL PyWinObject_AsDWORDArray(PyObject *obdwords, DWORD **pdwords, DWORD *item_cnt, BOOL bNoneOk=TRUE); + // Substitute for Python's inconsistent PyLong_AsVoidPtr + PYWINTYPES_EXPORT BOOL PyWinLong_AsVoidPtr(PyObject *ob, void **pptr); + PYWINTYPES_EXPORT PyObject *PyWinLong_FromVoidPtr(void *ptr); + + // Conversion for resource id/name and class atom + PYWINTYPES_EXPORT BOOL PyWinObject_AsResourceIdA(PyObject *ob, char **presource_id); + PYWINTYPES_EXPORT BOOL PyWinObject_AsResourceIdW(PyObject *ob, WCHAR **presource_id); + PYWINTYPES_EXPORT void PyWinObject_FreeResourceId(char *resource_id); + PYWINTYPES_EXPORT void PyWinObject_FreeResourceId(WCHAR *resource_id); + #ifdef UNICODE + #define PyWinObject_AsResourceId PyWinObject_AsResourceIdW + #else + #define PyWinObject_AsResourceId PyWinObject_AsResourceIdA + #endif + /* ** SECURITY_ATTRIBUTES support |