]> git.saurik.com Git - wxWidgets.git/blob - src/msw/ole/oleutils.cpp
8cf7899187bd82f42a82bb3a981610084a9896a6
[wxWidgets.git] / src / msw / ole / oleutils.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/ole/oleutils.cpp
3 // Purpose: implementation of OLE helper functions
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 19.02.98
7 // RCS-ID: $Id$
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // Declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #if defined(__BORLANDC__)
24 #pragma hdrstop
25 #endif
26
27 #if wxUSE_OLE
28
29 #ifndef WX_PRECOMP
30 #include "wx/log.h"
31 #endif
32
33 #ifndef __CYGWIN10__
34
35 #include "wx/msw/private.h"
36
37 #ifdef __WXWINCE__
38 #include <winreg.h>
39 #include <ole2.h>
40
41 #define GUID_DEFINED
42 #define UUID_DEFINED
43 #endif
44
45 // OLE
46 #ifndef __WXWINCE__
47 #include "wx/msw/ole/uuid.h"
48 #endif
49
50 #include "wx/msw/ole/oleutils.h"
51
52 #if defined(__VISUALC__) && (__VISUALC__ > 1000)
53 #include <docobj.h>
54 #endif
55
56 // ============================================================================
57 // Implementation
58 // ============================================================================
59
60 // return true if the iid is in the array
61 bool IsIidFromList(REFIID riid, const IID *aIids[], size_t nCount)
62 {
63 for ( size_t i = 0; i < nCount; i++ ) {
64 if ( riid == *aIids[i] )
65 return true;
66 }
67
68 return false;
69 }
70
71 WXDLLEXPORT BSTR wxConvertStringToOle(const wxString& str)
72 {
73 return wxBasicString(str).Get();
74 }
75
76 WXDLLEXPORT wxString wxConvertStringFromOle(BSTR bStr)
77 {
78 // NULL BSTR is equivalent to an empty string (this is the convention used
79 // by VB and hence we must follow it)
80 if ( !bStr )
81 return wxString();
82
83 const int len = SysStringLen(bStr);
84
85 #if wxUSE_UNICODE
86 wxString str(bStr, len);
87 #else
88 wxString str;
89 if (len)
90 {
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 */,
94 buf, len,
95 NULL, NULL /* no default char */));
96 }
97 #endif
98
99 return str;
100 }
101
102 // ----------------------------------------------------------------------------
103 // wxBasicString
104 // ----------------------------------------------------------------------------
105
106 wxBasicString::wxBasicString(const wxString& str)
107 {
108 m_bstrBuf = SysAllocString(str.wc_str(*wxConvCurrent));
109 }
110
111 wxBasicString::wxBasicString(const wxBasicString& src)
112 {
113 m_bstrBuf = src.Get();
114 }
115
116 wxBasicString& wxBasicString::operator=(const wxBasicString& src)
117 {
118 SysReAllocString(&m_bstrBuf, src);
119 return *this;
120 }
121
122 wxBasicString::~wxBasicString()
123 {
124 SysFreeString(m_bstrBuf);
125 }
126
127
128 // ----------------------------------------------------------------------------
129 // Convert variants
130 // ----------------------------------------------------------------------------
131
132 #if wxUSE_VARIANT
133
134 /*
135 * wxClearVariant
136 *
137 * Zeros a variant structure without regard to current contents
138 */
139 void wxClearVariant(VARIANTARG *pvarg)
140 {
141 pvarg->vt = VT_EMPTY;
142 pvarg->wReserved1 = 0;
143 pvarg->wReserved2 = 0;
144 pvarg->wReserved3 = 0;
145 pvarg->lVal = 0;
146 }
147
148 /*
149 * wxReleaseVariant
150 *
151 * Clears a particular variant structure and releases any external objects
152 * or memory contained in the variant. Supports the data types listed above.
153 */
154 void wxReleaseVariant(VARIANTARG *pvarg)
155 {
156 VARTYPE vt;
157 VARIANTARG _huge *pvargArray;
158 LONG lLBound, lUBound, l;
159
160 vt = (VARTYPE)(pvarg->vt & 0xfff); // mask off flags
161
162 // check if an array. If so, free its contents, then the array itself.
163 if (V_ISARRAY(pvarg))
164 {
165 // variant arrays are all this routine currently knows about. Since a
166 // variant can contain anything (even other arrays), call ourselves
167 // recursively.
168 if (vt == VT_VARIANT)
169 {
170 SafeArrayGetLBound(pvarg->parray, 1, &lLBound);
171 SafeArrayGetUBound(pvarg->parray, 1, &lUBound);
172
173 if (lUBound > lLBound)
174 {
175 lUBound -= lLBound;
176
177 SafeArrayAccessData(pvarg->parray, (void**)&pvargArray);
178
179 for (l = 0; l < lUBound; l++)
180 {
181 wxReleaseVariant(pvargArray);
182 pvargArray++;
183 }
184
185 SafeArrayUnaccessData(pvarg->parray);
186 }
187 }
188 else
189 {
190 wxLogWarning(wxT("wxReleaseVariant: Array contains non-variant type"));
191 }
192
193 // Free the array itself.
194 SafeArrayDestroy(pvarg->parray);
195 }
196 else
197 {
198 switch (vt)
199 {
200 case VT_DISPATCH:
201 if (pvarg->pdispVal)
202 pvarg->pdispVal->Release();
203 break;
204
205 case VT_BSTR:
206 SysFreeString(pvarg->bstrVal);
207 break;
208
209 case VT_I2:
210 case VT_I4:
211 case VT_BOOL:
212 case VT_R8:
213 case VT_ERROR: // to avoid erroring on an error return from Excel
214 case VT_EMPTY:
215 case VT_DATE:
216 // no work for these types
217 break;
218
219 default:
220 wxLogWarning(wxT("wxReleaseVariant: Unknown type"));
221 break;
222 }
223 }
224
225 wxClearVariant(pvarg);
226 }
227
228 WXDLLEXPORT bool wxConvertVariantToOle(const wxVariant& variant, VARIANTARG& oleVariant)
229 {
230 wxClearVariant(&oleVariant);
231 if (variant.IsNull())
232 {
233 oleVariant.vt = VT_NULL;
234 return true;
235 }
236
237 wxString type(variant.GetType());
238
239
240 if (type == wxT("long"))
241 {
242 oleVariant.vt = VT_I4;
243 oleVariant.lVal = variant.GetLong() ;
244 }
245 // cVal not always present
246 #ifndef __GNUWIN32__
247 else if (type == wxT("char"))
248 {
249 oleVariant.vt=VT_I1; // Signed Char
250 oleVariant.cVal=variant.GetChar();
251 }
252 #endif
253 else if (type == wxT("double"))
254 {
255 oleVariant.vt = VT_R8;
256 oleVariant.dblVal = variant.GetDouble();
257 }
258 else if (type == wxT("bool"))
259 {
260 oleVariant.vt = VT_BOOL;
261 // 'bool' required for VC++ 4 apparently
262 #if (defined(__VISUALC__) && (__VISUALC__ <= 1000))
263 oleVariant.bool = variant.GetBool();
264 #else
265 oleVariant.boolVal = variant.GetBool();
266 #endif
267 }
268 else if (type == wxT("string"))
269 {
270 wxString str( variant.GetString() );
271 oleVariant.vt = VT_BSTR;
272 oleVariant.bstrVal = wxConvertStringToOle(str);
273 }
274 #if wxUSE_DATETIME
275 else if (type == wxT("datetime"))
276 {
277 wxDateTime date( variant.GetDateTime() );
278 oleVariant.vt = VT_DATE;
279
280 SYSTEMTIME st;
281 date.GetAsMSWSysTime(&st);
282
283 SystemTimeToVariantTime(&st, &oleVariant.date);
284 }
285 #endif
286 else if (type == wxT("void*"))
287 {
288 oleVariant.vt = VT_DISPATCH;
289 oleVariant.pdispVal = (IDispatch*) variant.GetVoidPtr();
290 }
291 else if (type == wxT("list") || type == wxT("stringlist"))
292 {
293 oleVariant.vt = VT_VARIANT | VT_ARRAY;
294
295 SAFEARRAY *psa;
296 SAFEARRAYBOUND saBound;
297 VARIANTARG *pvargBase;
298 VARIANTARG *pvarg;
299 int i, j;
300
301 int iCount = variant.GetCount();
302
303 saBound.lLbound = 0;
304 saBound.cElements = iCount;
305
306 psa = SafeArrayCreate(VT_VARIANT, 1, &saBound);
307 if (psa == NULL)
308 return false;
309
310 SafeArrayAccessData(psa, (void**)&pvargBase);
311
312 pvarg = pvargBase;
313 for (i = 0; i < iCount; i++)
314 {
315 // copy each string in the list of strings
316 wxVariant eachVariant(variant[i]);
317 if (!wxConvertVariantToOle(eachVariant, * pvarg))
318 {
319 // memory failure: back out and free strings alloc'ed up to
320 // now, and then the array itself.
321 pvarg = pvargBase;
322 for (j = 0; j < i; j++)
323 {
324 SysFreeString(pvarg->bstrVal);
325 pvarg++;
326 }
327 SafeArrayDestroy(psa);
328 return false;
329 }
330 pvarg++;
331 }
332
333 SafeArrayUnaccessData(psa);
334
335 oleVariant.parray = psa;
336 }
337 else
338 {
339 oleVariant.vt = VT_NULL;
340 return false;
341 }
342 return true;
343 }
344
345 #ifndef VT_TYPEMASK
346 #define VT_TYPEMASK 0xfff
347 #endif
348
349 WXDLLEXPORT bool
350 wxConvertOleToVariant(const VARIANTARG& oleVariant, wxVariant& variant)
351 {
352 bool ok = true;
353 if ( oleVariant.vt & VT_ARRAY )
354 {
355
356 // Compute the total number of elements in all array dimensions
357 int cElements = 1;
358 for ( int cDims = 0; cDims < oleVariant.parray->cDims; cDims++ )
359 cElements *= oleVariant.parray->rgsabound[cDims].cElements;
360
361 // Get a pointer to the data
362 void* pvdata;
363 HRESULT hr = SafeArrayAccessData(oleVariant.parray, &pvdata);
364 if ( FAILED(hr) )
365 return false;
366
367 switch (oleVariant.vt & VT_TYPEMASK)
368 {
369 case VT_VARIANT:
370 {
371 variant.ClearList();
372 VARIANTARG *variant_data=(VARIANTARG*)pvdata;
373 for ( int i = 0; i < cElements; i++ )
374 {
375 VARIANTARG& oleElement = variant_data[i];
376 wxVariant vElement;
377 if ( !wxConvertOleToVariant(oleElement, vElement) )
378 {
379 ok = false;
380 variant.ClearList();
381 break;
382 }
383
384 variant.Append(vElement);
385 }
386 }
387 break;
388
389 case VT_BSTR:
390 {
391 wxArrayString strings;
392 BSTR *string_val=(BSTR*)pvdata;
393 for ( int i = 0; i < cElements; ++i )
394 {
395 wxString str=wxConvertStringFromOle(*string_val);
396 strings.Add(str);
397 ++string_val;
398 }
399 variant=strings;
400 }
401 break;
402
403 default:
404 wxLogDebug(wxT("unhandled VT_ARRAY type %x in wxConvertOleToVariant"),
405 oleVariant.vt & VT_TYPEMASK);
406 variant = wxVariant();
407 ok = false;
408 break;
409 }
410
411 SafeArrayUnaccessData(oleVariant.parray);
412 }
413 else if ( oleVariant.vt & VT_BYREF )
414 {
415 switch ( oleVariant.vt & VT_TYPEMASK )
416 {
417 case VT_VARIANT:
418 {
419 VARIANTARG& oleReference = *((LPVARIANT)oleVariant.byref);
420 if (!wxConvertOleToVariant(oleReference,variant))
421 return false;
422 break;
423 }
424
425 default:
426 wxLogError(wxT("wxAutomationObject::ConvertOleToVariant: [as yet] unhandled reference %X"),
427 oleVariant.vt);
428 return false;
429 }
430 }
431 else // simply type (not array or reference)
432 {
433 switch ( oleVariant.vt & VT_TYPEMASK )
434 {
435 case VT_BSTR:
436 {
437 wxString str(wxConvertStringFromOle(oleVariant.bstrVal));
438 variant = str;
439 }
440 break;
441
442 case VT_DATE:
443 #if wxUSE_DATETIME
444 {
445 SYSTEMTIME st;
446 VariantTimeToSystemTime(oleVariant.date, &st);
447
448 wxDateTime date;
449 date.SetFromMSWSysTime(st);
450 variant = date;
451 }
452 #endif // wxUSE_DATETIME
453 break;
454
455 case VT_I4:
456 variant = (long) oleVariant.lVal;
457 break;
458
459 case VT_I2:
460 variant = (long) oleVariant.iVal;
461 break;
462
463 case VT_BOOL:
464 variant = oleVariant.boolVal != 0;
465 break;
466
467 case VT_R8:
468 variant = oleVariant.dblVal;
469 break;
470
471 case VT_DISPATCH:
472 variant = (void*) oleVariant.pdispVal;
473 break;
474
475 case VT_NULL:
476 variant.MakeNull();
477 break;
478
479 case VT_EMPTY:
480 break; // Ignore Empty Variant, used only during destruction of objects
481
482 default:
483 wxLogError(wxT("wxAutomationObject::ConvertOleToVariant: Unknown variant value type %X -> %X"),
484 oleVariant.vt,oleVariant.vt&VT_TYPEMASK);
485 return false;
486 }
487 }
488
489 return ok;
490 }
491
492 #endif // wxUSE_VARIANT
493
494
495 // ----------------------------------------------------------------------------
496 // Debug support
497 // ----------------------------------------------------------------------------
498
499 #if wxUSE_DATAOBJ
500
501 #if wxDEBUG_LEVEL && ( ( defined(__VISUALC__) && (__VISUALC__ > 1000) ) || defined(__MWERKS__) )
502 static wxString GetIidName(REFIID riid)
503 {
504 // an association between symbolic name and numeric value of an IID
505 struct KNOWN_IID {
506 const IID *pIid;
507 const wxChar *szName;
508 };
509
510 // construct the table containing all known interfaces
511 #define ADD_KNOWN_IID(name) { &IID_I##name, wxT(#name) }
512
513 static const KNOWN_IID aKnownIids[] = {
514 ADD_KNOWN_IID(AdviseSink),
515 ADD_KNOWN_IID(AdviseSink2),
516 ADD_KNOWN_IID(BindCtx),
517 ADD_KNOWN_IID(ClassFactory),
518 #if ( !defined( __VISUALC__) || (__VISUALC__!=1010) ) && !defined(__MWERKS__)
519 ADD_KNOWN_IID(ContinueCallback),
520 ADD_KNOWN_IID(EnumOleDocumentViews),
521 ADD_KNOWN_IID(OleCommandTarget),
522 ADD_KNOWN_IID(OleDocument),
523 ADD_KNOWN_IID(OleDocumentSite),
524 ADD_KNOWN_IID(OleDocumentView),
525 ADD_KNOWN_IID(Print),
526 #endif
527 ADD_KNOWN_IID(DataAdviseHolder),
528 ADD_KNOWN_IID(DataObject),
529 ADD_KNOWN_IID(Debug),
530 ADD_KNOWN_IID(DebugStream),
531 ADD_KNOWN_IID(DfReserved1),
532 ADD_KNOWN_IID(DfReserved2),
533 ADD_KNOWN_IID(DfReserved3),
534 ADD_KNOWN_IID(Dispatch),
535 ADD_KNOWN_IID(DropSource),
536 ADD_KNOWN_IID(DropTarget),
537 ADD_KNOWN_IID(EnumCallback),
538 ADD_KNOWN_IID(EnumFORMATETC),
539 ADD_KNOWN_IID(EnumGeneric),
540 ADD_KNOWN_IID(EnumHolder),
541 ADD_KNOWN_IID(EnumMoniker),
542 ADD_KNOWN_IID(EnumOLEVERB),
543 ADD_KNOWN_IID(EnumSTATDATA),
544 ADD_KNOWN_IID(EnumSTATSTG),
545 ADD_KNOWN_IID(EnumString),
546 ADD_KNOWN_IID(EnumUnknown),
547 ADD_KNOWN_IID(EnumVARIANT),
548 ADD_KNOWN_IID(ExternalConnection),
549 ADD_KNOWN_IID(InternalMoniker),
550 ADD_KNOWN_IID(LockBytes),
551 ADD_KNOWN_IID(Malloc),
552 ADD_KNOWN_IID(Marshal),
553 ADD_KNOWN_IID(MessageFilter),
554 ADD_KNOWN_IID(Moniker),
555 ADD_KNOWN_IID(OleAdviseHolder),
556 ADD_KNOWN_IID(OleCache),
557 ADD_KNOWN_IID(OleCache2),
558 ADD_KNOWN_IID(OleCacheControl),
559 ADD_KNOWN_IID(OleClientSite),
560 ADD_KNOWN_IID(OleContainer),
561 ADD_KNOWN_IID(OleInPlaceActiveObject),
562 ADD_KNOWN_IID(OleInPlaceFrame),
563 ADD_KNOWN_IID(OleInPlaceObject),
564 ADD_KNOWN_IID(OleInPlaceSite),
565 ADD_KNOWN_IID(OleInPlaceUIWindow),
566 ADD_KNOWN_IID(OleItemContainer),
567 ADD_KNOWN_IID(OleLink),
568 ADD_KNOWN_IID(OleManager),
569 ADD_KNOWN_IID(OleObject),
570 ADD_KNOWN_IID(OlePresObj),
571 ADD_KNOWN_IID(OleWindow),
572 ADD_KNOWN_IID(PSFactory),
573 ADD_KNOWN_IID(ParseDisplayName),
574 ADD_KNOWN_IID(Persist),
575 ADD_KNOWN_IID(PersistFile),
576 ADD_KNOWN_IID(PersistStorage),
577 ADD_KNOWN_IID(PersistStream),
578 ADD_KNOWN_IID(ProxyManager),
579 ADD_KNOWN_IID(RootStorage),
580 ADD_KNOWN_IID(RpcChannel),
581 ADD_KNOWN_IID(RpcProxy),
582 ADD_KNOWN_IID(RpcStub),
583 ADD_KNOWN_IID(RunnableObject),
584 ADD_KNOWN_IID(RunningObjectTable),
585 ADD_KNOWN_IID(StdMarshalInfo),
586 ADD_KNOWN_IID(Storage),
587 ADD_KNOWN_IID(Stream),
588 ADD_KNOWN_IID(StubManager),
589 ADD_KNOWN_IID(Unknown),
590 ADD_KNOWN_IID(ViewObject),
591 ADD_KNOWN_IID(ViewObject2),
592 };
593
594 // don't clobber preprocessor name space
595 #undef ADD_KNOWN_IID
596
597 // try to find the interface in the table
598 for ( size_t ui = 0; ui < WXSIZEOF(aKnownIids); ui++ ) {
599 if ( riid == *aKnownIids[ui].pIid ) {
600 return aKnownIids[ui].szName;
601 }
602 }
603
604 #ifndef __WXWINCE__
605 // unknown IID, just transform to string
606 Uuid uuid(riid);
607 return wxString((const wxChar *)uuid);
608 #else
609 return wxEmptyString;
610 #endif
611 }
612
613 void wxLogQueryInterface(const wxChar *szInterface, REFIID riid)
614 {
615 wxLogTrace(wxTRACE_OleCalls, wxT("%s::QueryInterface (iid = %s)"),
616 szInterface, GetIidName(riid).c_str());
617 }
618
619 void wxLogAddRef(const wxChar *szInterface, ULONG cRef)
620 {
621 wxLogTrace(wxTRACE_OleCalls, wxT("After %s::AddRef: m_cRef = %d"), szInterface, cRef + 1);
622 }
623
624 void wxLogRelease(const wxChar *szInterface, ULONG cRef)
625 {
626 wxLogTrace(wxTRACE_OleCalls, wxT("After %s::Release: m_cRef = %d"), szInterface, cRef - 1);
627 }
628
629 #endif // wxDEBUG_LEVEL
630
631 #endif // wxUSE_DATAOBJ
632
633 #endif // __CYGWIN10__
634
635 #endif // wxUSE_OLE