X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a2fd865b0dc2abc2ae04811cbd88c90a146c9e4f..43f4e852a1b2ac37c3db6a2b87315192ac549191:/src/msw/ole/oleutils.cpp?ds=sidebyside diff --git a/src/msw/ole/oleutils.cpp b/src/msw/ole/oleutils.cpp index 8cf7899187..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 @@ -58,7 +59,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 +132,158 @@ wxBasicString::~wxBasicString() #if wxUSE_VARIANT -/* - * wxClearVariant - * - * Zeros a variant structure without regard to current contents - */ -void wxClearVariant(VARIANTARG *pvarg) +// ---------------------------------------------------------------------------- +// wxVariantDataCurrency +// ---------------------------------------------------------------------------- + + +#if wxUSE_ANY + +bool wxVariantDataCurrency::GetAsAny(wxAny* any) const { - pvarg->vt = VT_EMPTY; - pvarg->wReserved1 = 0; - pvarg->wReserved2 = 0; - pvarg->wReserved3 = 0; - pvarg->lVal = 0; + *any = m_value; + return true; } -/* - * 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) +wxVariantData* wxVariantDataCurrency::VariantDataFactory(const wxAny& any) { - VARTYPE vt; - VARIANTARG _huge *pvargArray; - LONG lLBound, lUBound, l; + return new wxVariantDataCurrency(wxANY_AS(any, CURRENCY)); +} - vt = (VARTYPE)(pvarg->vt & 0xfff); // mask off flags +REGISTER_WXANY_CONVERSION(CURRENCY, wxVariantDataCurrency) - // 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); +#endif // wxUSE_ANY - if (lUBound > lLBound) - { - lUBound -= lLBound; +bool wxVariantDataCurrency::Eq(wxVariantData& data) const +{ + wxASSERT_MSG( (data.GetType() == wxS("currency")), + "wxVariantDataCurrency::Eq: argument mismatch" ); - SafeArrayAccessData(pvarg->parray, (void**)&pvargArray); + wxVariantDataCurrency& otherData = (wxVariantDataCurrency&) data; - for (l = 0; l < lUBound; l++) - { - wxReleaseVariant(pvargArray); - pvargArray++; - } + return otherData.m_value.int64 == m_value.int64; +} - SafeArrayUnaccessData(pvarg->parray); - } - } - else - { - wxLogWarning(wxT("wxReleaseVariant: Array contains non-variant type")); - } +#if wxUSE_STD_IOSTREAM +bool wxVariantDataCurrency::Write(wxSTD ostream& str) const +{ + wxString s; + Write(s); + str << s; + return true; +} +#endif - // Free the array itself. - SafeArrayDestroy(pvarg->parray); - } - else +bool wxVariantDataCurrency::Write(wxString& str) const +{ + BSTR bStr = NULL; + if ( SUCCEEDED(VarBstrFromCy(m_value, LOCALE_USER_DEFAULT, 0, &bStr)) ) { - switch (vt) - { - case VT_DISPATCH: - if (pvarg->pdispVal) - pvarg->pdispVal->Release(); - break; + str = wxConvertStringFromOle(bStr); + SysFreeString(bStr); + return true; + } + return false; +} - case VT_BSTR: - SysFreeString(pvarg->bstrVal); - break; +// ---------------------------------------------------------------------------- +// wxVariantDataErrorCode +// ---------------------------------------------------------------------------- - 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; +#if wxUSE_ANY - default: - wxLogWarning(wxT("wxReleaseVariant: Unknown type")); - break; - } - } +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 - wxClearVariant(pvarg); +bool wxVariantDataErrorCode::Write(wxString& str) const +{ + str << m_value; + return true; +} + + +// ---------------------------------------------------------------------------- +// wxVariantDataSafeArray +// ---------------------------------------------------------------------------- + +#if wxUSE_ANY + +bool wxVariantDataSafeArray::GetAsAny(wxAny* any) const +{ + *any = m_value; + return true; +} + +wxVariantData* wxVariantDataSafeArray::VariantDataFactory(const wxAny& any) +{ + return new wxVariantDataSafeArray(wxANY_AS(any, SAFEARRAY*)); +} + +REGISTER_WXANY_CONVERSION(SAFEARRAY*, wxVariantDataSafeArray) + +#endif // wxUSE_ANY + +bool wxVariantDataSafeArray::Eq(wxVariantData& data) const +{ + wxASSERT_MSG( (data.GetType() == wxS("safearray")), + "wxVariantDataSafeArray::Eq: argument mismatch" ); + + wxVariantDataSafeArray& otherData = (wxVariantDataSafeArray&) data; + + return otherData.m_value == m_value; +} + +#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) { - wxClearVariant(&oleVariant); + VariantInit(&oleVariant); if (variant.IsNull()) { oleVariant.vt = VT_NULL; @@ -236,20 +292,64 @@ 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() ; } - // 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 +358,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 +383,24 @@ 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; - - 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) + wxSafeArray safeArray; + if (!safeArray.CreateFromListVariant(variant)) 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++; - } + oleVariant.vt = VT_VARIANT | VT_ARRAY; + oleVariant.parray = safeArray.Detach(); + } + else if (type == wxT("arrstring")) + { + wxSafeArray safeArray; - SafeArrayUnaccessData(psa); + if (!safeArray.CreateFromArrayString(variant.GetArrayString())) + return false; - oleVariant.parray = psa; + oleVariant.vt = VT_BSTR | VT_ARRAY; + oleVariant.parray = safeArray.Detach(); } else { @@ -352,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 ) { @@ -432,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)); @@ -452,6 +518,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 +537,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 +575,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 +592,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 +687,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); }