]>
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"
51 #include "wx/msw/ole/safearray.h"
53 #if defined(__VISUALC__) && (__VISUALC__ > 1000)
57 // ============================================================================
59 // ============================================================================
61 // return true if the iid is in the array
62 WXDLLEXPORT
bool IsIidFromList(REFIID riid
, const IID
*aIids
[], size_t nCount
)
64 for ( size_t i
= 0; i
< nCount
; i
++ ) {
65 if ( riid
== *aIids
[i
] )
72 WXDLLEXPORT BSTR
wxConvertStringToOle(const wxString
& str
)
74 return wxBasicString(str
).Get();
77 WXDLLEXPORT wxString
wxConvertStringFromOle(BSTR bStr
)
79 // NULL BSTR is equivalent to an empty string (this is the convention used
80 // by VB and hence we must follow it)
84 const int len
= SysStringLen(bStr
);
87 wxString
str(bStr
, len
);
92 wxStringBufferLength
buf(str
, len
); // asserts if len == 0
93 buf
.SetLength(WideCharToMultiByte(CP_ACP
, 0 /* no flags */,
94 bStr
, len
/* not necessarily NUL-terminated */,
96 NULL
, NULL
/* no default char */));
103 // ----------------------------------------------------------------------------
105 // ----------------------------------------------------------------------------
107 wxBasicString::wxBasicString(const wxString
& str
)
109 m_bstrBuf
= SysAllocString(str
.wc_str(*wxConvCurrent
));
112 wxBasicString::wxBasicString(const wxBasicString
& src
)
114 m_bstrBuf
= src
.Get();
117 wxBasicString
& wxBasicString::operator=(const wxBasicString
& src
)
119 SysReAllocString(&m_bstrBuf
, src
);
123 wxBasicString::~wxBasicString()
125 SysFreeString(m_bstrBuf
);
129 // ----------------------------------------------------------------------------
131 // ----------------------------------------------------------------------------
135 // ----------------------------------------------------------------------------
136 // wxVariantDataCurrency
137 // ----------------------------------------------------------------------------
142 bool wxVariantDataCurrency::GetAsAny(wxAny
* any
) const
148 wxVariantData
* wxVariantDataCurrency::VariantDataFactory(const wxAny
& any
)
150 return new wxVariantDataCurrency(wxANY_AS(any
, CURRENCY
));
153 REGISTER_WXANY_CONVERSION(CURRENCY
, wxVariantDataCurrency
)
157 bool wxVariantDataCurrency::Eq(wxVariantData
& data
) const
159 wxASSERT_MSG( (data
.GetType() == wxS("currency")),
160 "wxVariantDataCurrency::Eq: argument mismatch" );
162 wxVariantDataCurrency
& otherData
= (wxVariantDataCurrency
&) data
;
164 return otherData
.m_value
.int64
== m_value
.int64
;
167 #if wxUSE_STD_IOSTREAM
168 bool wxVariantDataCurrency::Write(wxSTD ostream
& str
) const
177 bool wxVariantDataCurrency::Write(wxString
& str
) const
180 if ( SUCCEEDED(VarBstrFromCy(m_value
, LOCALE_USER_DEFAULT
, 0, &bStr
)) )
182 str
= wxConvertStringFromOle(bStr
);
189 // ----------------------------------------------------------------------------
190 // wxVariantDataErrorCode
191 // ----------------------------------------------------------------------------
195 bool wxVariantDataErrorCode::GetAsAny(wxAny
* any
) const
201 wxVariantData
* wxVariantDataErrorCode::VariantDataFactory(const wxAny
& any
)
203 return new wxVariantDataErrorCode(wxANY_AS(any
, SCODE
));
206 REGISTER_WXANY_CONVERSION(SCODE
, wxVariantDataErrorCode
)
210 bool wxVariantDataErrorCode::Eq(wxVariantData
& data
) const
212 wxASSERT_MSG( (data
.GetType() == wxS("errorcode")),
213 "wxVariantDataErrorCode::Eq: argument mismatch" );
215 wxVariantDataErrorCode
& otherData
= (wxVariantDataErrorCode
&) data
;
217 return otherData
.m_value
== m_value
;
220 #if wxUSE_STD_IOSTREAM
221 bool wxVariantDataErrorCode::Write(wxSTD ostream
& str
) const
230 bool wxVariantDataErrorCode::Write(wxString
& str
) const
237 // ----------------------------------------------------------------------------
238 // wxVariantDataSafeArray
239 // ----------------------------------------------------------------------------
243 bool wxVariantDataSafeArray::GetAsAny(wxAny
* any
) const
249 wxVariantData
* wxVariantDataSafeArray::VariantDataFactory(const wxAny
& any
)
251 return new wxVariantDataSafeArray(wxANY_AS(any
, SAFEARRAY
*));
254 REGISTER_WXANY_CONVERSION(SAFEARRAY
*, wxVariantDataSafeArray
)
258 bool wxVariantDataSafeArray::Eq(wxVariantData
& data
) const
260 wxASSERT_MSG( (data
.GetType() == wxS("safearray")),
261 "wxVariantDataSafeArray::Eq: argument mismatch" );
263 wxVariantDataSafeArray
& otherData
= (wxVariantDataSafeArray
&) data
;
265 return otherData
.m_value
== m_value
;
268 #if wxUSE_STD_IOSTREAM
269 bool wxVariantDataSafeArray::Write(wxSTD ostream
& str
) const
278 bool wxVariantDataSafeArray::Write(wxString
& str
) const
280 str
.Printf(wxS("SAFEARRAY: %p"), (void*)m_value
);
284 WXDLLEXPORT
bool wxConvertVariantToOle(const wxVariant
& variant
, VARIANTARG
& oleVariant
)
286 VariantInit(&oleVariant
);
287 if (variant
.IsNull())
289 oleVariant
.vt
= VT_NULL
;
293 wxString
type(variant
.GetType());
295 if (type
== wxT("errorcode"))
297 wxVariantDataErrorCode
* const
298 ec
= wxStaticCastVariantData(variant
.GetData(),
299 wxVariantDataErrorCode
);
300 oleVariant
.vt
= VT_ERROR
;
301 oleVariant
.scode
= ec
->GetValue();
303 else if (type
== wxT("currency"))
305 wxVariantDataCurrency
* const
306 c
= wxStaticCastVariantData(variant
.GetData(),
307 wxVariantDataCurrency
);
308 oleVariant
.vt
= VT_CY
;
309 oleVariant
.cyVal
= c
->GetValue();
311 else if (type
== wxT("safearray"))
313 wxVariantDataSafeArray
* const
314 vsa
= wxStaticCastVariantData(variant
.GetData(),
315 wxVariantDataSafeArray
);
316 SAFEARRAY
* psa
= vsa
->GetValue();
320 HRESULT hr
= SafeArrayGetVartype(psa
, &vt
);
323 wxLogApiError(wxS("SafeArrayGetVartype()"), hr
);
324 SafeArrayDestroy(psa
);
327 oleVariant
.vt
= vt
| VT_ARRAY
;
328 oleVariant
.parray
= psa
;
330 else if (type
== wxT("long"))
332 oleVariant
.vt
= VT_I4
;
333 oleVariant
.lVal
= variant
.GetLong() ;
335 // Original VC6 came with SDK too old to contain VARIANT::llVal declaration
336 // and there doesn't seem to be any way to test for it as Microsoft simply
337 // added it to the later version of oaidl.h without changing anything else.
338 // So assume it's not present for VC6, even though it might be if an
339 // updated SDK is used. In this case the user would need to disable this
341 #if wxUSE_LONGLONG && !defined(__VISUALC6__)
342 else if (type
== wxT("longlong"))
344 oleVariant
.vt
= VT_I8
;
345 oleVariant
.llVal
= variant
.GetLongLong().GetValue();
348 else if (type
== wxT("char"))
350 oleVariant
.vt
=VT_I1
; // Signed Char
351 oleVariant
.cVal
=variant
.GetChar();
353 else if (type
== wxT("double"))
355 oleVariant
.vt
= VT_R8
;
356 oleVariant
.dblVal
= variant
.GetDouble();
358 else if (type
== wxT("bool"))
360 oleVariant
.vt
= VT_BOOL
;
361 oleVariant
.boolVal
= variant
.GetBool() ? VARIANT_TRUE
: VARIANT_FALSE
;
363 else if (type
== wxT("string"))
365 wxString
str( variant
.GetString() );
366 oleVariant
.vt
= VT_BSTR
;
367 oleVariant
.bstrVal
= wxConvertStringToOle(str
);
370 else if (type
== wxT("datetime"))
372 wxDateTime
date( variant
.GetDateTime() );
373 oleVariant
.vt
= VT_DATE
;
376 date
.GetAsMSWSysTime(&st
);
378 SystemTimeToVariantTime(&st
, &oleVariant
.date
);
381 else if (type
== wxT("void*"))
383 oleVariant
.vt
= VT_DISPATCH
;
384 oleVariant
.pdispVal
= (IDispatch
*) variant
.GetVoidPtr();
386 else if (type
== wxT("list"))
388 wxSafeArray
<VT_VARIANT
> safeArray
;
389 if (!safeArray
.CreateFromListVariant(variant
))
392 oleVariant
.vt
= VT_VARIANT
| VT_ARRAY
;
393 oleVariant
.parray
= safeArray
.Detach();
395 else if (type
== wxT("arrstring"))
397 wxSafeArray
<VT_BSTR
> safeArray
;
399 if (!safeArray
.CreateFromArrayString(variant
.GetArrayString()))
402 oleVariant
.vt
= VT_BSTR
| VT_ARRAY
;
403 oleVariant
.parray
= safeArray
.Detach();
407 oleVariant
.vt
= VT_NULL
;
414 #define VT_TYPEMASK 0xfff
418 wxConvertOleToVariant(const VARIANTARG
& oleVariant
, wxVariant
& variant
)
421 if ( oleVariant
.vt
& VT_ARRAY
)
423 // TODO: We currently return arrays as wxVariant of the list type
424 // containing the flattened form of array but we should allow
425 // getting it as wxVariantDataSafeArray instead. Doing this is
426 // simple, we'd just need to do something like this:
428 // if ( oleVariant.parray && SafeArrayGetDim(oleVariant.parray) > 1 )
430 // variant.SetData(new wxVariantDataSafeArray(oleVariant.parray));
433 // but currently we don't do it for compatibility reasons.
434 switch (oleVariant
.vt
& VT_TYPEMASK
)
437 ok
= wxSafeArray
<VT_I2
>::ConvertToVariant(oleVariant
.parray
, variant
);
440 ok
= wxSafeArray
<VT_I4
>::ConvertToVariant(oleVariant
.parray
, variant
);
443 ok
= wxSafeArray
<VT_R4
>::ConvertToVariant(oleVariant
.parray
, variant
);
446 ok
= wxSafeArray
<VT_R8
>::ConvertToVariant(oleVariant
.parray
, variant
);
449 ok
= wxSafeArray
<VT_VARIANT
>::ConvertToVariant(oleVariant
.parray
, variant
);
453 wxArrayString strings
;
454 if ( wxSafeArray
<VT_BSTR
>::ConvertToArrayString(oleVariant
.parray
, strings
) )
466 wxLogDebug(wxT("unhandled VT_ARRAY type %x in wxConvertOleToVariant"),
467 oleVariant
.vt
& VT_TYPEMASK
);
468 variant
= wxVariant();
471 else if ( oleVariant
.vt
& VT_BYREF
)
473 switch ( oleVariant
.vt
& VT_TYPEMASK
)
477 VARIANTARG
& oleReference
= *((LPVARIANT
)oleVariant
.byref
);
478 if (!wxConvertOleToVariant(oleReference
,variant
))
484 wxLogError(wxT("wxAutomationObject::ConvertOleToVariant: [as yet] unhandled reference %X"),
489 else // simply type (not array or reference)
491 switch ( oleVariant
.vt
& VT_TYPEMASK
)
494 variant
.SetData(new wxVariantDataErrorCode(oleVariant
.scode
));
498 variant
.SetData(new wxVariantDataCurrency(oleVariant
.cyVal
));
503 wxString
str(wxConvertStringFromOle(oleVariant
.bstrVal
));
512 VariantTimeToSystemTime(oleVariant
.date
, &st
);
515 date
.SetFromMSWSysTime(st
);
518 #endif // wxUSE_DATETIME
521 // See the comment before the __VISUALC6__ test above.
522 #if wxUSE_LONGLONG && !defined(__VISUALC6__)
524 variant
= wxLongLong(oleVariant
.llVal
);
526 #endif // wxUSE_LONGLONG
529 variant
= (long) oleVariant
.lVal
;
533 variant
= (long) oleVariant
.iVal
;
537 variant
= oleVariant
.boolVal
!= 0;
541 variant
= oleVariant
.fltVal
;
545 variant
= oleVariant
.dblVal
;
549 variant
= (void*) oleVariant
.pdispVal
;
557 break; // Ignore Empty Variant, used only during destruction of objects
560 wxLogError(wxT("wxAutomationObject::ConvertOleToVariant: Unknown variant value type %X -> %X"),
561 oleVariant
.vt
,oleVariant
.vt
&VT_TYPEMASK
);
569 #endif // wxUSE_VARIANT
572 // ----------------------------------------------------------------------------
574 // ----------------------------------------------------------------------------
578 #if wxDEBUG_LEVEL && (( defined(__VISUALC__) && (__VISUALC__ > 1000) ))
579 static wxString
GetIidName(REFIID riid
)
581 // an association between symbolic name and numeric value of an IID
584 const wxChar
*szName
;
587 // construct the table containing all known interfaces
588 #define ADD_KNOWN_IID(name) { &IID_I##name, wxT(#name) }
590 static const KNOWN_IID aKnownIids
[] = {
591 ADD_KNOWN_IID(AdviseSink
),
592 ADD_KNOWN_IID(AdviseSink2
),
593 ADD_KNOWN_IID(BindCtx
),
594 ADD_KNOWN_IID(ClassFactory
),
595 #if ( !defined( __VISUALC__) || (__VISUALC__!=1010) )
596 ADD_KNOWN_IID(ContinueCallback
),
597 ADD_KNOWN_IID(EnumOleDocumentViews
),
598 ADD_KNOWN_IID(OleCommandTarget
),
599 ADD_KNOWN_IID(OleDocument
),
600 ADD_KNOWN_IID(OleDocumentSite
),
601 ADD_KNOWN_IID(OleDocumentView
),
602 ADD_KNOWN_IID(Print
),
604 ADD_KNOWN_IID(DataAdviseHolder
),
605 ADD_KNOWN_IID(DataObject
),
606 ADD_KNOWN_IID(Debug
),
607 ADD_KNOWN_IID(DebugStream
),
608 ADD_KNOWN_IID(DfReserved1
),
609 ADD_KNOWN_IID(DfReserved2
),
610 ADD_KNOWN_IID(DfReserved3
),
611 ADD_KNOWN_IID(Dispatch
),
612 ADD_KNOWN_IID(DropSource
),
613 ADD_KNOWN_IID(DropTarget
),
614 ADD_KNOWN_IID(EnumCallback
),
615 ADD_KNOWN_IID(EnumFORMATETC
),
616 ADD_KNOWN_IID(EnumGeneric
),
617 ADD_KNOWN_IID(EnumHolder
),
618 ADD_KNOWN_IID(EnumMoniker
),
619 ADD_KNOWN_IID(EnumOLEVERB
),
620 ADD_KNOWN_IID(EnumSTATDATA
),
621 ADD_KNOWN_IID(EnumSTATSTG
),
622 ADD_KNOWN_IID(EnumString
),
623 ADD_KNOWN_IID(EnumUnknown
),
624 ADD_KNOWN_IID(EnumVARIANT
),
625 ADD_KNOWN_IID(ExternalConnection
),
626 ADD_KNOWN_IID(InternalMoniker
),
627 ADD_KNOWN_IID(LockBytes
),
628 ADD_KNOWN_IID(Malloc
),
629 ADD_KNOWN_IID(Marshal
),
630 ADD_KNOWN_IID(MessageFilter
),
631 ADD_KNOWN_IID(Moniker
),
632 ADD_KNOWN_IID(OleAdviseHolder
),
633 ADD_KNOWN_IID(OleCache
),
634 ADD_KNOWN_IID(OleCache2
),
635 ADD_KNOWN_IID(OleCacheControl
),
636 ADD_KNOWN_IID(OleClientSite
),
637 ADD_KNOWN_IID(OleContainer
),
638 ADD_KNOWN_IID(OleInPlaceActiveObject
),
639 ADD_KNOWN_IID(OleInPlaceFrame
),
640 ADD_KNOWN_IID(OleInPlaceObject
),
641 ADD_KNOWN_IID(OleInPlaceSite
),
642 ADD_KNOWN_IID(OleInPlaceUIWindow
),
643 ADD_KNOWN_IID(OleItemContainer
),
644 ADD_KNOWN_IID(OleLink
),
645 ADD_KNOWN_IID(OleManager
),
646 ADD_KNOWN_IID(OleObject
),
647 ADD_KNOWN_IID(OlePresObj
),
648 ADD_KNOWN_IID(OleWindow
),
649 ADD_KNOWN_IID(PSFactory
),
650 ADD_KNOWN_IID(ParseDisplayName
),
651 ADD_KNOWN_IID(Persist
),
652 ADD_KNOWN_IID(PersistFile
),
653 ADD_KNOWN_IID(PersistStorage
),
654 ADD_KNOWN_IID(PersistStream
),
655 ADD_KNOWN_IID(ProxyManager
),
656 ADD_KNOWN_IID(RootStorage
),
657 ADD_KNOWN_IID(RpcChannel
),
658 ADD_KNOWN_IID(RpcProxy
),
659 ADD_KNOWN_IID(RpcStub
),
660 ADD_KNOWN_IID(RunnableObject
),
661 ADD_KNOWN_IID(RunningObjectTable
),
662 ADD_KNOWN_IID(StdMarshalInfo
),
663 ADD_KNOWN_IID(Storage
),
664 ADD_KNOWN_IID(Stream
),
665 ADD_KNOWN_IID(StubManager
),
666 ADD_KNOWN_IID(Unknown
),
667 ADD_KNOWN_IID(ViewObject
),
668 ADD_KNOWN_IID(ViewObject2
),
671 // don't clobber preprocessor name space
674 // try to find the interface in the table
675 for ( size_t ui
= 0; ui
< WXSIZEOF(aKnownIids
); ui
++ ) {
676 if ( riid
== *aKnownIids
[ui
].pIid
) {
677 return aKnownIids
[ui
].szName
;
682 // unknown IID, just transform to string
684 return wxString((const wxChar
*)uuid
);
686 return wxEmptyString
;
690 WXDLLEXPORT
void wxLogQueryInterface(const wxChar
*szInterface
, REFIID riid
)
692 wxLogTrace(wxTRACE_OleCalls
, wxT("%s::QueryInterface (iid = %s)"),
693 szInterface
, GetIidName(riid
).c_str());
696 WXDLLEXPORT
void wxLogAddRef(const wxChar
*szInterface
, ULONG cRef
)
698 wxLogTrace(wxTRACE_OleCalls
, wxT("After %s::AddRef: m_cRef = %d"), szInterface
, cRef
+ 1);
701 WXDLLEXPORT
void wxLogRelease(const wxChar
*szInterface
, ULONG cRef
)
703 wxLogTrace(wxTRACE_OleCalls
, wxT("After %s::Release: m_cRef = %d"), szInterface
, cRef
- 1);
706 #endif // wxDEBUG_LEVEL
708 #endif // wxUSE_DATAOBJ
710 #endif // __CYGWIN10__