]>
git.saurik.com Git - wxWidgets.git/blob - src/msw/ole/oleutils.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/ole/oleutils.cpp
3 // Purpose: implementation of OLE helper functions
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
23 #if defined(__BORLANDC__)
35 #include "wx/msw/private.h"
47 #include "wx/msw/ole/uuid.h"
50 #include "wx/msw/ole/oleutils.h"
52 #if defined(__VISUALC__) && (__VISUALC__ > 1000)
56 // ============================================================================
58 // ============================================================================
60 // return true if the iid is in the array
61 WXDLLEXPORT
bool IsIidFromList(REFIID riid
, const IID
*aIids
[], size_t nCount
)
63 for ( size_t i
= 0; i
< nCount
; i
++ ) {
64 if ( riid
== *aIids
[i
] )
71 WXDLLEXPORT BSTR
wxConvertStringToOle(const wxString
& str
)
73 return wxBasicString(str
).Get();
76 WXDLLEXPORT wxString
wxConvertStringFromOle(BSTR bStr
)
78 // NULL BSTR is equivalent to an empty string (this is the convention used
79 // by VB and hence we must follow it)
83 const int len
= SysStringLen(bStr
);
86 wxString
str(bStr
, len
);
91 wxStringBufferLength
buf(str
, len
); // asserts if len == 0
92 buf
.SetLength(WideCharToMultiByte(CP_ACP
, 0 /* no flags */,
93 bStr
, len
/* not necessarily NUL-terminated */,
95 NULL
, NULL
/* no default char */));
102 // ----------------------------------------------------------------------------
104 // ----------------------------------------------------------------------------
106 wxBasicString::wxBasicString(const wxString
& str
)
108 m_bstrBuf
= SysAllocString(str
.wc_str(*wxConvCurrent
));
111 wxBasicString::wxBasicString(const wxBasicString
& src
)
113 m_bstrBuf
= src
.Get();
116 wxBasicString
& wxBasicString::operator=(const wxBasicString
& src
)
118 SysReAllocString(&m_bstrBuf
, src
);
122 wxBasicString::~wxBasicString()
124 SysFreeString(m_bstrBuf
);
128 // ----------------------------------------------------------------------------
130 // ----------------------------------------------------------------------------
137 // Helper class for creating and filling SAFEARRAY. To use it, call Create()
138 // first, then SetElement() for each element and finally Detach() the SAFEARRAY
139 // from it if you don't want it to be deleted when this class is.
140 class wxSafeArrayHelper
144 ~wxSafeArrayHelper();
146 bool Create(VARTYPE vt
, long count
); // creates and locks the array
148 bool SetElement(size_t index
, const wxVariant
& variant
);
149 bool SetElement(size_t index
, const wxString
& str
);
151 SAFEARRAY
* Detach(); // unlocks the array and gives up its ownership
159 wxSafeArrayHelper::wxSafeArrayHelper()
164 wxSafeArrayHelper::~wxSafeArrayHelper()
169 SafeArrayDestroy(m_array
);
173 bool wxSafeArrayHelper::Create(VARTYPE vt
, long count
)
175 SAFEARRAYBOUND saBound
;
178 saBound
.cElements
= count
;
179 m_array
= SafeArrayCreate(vt
, 1, &saBound
);
182 return SUCCEEDED( SafeArrayLock(m_array
) );
185 bool wxSafeArrayHelper::SetElement(size_t index
, const wxVariant
& variant
)
187 VARIANT
* data
= (VARIANT
*)m_array
->pvData
;
188 return wxConvertVariantToOle(variant
, data
[index
]);
191 bool wxSafeArrayHelper::SetElement(size_t index
, const wxString
& str
)
193 BSTR bstr
= wxConvertStringToOle(str
);
195 if ( !bstr
&& !str
.empty() )
197 // BSTR can be NULL for empty strings but if the string was
198 // not empty, it means we failed to allocate memory for it.
202 BSTR
* data
= (BSTR
*)m_array
->pvData
;
207 SAFEARRAY
* wxSafeArrayHelper::Detach()
210 SAFEARRAY
* result
= m_array
;
215 void wxSafeArrayHelper::Unlock()
218 SafeArrayUnlock(m_array
);
221 } // unnamed namespace
224 // ----------------------------------------------------------------------------
225 // wxVariantDataCurrency
226 // ----------------------------------------------------------------------------
231 bool wxVariantDataCurrency::GetAsAny(wxAny
* any
) const
237 wxVariantData
* wxVariantDataCurrency::VariantDataFactory(const wxAny
& any
)
239 return new wxVariantDataCurrency(wxANY_AS(any
, CURRENCY
));
242 REGISTER_WXANY_CONVERSION(CURRENCY
, wxVariantDataCurrency
)
246 bool wxVariantDataCurrency::Eq(wxVariantData
& data
) const
248 wxASSERT_MSG( (data
.GetType() == wxS("currency")),
249 "wxVariantDataCurrency::Eq: argument mismatch" );
251 wxVariantDataCurrency
& otherData
= (wxVariantDataCurrency
&) data
;
253 return otherData
.m_value
.int64
== m_value
.int64
;
256 #if wxUSE_STD_IOSTREAM
257 bool wxVariantDataCurrency::Write(wxSTD ostream
& str
) const
266 bool wxVariantDataCurrency::Write(wxString
& str
) const
269 if ( SUCCEEDED(VarBstrFromCy(m_value
, LOCALE_USER_DEFAULT
, 0, &bStr
)) )
271 str
= wxConvertStringFromOle(bStr
);
278 // ----------------------------------------------------------------------------
279 // wxVariantDataErrorCode
280 // ----------------------------------------------------------------------------
284 bool wxVariantDataErrorCode::GetAsAny(wxAny
* any
) const
290 wxVariantData
* wxVariantDataErrorCode::VariantDataFactory(const wxAny
& any
)
292 return new wxVariantDataErrorCode(wxANY_AS(any
, SCODE
));
295 REGISTER_WXANY_CONVERSION(SCODE
, wxVariantDataErrorCode
)
299 bool wxVariantDataErrorCode::Eq(wxVariantData
& data
) const
301 wxASSERT_MSG( (data
.GetType() == wxS("errorcode")),
302 "wxVariantDataErrorCode::Eq: argument mismatch" );
304 wxVariantDataErrorCode
& otherData
= (wxVariantDataErrorCode
&) data
;
306 return otherData
.m_value
== m_value
;
309 #if wxUSE_STD_IOSTREAM
310 bool wxVariantDataErrorCode::Write(wxSTD ostream
& str
) const
319 bool wxVariantDataErrorCode::Write(wxString
& str
) const
327 WXDLLEXPORT
bool wxConvertVariantToOle(const wxVariant
& variant
, VARIANTARG
& oleVariant
)
329 VariantInit(&oleVariant
);
330 if (variant
.IsNull())
332 oleVariant
.vt
= VT_NULL
;
336 wxString
type(variant
.GetType());
338 if (type
== wxT("errorcode"))
340 wxVariantDataErrorCode
* const
341 ec
= wxDynamicCastVariantData(variant
.GetData(),
342 wxVariantDataErrorCode
);
343 oleVariant
.vt
= VT_ERROR
;
344 oleVariant
.scode
= ec
->GetValue();
346 else if (type
== wxT("currency"))
348 wxVariantDataCurrency
* const
349 c
= wxDynamicCastVariantData(variant
.GetData(),
350 wxVariantDataCurrency
);
351 oleVariant
.vt
= VT_CY
;
352 oleVariant
.cyVal
= c
->GetValue();
354 else if (type
== wxT("long"))
356 oleVariant
.vt
= VT_I4
;
357 oleVariant
.lVal
= variant
.GetLong() ;
359 // Original VC6 came with SDK too old to contain VARIANT::llVal declaration
360 // and there doesn't seem to be any way to test for it as Microsoft simply
361 // added it to the later version of oaidl.h without changing anything else.
362 // So assume it's not present for VC6, even though it might be if an
363 // updated SDK is used. In this case the user would need to disable this
365 #if wxUSE_LONGLONG && !defined(__VISUALC6__)
366 else if (type
== wxT("longlong"))
368 oleVariant
.vt
= VT_I8
;
369 oleVariant
.llVal
= variant
.GetLongLong().GetValue();
372 else if (type
== wxT("char"))
374 oleVariant
.vt
=VT_I1
; // Signed Char
375 oleVariant
.cVal
=variant
.GetChar();
377 else if (type
== wxT("double"))
379 oleVariant
.vt
= VT_R8
;
380 oleVariant
.dblVal
= variant
.GetDouble();
382 else if (type
== wxT("bool"))
384 oleVariant
.vt
= VT_BOOL
;
385 oleVariant
.boolVal
= variant
.GetBool() ? VARIANT_TRUE
: VARIANT_FALSE
;
387 else if (type
== wxT("string"))
389 wxString
str( variant
.GetString() );
390 oleVariant
.vt
= VT_BSTR
;
391 oleVariant
.bstrVal
= wxConvertStringToOle(str
);
394 else if (type
== wxT("datetime"))
396 wxDateTime
date( variant
.GetDateTime() );
397 oleVariant
.vt
= VT_DATE
;
400 date
.GetAsMSWSysTime(&st
);
402 SystemTimeToVariantTime(&st
, &oleVariant
.date
);
405 else if (type
== wxT("void*"))
407 oleVariant
.vt
= VT_DISPATCH
;
408 oleVariant
.pdispVal
= (IDispatch
*) variant
.GetVoidPtr();
410 else if (type
== wxT("list"))
412 wxSafeArrayHelper sah
;
414 if (!sah
.Create(VT_VARIANT
, variant
.GetCount()))
417 for (size_t i
= 0; i
< variant
.GetCount(); i
++)
419 if (!sah
.SetElement(i
, variant
[i
]))
423 oleVariant
.vt
= VT_VARIANT
| VT_ARRAY
;
424 oleVariant
.parray
= sah
.Detach();
426 else if (type
== wxT("arrstring"))
428 wxArrayString
strings(variant
.GetArrayString());
429 wxSafeArrayHelper sah
;
431 if (!sah
.Create(VT_BSTR
, strings
.GetCount()))
434 for (size_t i
= 0; i
< strings
.GetCount(); i
++)
436 if (!sah
.SetElement(i
, strings
[i
]))
440 oleVariant
.vt
= VT_BSTR
| VT_ARRAY
;
441 oleVariant
.parray
= sah
.Detach();
445 oleVariant
.vt
= VT_NULL
;
452 #define VT_TYPEMASK 0xfff
456 wxConvertOleToVariant(const VARIANTARG
& oleVariant
, wxVariant
& variant
)
459 if ( oleVariant
.vt
& VT_ARRAY
)
462 // Compute the total number of elements in all array dimensions
464 for ( int cDims
= 0; cDims
< oleVariant
.parray
->cDims
; cDims
++ )
465 cElements
*= oleVariant
.parray
->rgsabound
[cDims
].cElements
;
467 // Get a pointer to the data
469 HRESULT hr
= SafeArrayAccessData(oleVariant
.parray
, &pvdata
);
473 switch (oleVariant
.vt
& VT_TYPEMASK
)
478 VARIANTARG
*variant_data
=(VARIANTARG
*)pvdata
;
479 for ( int i
= 0; i
< cElements
; i
++ )
481 VARIANTARG
& oleElement
= variant_data
[i
];
483 if ( !wxConvertOleToVariant(oleElement
, vElement
) )
490 variant
.Append(vElement
);
497 wxArrayString strings
;
498 BSTR
*string_val
=(BSTR
*)pvdata
;
499 for ( int i
= 0; i
< cElements
; ++i
)
501 wxString str
=wxConvertStringFromOle(*string_val
);
510 wxLogDebug(wxT("unhandled VT_ARRAY type %x in wxConvertOleToVariant"),
511 oleVariant
.vt
& VT_TYPEMASK
);
512 variant
= wxVariant();
517 SafeArrayUnaccessData(oleVariant
.parray
);
519 else if ( oleVariant
.vt
& VT_BYREF
)
521 switch ( oleVariant
.vt
& VT_TYPEMASK
)
525 VARIANTARG
& oleReference
= *((LPVARIANT
)oleVariant
.byref
);
526 if (!wxConvertOleToVariant(oleReference
,variant
))
532 wxLogError(wxT("wxAutomationObject::ConvertOleToVariant: [as yet] unhandled reference %X"),
537 else // simply type (not array or reference)
539 switch ( oleVariant
.vt
& VT_TYPEMASK
)
542 variant
.SetData(new wxVariantDataErrorCode(oleVariant
.scode
));
546 variant
.SetData(new wxVariantDataCurrency(oleVariant
.cyVal
));
551 wxString
str(wxConvertStringFromOle(oleVariant
.bstrVal
));
560 VariantTimeToSystemTime(oleVariant
.date
, &st
);
563 date
.SetFromMSWSysTime(st
);
566 #endif // wxUSE_DATETIME
569 // See the comment before the __VISUALC6__ test above.
570 #if wxUSE_LONGLONG && !defined(__VISUALC6__)
572 variant
= wxLongLong(oleVariant
.llVal
);
574 #endif // wxUSE_LONGLONG
577 variant
= (long) oleVariant
.lVal
;
581 variant
= (long) oleVariant
.iVal
;
585 variant
= oleVariant
.boolVal
!= 0;
589 variant
= oleVariant
.fltVal
;
593 variant
= oleVariant
.dblVal
;
597 variant
= (void*) oleVariant
.pdispVal
;
605 break; // Ignore Empty Variant, used only during destruction of objects
608 wxLogError(wxT("wxAutomationObject::ConvertOleToVariant: Unknown variant value type %X -> %X"),
609 oleVariant
.vt
,oleVariant
.vt
&VT_TYPEMASK
);
617 #endif // wxUSE_VARIANT
620 // ----------------------------------------------------------------------------
622 // ----------------------------------------------------------------------------
626 #if wxDEBUG_LEVEL && (( defined(__VISUALC__) && (__VISUALC__ > 1000) ))
627 static wxString
GetIidName(REFIID riid
)
629 // an association between symbolic name and numeric value of an IID
632 const wxChar
*szName
;
635 // construct the table containing all known interfaces
636 #define ADD_KNOWN_IID(name) { &IID_I##name, wxT(#name) }
638 static const KNOWN_IID aKnownIids
[] = {
639 ADD_KNOWN_IID(AdviseSink
),
640 ADD_KNOWN_IID(AdviseSink2
),
641 ADD_KNOWN_IID(BindCtx
),
642 ADD_KNOWN_IID(ClassFactory
),
643 #if ( !defined( __VISUALC__) || (__VISUALC__!=1010) )
644 ADD_KNOWN_IID(ContinueCallback
),
645 ADD_KNOWN_IID(EnumOleDocumentViews
),
646 ADD_KNOWN_IID(OleCommandTarget
),
647 ADD_KNOWN_IID(OleDocument
),
648 ADD_KNOWN_IID(OleDocumentSite
),
649 ADD_KNOWN_IID(OleDocumentView
),
650 ADD_KNOWN_IID(Print
),
652 ADD_KNOWN_IID(DataAdviseHolder
),
653 ADD_KNOWN_IID(DataObject
),
654 ADD_KNOWN_IID(Debug
),
655 ADD_KNOWN_IID(DebugStream
),
656 ADD_KNOWN_IID(DfReserved1
),
657 ADD_KNOWN_IID(DfReserved2
),
658 ADD_KNOWN_IID(DfReserved3
),
659 ADD_KNOWN_IID(Dispatch
),
660 ADD_KNOWN_IID(DropSource
),
661 ADD_KNOWN_IID(DropTarget
),
662 ADD_KNOWN_IID(EnumCallback
),
663 ADD_KNOWN_IID(EnumFORMATETC
),
664 ADD_KNOWN_IID(EnumGeneric
),
665 ADD_KNOWN_IID(EnumHolder
),
666 ADD_KNOWN_IID(EnumMoniker
),
667 ADD_KNOWN_IID(EnumOLEVERB
),
668 ADD_KNOWN_IID(EnumSTATDATA
),
669 ADD_KNOWN_IID(EnumSTATSTG
),
670 ADD_KNOWN_IID(EnumString
),
671 ADD_KNOWN_IID(EnumUnknown
),
672 ADD_KNOWN_IID(EnumVARIANT
),
673 ADD_KNOWN_IID(ExternalConnection
),
674 ADD_KNOWN_IID(InternalMoniker
),
675 ADD_KNOWN_IID(LockBytes
),
676 ADD_KNOWN_IID(Malloc
),
677 ADD_KNOWN_IID(Marshal
),
678 ADD_KNOWN_IID(MessageFilter
),
679 ADD_KNOWN_IID(Moniker
),
680 ADD_KNOWN_IID(OleAdviseHolder
),
681 ADD_KNOWN_IID(OleCache
),
682 ADD_KNOWN_IID(OleCache2
),
683 ADD_KNOWN_IID(OleCacheControl
),
684 ADD_KNOWN_IID(OleClientSite
),
685 ADD_KNOWN_IID(OleContainer
),
686 ADD_KNOWN_IID(OleInPlaceActiveObject
),
687 ADD_KNOWN_IID(OleInPlaceFrame
),
688 ADD_KNOWN_IID(OleInPlaceObject
),
689 ADD_KNOWN_IID(OleInPlaceSite
),
690 ADD_KNOWN_IID(OleInPlaceUIWindow
),
691 ADD_KNOWN_IID(OleItemContainer
),
692 ADD_KNOWN_IID(OleLink
),
693 ADD_KNOWN_IID(OleManager
),
694 ADD_KNOWN_IID(OleObject
),
695 ADD_KNOWN_IID(OlePresObj
),
696 ADD_KNOWN_IID(OleWindow
),
697 ADD_KNOWN_IID(PSFactory
),
698 ADD_KNOWN_IID(ParseDisplayName
),
699 ADD_KNOWN_IID(Persist
),
700 ADD_KNOWN_IID(PersistFile
),
701 ADD_KNOWN_IID(PersistStorage
),
702 ADD_KNOWN_IID(PersistStream
),
703 ADD_KNOWN_IID(ProxyManager
),
704 ADD_KNOWN_IID(RootStorage
),
705 ADD_KNOWN_IID(RpcChannel
),
706 ADD_KNOWN_IID(RpcProxy
),
707 ADD_KNOWN_IID(RpcStub
),
708 ADD_KNOWN_IID(RunnableObject
),
709 ADD_KNOWN_IID(RunningObjectTable
),
710 ADD_KNOWN_IID(StdMarshalInfo
),
711 ADD_KNOWN_IID(Storage
),
712 ADD_KNOWN_IID(Stream
),
713 ADD_KNOWN_IID(StubManager
),
714 ADD_KNOWN_IID(Unknown
),
715 ADD_KNOWN_IID(ViewObject
),
716 ADD_KNOWN_IID(ViewObject2
),
719 // don't clobber preprocessor name space
722 // try to find the interface in the table
723 for ( size_t ui
= 0; ui
< WXSIZEOF(aKnownIids
); ui
++ ) {
724 if ( riid
== *aKnownIids
[ui
].pIid
) {
725 return aKnownIids
[ui
].szName
;
730 // unknown IID, just transform to string
732 return wxString((const wxChar
*)uuid
);
734 return wxEmptyString
;
738 WXDLLEXPORT
void wxLogQueryInterface(const wxChar
*szInterface
, REFIID riid
)
740 wxLogTrace(wxTRACE_OleCalls
, wxT("%s::QueryInterface (iid = %s)"),
741 szInterface
, GetIidName(riid
).c_str());
744 WXDLLEXPORT
void wxLogAddRef(const wxChar
*szInterface
, ULONG cRef
)
746 wxLogTrace(wxTRACE_OleCalls
, wxT("After %s::AddRef: m_cRef = %d"), szInterface
, cRef
+ 1);
749 WXDLLEXPORT
void wxLogRelease(const wxChar
*szInterface
, ULONG cRef
)
751 wxLogTrace(wxTRACE_OleCalls
, wxT("After %s::Release: m_cRef = %d"), szInterface
, cRef
- 1);
754 #endif // wxDEBUG_LEVEL
756 #endif // wxUSE_DATAOBJ
758 #endif // __CYGWIN10__