[pywin32-checkins] /hgroot/pywin32/pywin32: IDispatch failures will try and get err...
OLD project page for the Python extensions for Windows
Brought to you by:
mhammond
From: <pyw...@li...> - 2016-04-16 03:53:56
|
changeset fac37b1e89a7 in /hgroot/pywin32/pywin32 details: http://pywin32.hg.sourceforge.net/hgweb/pywin32/pywin32/hgroot/pywin32/pywin32?cmd=changeset;node=fac37b1e89a7 summary: IDispatch failures will try and get error information via IErrorInfo (Stefan Schukat via patch #130) diffstat: CHANGES.txt | 3 + com/win32com/src/PyIDispatch.cpp | 78 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 76 insertions(+), 5 deletions(-) diffs (129 lines): diff -r cc08f2559b15 -r fac37b1e89a7 CHANGES.txt --- a/CHANGES.txt Thu Oct 22 08:54:40 2015 -0700 +++ b/CHANGES.txt Sat Apr 16 13:53:01 2016 +1000 @@ -6,6 +6,9 @@ Since build 220: ---------------- +* IDispatch failures will try and get error information via IErrorInfo (Stefan + Schukat via patch #130) + * A null SPropTagArray will now return None instead of crashing. * New mapi/exchange interfaces PyIExchangeManageStoreEx, PyIMAPIAdviseSink, diff -r cc08f2559b15 -r fac37b1e89a7 com/win32com/src/PyIDispatch.cpp --- a/com/win32com/src/PyIDispatch.cpp Thu Oct 22 08:54:40 2015 -0700 +++ b/com/win32com/src/PyIDispatch.cpp Sat Apr 16 13:53:01 2016 +1000 @@ -4,7 +4,69 @@ #include "stdafx.h" #include "PythonCOM.h" -static BOOL HandledDispatchFailure(HRESULT hr, EXCEPINFO *einfo, UINT nArgErr, UINT cArgs) +// Check if IDispatch implementation transports via IErrorInfo instead of +// EXCEPINFO +static BOOL ExcepInfoFromIErrorInfo(EXCEPINFO *einfo, IDispatch* pDisp, HRESULT scode) +{ + if (NULL == einfo || pDisp == NULL) { + return FALSE; + } + ISupportErrorInfo *pSEI; + HRESULT hr; + Py_BEGIN_ALLOW_THREADS + hr = pDisp->QueryInterface(IID_ISupportErrorInfo, (void **)&pSEI); + if (SUCCEEDED(hr)) { + hr = pSEI->InterfaceSupportsErrorInfo(IID_IDispatch); + pSEI->Release(); // Finished with this object + } + Py_END_ALLOW_THREADS + + // InterfaceSupportsErrorInfo returning S_FALSE means we should ignore it. + if (FAILED(hr) || hr == S_FALSE) { + return FALSE; + } + + // ErrorInfo via IErrorInfo hence transform to EXCEPINFO + IErrorInfo *pEI; + Py_BEGIN_ALLOW_THREADS + hr=GetErrorInfo(0, &pEI); + Py_END_ALLOW_THREADS + + if (hr!=S_OK) { + return FALSE; + } + // These strings will be freed when PyCom_CleanupExcepInfo is called + // by our caller. + BSTR desc = NULL; + BSTR source = NULL; + BSTR helpfile = NULL; + + Py_BEGIN_ALLOW_THREADS + hr=pEI->GetDescription(&desc); + if (hr==S_OK) { + einfo->bstrDescription = desc; + } + hr=pEI->GetSource(&source); + if (hr==S_OK) { + einfo->bstrSource = source; + } + hr=pEI->GetHelpFile(&helpfile); + if (hr==S_OK) { + einfo->bstrHelpFile = helpfile; + } + DWORD helpContext = 0; + hr = pEI->GetHelpContext(&helpContext); + if (hr==S_OK) { + einfo->dwHelpContext = helpContext; + } + einfo->wCode = 0; + einfo->scode = scode; + Py_END_ALLOW_THREADS + PYCOM_RELEASE(pEI); + return TRUE; +} + +static BOOL HandledDispatchFailure(HRESULT hr, EXCEPINFO *einfo, UINT nArgErr, UINT cArgs, IDispatch *pDisp) { if ( hr == DISP_E_EXCEPTION ) { @@ -23,7 +85,13 @@ nArgErr =(UINT)-1; else nArgErr = cArgs - nArgErr; /* convert to usable index */ - PyCom_BuildPyExceptionFromEXCEPINFO(hr, NULL, nArgErr); + // See if we can fill the EXCEPINFO via IErrorInfo. + if(ExcepInfoFromIErrorInfo(einfo, pDisp, hr)) { + PyCom_BuildPyExceptionFromEXCEPINFO(hr, einfo, nArgErr); + } else { + PyCom_BuildPyExceptionFromEXCEPINFO(hr, NULL, nArgErr); + } + return TRUE; } return FALSE; @@ -270,7 +338,7 @@ PY_INTERFACE_POSTCALL; if (!PyCom_FinishUntypedDISPPARAMS(&dispparams, helpers) || - HandledDispatchFailure(hr, &excepInfo, nArgErr, dispparams.cArgs) ) { + HandledDispatchFailure(hr, &excepInfo, nArgErr, dispparams.cArgs, pMyDispatch) ) { if ( pVarResultUse ) VariantClear(pVarResultUse); return NULL; @@ -425,7 +493,7 @@ PY_INTERFACE_POSTCALL; } - if ( !HandledDispatchFailure(hr, &excepInfo, nArgErr, dispparams.cArgs) ) + if ( !HandledDispatchFailure(hr, &excepInfo, nArgErr, dispparams.cArgs, pMyDispatch) ) { // Now get fancy with the args. Any args specified as BYREF get returned // to Python. @@ -657,7 +725,7 @@ PY_INTERFACE_POSTCALL; if (!PyCom_FinishUntypedDISPPARAMS(&dispparams, helpers) || - HandledDispatchFailure(hr, &excepInfo, (UINT)-1, dispparams.cArgs) ) { + HandledDispatchFailure(hr, &excepInfo, (UINT)-1, dispparams.cArgs, pMyDispatch) ) { if ( pVarResultUse ) VariantClear(pVarResultUse); return NULL; |