]>
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__