X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a2fd865b0dc2abc2ae04811cbd88c90a146c9e4f..eea4d01c65f9b29baa1193db762b4c6b8144af24:/src/msw/ole/automtn.cpp diff --git a/src/msw/ole/automtn.cpp b/src/msw/ole/automtn.cpp index 04f367675d..12a46ffcad 100644 --- a/src/msw/ole/automtn.cpp +++ b/src/msw/ole/automtn.cpp @@ -54,15 +54,16 @@ #include "wx/datetime.h" #endif // wxUSE_DATETIME -extern void wxClearVariant(VARIANTARG *pvarg) ; -extern void wxReleaseVariant(VARIANTARG *pvarg) ; -// static void ShowException(LPOLESTR szMember, HRESULT hr, EXCEPINFO *pexcep, unsigned int uiArgErr); - #if wxUSE_OLE_AUTOMATION -/* - * wxAutomationObject - */ +// Report an OLE error when calling the specified method to the user via wxLog. +static void +ShowException(const wxString& member, + HRESULT hr, + EXCEPINFO *pexcep = NULL, + unsigned int uiArgErr = 0); + +// wxAutomationObject wxAutomationObject::wxAutomationObject(WXIDISPATCH* dispatchPtr) { @@ -87,15 +88,12 @@ bool wxAutomationObject::Invoke(const wxString& member, int action, if (!m_dispatchPtr) return false; - // nonConstMember is necessary because the wxString class doesn't have enough consts... - wxString nonConstMember(member); - - int ch = nonConstMember.Find('.'); + int ch = member.Find('.'); if (ch != -1) { // Use dot notation to get the next object - wxString member2(nonConstMember.Left((size_t) ch)); - wxString rest(nonConstMember.Right(nonConstMember.length() - ch - 1)); + wxString member2(member.Left((size_t) ch)); + wxString rest(member.Right(member.length() - ch - 1)); wxAutomationObject obj; if (!GetObject(obj, member2)) return false; @@ -103,7 +101,7 @@ bool wxAutomationObject::Invoke(const wxString& member, int action, } VARIANTARG vReturn; - wxClearVariant(& vReturn); + VariantInit(& vReturn); VARIANTARG* vReturnPtr = & vReturn; @@ -111,7 +109,7 @@ bool wxAutomationObject::Invoke(const wxString& member, int action, int namedArgCount = 0; int i; for (i = 0; i < noArgs; i++) - if (!INVOKEARG(i).GetName().IsNull()) + if ( !INVOKEARG(i).GetName().empty() ) { namedArgCount ++; } @@ -126,7 +124,7 @@ bool wxAutomationObject::Invoke(const wxString& member, int action, int j = 0; for (i = 0; i < namedArgCount; i++) { - if (!INVOKEARG(i).GetName().IsNull()) + if ( !INVOKEARG(i).GetName().empty() ) { argNames[(namedArgCount-j)] = wxConvertStringToOle(INVOKEARG(i).GetName()); j ++; @@ -146,7 +144,7 @@ bool wxAutomationObject::Invoke(const wxString& member, int action, 1 + namedArgCount, LOCALE_SYSTEM_DEFAULT, dispIds); if (FAILED(hr)) { -// ShowException(szMember, hr, NULL, 0); + ShowException(member, hr); delete[] argNames; delete[] dispIds; return false; @@ -194,13 +192,13 @@ bool wxAutomationObject::Invoke(const wxString& member, int action, delete[] dispIds; for (i = 0; i < noArgs; i++) - wxReleaseVariant(& oleArgs[i]) ; + VariantClear(& oleArgs[i]) ; delete[] oleArgs; if (FAILED(hr)) { // display the exception information if appropriate: -// ShowException((const char*) member, hr, &excep, uiArgErr); + ShowException(member, hr, &excep, uiArgErr); // free exception structure information SysFreeString(excep.bstrSource); @@ -208,7 +206,7 @@ bool wxAutomationObject::Invoke(const wxString& member, int action, SysFreeString(excep.bstrHelpFile); if (vReturnPtr) - wxReleaseVariant(vReturnPtr); + VariantClear(vReturnPtr); return false; } else @@ -222,7 +220,7 @@ bool wxAutomationObject::Invoke(const wxString& member, int action, { vReturn.pdispVal = NULL; } - wxReleaseVariant(& vReturn); + VariantClear(& vReturn); } } return true; @@ -488,33 +486,85 @@ bool wxAutomationObject::GetObject(wxAutomationObject& obj, const wxString& prop return false; } +namespace +{ + +HRESULT wxCLSIDFromProgID(const wxString& progId, CLSID& clsId) +{ + HRESULT hr = CLSIDFromProgID(wxBasicString(progId), &clsId); + if ( FAILED(hr) ) + { + wxLogSysError(hr, _("Failed to find CLSID of \"%s\""), progId); + } + return hr; +} + +void *DoCreateInstance(const wxString& progId, const CLSID& clsId) +{ + // get the server IDispatch interface + // + // NB: using CLSCTX_INPROC_HANDLER results in failure when getting + // Automation interface for Microsoft Office applications so don't use + // CLSCTX_ALL which includes it + void *pDispatch = NULL; + HRESULT hr = CoCreateInstance(clsId, NULL, CLSCTX_SERVER, + IID_IDispatch, &pDispatch); + if (FAILED(hr)) + { + wxLogSysError(hr, _("Failed to create an instance of \"%s\""), progId); + return NULL; + } + + return pDispatch; +} + +} // anonymous namespace + // Get a dispatch pointer from the current object associated -// with a class id -bool wxAutomationObject::GetInstance(const wxString& classId) const +// with a ProgID +bool wxAutomationObject::GetInstance(const wxString& progId, int flags) const { if (m_dispatchPtr) return false; CLSID clsId; - IUnknown * pUnk = NULL; - - wxBasicString unicodeName(classId); - - if (FAILED(CLSIDFromProgID((BSTR) unicodeName, &clsId))) - { - wxLogWarning(wxT("Cannot obtain CLSID from ProgID")); + HRESULT hr = wxCLSIDFromProgID(progId, clsId); + if (FAILED(hr)) return false; - } - if (FAILED(GetActiveObject(clsId, NULL, &pUnk))) + IUnknown *pUnk = NULL; + hr = GetActiveObject(clsId, NULL, &pUnk); + if (FAILED(hr)) { - wxLogWarning(wxT("Cannot find an active object")); + if ( flags & wxAutomationInstance_CreateIfNeeded ) + { + const_cast(this)-> + m_dispatchPtr = DoCreateInstance(progId, clsId); + if ( m_dispatchPtr ) + return true; + } + else + { + // Log an error except if we're supposed to fail silently when the + // error is that no current instance exists. + if ( hr != MK_E_UNAVAILABLE || + !(flags & wxAutomationInstance_SilentIfNone) ) + { + wxLogSysError(hr, + _("Cannot get an active instance of \"%s\""), + progId); + } + } + return false; } - if (pUnk->QueryInterface(IID_IDispatch, (LPVOID*) &m_dispatchPtr) != S_OK) + hr = pUnk->QueryInterface(IID_IDispatch, (LPVOID*) &m_dispatchPtr); + if (FAILED(hr)) { - wxLogWarning(wxT("Cannot find IDispatch interface")); + wxLogSysError(hr, + _("Failed to get OLE automation interface for \"%s\""), + progId); return false; } @@ -522,98 +572,95 @@ bool wxAutomationObject::GetInstance(const wxString& classId) const } // Get a dispatch pointer from a new object associated -// with the given class id -bool wxAutomationObject::CreateInstance(const wxString& classId) const +// with the given ProgID +bool wxAutomationObject::CreateInstance(const wxString& progId) const { if (m_dispatchPtr) return false; CLSID clsId; - - wxBasicString unicodeName(classId); - - if (FAILED(CLSIDFromProgID((BSTR) unicodeName, &clsId))) - { - wxLogWarning(wxT("Cannot obtain CLSID from ProgID")); + HRESULT hr = wxCLSIDFromProgID(progId, clsId); + if (FAILED(hr)) return false; - } - // get the server IDispatch interface - // - // NB: using CLSCTX_INPROC_HANDLER results in failure when getting - // Automation interface for Microsoft Office applications so don't use - // CLSCTX_ALL which includes it - if (FAILED(CoCreateInstance(clsId, NULL, CLSCTX_SERVER, IID_IDispatch, - (void**)&m_dispatchPtr))) - { - wxLogWarning(wxT("Cannot start an instance of this class.")); - return false; - } + const_cast(this)-> + m_dispatchPtr = DoCreateInstance(progId, clsId); - return true; + return m_dispatchPtr != NULL; } -#endif // wxUSE_OLE_AUTOMATION - -#if 0 - -void ShowException(LPOLESTR szMember, HRESULT hr, EXCEPINFO *pexcep, unsigned int uiArgErr) +static void +ShowException(const wxString& member, + HRESULT hr, + EXCEPINFO *pexcep, + unsigned int uiArgErr) { - TCHAR szBuf[512]; - + wxString message; switch (GetScode(hr)) { case DISP_E_UNKNOWNNAME: - wsprintf(szBuf, L"%s: Unknown name or named argument.", szMember); + message = _("Unknown name or named argument."); break; case DISP_E_BADPARAMCOUNT: - wsprintf(szBuf, L"%s: Incorrect number of arguments.", szMember); + message = _("Incorrect number of arguments."); break; case DISP_E_EXCEPTION: - wsprintf(szBuf, L"%s: Error %d: ", szMember, pexcep->wCode); - if (pexcep->bstrDescription != NULL) - lstrcat(szBuf, pexcep->bstrDescription); + if ( pexcep ) + { + if ( pexcep->bstrDescription ) + message << pexcep->bstrDescription << wxS(" "); + message += wxString::Format(wxS("error code %u"), pexcep->wCode); + } else - lstrcat(szBuf, L"<>"); + { + message = _("Unknown exception"); + } break; case DISP_E_MEMBERNOTFOUND: - wsprintf(szBuf, L"%s: method or property not found.", szMember); + message = _("Method or property not found."); break; case DISP_E_OVERFLOW: - wsprintf(szBuf, L"%s: Overflow while coercing argument values.", szMember); + message = _("Overflow while coercing argument values."); break; case DISP_E_NONAMEDARGS: - wsprintf(szBuf, L"%s: Object implementation does not support named arguments.", - szMember); + message = _("Object implementation does not support named arguments."); break; case DISP_E_UNKNOWNLCID: - wsprintf(szBuf, L"%s: The locale ID is unknown.", szMember); + message = _("The locale ID is unknown."); break; case DISP_E_PARAMNOTOPTIONAL: - wsprintf(szBuf, L"%s: Missing a required parameter.", szMember); + message = _("Missing a required parameter."); break; case DISP_E_PARAMNOTFOUND: - wsprintf(szBuf, L"%s: Argument not found, argument %d.", szMember, uiArgErr); + message.Printf(_("Argument %u not found."), uiArgErr); break; case DISP_E_TYPEMISMATCH: - wsprintf(szBuf, L"%s: Type mismatch, argument %d.", szMember, uiArgErr); + message.Printf(_("Type mismatch in argument %u."), uiArgErr); + break; + + case ERROR_FILE_NOT_FOUND: + message = _("The system cannot find the file specified."); + break; + + case REGDB_E_CLASSNOTREG: + message = _("Class not registered."); break; default: - wsprintf(szBuf, L"%s: Unknown error occurred.", szMember); + message.Printf(_("Unknown error %08x"), hr); break; } - wxLogWarning(szBuf); + wxLogError(_("OLE Automation error in %s: %s"), member, message); } -#endif +#endif // wxUSE_OLE_AUTOMATION