X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f0d38b659f54a9c4775b3fc0cfd7ba44d91f3081..43f4e852a1b2ac37c3db6a2b87315192ac549191:/src/msw/ole/oleutils.cpp diff --git a/src/msw/ole/oleutils.cpp b/src/msw/ole/oleutils.cpp index c5f1f053c9..293b4e68ba 100644 --- a/src/msw/ole/oleutils.cpp +++ b/src/msw/ole/oleutils.cpp @@ -48,6 +48,7 @@ #endif #include "wx/msw/ole/oleutils.h" +#include "wx/msw/ole/safearray.h" #if defined(__VISUALC__) && (__VISUALC__ > 1000) #include @@ -131,95 +132,154 @@ wxBasicString::~wxBasicString() #if wxUSE_VARIANT -namespace +// ---------------------------------------------------------------------------- +// wxVariantDataCurrency +// ---------------------------------------------------------------------------- + + +#if wxUSE_ANY + +bool wxVariantDataCurrency::GetAsAny(wxAny* any) const { + *any = m_value; + return true; +} -// 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 +wxVariantData* wxVariantDataCurrency::VariantDataFactory(const wxAny& any) { -public: - wxSafeArrayHelper(); - ~wxSafeArrayHelper(); + return new wxVariantDataCurrency(wxANY_AS(any, CURRENCY)); +} - bool Create(VARTYPE vt, long count); // creates and locks the array +REGISTER_WXANY_CONVERSION(CURRENCY, wxVariantDataCurrency) - bool SetElement(size_t index, const wxVariant& variant); - bool SetElement(size_t index, const wxString& str); +#endif // wxUSE_ANY - SAFEARRAY* Detach(); // unlocks the array and gives up its ownership +bool wxVariantDataCurrency::Eq(wxVariantData& data) const +{ + wxASSERT_MSG( (data.GetType() == wxS("currency")), + "wxVariantDataCurrency::Eq: argument mismatch" ); -private: - void Unlock(); + wxVariantDataCurrency& otherData = (wxVariantDataCurrency&) data; - SAFEARRAY* m_array; -}; + return otherData.m_value.int64 == m_value.int64; +} -wxSafeArrayHelper::wxSafeArrayHelper() +#if wxUSE_STD_IOSTREAM +bool wxVariantDataCurrency::Write(wxSTD ostream& str) const { - m_array = NULL; + wxString s; + Write(s); + str << s; + return true; } +#endif -wxSafeArrayHelper::~wxSafeArrayHelper() +bool wxVariantDataCurrency::Write(wxString& str) const { - if ( m_array ) + BSTR bStr = NULL; + if ( SUCCEEDED(VarBstrFromCy(m_value, LOCALE_USER_DEFAULT, 0, &bStr)) ) { - Unlock(); - SafeArrayDestroy(m_array); + str = wxConvertStringFromOle(bStr); + SysFreeString(bStr); + return true; } + return false; +} + +// ---------------------------------------------------------------------------- +// wxVariantDataErrorCode +// ---------------------------------------------------------------------------- + +#if wxUSE_ANY + +bool wxVariantDataErrorCode::GetAsAny(wxAny* any) const +{ + *any = m_value; + return true; } -bool wxSafeArrayHelper::Create(VARTYPE vt, long count) +wxVariantData* wxVariantDataErrorCode::VariantDataFactory(const wxAny& any) { - SAFEARRAYBOUND saBound; + return new wxVariantDataErrorCode(wxANY_AS(any, SCODE)); +} - saBound.lLbound = 0; - saBound.cElements = count; - m_array = SafeArrayCreate(vt, 1, &saBound); - if ( !m_array ) - return false; - return SUCCEEDED( SafeArrayLock(m_array) ); +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; } -bool wxSafeArrayHelper::SetElement(size_t index, const wxVariant& variant) +#if wxUSE_STD_IOSTREAM +bool wxVariantDataErrorCode::Write(wxSTD ostream& str) const { - VARIANT* data = (VARIANT*)m_array->pvData; - return wxConvertVariantToOle(variant, data[index]); + wxString s; + Write(s); + str << s; + return true; } +#endif -bool wxSafeArrayHelper::SetElement(size_t index, const wxString& str) +bool wxVariantDataErrorCode::Write(wxString& str) const { - BSTR bstr = wxConvertStringToOle(str); + str << m_value; + return true; +} - 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; +// ---------------------------------------------------------------------------- +// wxVariantDataSafeArray +// ---------------------------------------------------------------------------- + +#if wxUSE_ANY + +bool wxVariantDataSafeArray::GetAsAny(wxAny* any) const +{ + *any = m_value; return true; } -SAFEARRAY* wxSafeArrayHelper::Detach() +wxVariantData* wxVariantDataSafeArray::VariantDataFactory(const wxAny& any) { - Unlock(); - SAFEARRAY* result = m_array; - m_array = NULL; - return result; + return new wxVariantDataSafeArray(wxANY_AS(any, SAFEARRAY*)); } -void wxSafeArrayHelper::Unlock() +REGISTER_WXANY_CONVERSION(SAFEARRAY*, wxVariantDataSafeArray) + +#endif // wxUSE_ANY + +bool wxVariantDataSafeArray::Eq(wxVariantData& data) const { - if ( m_array ) - SafeArrayUnlock(m_array); + wxASSERT_MSG( (data.GetType() == wxS("safearray")), + "wxVariantDataSafeArray::Eq: argument mismatch" ); + + wxVariantDataSafeArray& otherData = (wxVariantDataSafeArray&) data; + + return otherData.m_value == m_value; } -} // unnamed namespace +#if wxUSE_STD_IOSTREAM +bool wxVariantDataSafeArray::Write(wxSTD ostream& str) const +{ + wxString s; + Write(s); + str << s; + return true; +} +#endif +bool wxVariantDataSafeArray::Write(wxString& str) const +{ + str.Printf(wxS("SAFEARRAY: %p"), (void*)m_value); + return true; +} WXDLLEXPORT bool wxConvertVariantToOle(const wxVariant& variant, VARIANTARG& oleVariant) { @@ -232,8 +292,42 @@ WXDLLEXPORT bool wxConvertVariantToOle(const wxVariant& variant, VARIANTARG& ole wxString type(variant.GetType()); - - if (type == wxT("long")) + if (type == wxT("errorcode")) + { + wxVariantDataErrorCode* const + ec = wxStaticCastVariantData(variant.GetData(), + wxVariantDataErrorCode); + oleVariant.vt = VT_ERROR; + oleVariant.scode = ec->GetValue(); + } + else if (type == wxT("currency")) + { + wxVariantDataCurrency* const + c = wxStaticCastVariantData(variant.GetData(), + wxVariantDataCurrency); + oleVariant.vt = VT_CY; + oleVariant.cyVal = c->GetValue(); + } + else if (type == wxT("safearray")) + { + wxVariantDataSafeArray* const + vsa = wxStaticCastVariantData(variant.GetData(), + wxVariantDataSafeArray); + SAFEARRAY* psa = vsa->GetValue(); + VARTYPE vt; + + wxCHECK(psa, false); + HRESULT hr = SafeArrayGetVartype(psa, &vt); + if ( FAILED(hr) ) + { + wxLogApiError(wxS("SafeArrayGetVartype()"), hr); + SafeArrayDestroy(psa); + return false; + } + oleVariant.vt = vt | VT_ARRAY; + oleVariant.parray = psa; + } + else if (type == wxT("long")) { oleVariant.vt = VT_I4; oleVariant.lVal = variant.GetLong() ; @@ -291,36 +385,22 @@ WXDLLEXPORT bool wxConvertVariantToOle(const wxVariant& variant, VARIANTARG& ole } else if (type == wxT("list")) { - wxSafeArrayHelper sah; - - if (!sah.Create(VT_VARIANT, variant.GetCount())) + wxSafeArray safeArray; + if (!safeArray.CreateFromListVariant(variant)) return false; - for (size_t i = 0; i < variant.GetCount(); i++) - { - if (!sah.SetElement(i, variant[i])) - return false; - } - oleVariant.vt = VT_VARIANT | VT_ARRAY; - oleVariant.parray = sah.Detach(); + oleVariant.parray = safeArray.Detach(); } else if (type == wxT("arrstring")) { - wxArrayString strings(variant.GetArrayString()); - wxSafeArrayHelper sah; + wxSafeArray safeArray; - if (!sah.Create(VT_BSTR, strings.GetCount())) + if (!safeArray.CreateFromArrayString(variant.GetArrayString())) return false; - for (size_t i = 0; i < strings.GetCount(); i++) - { - if (!sah.SetElement(i, strings[i])) - return false; - } - oleVariant.vt = VT_BSTR | VT_ARRAY; - oleVariant.parray = sah.Detach(); + oleVariant.parray = safeArray.Detach(); } else { @@ -340,63 +420,53 @@ wxConvertOleToVariant(const VARIANTARG& oleVariant, wxVariant& variant) bool ok = true; if ( oleVariant.vt & VT_ARRAY ) { - - // Compute the total number of elements in all array dimensions - int cElements = 1; - for ( int cDims = 0; cDims < oleVariant.parray->cDims; cDims++ ) - cElements *= oleVariant.parray->rgsabound[cDims].cElements; - - // Get a pointer to the data - void* pvdata; - HRESULT hr = SafeArrayAccessData(oleVariant.parray, &pvdata); - if ( FAILED(hr) ) - return false; - + // TODO: We currently return arrays as wxVariant of the list type + // containing the flattened form of array but we should allow + // getting it as wxVariantDataSafeArray instead. Doing this is + // simple, we'd just need to do something like this: + // + // if ( oleVariant.parray && SafeArrayGetDim(oleVariant.parray) > 1 ) + // { + // variant.SetData(new wxVariantDataSafeArray(oleVariant.parray)); + // } + // + // but currently we don't do it for compatibility reasons. switch (oleVariant.vt & VT_TYPEMASK) { + case VT_I2: + ok = wxSafeArray::ConvertToVariant(oleVariant.parray, variant); + break; + case VT_I4: + ok = wxSafeArray::ConvertToVariant(oleVariant.parray, variant); + break; + case VT_R4: + ok = wxSafeArray::ConvertToVariant(oleVariant.parray, variant); + break; + case VT_R8: + ok = wxSafeArray::ConvertToVariant(oleVariant.parray, variant); + break; case VT_VARIANT: - { - variant.ClearList(); - VARIANTARG *variant_data=(VARIANTARG*)pvdata; - for ( int i = 0; i < cElements; i++ ) - { - VARIANTARG& oleElement = variant_data[i]; - wxVariant vElement; - if ( !wxConvertOleToVariant(oleElement, vElement) ) - { - ok = false; - variant.ClearList(); - break; - } - - variant.Append(vElement); - } - } + ok = wxSafeArray::ConvertToVariant(oleVariant.parray, variant); break; - case VT_BSTR: { wxArrayString strings; - BSTR *string_val=(BSTR*)pvdata; - for ( int i = 0; i < cElements; ++i ) - { - wxString str=wxConvertStringFromOle(*string_val); - strings.Add(str); - ++string_val; - } - variant=strings; + if ( wxSafeArray::ConvertToArrayString(oleVariant.parray, strings) ) + variant = strings; + else + ok = false; } break; - default: - wxLogDebug(wxT("unhandled VT_ARRAY type %x in wxConvertOleToVariant"), - oleVariant.vt & VT_TYPEMASK); - variant = wxVariant(); ok = false; break; } - - SafeArrayUnaccessData(oleVariant.parray); + if ( !ok ) + { + wxLogDebug(wxT("unhandled VT_ARRAY type %x in wxConvertOleToVariant"), + oleVariant.vt & VT_TYPEMASK); + variant = wxVariant(); + } } else if ( oleVariant.vt & VT_BYREF ) { @@ -420,6 +490,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));