X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a2fd865b0dc2abc2ae04811cbd88c90a146c9e4f..7c70331e28be93b833dfa4f2594a25841fcb6e20:/src/msw/ole/oleutils.cpp diff --git a/src/msw/ole/oleutils.cpp b/src/msw/ole/oleutils.cpp index 8cf7899187..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,103 +131,202 @@ wxBasicString::~wxBasicString() #if wxUSE_VARIANT -/* - * wxClearVariant - * - * Zeros a variant structure without regard to current contents - */ -void wxClearVariant(VARIANTARG *pvarg) -{ - pvarg->vt = VT_EMPTY; - pvarg->wReserved1 = 0; - pvarg->wReserved2 = 0; - pvarg->wReserved3 = 0; - pvarg->lVal = 0; -} +namespace +{ -/* - * wxReleaseVariant - * - * Clears a particular variant structure and releases any external objects - * or memory contained in the variant. Supports the data types listed above. - */ -void wxReleaseVariant(VARIANTARG *pvarg) +// 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 { - VARTYPE vt; - VARIANTARG _huge *pvargArray; - LONG lLBound, lUBound, l; +public: + wxSafeArrayHelper(); + ~wxSafeArrayHelper(); - vt = (VARTYPE)(pvarg->vt & 0xfff); // mask off flags + bool Create(VARTYPE vt, long count); // creates and locks the array - // 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); + bool SetElement(size_t index, const wxVariant& variant); + bool SetElement(size_t index, const wxString& str); - if (lUBound > lLBound) - { - lUBound -= lLBound; + SAFEARRAY* Detach(); // unlocks the array and gives up its ownership - SafeArrayAccessData(pvarg->parray, (void**)&pvargArray); +private: + void Unlock(); - for (l = 0; l < lUBound; l++) - { - wxReleaseVariant(pvargArray); - pvargArray++; - } + SAFEARRAY* m_array; +}; - SafeArrayUnaccessData(pvarg->parray); - } - } - else - { - wxLogWarning(wxT("wxReleaseVariant: Array contains non-variant type")); - } +wxSafeArrayHelper::wxSafeArrayHelper() +{ + m_array = NULL; +} - // Free the array itself. - SafeArrayDestroy(pvarg->parray); +wxSafeArrayHelper::~wxSafeArrayHelper() +{ + if ( m_array ) + { + Unlock(); + SafeArrayDestroy(m_array); } - else +} + +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() ) { - switch (vt) - { - case VT_DISPATCH: - if (pvarg->pdispVal) - pvarg->pdispVal->Release(); - break; + // 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; + } - case VT_BSTR: - SysFreeString(pvarg->bstrVal); - break; + BSTR* data = (BSTR*)m_array->pvData; + data[index] = bstr; + return true; +} - case VT_I2: - case VT_I4: - case VT_BOOL: - case VT_R8: - case VT_ERROR: // to avoid erroring on an error return from Excel - case VT_EMPTY: - case VT_DATE: - // no work for these types - break; +SAFEARRAY* wxSafeArrayHelper::Detach() +{ + Unlock(); + SAFEARRAY* result = m_array; + m_array = NULL; + return result; +} - default: - wxLogWarning(wxT("wxReleaseVariant: Unknown type")); - break; - } +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 +// ---------------------------------------------------------------------------- - wxClearVariant(pvarg); +#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) { - wxClearVariant(&oleVariant); + VariantInit(&oleVariant); if (variant.IsNull()) { oleVariant.vt = VT_NULL; @@ -236,20 +335,45 @@ 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() ; } - // cVal not always present -#ifndef __GNUWIN32__ + // 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 oleVariant.cVal=variant.GetChar(); } -#endif else if (type == wxT("double")) { oleVariant.vt = VT_R8; @@ -258,12 +382,7 @@ WXDLLEXPORT bool wxConvertVariantToOle(const wxVariant& variant, VARIANTARG& ole 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 + oleVariant.boolVal = variant.GetBool() ? VARIANT_TRUE : VARIANT_FALSE; } else if (type == wxT("string")) { @@ -288,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 { @@ -432,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)); @@ -452,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; @@ -464,6 +585,10 @@ wxConvertOleToVariant(const VARIANTARG& oleVariant, wxVariant& variant) variant = oleVariant.boolVal != 0; break; + case VT_R4: + variant = oleVariant.fltVal; + break; + case VT_R8: variant = oleVariant.dblVal; break; @@ -498,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 @@ -515,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), @@ -610,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); }