/////////////////////////////////////////////////////////////////////////////// // Name: src/msw/ole/oleutils.cpp // Purpose: implementation of OLE helper functions // Author: Vadim Zeitlin // Modified by: // Created: 19.02.98 // Copyright: (c) 1998 Vadim Zeitlin // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// // ============================================================================ // Declarations // ============================================================================ // ---------------------------------------------------------------------------- // headers // ---------------------------------------------------------------------------- // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #if defined(__BORLANDC__) #pragma hdrstop #endif #if wxUSE_OLE #ifndef __CYGWIN10__ #include "wx/msw/private.h" #include "wx/msw/ole/oleutils.h" #include "wx/msw/ole/safearray.h" // ============================================================================ // Implementation // ============================================================================ WXDLLEXPORT BSTR wxConvertStringToOle(const wxString& str) { return wxBSTR(str).Detach(); } WXDLLEXPORT wxString wxConvertStringFromOle(BSTR bStr) { // NULL BSTR is equivalent to an empty string (this is the convention used // by VB and hence we must follow it) if ( !bStr ) return wxString(); const int len = SysStringLen(bStr); #if wxUSE_UNICODE wxString str(bStr, len); #else wxString str; if (len) { wxStringBufferLength buf(str, len); // asserts if len == 0 buf.SetLength(WideCharToMultiByte(CP_ACP, 0 /* no flags */, bStr, len /* not necessarily NUL-terminated */, buf, len, NULL, NULL /* no default char */)); } #endif return str; } // ---------------------------------------------------------------------------- // wxBSTR // ---------------------------------------------------------------------------- wxBSTR::wxBSTR(BSTR bstr, bool copy) { if ( copy ) m_bstr = ::SysAllocString(bstr); else m_bstr = bstr; } wxBSTR& wxBSTR::operator=(const wxBSTR& wxbstr) { if ( wxbstr != *this ) { Free(); m_bstr = wxbstr.GetCopy(); } return *this; } void wxBSTR::Attach(BSTR bstr) { wxCHECK_RET(m_bstr != bstr, wxS("Attaching already attached BSTR!")); Free(); m_bstr = bstr; } BSTR wxBSTR::Detach() { BSTR bstr = m_bstr; m_bstr = NULL; return bstr; } void wxBSTR::Free() { ::SysFreeString(m_bstr); m_bstr = NULL; } // ---------------------------------------------------------------------------- // Convert variants // ---------------------------------------------------------------------------- #if wxUSE_VARIANT // ---------------------------------------------------------------------------- // wxVariantDataCurrency // ---------------------------------------------------------------------------- #if wxUSE_ANY bool wxVariantDataCurrency::GetAsAny(wxAny* any) const { *any = m_value; return true; } wxVariantData* wxVariantDataCurrency::VariantDataFactory(const wxAny& any) { return new wxVariantDataCurrency(any.As()); } 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(any.As()); } 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; } // ---------------------------------------------------------------------------- // wxVariantDataSafeArray // ---------------------------------------------------------------------------- #if wxUSE_ANY bool wxVariantDataSafeArray::GetAsAny(wxAny* any) const { *any = m_value; return true; } wxVariantData* wxVariantDataSafeArray::VariantDataFactory(const wxAny& any) { return new wxVariantDataSafeArray(any.As()); } 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) { VariantInit(&oleVariant); if (variant.IsNull()) { oleVariant.vt = VT_NULL; return true; } wxString type(variant.GetType()); 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() ; } #if wxUSE_LONGLONG 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(); } else if (type == wxT("double")) { oleVariant.vt = VT_R8; oleVariant.dblVal = variant.GetDouble(); } else if (type == wxT("bool")) { oleVariant.vt = VT_BOOL; oleVariant.boolVal = variant.GetBool() ? VARIANT_TRUE : VARIANT_FALSE; } else if (type == wxT("string")) { wxString str( variant.GetString() ); oleVariant.vt = VT_BSTR; oleVariant.bstrVal = wxConvertStringToOle(str); } #if wxUSE_DATETIME else if (type == wxT("datetime")) { wxDateTime date( variant.GetDateTime() ); oleVariant.vt = VT_DATE; SYSTEMTIME st; date.GetAsMSWSysTime(&st); SystemTimeToVariantTime(&st, &oleVariant.date); } #endif else if (type == wxT("void*")) { oleVariant.vt = VT_DISPATCH; oleVariant.pdispVal = (IDispatch*) variant.GetVoidPtr(); } else if (type == wxT("list")) { wxSafeArray safeArray; if (!safeArray.CreateFromListVariant(variant)) return false; oleVariant.vt = VT_VARIANT | VT_ARRAY; oleVariant.parray = safeArray.Detach(); } else if (type == wxT("arrstring")) { wxSafeArray safeArray; if (!safeArray.CreateFromArrayString(variant.GetArrayString())) return false; oleVariant.vt = VT_BSTR | VT_ARRAY; oleVariant.parray = safeArray.Detach(); } else { oleVariant.vt = VT_NULL; return false; } return true; } WXDLLEXPORT bool wxConvertOleToVariant(const VARIANTARG& oleVariant, wxVariant& variant, long flags) { bool ok = true; if ( oleVariant.vt & VT_ARRAY ) { if ( flags & wxOleConvertVariant_ReturnSafeArrays ) { variant.SetData(new wxVariantDataSafeArray(oleVariant.parray)); } else { 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: ok = wxSafeArray::ConvertToVariant(oleVariant.parray, variant); break; case VT_BSTR: { wxArrayString strings; if ( wxSafeArray::ConvertToArrayString(oleVariant.parray, strings) ) variant = strings; else ok = false; } break; default: ok = false; break; } if ( !ok ) { wxLogDebug(wxT("unhandled VT_ARRAY type %x in wxConvertOleToVariant"), oleVariant.vt & VT_TYPEMASK); variant = wxVariant(); } } } else if ( oleVariant.vt & VT_BYREF ) { switch ( oleVariant.vt & VT_TYPEMASK ) { case VT_VARIANT: { VARIANTARG& oleReference = *((LPVARIANT)oleVariant.byref); if (!wxConvertOleToVariant(oleReference,variant)) return false; break; } default: wxLogError(wxT("wxAutomationObject::ConvertOleToVariant: [as yet] unhandled reference %X"), oleVariant.vt); return false; } } else // simply type (not array or reference) { 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)); variant = str; } break; case VT_DATE: #if wxUSE_DATETIME { SYSTEMTIME st; VariantTimeToSystemTime(oleVariant.date, &st); wxDateTime date; date.SetFromMSWSysTime(st); variant = date; } #endif // wxUSE_DATETIME break; #if wxUSE_LONGLONG case VT_I8: variant = wxLongLong(oleVariant.llVal); break; #endif // wxUSE_LONGLONG case VT_I4: variant = (long) oleVariant.lVal; break; case VT_I2: variant = (long) oleVariant.iVal; break; case VT_BOOL: variant = oleVariant.boolVal != 0; break; case VT_R4: variant = oleVariant.fltVal; break; case VT_R8: variant = oleVariant.dblVal; break; case VT_DISPATCH: variant = (void*) oleVariant.pdispVal; break; case VT_NULL: case VT_EMPTY: variant.MakeNull(); break; default: wxLogError(wxT("wxAutomationObject::ConvertOleToVariant: Unknown variant value type %X -> %X"), oleVariant.vt,oleVariant.vt&VT_TYPEMASK); return false; } } return ok; } #endif // wxUSE_VARIANT #endif // __CYGWIN10__ #endif // wxUSE_OLE