]> git.saurik.com Git - wxWidgets.git/blob - src/msw/ole/oleutils.cpp
2b10b4ae04376c879d9a4d12254098aa85d7713a
[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 WXDLLEXPORT bool wxConvertVariantToOle(const wxVariant& variant, VARIANTARG& oleVariant)
135 {
136 VariantInit(&oleVariant);
137 if (variant.IsNull())
138 {
139 oleVariant.vt = VT_NULL;
140 return true;
141 }
142
143 wxString type(variant.GetType());
144
145
146 if (type == wxT("long"))
147 {
148 oleVariant.vt = VT_I4;
149 oleVariant.lVal = variant.GetLong() ;
150 }
151 // cVal not always present
152 #ifndef __GNUWIN32__
153 else if (type == wxT("char"))
154 {
155 oleVariant.vt=VT_I1; // Signed Char
156 oleVariant.cVal=variant.GetChar();
157 }
158 #endif
159 else if (type == wxT("double"))
160 {
161 oleVariant.vt = VT_R8;
162 oleVariant.dblVal = variant.GetDouble();
163 }
164 else if (type == wxT("bool"))
165 {
166 oleVariant.vt = VT_BOOL;
167 // 'bool' required for VC++ 4 apparently
168 #if (defined(__VISUALC__) && (__VISUALC__ <= 1000))
169 oleVariant.bool = variant.GetBool();
170 #else
171 oleVariant.boolVal = variant.GetBool();
172 #endif
173 }
174 else if (type == wxT("string"))
175 {
176 wxString str( variant.GetString() );
177 oleVariant.vt = VT_BSTR;
178 oleVariant.bstrVal = wxConvertStringToOle(str);
179 }
180 #if wxUSE_DATETIME
181 else if (type == wxT("datetime"))
182 {
183 wxDateTime date( variant.GetDateTime() );
184 oleVariant.vt = VT_DATE;
185
186 SYSTEMTIME st;
187 date.GetAsMSWSysTime(&st);
188
189 SystemTimeToVariantTime(&st, &oleVariant.date);
190 }
191 #endif
192 else if (type == wxT("void*"))
193 {
194 oleVariant.vt = VT_DISPATCH;
195 oleVariant.pdispVal = (IDispatch*) variant.GetVoidPtr();
196 }
197 else if (type == wxT("list") || type == wxT("stringlist"))
198 {
199 oleVariant.vt = VT_VARIANT | VT_ARRAY;
200
201 SAFEARRAY *psa;
202 SAFEARRAYBOUND saBound;
203 VARIANTARG *pvargBase;
204 VARIANTARG *pvarg;
205 int i, j;
206
207 int iCount = variant.GetCount();
208
209 saBound.lLbound = 0;
210 saBound.cElements = iCount;
211
212 psa = SafeArrayCreate(VT_VARIANT, 1, &saBound);
213 if (psa == NULL)
214 return false;
215
216 SafeArrayAccessData(psa, (void**)&pvargBase);
217
218 pvarg = pvargBase;
219 for (i = 0; i < iCount; i++)
220 {
221 // copy each string in the list of strings
222 wxVariant eachVariant(variant[i]);
223 if (!wxConvertVariantToOle(eachVariant, * pvarg))
224 {
225 // memory failure: back out and free strings alloc'ed up to
226 // now, and then the array itself.
227 pvarg = pvargBase;
228 for (j = 0; j < i; j++)
229 {
230 SysFreeString(pvarg->bstrVal);
231 pvarg++;
232 }
233 SafeArrayDestroy(psa);
234 return false;
235 }
236 pvarg++;
237 }
238
239 SafeArrayUnaccessData(psa);
240
241 oleVariant.parray = psa;
242 }
243 else
244 {
245 oleVariant.vt = VT_NULL;
246 return false;
247 }
248 return true;
249 }
250
251 #ifndef VT_TYPEMASK
252 #define VT_TYPEMASK 0xfff
253 #endif
254
255 WXDLLEXPORT bool
256 wxConvertOleToVariant(const VARIANTARG& oleVariant, wxVariant& variant)
257 {
258 bool ok = true;
259 if ( oleVariant.vt & VT_ARRAY )
260 {
261
262 // Compute the total number of elements in all array dimensions
263 int cElements = 1;
264 for ( int cDims = 0; cDims < oleVariant.parray->cDims; cDims++ )
265 cElements *= oleVariant.parray->rgsabound[cDims].cElements;
266
267 // Get a pointer to the data
268 void* pvdata;
269 HRESULT hr = SafeArrayAccessData(oleVariant.parray, &pvdata);
270 if ( FAILED(hr) )
271 return false;
272
273 switch (oleVariant.vt & VT_TYPEMASK)
274 {
275 case VT_VARIANT:
276 {
277 variant.ClearList();
278 VARIANTARG *variant_data=(VARIANTARG*)pvdata;
279 for ( int i = 0; i < cElements; i++ )
280 {
281 VARIANTARG& oleElement = variant_data[i];
282 wxVariant vElement;
283 if ( !wxConvertOleToVariant(oleElement, vElement) )
284 {
285 ok = false;
286 variant.ClearList();
287 break;
288 }
289
290 variant.Append(vElement);
291 }
292 }
293 break;
294
295 case VT_BSTR:
296 {
297 wxArrayString strings;
298 BSTR *string_val=(BSTR*)pvdata;
299 for ( int i = 0; i < cElements; ++i )
300 {
301 wxString str=wxConvertStringFromOle(*string_val);
302 strings.Add(str);
303 ++string_val;
304 }
305 variant=strings;
306 }
307 break;
308
309 default:
310 wxLogDebug(wxT("unhandled VT_ARRAY type %x in wxConvertOleToVariant"),
311 oleVariant.vt & VT_TYPEMASK);
312 variant = wxVariant();
313 ok = false;
314 break;
315 }
316
317 SafeArrayUnaccessData(oleVariant.parray);
318 }
319 else if ( oleVariant.vt & VT_BYREF )
320 {
321 switch ( oleVariant.vt & VT_TYPEMASK )
322 {
323 case VT_VARIANT:
324 {
325 VARIANTARG& oleReference = *((LPVARIANT)oleVariant.byref);
326 if (!wxConvertOleToVariant(oleReference,variant))
327 return false;
328 break;
329 }
330
331 default:
332 wxLogError(wxT("wxAutomationObject::ConvertOleToVariant: [as yet] unhandled reference %X"),
333 oleVariant.vt);
334 return false;
335 }
336 }
337 else // simply type (not array or reference)
338 {
339 switch ( oleVariant.vt & VT_TYPEMASK )
340 {
341 case VT_BSTR:
342 {
343 wxString str(wxConvertStringFromOle(oleVariant.bstrVal));
344 variant = str;
345 }
346 break;
347
348 case VT_DATE:
349 #if wxUSE_DATETIME
350 {
351 SYSTEMTIME st;
352 VariantTimeToSystemTime(oleVariant.date, &st);
353
354 wxDateTime date;
355 date.SetFromMSWSysTime(st);
356 variant = date;
357 }
358 #endif // wxUSE_DATETIME
359 break;
360
361 case VT_I4:
362 variant = (long) oleVariant.lVal;
363 break;
364
365 case VT_I2:
366 variant = (long) oleVariant.iVal;
367 break;
368
369 case VT_BOOL:
370 variant = oleVariant.boolVal != 0;
371 break;
372
373 case VT_R8:
374 variant = oleVariant.dblVal;
375 break;
376
377 case VT_DISPATCH:
378 variant = (void*) oleVariant.pdispVal;
379 break;
380
381 case VT_NULL:
382 variant.MakeNull();
383 break;
384
385 case VT_EMPTY:
386 break; // Ignore Empty Variant, used only during destruction of objects
387
388 default:
389 wxLogError(wxT("wxAutomationObject::ConvertOleToVariant: Unknown variant value type %X -> %X"),
390 oleVariant.vt,oleVariant.vt&VT_TYPEMASK);
391 return false;
392 }
393 }
394
395 return ok;
396 }
397
398 #endif // wxUSE_VARIANT
399
400
401 // ----------------------------------------------------------------------------
402 // Debug support
403 // ----------------------------------------------------------------------------
404
405 #if wxUSE_DATAOBJ
406
407 #if wxDEBUG_LEVEL && ( ( defined(__VISUALC__) && (__VISUALC__ > 1000) ) || defined(__MWERKS__) )
408 static wxString GetIidName(REFIID riid)
409 {
410 // an association between symbolic name and numeric value of an IID
411 struct KNOWN_IID {
412 const IID *pIid;
413 const wxChar *szName;
414 };
415
416 // construct the table containing all known interfaces
417 #define ADD_KNOWN_IID(name) { &IID_I##name, wxT(#name) }
418
419 static const KNOWN_IID aKnownIids[] = {
420 ADD_KNOWN_IID(AdviseSink),
421 ADD_KNOWN_IID(AdviseSink2),
422 ADD_KNOWN_IID(BindCtx),
423 ADD_KNOWN_IID(ClassFactory),
424 #if ( !defined( __VISUALC__) || (__VISUALC__!=1010) ) && !defined(__MWERKS__)
425 ADD_KNOWN_IID(ContinueCallback),
426 ADD_KNOWN_IID(EnumOleDocumentViews),
427 ADD_KNOWN_IID(OleCommandTarget),
428 ADD_KNOWN_IID(OleDocument),
429 ADD_KNOWN_IID(OleDocumentSite),
430 ADD_KNOWN_IID(OleDocumentView),
431 ADD_KNOWN_IID(Print),
432 #endif
433 ADD_KNOWN_IID(DataAdviseHolder),
434 ADD_KNOWN_IID(DataObject),
435 ADD_KNOWN_IID(Debug),
436 ADD_KNOWN_IID(DebugStream),
437 ADD_KNOWN_IID(DfReserved1),
438 ADD_KNOWN_IID(DfReserved2),
439 ADD_KNOWN_IID(DfReserved3),
440 ADD_KNOWN_IID(Dispatch),
441 ADD_KNOWN_IID(DropSource),
442 ADD_KNOWN_IID(DropTarget),
443 ADD_KNOWN_IID(EnumCallback),
444 ADD_KNOWN_IID(EnumFORMATETC),
445 ADD_KNOWN_IID(EnumGeneric),
446 ADD_KNOWN_IID(EnumHolder),
447 ADD_KNOWN_IID(EnumMoniker),
448 ADD_KNOWN_IID(EnumOLEVERB),
449 ADD_KNOWN_IID(EnumSTATDATA),
450 ADD_KNOWN_IID(EnumSTATSTG),
451 ADD_KNOWN_IID(EnumString),
452 ADD_KNOWN_IID(EnumUnknown),
453 ADD_KNOWN_IID(EnumVARIANT),
454 ADD_KNOWN_IID(ExternalConnection),
455 ADD_KNOWN_IID(InternalMoniker),
456 ADD_KNOWN_IID(LockBytes),
457 ADD_KNOWN_IID(Malloc),
458 ADD_KNOWN_IID(Marshal),
459 ADD_KNOWN_IID(MessageFilter),
460 ADD_KNOWN_IID(Moniker),
461 ADD_KNOWN_IID(OleAdviseHolder),
462 ADD_KNOWN_IID(OleCache),
463 ADD_KNOWN_IID(OleCache2),
464 ADD_KNOWN_IID(OleCacheControl),
465 ADD_KNOWN_IID(OleClientSite),
466 ADD_KNOWN_IID(OleContainer),
467 ADD_KNOWN_IID(OleInPlaceActiveObject),
468 ADD_KNOWN_IID(OleInPlaceFrame),
469 ADD_KNOWN_IID(OleInPlaceObject),
470 ADD_KNOWN_IID(OleInPlaceSite),
471 ADD_KNOWN_IID(OleInPlaceUIWindow),
472 ADD_KNOWN_IID(OleItemContainer),
473 ADD_KNOWN_IID(OleLink),
474 ADD_KNOWN_IID(OleManager),
475 ADD_KNOWN_IID(OleObject),
476 ADD_KNOWN_IID(OlePresObj),
477 ADD_KNOWN_IID(OleWindow),
478 ADD_KNOWN_IID(PSFactory),
479 ADD_KNOWN_IID(ParseDisplayName),
480 ADD_KNOWN_IID(Persist),
481 ADD_KNOWN_IID(PersistFile),
482 ADD_KNOWN_IID(PersistStorage),
483 ADD_KNOWN_IID(PersistStream),
484 ADD_KNOWN_IID(ProxyManager),
485 ADD_KNOWN_IID(RootStorage),
486 ADD_KNOWN_IID(RpcChannel),
487 ADD_KNOWN_IID(RpcProxy),
488 ADD_KNOWN_IID(RpcStub),
489 ADD_KNOWN_IID(RunnableObject),
490 ADD_KNOWN_IID(RunningObjectTable),
491 ADD_KNOWN_IID(StdMarshalInfo),
492 ADD_KNOWN_IID(Storage),
493 ADD_KNOWN_IID(Stream),
494 ADD_KNOWN_IID(StubManager),
495 ADD_KNOWN_IID(Unknown),
496 ADD_KNOWN_IID(ViewObject),
497 ADD_KNOWN_IID(ViewObject2),
498 };
499
500 // don't clobber preprocessor name space
501 #undef ADD_KNOWN_IID
502
503 // try to find the interface in the table
504 for ( size_t ui = 0; ui < WXSIZEOF(aKnownIids); ui++ ) {
505 if ( riid == *aKnownIids[ui].pIid ) {
506 return aKnownIids[ui].szName;
507 }
508 }
509
510 #ifndef __WXWINCE__
511 // unknown IID, just transform to string
512 Uuid uuid(riid);
513 return wxString((const wxChar *)uuid);
514 #else
515 return wxEmptyString;
516 #endif
517 }
518
519 void wxLogQueryInterface(const wxChar *szInterface, REFIID riid)
520 {
521 wxLogTrace(wxTRACE_OleCalls, wxT("%s::QueryInterface (iid = %s)"),
522 szInterface, GetIidName(riid).c_str());
523 }
524
525 void wxLogAddRef(const wxChar *szInterface, ULONG cRef)
526 {
527 wxLogTrace(wxTRACE_OleCalls, wxT("After %s::AddRef: m_cRef = %d"), szInterface, cRef + 1);
528 }
529
530 void wxLogRelease(const wxChar *szInterface, ULONG cRef)
531 {
532 wxLogTrace(wxTRACE_OleCalls, wxT("After %s::Release: m_cRef = %d"), szInterface, cRef - 1);
533 }
534
535 #endif // wxDEBUG_LEVEL
536
537 #endif // wxUSE_DATAOBJ
538
539 #endif // __CYGWIN10__
540
541 #endif // wxUSE_OLE