X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/51909b8b0bcc5291ec57ac22d8d0e5d73ae51d65..7c70331e28be93b833dfa4f2594a25841fcb6e20:/src/msw/ole/oleutils.cpp diff --git a/src/msw/ole/oleutils.cpp b/src/msw/ole/oleutils.cpp index c992ce0af5..f6ec69f5f6 100644 --- a/src/msw/ole/oleutils.cpp +++ b/src/msw/ole/oleutils.cpp @@ -58,7 +58,7 @@ // ============================================================================ // return true if the iid is in the array -bool IsIidFromList(REFIID riid, const IID *aIids[], size_t nCount) +WXDLLEXPORT bool IsIidFromList(REFIID riid, const IID *aIids[], size_t nCount) { for ( size_t i = 0; i < nCount; i++ ) { if ( riid == *aIids[i] ) @@ -131,6 +131,199 @@ wxBasicString::~wxBasicString() #if wxUSE_VARIANT +namespace +{ + +// Helper class for creating and filling SAFEARRAY. To use it, call Create() +// first, then SetElement() for each element and finally Detach() the SAFEARRAY +// from it if you don't want it to be deleted when this class is. +class wxSafeArrayHelper +{ +public: + wxSafeArrayHelper(); + ~wxSafeArrayHelper(); + + bool Create(VARTYPE vt, long count); // creates and locks the array + + bool SetElement(size_t index, const wxVariant& variant); + bool SetElement(size_t index, const wxString& str); + + SAFEARRAY* Detach(); // unlocks the array and gives up its ownership + +private: + void Unlock(); + + SAFEARRAY* m_array; +}; + +wxSafeArrayHelper::wxSafeArrayHelper() +{ + m_array = NULL; +} + +wxSafeArrayHelper::~wxSafeArrayHelper() +{ + if ( m_array ) + { + Unlock(); + SafeArrayDestroy(m_array); + } +} + +bool wxSafeArrayHelper::Create(VARTYPE vt, long count) +{ + SAFEARRAYBOUND saBound; + + saBound.lLbound = 0; + saBound.cElements = count; + m_array = SafeArrayCreate(vt, 1, &saBound); + if ( !m_array ) + return false; + return SUCCEEDED( SafeArrayLock(m_array) ); +} + +bool wxSafeArrayHelper::SetElement(size_t index, const wxVariant& variant) +{ + VARIANT* data = (VARIANT*)m_array->pvData; + return wxConvertVariantToOle(variant, data[index]); +} + +bool wxSafeArrayHelper::SetElement(size_t index, const wxString& str) +{ + BSTR bstr = wxConvertStringToOle(str); + + if ( !bstr && !str.empty() ) + { + // BSTR can be NULL for empty strings but if the string was + // not empty, it means we failed to allocate memory for it. + return false; + } + + BSTR* data = (BSTR*)m_array->pvData; + data[index] = bstr; + return true; +} + +SAFEARRAY* wxSafeArrayHelper::Detach() +{ + Unlock(); + SAFEARRAY* result = m_array; + m_array = NULL; + return result; +} + +void wxSafeArrayHelper::Unlock() +{ + if ( m_array ) + SafeArrayUnlock(m_array); +} + +} // unnamed namespace + + +// ---------------------------------------------------------------------------- +// wxVariantDataCurrency +// ---------------------------------------------------------------------------- + + +#if wxUSE_ANY + +bool wxVariantDataCurrency::GetAsAny(wxAny* any) const +{ + *any = m_value; + return true; +} + +wxVariantData* wxVariantDataCurrency::VariantDataFactory(const wxAny& any) +{ + return new wxVariantDataCurrency(wxANY_AS(any, CURRENCY)); +} + +REGISTER_WXANY_CONVERSION(CURRENCY, wxVariantDataCurrency) + +#endif // wxUSE_ANY + +bool wxVariantDataCurrency::Eq(wxVariantData& data) const +{ + wxASSERT_MSG( (data.GetType() == wxS("currency")), + "wxVariantDataCurrency::Eq: argument mismatch" ); + + wxVariantDataCurrency& otherData = (wxVariantDataCurrency&) data; + + return otherData.m_value.int64 == m_value.int64; +} + +#if wxUSE_STD_IOSTREAM +bool wxVariantDataCurrency::Write(wxSTD ostream& str) const +{ + wxString s; + Write(s); + str << s; + return true; +} +#endif + +bool wxVariantDataCurrency::Write(wxString& str) const +{ + BSTR bStr = NULL; + if ( SUCCEEDED(VarBstrFromCy(m_value, LOCALE_USER_DEFAULT, 0, &bStr)) ) + { + str = wxConvertStringFromOle(bStr); + SysFreeString(bStr); + return true; + } + return false; +} + +// ---------------------------------------------------------------------------- +// wxVariantDataErrorCode +// ---------------------------------------------------------------------------- + +#if wxUSE_ANY + +bool wxVariantDataErrorCode::GetAsAny(wxAny* any) const +{ + *any = m_value; + return true; +} + +wxVariantData* wxVariantDataErrorCode::VariantDataFactory(const wxAny& any) +{ + return new wxVariantDataErrorCode(wxANY_AS(any, SCODE)); +} + +REGISTER_WXANY_CONVERSION(SCODE, wxVariantDataErrorCode) + +#endif // wxUSE_ANY + +bool wxVariantDataErrorCode::Eq(wxVariantData& data) const +{ + wxASSERT_MSG( (data.GetType() == wxS("errorcode")), + "wxVariantDataErrorCode::Eq: argument mismatch" ); + + wxVariantDataErrorCode& otherData = (wxVariantDataErrorCode&) data; + + return otherData.m_value == m_value; +} + +#if wxUSE_STD_IOSTREAM +bool wxVariantDataErrorCode::Write(wxSTD ostream& str) const +{ + wxString s; + Write(s); + str << s; + return true; +} +#endif + +bool wxVariantDataErrorCode::Write(wxString& str) const +{ + str << m_value; + return true; +} + + + WXDLLEXPORT bool wxConvertVariantToOle(const wxVariant& variant, VARIANTARG& oleVariant) { VariantInit(&oleVariant); @@ -142,12 +335,40 @@ WXDLLEXPORT bool wxConvertVariantToOle(const wxVariant& variant, VARIANTARG& ole wxString type(variant.GetType()); - - if (type == wxT("long")) + if (type == wxT("errorcode")) + { + wxVariantDataErrorCode* const + ec = wxDynamicCastVariantData(variant.GetData(), + wxVariantDataErrorCode); + oleVariant.vt = VT_ERROR; + oleVariant.scode = ec->GetValue(); + } + else if (type == wxT("currency")) + { + wxVariantDataCurrency* const + c = wxDynamicCastVariantData(variant.GetData(), + wxVariantDataCurrency); + oleVariant.vt = VT_CY; + oleVariant.cyVal = c->GetValue(); + } + else if (type == wxT("long")) { oleVariant.vt = VT_I4; oleVariant.lVal = variant.GetLong() ; } + // Original VC6 came with SDK too old to contain VARIANT::llVal declaration + // and there doesn't seem to be any way to test for it as Microsoft simply + // added it to the later version of oaidl.h without changing anything else. + // So assume it's not present for VC6, even though it might be if an + // updated SDK is used. In this case the user would need to disable this + // check himself. +#if wxUSE_LONGLONG && !defined(__VISUALC6__) + else if (type == wxT("longlong")) + { + oleVariant.vt = VT_I8; + oleVariant.llVal = variant.GetLongLong().GetValue(); + } +#endif else if (type == wxT("char")) { oleVariant.vt=VT_I1; // Signed Char @@ -186,51 +407,38 @@ WXDLLEXPORT bool wxConvertVariantToOle(const wxVariant& variant, VARIANTARG& ole oleVariant.vt = VT_DISPATCH; oleVariant.pdispVal = (IDispatch*) variant.GetVoidPtr(); } - else if (type == wxT("list") || type == wxT("stringlist")) + else if (type == wxT("list")) { - oleVariant.vt = VT_VARIANT | VT_ARRAY; + wxSafeArrayHelper sah; - SAFEARRAY *psa; - SAFEARRAYBOUND saBound; - VARIANTARG *pvargBase; - VARIANTARG *pvarg; - int i, j; + if (!sah.Create(VT_VARIANT, variant.GetCount())) + return false; - int iCount = variant.GetCount(); + for (size_t i = 0; i < variant.GetCount(); i++) + { + if (!sah.SetElement(i, variant[i])) + return false; + } - saBound.lLbound = 0; - saBound.cElements = iCount; + oleVariant.vt = VT_VARIANT | VT_ARRAY; + oleVariant.parray = sah.Detach(); + } + else if (type == wxT("arrstring")) + { + wxArrayString strings(variant.GetArrayString()); + wxSafeArrayHelper sah; - psa = SafeArrayCreate(VT_VARIANT, 1, &saBound); - if (psa == NULL) + if (!sah.Create(VT_BSTR, strings.GetCount())) return false; - SafeArrayAccessData(psa, (void**)&pvargBase); - - pvarg = pvargBase; - for (i = 0; i < iCount; i++) + for (size_t i = 0; i < strings.GetCount(); 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); + if (!sah.SetElement(i, strings[i])) return false; - } - pvarg++; } - SafeArrayUnaccessData(psa); - - oleVariant.parray = psa; + oleVariant.vt = VT_BSTR | VT_ARRAY; + oleVariant.parray = sah.Detach(); } else { @@ -330,6 +538,14 @@ wxConvertOleToVariant(const VARIANTARG& oleVariant, wxVariant& variant) { switch ( oleVariant.vt & VT_TYPEMASK ) { + case VT_ERROR: + variant.SetData(new wxVariantDataErrorCode(oleVariant.scode)); + break; + + case VT_CY: + variant.SetData(new wxVariantDataCurrency(oleVariant.cyVal)); + break; + case VT_BSTR: { wxString str(wxConvertStringFromOle(oleVariant.bstrVal)); @@ -350,6 +566,13 @@ wxConvertOleToVariant(const VARIANTARG& oleVariant, wxVariant& variant) #endif // wxUSE_DATETIME break; + // See the comment before the __VISUALC6__ test above. +#if wxUSE_LONGLONG && !defined(__VISUALC6__) + case VT_I8: + variant = wxLongLong(oleVariant.llVal); + break; +#endif // wxUSE_LONGLONG + case VT_I4: variant = (long) oleVariant.lVal; break; @@ -400,7 +623,7 @@ wxConvertOleToVariant(const VARIANTARG& oleVariant, wxVariant& variant) #if wxUSE_DATAOBJ -#if wxDEBUG_LEVEL && ( ( defined(__VISUALC__) && (__VISUALC__ > 1000) ) || defined(__MWERKS__) ) +#if wxDEBUG_LEVEL && (( defined(__VISUALC__) && (__VISUALC__ > 1000) )) static wxString GetIidName(REFIID riid) { // an association between symbolic name and numeric value of an IID @@ -417,7 +640,7 @@ static wxString GetIidName(REFIID riid) ADD_KNOWN_IID(AdviseSink2), ADD_KNOWN_IID(BindCtx), ADD_KNOWN_IID(ClassFactory), -#if ( !defined( __VISUALC__) || (__VISUALC__!=1010) ) && !defined(__MWERKS__) +#if ( !defined( __VISUALC__) || (__VISUALC__!=1010) ) ADD_KNOWN_IID(ContinueCallback), ADD_KNOWN_IID(EnumOleDocumentViews), ADD_KNOWN_IID(OleCommandTarget), @@ -512,18 +735,18 @@ static wxString GetIidName(REFIID riid) #endif } -void wxLogQueryInterface(const wxChar *szInterface, REFIID riid) +WXDLLEXPORT void wxLogQueryInterface(const wxChar *szInterface, REFIID riid) { wxLogTrace(wxTRACE_OleCalls, wxT("%s::QueryInterface (iid = %s)"), szInterface, GetIidName(riid).c_str()); } -void wxLogAddRef(const wxChar *szInterface, ULONG cRef) +WXDLLEXPORT void wxLogAddRef(const wxChar *szInterface, ULONG cRef) { wxLogTrace(wxTRACE_OleCalls, wxT("After %s::AddRef: m_cRef = %d"), szInterface, cRef + 1); } -void wxLogRelease(const wxChar *szInterface, ULONG cRef) +WXDLLEXPORT void wxLogRelease(const wxChar *szInterface, ULONG cRef) { wxLogTrace(wxTRACE_OleCalls, wxT("After %s::Release: m_cRef = %d"), szInterface, cRef - 1); }