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