]> git.saurik.com Git - wxWidgets.git/blame - src/msw/ole/oleutils.cpp
Enable variadic macros for VC9 and later.
[wxWidgets.git] / src / msw / ole / oleutils.cpp
CommitLineData
bbf1f0e5 1///////////////////////////////////////////////////////////////////////////////
521bf4ff 2// Name: src/msw/ole/oleutils.cpp
bbf1f0e5
KB
3// Purpose: implementation of OLE helper functions
4// Author: Vadim Zeitlin
3f4a0c5b 5// Modified by:
bbf1f0e5
KB
6// Created: 19.02.98
7// RCS-ID: $Id$
8// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
65571936 9// Licence: wxWindows licence
bbf1f0e5
KB
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// Declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
bbf1f0e5 20// For compilers that support precompilation, includes "wx.h".
bbf1f0e5
KB
21#include "wx/wxprec.h"
22
23#if defined(__BORLANDC__)
e4db172a 24 #pragma hdrstop
bbf1f0e5
KB
25#endif
26
21709999
JS
27#if wxUSE_OLE
28
e4db172a
WS
29#ifndef WX_PRECOMP
30 #include "wx/log.h"
31#endif
32
ae090fdb
JS
33#ifndef __CYGWIN10__
34
4676948b
JS
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
bbf1f0e5
KB
44
45// OLE
4676948b 46#ifndef __WXWINCE__
3096bd2f 47#include "wx/msw/ole/uuid.h"
4676948b
JS
48#endif
49
3096bd2f 50#include "wx/msw/ole/oleutils.h"
bbf1f0e5 51
3f4a0c5b
VZ
52#if defined(__VISUALC__) && (__VISUALC__ > 1000)
53 #include <docobj.h>
bbf1f0e5
KB
54#endif
55
56// ============================================================================
57// Implementation
58// ============================================================================
59
0a0e6a5b 60// return true if the iid is in the array
d0400222 61WXDLLEXPORT bool IsIidFromList(REFIID riid, const IID *aIids[], size_t nCount)
bbf1f0e5
KB
62{
63 for ( size_t i = 0; i < nCount; i++ ) {
64 if ( riid == *aIids[i] )
0a0e6a5b 65 return true;
bbf1f0e5
KB
66 }
67
0a0e6a5b 68 return false;
bbf1f0e5
KB
69}
70
e2898549 71WXDLLEXPORT BSTR wxConvertStringToOle(const wxString& str)
94113cc5 72{
c45ead7b 73 return wxBasicString(str).Get();
94113cc5
JS
74}
75
e2898549 76WXDLLEXPORT wxString wxConvertStringFromOle(BSTR bStr)
94113cc5 77{
795b0f14
VZ
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
59af032a
VZ
83 const int len = SysStringLen(bStr);
84
94113cc5 85#if wxUSE_UNICODE
59af032a 86 wxString str(bStr, len);
94113cc5 87#else
bba85010 88 wxString str;
9968f7b4 89 if (len)
bba85010 90 {
9968f7b4
VZ
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 */));
bba85010 96 }
94113cc5 97#endif
59af032a 98
94113cc5
JS
99 return str;
100}
101
102// ----------------------------------------------------------------------------
103// wxBasicString
104// ----------------------------------------------------------------------------
105
a518e508 106wxBasicString::wxBasicString(const wxString& str)
94113cc5 107{
a518e508 108 m_bstrBuf = SysAllocString(str.wc_str(*wxConvCurrent));
94113cc5
JS
109}
110
a518e508 111wxBasicString::wxBasicString(const wxBasicString& src)
94113cc5 112{
a518e508 113 m_bstrBuf = src.Get();
94113cc5
JS
114}
115
a518e508 116wxBasicString& wxBasicString::operator=(const wxBasicString& src)
94113cc5 117{
a518e508
VZ
118 SysReAllocString(&m_bstrBuf, src);
119 return *this;
94113cc5
JS
120}
121
94113cc5
JS
122wxBasicString::~wxBasicString()
123{
a518e508 124 SysFreeString(m_bstrBuf);
94113cc5
JS
125}
126
a2fd865b
VS
127
128// ----------------------------------------------------------------------------
129// Convert variants
130// ----------------------------------------------------------------------------
131
132#if wxUSE_VARIANT
133
a2fd865b
VS
134WXDLLEXPORT bool wxConvertVariantToOle(const wxVariant& variant, VARIANTARG& oleVariant)
135{
1fbfbfb0 136 VariantInit(&oleVariant);
a2fd865b
VS
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 }
30ee0b97
VZ
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__)
4b666be6
VZ
158 else if (type == wxT("longlong"))
159 {
160 oleVariant.vt = VT_I8;
161 oleVariant.llVal = variant.GetLongLong().GetValue();
162 }
163#endif
a2fd865b
VS
164 else if (type == wxT("char"))
165 {
166 oleVariant.vt=VT_I1; // Signed Char
167 oleVariant.cVal=variant.GetChar();
168 }
a2fd865b
VS
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;
85ecb1d5 177 oleVariant.boolVal = variant.GetBool() ? VARIANT_TRUE : VARIANT_FALSE;
a2fd865b
VS
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("stringlist"))
203 {
204 oleVariant.vt = VT_VARIANT | VT_ARRAY;
205
206 SAFEARRAY *psa;
207 SAFEARRAYBOUND saBound;
208 VARIANTARG *pvargBase;
209 VARIANTARG *pvarg;
210 int i, j;
211
212 int iCount = variant.GetCount();
213
214 saBound.lLbound = 0;
215 saBound.cElements = iCount;
216
217 psa = SafeArrayCreate(VT_VARIANT, 1, &saBound);
218 if (psa == NULL)
219 return false;
220
221 SafeArrayAccessData(psa, (void**)&pvargBase);
222
223 pvarg = pvargBase;
224 for (i = 0; i < iCount; i++)
225 {
226 // copy each string in the list of strings
227 wxVariant eachVariant(variant[i]);
228 if (!wxConvertVariantToOle(eachVariant, * pvarg))
229 {
230 // memory failure: back out and free strings alloc'ed up to
231 // now, and then the array itself.
232 pvarg = pvargBase;
233 for (j = 0; j < i; j++)
234 {
235 SysFreeString(pvarg->bstrVal);
236 pvarg++;
237 }
238 SafeArrayDestroy(psa);
239 return false;
240 }
241 pvarg++;
242 }
243
244 SafeArrayUnaccessData(psa);
245
246 oleVariant.parray = psa;
247 }
248 else
249 {
250 oleVariant.vt = VT_NULL;
251 return false;
252 }
253 return true;
254}
255
256#ifndef VT_TYPEMASK
257#define VT_TYPEMASK 0xfff
258#endif
259
260WXDLLEXPORT bool
261wxConvertOleToVariant(const VARIANTARG& oleVariant, wxVariant& variant)
262{
263 bool ok = true;
264 if ( oleVariant.vt & VT_ARRAY )
265 {
266
267 // Compute the total number of elements in all array dimensions
268 int cElements = 1;
269 for ( int cDims = 0; cDims < oleVariant.parray->cDims; cDims++ )
270 cElements *= oleVariant.parray->rgsabound[cDims].cElements;
271
272 // Get a pointer to the data
273 void* pvdata;
274 HRESULT hr = SafeArrayAccessData(oleVariant.parray, &pvdata);
275 if ( FAILED(hr) )
276 return false;
277
278 switch (oleVariant.vt & VT_TYPEMASK)
279 {
280 case VT_VARIANT:
281 {
282 variant.ClearList();
283 VARIANTARG *variant_data=(VARIANTARG*)pvdata;
284 for ( int i = 0; i < cElements; i++ )
285 {
286 VARIANTARG& oleElement = variant_data[i];
287 wxVariant vElement;
288 if ( !wxConvertOleToVariant(oleElement, vElement) )
289 {
290 ok = false;
291 variant.ClearList();
292 break;
293 }
294
295 variant.Append(vElement);
296 }
297 }
298 break;
299
300 case VT_BSTR:
301 {
302 wxArrayString strings;
303 BSTR *string_val=(BSTR*)pvdata;
304 for ( int i = 0; i < cElements; ++i )
305 {
306 wxString str=wxConvertStringFromOle(*string_val);
307 strings.Add(str);
308 ++string_val;
309 }
310 variant=strings;
311 }
312 break;
313
314 default:
315 wxLogDebug(wxT("unhandled VT_ARRAY type %x in wxConvertOleToVariant"),
316 oleVariant.vt & VT_TYPEMASK);
317 variant = wxVariant();
318 ok = false;
319 break;
320 }
321
322 SafeArrayUnaccessData(oleVariant.parray);
323 }
324 else if ( oleVariant.vt & VT_BYREF )
325 {
326 switch ( oleVariant.vt & VT_TYPEMASK )
327 {
328 case VT_VARIANT:
329 {
330 VARIANTARG& oleReference = *((LPVARIANT)oleVariant.byref);
331 if (!wxConvertOleToVariant(oleReference,variant))
332 return false;
333 break;
334 }
335
336 default:
337 wxLogError(wxT("wxAutomationObject::ConvertOleToVariant: [as yet] unhandled reference %X"),
338 oleVariant.vt);
339 return false;
340 }
341 }
342 else // simply type (not array or reference)
343 {
344 switch ( oleVariant.vt & VT_TYPEMASK )
345 {
346 case VT_BSTR:
347 {
348 wxString str(wxConvertStringFromOle(oleVariant.bstrVal));
349 variant = str;
350 }
351 break;
352
353 case VT_DATE:
354#if wxUSE_DATETIME
355 {
356 SYSTEMTIME st;
357 VariantTimeToSystemTime(oleVariant.date, &st);
358
359 wxDateTime date;
360 date.SetFromMSWSysTime(st);
361 variant = date;
362 }
363#endif // wxUSE_DATETIME
364 break;
365
30ee0b97
VZ
366 // See the comment before the __VISUALC6__ test above.
367#if wxUSE_LONGLONG && !defined(__VISUALC6__)
4b666be6
VZ
368 case VT_I8:
369 variant = wxLongLong(oleVariant.llVal);
370 break;
371#endif // wxUSE_LONGLONG
372
a2fd865b
VS
373 case VT_I4:
374 variant = (long) oleVariant.lVal;
375 break;
376
377 case VT_I2:
378 variant = (long) oleVariant.iVal;
379 break;
380
381 case VT_BOOL:
382 variant = oleVariant.boolVal != 0;
383 break;
384
51909b8b
VZ
385 case VT_R4:
386 variant = oleVariant.fltVal;
387 break;
388
a2fd865b
VS
389 case VT_R8:
390 variant = oleVariant.dblVal;
391 break;
392
393 case VT_DISPATCH:
394 variant = (void*) oleVariant.pdispVal;
395 break;
396
397 case VT_NULL:
398 variant.MakeNull();
399 break;
400
401 case VT_EMPTY:
402 break; // Ignore Empty Variant, used only during destruction of objects
403
404 default:
405 wxLogError(wxT("wxAutomationObject::ConvertOleToVariant: Unknown variant value type %X -> %X"),
406 oleVariant.vt,oleVariant.vt&VT_TYPEMASK);
407 return false;
408 }
409 }
410
411 return ok;
412}
413
414#endif // wxUSE_VARIANT
415
c740f496 416
bbf1f0e5
KB
417// ----------------------------------------------------------------------------
418// Debug support
419// ----------------------------------------------------------------------------
420
a2fd865b
VS
421#if wxUSE_DATAOBJ
422
2415cf67 423#if wxDEBUG_LEVEL && (( defined(__VISUALC__) && (__VISUALC__ > 1000) ))
f6bcfd97 424static wxString GetIidName(REFIID riid)
bbf1f0e5
KB
425{
426 // an association between symbolic name and numeric value of an IID
427 struct KNOWN_IID {
428 const IID *pIid;
f6bcfd97 429 const wxChar *szName;
bbf1f0e5
KB
430 };
431
432 // construct the table containing all known interfaces
9a83f860 433 #define ADD_KNOWN_IID(name) { &IID_I##name, wxT(#name) }
bbf1f0e5
KB
434
435 static const KNOWN_IID aKnownIids[] = {
436 ADD_KNOWN_IID(AdviseSink),
437 ADD_KNOWN_IID(AdviseSink2),
438 ADD_KNOWN_IID(BindCtx),
439 ADD_KNOWN_IID(ClassFactory),
2415cf67 440#if ( !defined( __VISUALC__) || (__VISUALC__!=1010) )
bbf1f0e5
KB
441 ADD_KNOWN_IID(ContinueCallback),
442 ADD_KNOWN_IID(EnumOleDocumentViews),
443 ADD_KNOWN_IID(OleCommandTarget),
444 ADD_KNOWN_IID(OleDocument),
445 ADD_KNOWN_IID(OleDocumentSite),
446 ADD_KNOWN_IID(OleDocumentView),
447 ADD_KNOWN_IID(Print),
27a9bd48 448#endif
bbf1f0e5
KB
449 ADD_KNOWN_IID(DataAdviseHolder),
450 ADD_KNOWN_IID(DataObject),
451 ADD_KNOWN_IID(Debug),
452 ADD_KNOWN_IID(DebugStream),
453 ADD_KNOWN_IID(DfReserved1),
454 ADD_KNOWN_IID(DfReserved2),
455 ADD_KNOWN_IID(DfReserved3),
456 ADD_KNOWN_IID(Dispatch),
457 ADD_KNOWN_IID(DropSource),
458 ADD_KNOWN_IID(DropTarget),
459 ADD_KNOWN_IID(EnumCallback),
460 ADD_KNOWN_IID(EnumFORMATETC),
461 ADD_KNOWN_IID(EnumGeneric),
462 ADD_KNOWN_IID(EnumHolder),
463 ADD_KNOWN_IID(EnumMoniker),
464 ADD_KNOWN_IID(EnumOLEVERB),
465 ADD_KNOWN_IID(EnumSTATDATA),
466 ADD_KNOWN_IID(EnumSTATSTG),
467 ADD_KNOWN_IID(EnumString),
468 ADD_KNOWN_IID(EnumUnknown),
469 ADD_KNOWN_IID(EnumVARIANT),
470 ADD_KNOWN_IID(ExternalConnection),
471 ADD_KNOWN_IID(InternalMoniker),
472 ADD_KNOWN_IID(LockBytes),
473 ADD_KNOWN_IID(Malloc),
474 ADD_KNOWN_IID(Marshal),
475 ADD_KNOWN_IID(MessageFilter),
476 ADD_KNOWN_IID(Moniker),
477 ADD_KNOWN_IID(OleAdviseHolder),
478 ADD_KNOWN_IID(OleCache),
479 ADD_KNOWN_IID(OleCache2),
480 ADD_KNOWN_IID(OleCacheControl),
481 ADD_KNOWN_IID(OleClientSite),
482 ADD_KNOWN_IID(OleContainer),
483 ADD_KNOWN_IID(OleInPlaceActiveObject),
484 ADD_KNOWN_IID(OleInPlaceFrame),
485 ADD_KNOWN_IID(OleInPlaceObject),
486 ADD_KNOWN_IID(OleInPlaceSite),
487 ADD_KNOWN_IID(OleInPlaceUIWindow),
488 ADD_KNOWN_IID(OleItemContainer),
489 ADD_KNOWN_IID(OleLink),
490 ADD_KNOWN_IID(OleManager),
491 ADD_KNOWN_IID(OleObject),
492 ADD_KNOWN_IID(OlePresObj),
493 ADD_KNOWN_IID(OleWindow),
494 ADD_KNOWN_IID(PSFactory),
495 ADD_KNOWN_IID(ParseDisplayName),
496 ADD_KNOWN_IID(Persist),
497 ADD_KNOWN_IID(PersistFile),
498 ADD_KNOWN_IID(PersistStorage),
499 ADD_KNOWN_IID(PersistStream),
500 ADD_KNOWN_IID(ProxyManager),
501 ADD_KNOWN_IID(RootStorage),
502 ADD_KNOWN_IID(RpcChannel),
503 ADD_KNOWN_IID(RpcProxy),
504 ADD_KNOWN_IID(RpcStub),
505 ADD_KNOWN_IID(RunnableObject),
506 ADD_KNOWN_IID(RunningObjectTable),
507 ADD_KNOWN_IID(StdMarshalInfo),
508 ADD_KNOWN_IID(Storage),
509 ADD_KNOWN_IID(Stream),
510 ADD_KNOWN_IID(StubManager),
511 ADD_KNOWN_IID(Unknown),
512 ADD_KNOWN_IID(ViewObject),
513 ADD_KNOWN_IID(ViewObject2),
514 };
515
516 // don't clobber preprocessor name space
517 #undef ADD_KNOWN_IID
518
519 // try to find the interface in the table
c86f1403 520 for ( size_t ui = 0; ui < WXSIZEOF(aKnownIids); ui++ ) {
bbf1f0e5
KB
521 if ( riid == *aKnownIids[ui].pIid ) {
522 return aKnownIids[ui].szName;
523 }
524 }
525
4676948b 526#ifndef __WXWINCE__
bbf1f0e5 527 // unknown IID, just transform to string
f6bcfd97
BP
528 Uuid uuid(riid);
529 return wxString((const wxChar *)uuid);
4676948b
JS
530#else
531 return wxEmptyString;
532#endif
bbf1f0e5
KB
533}
534
d0400222 535WXDLLEXPORT void wxLogQueryInterface(const wxChar *szInterface, REFIID riid)
bbf1f0e5 536{
ba14d986 537 wxLogTrace(wxTRACE_OleCalls, wxT("%s::QueryInterface (iid = %s)"),
f6bcfd97 538 szInterface, GetIidName(riid).c_str());
bbf1f0e5
KB
539}
540
d0400222 541WXDLLEXPORT void wxLogAddRef(const wxChar *szInterface, ULONG cRef)
bbf1f0e5 542{
ba14d986 543 wxLogTrace(wxTRACE_OleCalls, wxT("After %s::AddRef: m_cRef = %d"), szInterface, cRef + 1);
bbf1f0e5
KB
544}
545
d0400222 546WXDLLEXPORT void wxLogRelease(const wxChar *szInterface, ULONG cRef)
bbf1f0e5 547{
ba14d986 548 wxLogTrace(wxTRACE_OleCalls, wxT("After %s::Release: m_cRef = %d"), szInterface, cRef - 1);
bbf1f0e5
KB
549}
550
4b6a582b 551#endif // wxDEBUG_LEVEL
aeab10d0 552
a2fd865b 553#endif // wxUSE_DATAOBJ
aeab10d0 554
4b6a582b 555#endif // __CYGWIN10__
aeab10d0 556
4b6a582b 557#endif // wxUSE_OLE