X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/d3ffaafb37c6321640aec28588940a2eda64dfd9..ccc040255c07064f2ed96f1a345d21860b202cb6:/src/msw/ole/automtn.cpp diff --git a/src/msw/ole/automtn.cpp b/src/msw/ole/automtn.cpp index db0df28fb2..369dfec16f 100644 --- a/src/msw/ole/automtn.cpp +++ b/src/msw/ole/automtn.cpp @@ -56,6 +56,8 @@ #if wxUSE_OLE_AUTOMATION +#include + // Report an OLE error when calling the specified method to the user via wxLog. static void ShowException(const wxString& member, @@ -68,6 +70,7 @@ ShowException(const wxString& member, wxAutomationObject::wxAutomationObject(WXIDISPATCH* dispatchPtr) { m_dispatchPtr = dispatchPtr; + m_lcid = LOCALE_SYSTEM_DEFAULT; } wxAutomationObject::~wxAutomationObject() @@ -79,9 +82,24 @@ wxAutomationObject::~wxAutomationObject() } } +namespace +{ + +// A simple helper that ensures that VARIANT is destroyed on scope exit. +struct wxOleVariantArg : VARIANTARG +{ + wxOleVariantArg() { VariantInit(this); } + ~wxOleVariantArg() { VariantClear(this); } +}; + +} // anonymous namespace + + #define INVOKEARG(i) (args ? args[i] : *(ptrArgs[i])) // For Put/Get, no named arguments are allowed. +// WARNING: if args contain IDispatches, their reference count will be decreased +// by one after Invoke() returns! bool wxAutomationObject::Invoke(const wxString& member, int action, wxVariant& retValue, int noArgs, wxVariant args[], const wxVariant* ptrArgs[]) const { @@ -100,23 +118,23 @@ bool wxAutomationObject::Invoke(const wxString& member, int action, return obj.Invoke(rest, action, retValue, noArgs, args, ptrArgs); } - VARIANTARG vReturn; - VariantInit(& vReturn); - - VARIANTARG* vReturnPtr = & vReturn; + wxOleVariantArg vReturn; + wxOleVariantArg* vReturnPtr = & vReturn; // Find number of names args int namedArgCount = 0; int i; for (i = 0; i < noArgs; i++) - if (!INVOKEARG(i).GetName().IsNull()) + { + if ( !INVOKEARG(i).GetName().empty() ) { namedArgCount ++; } + } int namedArgStringCount = namedArgCount + 1; - BSTR* argNames = new BSTR[namedArgStringCount]; - argNames[0] = wxConvertStringToOle(member); + wxVector argNames(namedArgStringCount, wxString()); + argNames[0] = member; // Note that arguments are specified in reverse order // (all totally logical; hey, we're dealing with OLE here.) @@ -124,15 +142,15 @@ 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()); + argNames[(namedArgCount-j)] = INVOKEARG(i).GetName(); j ++; } } // + 1 for the member name, + 1 again in case we're a 'put' - DISPID* dispIds = new DISPID[namedArgCount + 2]; + wxVector dispIds(namedArgCount + 2); HRESULT hr; DISPPARAMS dispparams; @@ -140,13 +158,14 @@ bool wxAutomationObject::Invoke(const wxString& member, int action, // Get the IDs for the member and its arguments. GetIDsOfNames expects the // member name as the first name, followed by argument names (if any). - hr = ((IDispatch*)m_dispatchPtr)->GetIDsOfNames(IID_NULL, argNames, - 1 + namedArgCount, LOCALE_SYSTEM_DEFAULT, dispIds); + hr = ((IDispatch*)m_dispatchPtr)->GetIDsOfNames(IID_NULL, + // We rely on the fact that wxBasicString is + // just BSTR with some methods here. + reinterpret_cast(&argNames[0]), + 1 + namedArgCount, m_lcid, &dispIds[0]); if (FAILED(hr)) { ShowException(member, hr); - delete[] argNames; - delete[] dispIds; return false; } @@ -160,41 +179,25 @@ bool wxAutomationObject::Invoke(const wxString& member, int action, } // Convert the wxVariants to VARIANTARGs - VARIANTARG* oleArgs = new VARIANTARG[noArgs]; + wxVector oleArgs(noArgs); for (i = 0; i < noArgs; i++) { // Again, reverse args if (!wxConvertVariantToOle(INVOKEARG((noArgs-1) - i), oleArgs[i])) - { - delete[] argNames; - delete[] dispIds; - delete[] oleArgs; return false; - } } - dispparams.rgdispidNamedArgs = dispIds + 1; - dispparams.rgvarg = oleArgs; + dispparams.rgdispidNamedArgs = &dispIds[0] + 1; + dispparams.rgvarg = oleArgs.empty() ? NULL : &oleArgs[0]; dispparams.cArgs = noArgs; dispparams.cNamedArgs = namedArgCount; EXCEPINFO excep; wxZeroMemory(excep); - hr = ((IDispatch*)m_dispatchPtr)->Invoke(dispIds[0], IID_NULL, LOCALE_SYSTEM_DEFAULT, + hr = ((IDispatch*)m_dispatchPtr)->Invoke(dispIds[0], IID_NULL, m_lcid, (WORD)action, &dispparams, vReturnPtr, &excep, &uiArgErr); - for (i = 0; i < namedArgStringCount; i++) - { - SysFreeString(argNames[i]); - } - delete[] argNames; - delete[] dispIds; - - for (i = 0; i < noArgs; i++) - VariantClear(& oleArgs[i]) ; - delete[] oleArgs; - if (FAILED(hr)) { // display the exception information if appropriate: @@ -205,8 +208,6 @@ bool wxAutomationObject::Invoke(const wxString& member, int action, SysFreeString(excep.bstrDescription); SysFreeString(excep.bstrHelpFile); - if (vReturnPtr) - VariantClear(vReturnPtr); return false; } else @@ -214,13 +215,19 @@ bool wxAutomationObject::Invoke(const wxString& member, int action, if (vReturnPtr) { // Convert result to wxVariant form - wxConvertOleToVariant(vReturn, retValue); + if (!wxConvertOleToVariant(vReturn, retValue)) + return false; // Mustn't release the dispatch pointer if (vReturn.vt == VT_DISPATCH) { vReturn.pdispVal = NULL; } - VariantClear(& vReturn); + // Mustn't free the SAFEARRAY if it is contained in the retValue + if ((vReturn.vt & VT_ARRAY) && + retValue.GetType() == wxS("safearray")) + { + vReturn.parray = NULL; + } } } return true; @@ -467,6 +474,7 @@ bool wxAutomationObject::GetObject(wxAutomationObject& obj, const wxString& prop if (dispatch) { obj.SetDispatchPtr(dispatch); + obj.SetLCID(GetLCID()); return true; } else @@ -480,6 +488,7 @@ bool wxAutomationObject::GetObject(wxAutomationObject& obj, const wxString& prop if (dispatch) { obj.SetDispatchPtr(dispatch); + obj.SetLCID(GetLCID()); return true; } else @@ -545,8 +554,15 @@ bool wxAutomationObject::GetInstance(const wxString& progId, int flags) const } else { - wxLogSysError(hr, - _("Cannot get an active instance of \"%s\""), progId); + // 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; @@ -582,6 +598,16 @@ bool wxAutomationObject::CreateInstance(const wxString& progId) const return m_dispatchPtr != NULL; } +LCID wxAutomationObject::GetLCID() const +{ + return m_lcid; +} + +void wxAutomationObject::SetLCID(LCID lcid) +{ + m_lcid = lcid; +} + static void ShowException(const wxString& member, HRESULT hr,