X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/6b12494db92e3b1d5425a5156551838b323d555a..6686fbad16ec929f33cbbcc1b638bf00406218c5:/src/msw/ole/automtn.cpp diff --git a/src/msw/ole/automtn.cpp b/src/msw/ole/automtn.cpp index d0185644ae..db0df28fb2 100644 --- a/src/msw/ole/automtn.cpp +++ b/src/msw/ole/automtn.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: automtn.cpp +// Name: src/msw/ole/automtn.cpp // Purpose: OLE automation utilities // Author: Julian Smart // Modified by: @@ -9,31 +9,29 @@ // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) -#pragma implementation "automtn.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #if defined(__BORLANDC__) -#pragma hdrstop + #pragma hdrstop #endif -#include "wx/defs.h" - -// Watcom C++ gives a linker error if this is compiled in. // With Borland C++, all samples crash if this is compiled in. -#if wxUSE_OLE && !(defined(__BORLANDC__) && (__BORLANDC__ < 0x520)) && !defined(__CYGWIN10__) +#if (defined(__BORLANDC__) && (__BORLANDC__ < 0x520)) || defined(__CYGWIN10__) + #undef wxUSE_OLE_AUTOMATION + #define wxUSE_OLE_AUTOMATION 0 +#endif + +#ifndef WX_PRECOMP + #include "wx/log.h" + #include "wx/math.h" +#endif #define _FORCENAMELESSUNION -#include "wx/log.h" #include "wx/msw/private.h" #include "wx/msw/ole/oleutils.h" #include "wx/msw/ole/automtn.h" -#include - #ifdef __WXWINCE__ #include "wx/msw/wince/time.h" #else @@ -52,46 +50,33 @@ #include -// Verifies will fail if the needed buffer size is too large -#define MAX_TIME_BUFFER_SIZE 128 // matches that in timecore.cpp -#define MIN_DATE (-657434L) // about year 100 -#define MAX_DATE 2958465L // about year 9999 - -// Half a second, expressed in days -#define HALF_SECOND (1.0/172800.0) - -// One-based array of days in year at month start -static int rgMonthDays[13] = - {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}; - #if wxUSE_DATETIME #include "wx/datetime.h" +#endif // wxUSE_DATETIME -static BOOL OleDateFromTm(WORD wYear, WORD wMonth, WORD wDay, - WORD wHour, WORD wMinute, WORD wSecond, DATE& dtDest); -static BOOL TmFromOleDate(DATE dtSrc, struct tm& tmDest); -#endif // wxUSE_TIMEDATE +#if wxUSE_OLE_AUTOMATION -static void ClearVariant(VARIANTARG *pvarg) ; -static void ReleaseVariant(VARIANTARG *pvarg) ; -// static void ShowException(LPOLESTR szMember, HRESULT hr, EXCEPINFO *pexcep, unsigned int uiArgErr); +// 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::wxAutomationObject(WXIDISPATCH* dispatchPtr) { - m_dispatchPtr = dispatchPtr; + m_dispatchPtr = dispatchPtr; } wxAutomationObject::~wxAutomationObject() { - if (m_dispatchPtr) - { - ((IDispatch*)m_dispatchPtr)->Release(); - m_dispatchPtr = NULL; - } + if (m_dispatchPtr) + { + ((IDispatch*)m_dispatchPtr)->Release(); + m_dispatchPtr = NULL; + } } #define INVOKEARG(i) (args ? args[i] : *(ptrArgs[i])) @@ -100,344 +85,341 @@ wxAutomationObject::~wxAutomationObject() bool wxAutomationObject::Invoke(const wxString& member, int action, wxVariant& retValue, int noArgs, wxVariant args[], const wxVariant* ptrArgs[]) const { - if (!m_dispatchPtr) - return FALSE; - - // nonConstMember is necessary because the wxString class doesn't have enough consts... - wxString nonConstMember(member); - - int ch = nonConstMember.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)); - wxAutomationObject obj; - if (!GetObject(obj, member2)) - return FALSE; - return obj.Invoke(rest, action, retValue, noArgs, args, ptrArgs); - } - - VARIANTARG vReturn; - ClearVariant(& vReturn); - - VARIANTARG* vReturnPtr = & vReturn; - - // Find number of names args - int namedArgCount = 0; - int i; - for (i = 0; i < noArgs; i++) - if (!INVOKEARG(i).GetName().IsNull()) - { - namedArgCount ++; - } - - int namedArgStringCount = namedArgCount + 1; - BSTR* argNames = new BSTR[namedArgStringCount]; - argNames[0] = wxConvertStringToOle(member); - - // Note that arguments are specified in reverse order - // (all totally logical; hey, we're dealing with OLE here.) - - int j = 0; - for (i = 0; i < namedArgCount; i++) - { - if (!INVOKEARG(i).GetName().IsNull()) - { - argNames[(namedArgCount-j)] = wxConvertStringToOle(INVOKEARG(i).GetName()); - j ++; - } - } - - // + 1 for the member name, + 1 again in case we're a 'put' - DISPID* dispIds = new DISPID[namedArgCount + 2]; - - HRESULT hr; - DISPPARAMS dispparams; - unsigned int uiArgErr; - EXCEPINFO excep; - - // 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); - if (FAILED(hr)) - { -// ShowException(szMember, hr, NULL, 0); - delete[] argNames; - delete[] dispIds; - return FALSE; - } - - // if doing a property put(ref), we need to adjust the first argument to have a - // named arg of DISPID_PROPERTYPUT. - if (action & (DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF)) - { - namedArgCount = 1; - dispIds[1] = DISPID_PROPERTYPUT; - vReturnPtr = (VARIANTARG*) NULL; - } - - // Convert the wxVariants to VARIANTARGs - VARIANTARG* oleArgs = new VARIANTARG[noArgs]; - for (i = 0; i < noArgs; i++) - { - // Again, reverse args - if (!wxConvertVariantToOle(INVOKEARG((noArgs-1) - i), oleArgs[i])) + if (!m_dispatchPtr) + return false; + + int ch = member.Find('.'); + if (ch != -1) + { + // Use dot notation to get the next object + wxString member2(member.Left((size_t) ch)); + wxString rest(member.Right(member.length() - ch - 1)); + wxAutomationObject obj; + if (!GetObject(obj, member2)) + return false; + return obj.Invoke(rest, action, retValue, noArgs, args, ptrArgs); + } + + VARIANTARG vReturn; + VariantInit(& vReturn); + + VARIANTARG* vReturnPtr = & vReturn; + + // Find number of names args + int namedArgCount = 0; + int i; + for (i = 0; i < noArgs; i++) + if (!INVOKEARG(i).GetName().IsNull()) + { + namedArgCount ++; + } + + int namedArgStringCount = namedArgCount + 1; + BSTR* argNames = new BSTR[namedArgStringCount]; + argNames[0] = wxConvertStringToOle(member); + + // Note that arguments are specified in reverse order + // (all totally logical; hey, we're dealing with OLE here.) + + int j = 0; + for (i = 0; i < namedArgCount; i++) + { + if (!INVOKEARG(i).GetName().IsNull()) { - delete[] argNames; - delete[] dispIds; + argNames[(namedArgCount-j)] = wxConvertStringToOle(INVOKEARG(i).GetName()); + j ++; + } + } + + // + 1 for the member name, + 1 again in case we're a 'put' + DISPID* dispIds = new DISPID[namedArgCount + 2]; + + HRESULT hr; + DISPPARAMS dispparams; + unsigned int uiArgErr; + + // 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); + if (FAILED(hr)) + { + ShowException(member, hr); + delete[] argNames; + delete[] dispIds; + return false; + } + + // if doing a property put(ref), we need to adjust the first argument to have a + // named arg of DISPID_PROPERTYPUT. + if (action & (DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF)) + { + namedArgCount = 1; + dispIds[1] = DISPID_PROPERTYPUT; + vReturnPtr = NULL; + } + + // Convert the wxVariants to VARIANTARGs + VARIANTARG* oleArgs = new VARIANTARG[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; + return false; + } + } + + dispparams.rgdispidNamedArgs = dispIds + 1; + dispparams.rgvarg = oleArgs; + dispparams.cArgs = noArgs; + dispparams.cNamedArgs = namedArgCount; + + EXCEPINFO excep; + wxZeroMemory(excep); + + hr = ((IDispatch*)m_dispatchPtr)->Invoke(dispIds[0], IID_NULL, LOCALE_SYSTEM_DEFAULT, + (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: + ShowException(member, hr, &excep, uiArgErr); + + // free exception structure information + SysFreeString(excep.bstrSource); + SysFreeString(excep.bstrDescription); + SysFreeString(excep.bstrHelpFile); + + if (vReturnPtr) + VariantClear(vReturnPtr); + return false; + } + else + { + if (vReturnPtr) + { + // Convert result to wxVariant form + wxConvertOleToVariant(vReturn, retValue); + // Mustn't release the dispatch pointer + if (vReturn.vt == VT_DISPATCH) + { + vReturn.pdispVal = NULL; + } + VariantClear(& vReturn); } - } - - dispparams.rgdispidNamedArgs = dispIds + 1; - dispparams.rgvarg = oleArgs; - dispparams.cArgs = noArgs; - dispparams.cNamedArgs = namedArgCount; - - excep.pfnDeferredFillIn = NULL; - - hr = ((IDispatch*)m_dispatchPtr)->Invoke(dispIds[0], IID_NULL, LOCALE_SYSTEM_DEFAULT, - action, &dispparams, vReturnPtr, &excep, &uiArgErr); - - for (i = 0; i < namedArgStringCount; i++) - { - SysFreeString(argNames[i]); - } - delete[] argNames; - delete[] dispIds; - - for (i = 0; i < noArgs; i++) - ReleaseVariant(& oleArgs[i]) ; - delete[] oleArgs; - - if (FAILED(hr)) - { - // display the exception information if appropriate: -// ShowException((const char*) member, hr, &excep, uiArgErr); - - // free exception structure information - SysFreeString(excep.bstrSource); - SysFreeString(excep.bstrDescription); - SysFreeString(excep.bstrHelpFile); - - if (vReturnPtr) - ReleaseVariant(vReturnPtr); - return FALSE; - } - else - { - if (vReturnPtr) - { - // Convert result to wxVariant form - wxConvertOleToVariant(vReturn, retValue); - // Mustn't release the dispatch pointer - if (vReturn.vt == VT_DISPATCH) - { - vReturn.pdispVal = (IDispatch*) NULL; - } - ReleaseVariant(& vReturn); - } - } - return TRUE; + } + return true; } // Invoke a member function wxVariant wxAutomationObject::CallMethod(const wxString& member, int noArgs, wxVariant args[]) { - wxVariant retVariant; - if (!Invoke(member, DISPATCH_METHOD, retVariant, noArgs, args)) - { - retVariant.MakeNull(); - } - return retVariant; + wxVariant retVariant; + if (!Invoke(member, DISPATCH_METHOD, retVariant, noArgs, args)) + { + retVariant.MakeNull(); + } + return retVariant; } wxVariant wxAutomationObject::CallMethodArray(const wxString& member, int noArgs, const wxVariant **args) { - wxVariant retVariant; - if (!Invoke(member, DISPATCH_METHOD, retVariant, noArgs, NULL, args)) - { - retVariant.MakeNull(); - } - return retVariant; + wxVariant retVariant; + if (!Invoke(member, DISPATCH_METHOD, retVariant, noArgs, NULL, args)) + { + retVariant.MakeNull(); + } + return retVariant; } wxVariant wxAutomationObject::CallMethod(const wxString& member, - const wxVariant& arg1, const wxVariant& arg2, - const wxVariant& arg3, const wxVariant& arg4, - const wxVariant& arg5, const wxVariant& arg6) + const wxVariant& arg1, const wxVariant& arg2, + const wxVariant& arg3, const wxVariant& arg4, + const wxVariant& arg5, const wxVariant& arg6) { - const wxVariant** args = new const wxVariant*[6]; - int i = 0; - if (!arg1.IsNull()) - { - args[i] = & arg1; - i ++; - } - if (!arg2.IsNull()) - { - args[i] = & arg2; - i ++; - } - if (!arg3.IsNull()) - { - args[i] = & arg3; - i ++; - } - if (!arg4.IsNull()) - { - args[i] = & arg4; - i ++; - } - if (!arg5.IsNull()) - { - args[i] = & arg5; - i ++; - } - if (!arg6.IsNull()) - { - args[i] = & arg6; - i ++; - } - wxVariant retVariant; - if (!Invoke(member, DISPATCH_METHOD, retVariant, i, NULL, args)) - { - retVariant.MakeNull(); - } - delete[] args; - return retVariant; + const wxVariant** args = new const wxVariant*[6]; + int i = 0; + if (!arg1.IsNull()) + { + args[i] = & arg1; + i ++; + } + if (!arg2.IsNull()) + { + args[i] = & arg2; + i ++; + } + if (!arg3.IsNull()) + { + args[i] = & arg3; + i ++; + } + if (!arg4.IsNull()) + { + args[i] = & arg4; + i ++; + } + if (!arg5.IsNull()) + { + args[i] = & arg5; + i ++; + } + if (!arg6.IsNull()) + { + args[i] = & arg6; + i ++; + } + wxVariant retVariant; + if (!Invoke(member, DISPATCH_METHOD, retVariant, i, NULL, args)) + { + retVariant.MakeNull(); + } + delete[] args; + return retVariant; } // Get/Set property wxVariant wxAutomationObject::GetPropertyArray(const wxString& property, int noArgs, const wxVariant **args) const { - wxVariant retVariant; - if (!Invoke(property, DISPATCH_PROPERTYGET, retVariant, noArgs, NULL, args)) - { - retVariant.MakeNull(); - } - return retVariant; + wxVariant retVariant; + if (!Invoke(property, DISPATCH_PROPERTYGET, retVariant, noArgs, NULL, args)) + { + retVariant.MakeNull(); + } + return retVariant; } wxVariant wxAutomationObject::GetProperty(const wxString& property, int noArgs, wxVariant args[]) const { - wxVariant retVariant; - if (!Invoke(property, DISPATCH_PROPERTYGET, retVariant, noArgs, args)) - { - retVariant.MakeNull(); - } - return retVariant; + wxVariant retVariant; + if (!Invoke(property, DISPATCH_PROPERTYGET, retVariant, noArgs, args)) + { + retVariant.MakeNull(); + } + return retVariant; } wxVariant wxAutomationObject::GetProperty(const wxString& property, - const wxVariant& arg1, const wxVariant& arg2, - const wxVariant& arg3, const wxVariant& arg4, - const wxVariant& arg5, const wxVariant& arg6) + const wxVariant& arg1, const wxVariant& arg2, + const wxVariant& arg3, const wxVariant& arg4, + const wxVariant& arg5, const wxVariant& arg6) { - const wxVariant** args = new const wxVariant*[6]; - int i = 0; - if (!arg1.IsNull()) - { - args[i] = & arg1; - i ++; - } - if (!arg2.IsNull()) - { - args[i] = & arg2; - i ++; - } - if (!arg3.IsNull()) - { - args[i] = & arg3; - i ++; - } - if (!arg4.IsNull()) - { - args[i] = & arg4; - i ++; - } - if (!arg5.IsNull()) - { - args[i] = & arg5; - i ++; - } - if (!arg6.IsNull()) - { - args[i] = & arg6; - i ++; - } - wxVariant retVariant; - if (!Invoke(property, DISPATCH_PROPERTYGET, retVariant, i, NULL, args)) - { - retVariant.MakeNull(); - } - delete[] args; - return retVariant; + const wxVariant** args = new const wxVariant*[6]; + int i = 0; + if (!arg1.IsNull()) + { + args[i] = & arg1; + i ++; + } + if (!arg2.IsNull()) + { + args[i] = & arg2; + i ++; + } + if (!arg3.IsNull()) + { + args[i] = & arg3; + i ++; + } + if (!arg4.IsNull()) + { + args[i] = & arg4; + i ++; + } + if (!arg5.IsNull()) + { + args[i] = & arg5; + i ++; + } + if (!arg6.IsNull()) + { + args[i] = & arg6; + i ++; + } + wxVariant retVariant; + if (!Invoke(property, DISPATCH_PROPERTYGET, retVariant, i, NULL, args)) + { + retVariant.MakeNull(); + } + delete[] args; + return retVariant; } bool wxAutomationObject::PutProperty(const wxString& property, int noArgs, wxVariant args[]) { - wxVariant retVariant; - if (!Invoke(property, DISPATCH_PROPERTYPUT, retVariant, noArgs, args)) - { - return FALSE; - } - return TRUE; + wxVariant retVariant; + if (!Invoke(property, DISPATCH_PROPERTYPUT, retVariant, noArgs, args)) + { + return false; + } + return true; } bool wxAutomationObject::PutPropertyArray(const wxString& property, int noArgs, const wxVariant **args) { - wxVariant retVariant; - if (!Invoke(property, DISPATCH_PROPERTYPUT, retVariant, noArgs, NULL, args)) - { - return FALSE; - } - return TRUE; + wxVariant retVariant; + if (!Invoke(property, DISPATCH_PROPERTYPUT, retVariant, noArgs, NULL, args)) + { + return false; + } + return true; } bool wxAutomationObject::PutProperty(const wxString& property, - const wxVariant& arg1, const wxVariant& arg2, - const wxVariant& arg3, const wxVariant& arg4, - const wxVariant& arg5, const wxVariant& arg6) + const wxVariant& arg1, const wxVariant& arg2, + const wxVariant& arg3, const wxVariant& arg4, + const wxVariant& arg5, const wxVariant& arg6) { - const wxVariant** args = new const wxVariant*[6]; - int i = 0; - if (!arg1.IsNull()) - { - args[i] = & arg1; - i ++; - } - if (!arg2.IsNull()) - { - args[i] = & arg2; - i ++; - } - if (!arg3.IsNull()) - { - args[i] = & arg3; - i ++; - } - if (!arg4.IsNull()) - { - args[i] = & arg4; - i ++; - } - if (!arg5.IsNull()) - { - args[i] = & arg5; - i ++; - } - if (!arg6.IsNull()) - { - args[i] = & arg6; - i ++; - } - wxVariant retVariant; - bool ret = Invoke(property, DISPATCH_PROPERTYPUT, retVariant, i, NULL, args); - delete[] args; - return ret; + const wxVariant** args = new const wxVariant*[6]; + int i = 0; + if (!arg1.IsNull()) + { + args[i] = & arg1; + i ++; + } + if (!arg2.IsNull()) + { + args[i] = & arg2; + i ++; + } + if (!arg3.IsNull()) + { + args[i] = & arg3; + i ++; + } + if (!arg4.IsNull()) + { + args[i] = & arg4; + i ++; + } + if (!arg5.IsNull()) + { + args[i] = & arg5; + i ++; + } + if (!arg6.IsNull()) + { + args[i] = & arg6; + i ++; + } + wxVariant retVariant; + bool ret = Invoke(property, DISPATCH_PROPERTYPUT, retVariant, i, NULL, args); + delete[] args; + return ret; } @@ -447,16 +429,16 @@ bool wxAutomationObject::PutProperty(const wxString& property, // with it and letting the destructor call Release. WXIDISPATCH* wxAutomationObject::GetDispatchProperty(const wxString& property, int noArgs, wxVariant args[]) const { - wxVariant retVariant; - if (Invoke(property, DISPATCH_PROPERTYGET, retVariant, noArgs, args)) - { - if (retVariant.GetType() == wxT("void*")) - { - return (WXIDISPATCH*) retVariant.GetVoidPtr(); - } - } - - return (WXIDISPATCH*) NULL; + wxVariant retVariant; + if (Invoke(property, DISPATCH_PROPERTYGET, retVariant, noArgs, args)) + { + if (retVariant.GetType() == wxT("void*")) + { + return (WXIDISPATCH*) retVariant.GetVoidPtr(); + } + } + + return NULL; } // Uses DISPATCH_PROPERTYGET @@ -465,798 +447,213 @@ WXIDISPATCH* wxAutomationObject::GetDispatchProperty(const wxString& property, i // with it and letting the destructor call Release. WXIDISPATCH* wxAutomationObject::GetDispatchProperty(const wxString& property, int noArgs, const wxVariant **args) const { - wxVariant retVariant; - if (Invoke(property, DISPATCH_PROPERTYGET, retVariant, noArgs, NULL, args)) - { - if (retVariant.GetType() == wxT("void*")) - { - return (WXIDISPATCH*) retVariant.GetVoidPtr(); - } - } - - return (WXIDISPATCH*) NULL; + wxVariant retVariant; + if (Invoke(property, DISPATCH_PROPERTYGET, retVariant, noArgs, NULL, args)) + { + if (retVariant.GetType() == wxT("void*")) + { + return (WXIDISPATCH*) retVariant.GetVoidPtr(); + } + } + + return NULL; } // A way of initialising another wxAutomationObject with a dispatch object bool wxAutomationObject::GetObject(wxAutomationObject& obj, const wxString& property, int noArgs, wxVariant args[]) const { - WXIDISPATCH* dispatch = GetDispatchProperty(property, noArgs, args); - if (dispatch) - { - obj.SetDispatchPtr(dispatch); - return TRUE; - } - else - return FALSE; + WXIDISPATCH* dispatch = GetDispatchProperty(property, noArgs, args); + if (dispatch) + { + obj.SetDispatchPtr(dispatch); + return true; + } + else + return false; } // A way of initialising another wxAutomationObject with a dispatch object bool wxAutomationObject::GetObject(wxAutomationObject& obj, const wxString& property, int noArgs, const wxVariant **args) const { - WXIDISPATCH* dispatch = GetDispatchProperty(property, noArgs, args); - if (dispatch) - { - obj.SetDispatchPtr(dispatch); - return TRUE; - } - else - return FALSE; + WXIDISPATCH* dispatch = GetDispatchProperty(property, noArgs, args); + if (dispatch) + { + obj.SetDispatchPtr(dispatch); + return true; + } + else + return false; } -// Get a dispatch pointer from the current object associated -// with a class id -bool wxAutomationObject::GetInstance(const wxString& classId) const +namespace { - if (m_dispatchPtr) - return FALSE; - - CLSID clsId; - IUnknown * pUnk = NULL; - - wxBasicString unicodeName(classId.mb_str()); - - if (FAILED(CLSIDFromProgID((BSTR) unicodeName, &clsId))) - { - wxLogWarning(wxT("Cannot obtain CLSID from ProgID")); - return FALSE; - } - - if (FAILED(GetActiveObject(clsId, NULL, &pUnk))) - { - wxLogWarning(wxT("Cannot find an active object")); - return FALSE; - } - - if (pUnk->QueryInterface(IID_IDispatch, (LPVOID*) &m_dispatchPtr) != S_OK) - { - wxLogWarning(wxT("Cannot find IDispatch interface")); - return FALSE; - } - - return TRUE; -} -// Get a dispatch pointer from a new object associated -// with the given class id -bool wxAutomationObject::CreateInstance(const wxString& classId) const +HRESULT wxCLSIDFromProgID(const wxString& progId, CLSID& clsId) { - if (m_dispatchPtr) - return FALSE; - - CLSID clsId; - - wxBasicString unicodeName(classId.mb_str()); - - if (FAILED(CLSIDFromProgID((BSTR) unicodeName, &clsId))) - { - wxLogWarning(wxT("Cannot obtain CLSID from ProgID")); - return FALSE; - } - - // start a new copy of Excel, grab the IDispatch interface - if (FAILED(CoCreateInstance(clsId, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void**)&m_dispatchPtr))) - { - wxLogWarning(wxT("Cannot start an instance of this class.")); - return FALSE; - } - - return TRUE; + HRESULT hr = CLSIDFromProgID(wxBasicString(progId), &clsId); + if ( FAILED(hr) ) + { + wxLogSysError(hr, _("Failed to find CLSID of \"%s\""), progId); + } + return hr; } - -bool wxConvertVariantToOle(const wxVariant& variant, VARIANTARG& oleVariant) +void *DoCreateInstance(const wxString& progId, const CLSID& clsId) { - ClearVariant(&oleVariant); - if (variant.IsNull()) - { - oleVariant.vt = VT_NULL; - return TRUE; - } - - wxString type(variant.GetType()); - - - if (type == wxT("long")) + // 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)) { - oleVariant.vt = VT_I4; - oleVariant.lVal = variant.GetLong() ; + wxLogSysError(hr, _("Failed to create an instance of \"%s\""), progId); + return NULL; } - // cVal not always present -#ifndef __GNUWIN32__ - else if (type == wxT("char")) - { - oleVariant.vt=VT_I1; // Signed Char - oleVariant.cVal=variant.GetChar(); - } -#endif - else if (type == wxT("double")) - { - oleVariant.vt = VT_R8; - oleVariant.dblVal = variant.GetDouble(); - } - else if (type == wxT("bool")) - { - oleVariant.vt = VT_BOOL; - // 'bool' required for VC++ 4 apparently -#if (defined(__VISUALC__) && (__VISUALC__ <= 1000)) - oleVariant.bool = variant.GetBool(); -#else - oleVariant.boolVal = variant.GetBool(); -#endif - } - else if (type == wxT("string")) - { - wxString str( variant.GetString() ); - oleVariant.vt = VT_BSTR; - oleVariant.bstrVal = wxConvertStringToOle(str); - } -// For some reason, Watcom C++ can't link variant.cpp with time/date classes compiled -// Now obsolete -#if 0 // wxUSE_TIMEDATE && !defined(__WATCOMC__) - else if (type == wxT("date")) - { - wxDate date( variant.GetDate() ); - oleVariant.vt = VT_DATE; - if (!OleDateFromTm(date.GetYear(), date.GetMonth(), date.GetDay(), - 0, 0, 0, oleVariant.date)) - return FALSE; - } - else if (type == wxT("time")) - { - wxTime time( variant.GetTime() ); - oleVariant.vt = VT_DATE; - - if (!OleDateFromTm(time.GetYear(), time.GetMonth(), time.GetDay(), - time.GetHour(), time.GetMinute(), time.GetSecond(), oleVariant.date)) - return FALSE; - } -#endif -#if wxUSE_DATETIME - else if (type == wxT("datetime")) - { - wxDateTime date( variant.GetDateTime() ); - oleVariant.vt = VT_DATE; - - if (!OleDateFromTm(date.GetYear(), date.GetMonth(), date.GetDay(), - date.GetHour(), date.GetMinute(), date.GetSecond(), oleVariant.date)) - return FALSE; - } -#endif - else if (type == wxT("void*")) - { - oleVariant.vt = VT_DISPATCH; - oleVariant.pdispVal = (IDispatch*) variant.GetVoidPtr(); - } - else if (type == wxT("list") || type == wxT("stringlist")) - { - oleVariant.vt = VT_VARIANT | VT_ARRAY; - - SAFEARRAY *psa; - SAFEARRAYBOUND saBound; - VARIANTARG *pvargBase; - VARIANTARG *pvarg; - int i, j; - - int iCount = variant.GetCount(); - - saBound.lLbound = 0; - saBound.cElements = iCount; - - psa = SafeArrayCreate(VT_VARIANT, 1, &saBound); - if (psa == NULL) - return FALSE; - - SafeArrayAccessData(psa, (void**)&pvargBase); - - pvarg = pvargBase; - for (i = 0; i < iCount; i++) - { - // copy each string in the list of strings - wxVariant eachVariant(variant[i]); - if (!wxConvertVariantToOle(eachVariant, * pvarg)) - { - // memory failure: back out and free strings alloc'ed up to - // now, and then the array itself. - pvarg = pvargBase; - for (j = 0; j < i; j++) - { - SysFreeString(pvarg->bstrVal); - pvarg++; - } - SafeArrayDestroy(psa); - return FALSE; - } - pvarg++; - } - - SafeArrayUnaccessData(psa); - - oleVariant.parray = psa; - } - else - { - oleVariant.vt = VT_NULL; - return FALSE; - } - return TRUE; + return pDispatch; } -#ifndef VT_TYPEMASK -#define VT_TYPEMASK 0xfff -#endif +} // anonymous namespace -bool wxConvertOleToVariant(const VARIANTARG& oleVariant, wxVariant& variant) +// Get a dispatch pointer from the current object associated +// with a ProgID +bool wxAutomationObject::GetInstance(const wxString& progId, int flags) const { - switch (oleVariant.vt & VT_TYPEMASK) - { - case VT_BSTR: - { - wxString str(wxConvertStringFromOle(oleVariant.bstrVal)); - variant = str; - break; - } - case VT_DATE: - { -#if wxUSE_DATETIME - struct tm tmTemp; - if (!TmFromOleDate(oleVariant.date, tmTemp)) - return FALSE; + if (m_dispatchPtr) + return false; - wxDateTime date(tmTemp.tm_yday, (wxDateTime::Month) tmTemp.tm_mon, tmTemp.tm_year, tmTemp.tm_hour, tmTemp.tm_min, tmTemp.tm_sec); + CLSID clsId; + HRESULT hr = wxCLSIDFromProgID(progId, clsId); + if (FAILED(hr)) + return false; - variant = date; -#endif + IUnknown *pUnk = NULL; + hr = GetActiveObject(clsId, NULL, &pUnk); + if (FAILED(hr)) + { + if ( flags & wxAutomationInstance_CreateIfNeeded ) + { + const_cast(this)-> + m_dispatchPtr = DoCreateInstance(progId, clsId); + if ( m_dispatchPtr ) + return true; + } + else + { + wxLogSysError(hr, + _("Cannot get an active instance of \"%s\""), progId); + } - break; - } - case VT_I4: - { - variant = (long) oleVariant.lVal; - break; - } - case VT_I2: - { - variant = (long) oleVariant.iVal; - break; - } - - case VT_BOOL: - { -#if (defined(_MSC_VER) && (_MSC_VER <= 1000) && !defined(__MWERKS__) ) //GC -#ifndef HAVE_BOOL // Can't use bool operator if no native bool type - variant = (long) (oleVariant.bool != 0); -#else - variant = (bool) (oleVariant.bool != 0); -#endif -#else -#ifndef HAVE_BOOL // Can't use bool operator if no native bool type - variant = (long) (oleVariant.boolVal != 0); -#else - variant = (bool) (oleVariant.boolVal != 0); -#endif -#endif - break; - } - case VT_R8: - { - variant = oleVariant.dblVal; - break; - } - case VT_ARRAY: - { - variant.ClearList(); - - int cDims, cElements, i; - VARIANTARG* pvdata; - - // Iterate the dimensions: number of elements is x*y*z - for (cDims = 0, cElements = 1; - cDims < oleVariant.parray->cDims; cDims ++) - cElements *= oleVariant.parray->rgsabound[cDims].cElements; - - // Get a pointer to the data - HRESULT hr = SafeArrayAccessData(oleVariant.parray, (void HUGEP* FAR*) & pvdata); - if (hr != NOERROR) - return FALSE; - // Iterate the data. - for (i = 0; i < cElements; i++) - { - VARIANTARG& oleElement = pvdata[i]; - wxVariant vElement; - if (!wxConvertOleToVariant(oleElement, vElement)) - return FALSE; - - variant.Append(vElement); - } - SafeArrayUnaccessData(oleVariant.parray); - break; - } - case VT_DISPATCH: - { - variant = (void*) oleVariant.pdispVal; - break; - } - case VT_NULL: - { - variant.MakeNull(); - break; - } - case VT_EMPTY: - { - break; // Ignore Empty Variant, used only during destruction of objects - } - default: - { - wxLogError(wxT("wxAutomationObject::ConvertOleToVariant: Unknown variant value type")); - return FALSE; - } - } - return TRUE; -} + return false; + } -BSTR wxConvertStringToOle(const wxString& str) -{ -/* - unsigned int len = strlen((const char*) str); - unsigned short* s = new unsigned short[len*2+2]; - unsigned int i; - memset(s, 0, len*2+2); - for (i=0; i < len; i++) - s[i*2] = str[i]; -*/ - wxBasicString bstr(str.mb_str()); - return bstr.Get(); -} + hr = pUnk->QueryInterface(IID_IDispatch, (LPVOID*) &m_dispatchPtr); + if (FAILED(hr)) + { + wxLogSysError(hr, + _("Failed to get OLE automation interface for \"%s\""), + progId); + return false; + } -wxString wxConvertStringFromOle(BSTR bStr) -{ -#if wxUSE_UNICODE - wxString str(bStr); -#else - int len = SysStringLen(bStr) + 1; - char *buf = new char[len]; - (void)wcstombs( buf, bStr, len); - wxString str(buf); - delete[] buf; -#endif - return str; + return true; } -// ---------------------------------------------------------------------------- -// wxBasicString -// ---------------------------------------------------------------------------- - -// ctor takes an ANSI string and transforms it to Unicode -wxBasicString::wxBasicString(const char *sz) +// Get a dispatch pointer from a new object associated +// with the given ProgID +bool wxAutomationObject::CreateInstance(const wxString& progId) const { - Init(sz); -} + if (m_dispatchPtr) + return false; -// ctor takes an ANSI or Unicode string and transforms it to Unicode -wxBasicString::wxBasicString(const wxString& str) -{ -#if wxUSE_UNICODE - m_wzBuf = new OLECHAR[str.Length() + 1]; - memcpy(m_wzBuf, str.c_str(), str.Length()*2); - m_wzBuf[str.Length()] = L'\0'; -#else - Init(str.c_str()); -#endif -} + CLSID clsId; + HRESULT hr = wxCLSIDFromProgID(progId, clsId); + if (FAILED(hr)) + return false; -// Takes an ANSI string and transforms it to Unicode -void wxBasicString::Init(const char *sz) -{ - // get the size of required buffer - UINT lenAnsi = strlen(sz); -#ifdef __MWERKS__ - UINT lenWide = lenAnsi * 2 ; -#else - UINT lenWide = mbstowcs(NULL, sz, lenAnsi); -#endif - - if ( lenWide > 0 ) { - m_wzBuf = new OLECHAR[lenWide + 1]; - mbstowcs(m_wzBuf, sz, lenAnsi); - m_wzBuf[lenWide] = L'\0'; - } - else { - m_wzBuf = NULL; - } -} + const_cast(this)-> + m_dispatchPtr = DoCreateInstance(progId, clsId); -// dtor frees memory -wxBasicString::~wxBasicString() -{ - delete [] m_wzBuf; + return m_dispatchPtr != NULL; } -///////////////////////////////////////////////////////////////////////////// -// COleDateTime class HELPERS - implementation - -BOOL OleDateFromTm(WORD wYear, WORD wMonth, WORD wDay, - WORD wHour, WORD wMinute, WORD wSecond, DATE& dtDest) +static void +ShowException(const wxString& member, + HRESULT hr, + EXCEPINFO *pexcep, + unsigned int uiArgErr) { - // Validate year and month (ignore day of week and milliseconds) - if (wYear > 9999 || wMonth < 1 || wMonth > 12) - return FALSE; - - // Check for leap year and set the number of days in the month - BOOL bLeapYear = ((wYear & 3) == 0) && - ((wYear % 100) != 0 || (wYear % 400) == 0); - - int nDaysInMonth = - rgMonthDays[wMonth] - rgMonthDays[wMonth-1] + - ((bLeapYear && wDay == 29 && wMonth == 2) ? 1 : 0); - - // Finish validating the date - if (wDay < 1 || wDay > nDaysInMonth || - wHour > 23 || wMinute > 59 || - wSecond > 59) - { - return FALSE; - } - - // Cache the date in days and time in fractional days - long nDate; - double dblTime; + wxString message; + switch (GetScode(hr)) + { + case DISP_E_UNKNOWNNAME: + message = _("Unknown name or named argument."); + break; - //It is a valid date; make Jan 1, 1AD be 1 - nDate = wYear*365L + wYear/4 - wYear/100 + wYear/400 + - rgMonthDays[wMonth-1] + wDay; + case DISP_E_BADPARAMCOUNT: + message = _("Incorrect number of arguments."); + break; - // If leap year and it's before March, subtract 1: - if (wMonth <= 2 && bLeapYear) - --nDate; + case DISP_E_EXCEPTION: + if ( pexcep ) + { + if ( pexcep->bstrDescription ) + message << pexcep->bstrDescription << wxS(" "); + message += wxString::Format(wxS("error code %u"), pexcep->wCode); + } + else + { + message = _("Unknown exception"); + } + break; - // Offset so that 12/30/1899 is 0 - nDate -= 693959L; + case DISP_E_MEMBERNOTFOUND: + message = _("Method or property not found."); + break; - dblTime = (((long)wHour * 3600L) + // hrs in seconds - ((long)wMinute * 60L) + // mins in seconds - ((long)wSecond)) / 86400.; + case DISP_E_OVERFLOW: + message = _("Overflow while coercing argument values."); + break; - dtDest = (double) nDate + ((nDate >= 0) ? dblTime : -dblTime); + case DISP_E_NONAMEDARGS: + message = _("Object implementation does not support named arguments."); + break; - return TRUE; -} + case DISP_E_UNKNOWNLCID: + message = _("The locale ID is unknown."); + break; -BOOL TmFromOleDate(DATE dtSrc, struct tm& tmDest) -{ - // The legal range does not actually span year 0 to 9999. - if (dtSrc > MAX_DATE || dtSrc < MIN_DATE) // about year 100 to about 9999 - return FALSE; - - long nDaysAbsolute; // Number of days since 1/1/0 - long nSecsInDay; // Time in seconds since midnight - long nMinutesInDay; // Minutes in day - - long n400Years; // Number of 400 year increments since 1/1/0 - long n400Century; // Century within 400 year block (0,1,2 or 3) - long n4Years; // Number of 4 year increments since 1/1/0 - long n4Day; // Day within 4 year block - // (0 is 1/1/yr1, 1460 is 12/31/yr4) - long n4Yr; // Year within 4 year block (0,1,2 or 3) - BOOL bLeap4 = TRUE; // TRUE if 4 year block includes leap year - - double dblDate = dtSrc; // tempory serial date - - // Round to the second - dblDate += ((dtSrc > 0.0) ? HALF_SECOND : -HALF_SECOND); - - nDaysAbsolute = (long)dblDate + 693959L; // Add days from 1/1/0 to 12/30/1899 - - dblDate = fabs(dblDate); - nSecsInDay = (long)((dblDate - floor(dblDate)) * 86400.); - - // Calculate the day of week (sun=1, mon=2...) - // -1 because 1/1/0 is Sat. +1 because we want 1-based - tmDest.tm_wday = (int)((nDaysAbsolute - 1) % 7L) + 1; - - // Leap years every 4 yrs except centuries not multiples of 400. - n400Years = (long)(nDaysAbsolute / 146097L); - - // Set nDaysAbsolute to day within 400-year block - nDaysAbsolute %= 146097L; - - // -1 because first century has extra day - n400Century = (long)((nDaysAbsolute - 1) / 36524L); - - // Non-leap century - if (n400Century != 0) - { - // Set nDaysAbsolute to day within century - nDaysAbsolute = (nDaysAbsolute - 1) % 36524L; - - // +1 because 1st 4 year increment has 1460 days - n4Years = (long)((nDaysAbsolute + 1) / 1461L); - - if (n4Years != 0) - n4Day = (long)((nDaysAbsolute + 1) % 1461L); - else - { - bLeap4 = FALSE; - n4Day = (long)nDaysAbsolute; - } - } - else - { - // Leap century - not special case! - n4Years = (long)(nDaysAbsolute / 1461L); - n4Day = (long)(nDaysAbsolute % 1461L); - } - - if (bLeap4) - { - // -1 because first year has 366 days - n4Yr = (n4Day - 1) / 365; - - if (n4Yr != 0) - n4Day = (n4Day - 1) % 365; - } - else - { - n4Yr = n4Day / 365; - n4Day %= 365; - } - - // n4Day is now 0-based day of year. Save 1-based day of year, year number - tmDest.tm_yday = (int)n4Day + 1; - tmDest.tm_year = n400Years * 400 + n400Century * 100 + n4Years * 4 + n4Yr; - - // Handle leap year: before, on, and after Feb. 29. - if (n4Yr == 0 && bLeap4) - { - // Leap Year - if (n4Day == 59) - { - /* Feb. 29 */ - tmDest.tm_mon = 2; - tmDest.tm_mday = 29; - goto DoTime; - } - - // Pretend it's not a leap year for month/day comp. - if (n4Day >= 60) - --n4Day; - } - - // Make n4DaY a 1-based day of non-leap year and compute - // month/day for everything but Feb. 29. - ++n4Day; - - // Month number always >= n/32, so save some loop time */ - for (tmDest.tm_mon = (n4Day >> 5) + 1; - n4Day > rgMonthDays[tmDest.tm_mon]; tmDest.tm_mon++) - ; - - tmDest.tm_mday = (int)(n4Day - rgMonthDays[tmDest.tm_mon-1]); - -DoTime: - if (nSecsInDay == 0) - tmDest.tm_hour = tmDest.tm_min = tmDest.tm_sec = 0; - else - { - tmDest.tm_sec = (int)nSecsInDay % 60L; - nMinutesInDay = nSecsInDay / 60L; - tmDest.tm_min = (int)nMinutesInDay % 60; - tmDest.tm_hour = (int)nMinutesInDay / 60; - } - - return TRUE; -} + case DISP_E_PARAMNOTOPTIONAL: + message = _("Missing a required parameter."); + break; -// this function is not used -#if 0 -void TmConvertToStandardFormat(struct tm& tmSrc) -{ - // Convert afx internal tm to format expected by runtimes (_tcsftime, etc) - tmSrc.tm_year -= 1900; // year is based on 1900 - tmSrc.tm_mon -= 1; // month of year is 0-based - tmSrc.tm_wday -= 1; // day of week is 0-based - tmSrc.tm_yday -= 1; // day of year is 0-based -} + case DISP_E_PARAMNOTFOUND: + message.Printf(_("Argument %u not found."), uiArgErr); + break; -double DoubleFromDate(DATE dt) -{ - // No problem if positive - if (dt >= 0) - return dt; - - // If negative, must convert since negative dates not continuous - // (examples: -1.25 to -.75, -1.50 to -.50, -1.75 to -.25) - double temp = ceil(dt); - return temp - (dt - temp); -} + case DISP_E_TYPEMISMATCH: + message.Printf(_("Type mismatch in argument %u."), uiArgErr); + break; -DATE DateFromDouble(double dbl) -{ - // No problem if positive - if (dbl >= 0) - return dbl; - - // If negative, must convert since negative dates not continuous - // (examples: -.75 to -1.25, -.50 to -1.50, -.25 to -1.75) - double temp = floor(dbl); // dbl is now whole part - return temp + (temp - dbl); -} -#endif // 0 - -/* - * ClearVariant - * - * Zeros a variant structure without regard to current contents - */ -static void ClearVariant(VARIANTARG *pvarg) -{ - pvarg->vt = VT_EMPTY; - pvarg->wReserved1 = 0; - pvarg->wReserved2 = 0; - pvarg->wReserved3 = 0; - pvarg->lVal = 0; -} + case ERROR_FILE_NOT_FOUND: + message = _("The system cannot find the file specified."); + break; -/* - * ReleaseVariant - * - * Clears a particular variant structure and releases any external objects - * or memory contained in the variant. Supports the data types listed above. - */ -static void ReleaseVariant(VARIANTARG *pvarg) -{ - VARTYPE vt; - VARIANTARG _huge *pvargArray; - long lLBound, lUBound, l; - - vt = pvarg->vt & 0xfff; // mask off flags - - // check if an array. If so, free its contents, then the array itself. - if (V_ISARRAY(pvarg)) - { - // variant arrays are all this routine currently knows about. Since a - // variant can contain anything (even other arrays), call ourselves - // recursively. - if (vt == VT_VARIANT) - { - SafeArrayGetLBound(pvarg->parray, 1, &lLBound); - SafeArrayGetUBound(pvarg->parray, 1, &lUBound); - - if (lUBound > lLBound) - { - lUBound -= lLBound; - - SafeArrayAccessData(pvarg->parray, (void**)&pvargArray); - - for (l = 0; l < lUBound; l++) - { - ReleaseVariant(pvargArray); - pvargArray++; - } - - SafeArrayUnaccessData(pvarg->parray); - } - } - else - { - wxLogWarning(wxT("ReleaseVariant: Array contains non-variant type")); - } - - // Free the array itself. - SafeArrayDestroy(pvarg->parray); - } - else - { - switch (vt) - { - case VT_DISPATCH: - if (pvarg->pdispVal) - pvarg->pdispVal->Release(); - break; - - case VT_BSTR: - SysFreeString(pvarg->bstrVal); - break; - - case VT_I2: - case VT_BOOL: - case VT_R8: - case VT_ERROR: // to avoid erroring on an error return from Excel - // no work for these types - break; - - default: - wxLogWarning(wxT("ReleaseVariant: Unknown type")); - break; - } - } - - ClearVariant(pvarg); -} + case REGDB_E_CLASSNOTREG: + message = _("Class not registered."); + break; -#if 0 + default: + message.Printf(_("Unknown error %08x"), hr); + break; + } -void ShowException(LPOLESTR szMember, HRESULT hr, EXCEPINFO *pexcep, unsigned int uiArgErr) -{ - TCHAR szBuf[512]; - - switch (GetScode(hr)) - { - case DISP_E_UNKNOWNNAME: - wsprintf(szBuf, L"%s: Unknown name or named argument.", szMember); - break; - - case DISP_E_BADPARAMCOUNT: - wsprintf(szBuf, L"%s: Incorrect number of arguments.", szMember); - break; - - case DISP_E_EXCEPTION: - wsprintf(szBuf, L"%s: Error %d: ", szMember, pexcep->wCode); - if (pexcep->bstrDescription != NULL) - lstrcat(szBuf, pexcep->bstrDescription); - else - lstrcat(szBuf, L"<>"); - break; - - case DISP_E_MEMBERNOTFOUND: - wsprintf(szBuf, L"%s: method or property not found.", szMember); - break; - - case DISP_E_OVERFLOW: - wsprintf(szBuf, L"%s: Overflow while coercing argument values.", szMember); - break; - - case DISP_E_NONAMEDARGS: - wsprintf(szBuf, L"%s: Object implementation does not support named arguments.", - szMember); - break; - - case DISP_E_UNKNOWNLCID: - wsprintf(szBuf, L"%s: The locale ID is unknown.", szMember); - break; - - case DISP_E_PARAMNOTOPTIONAL: - wsprintf(szBuf, L"%s: Missing a required parameter.", szMember); - break; - - case DISP_E_PARAMNOTFOUND: - wsprintf(szBuf, L"%s: Argument not found, argument %d.", szMember, uiArgErr); - break; - - case DISP_E_TYPEMISMATCH: - wsprintf(szBuf, L"%s: Type mismatch, argument %d.", szMember, uiArgErr); - break; - - default: - wsprintf(szBuf, L"%s: Unknown error occured.", szMember); - break; - } - - wxLogWarning(szBuf); + wxLogError(_("OLE Automation error in %s: %s"), member, message); } -#endif - -#endif // wxUSE_OLE && !(defined(__BORLANDC__) && (__BORLANDC__ < 0x520)) && !defined(__CYGWIN10__) - +#endif // wxUSE_OLE_AUTOMATION