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