]> git.saurik.com Git - wxWidgets.git/blame - src/msw/ole/automtn.cpp
implemented DrawCheckButton() for XP renderer; code cleanup
[wxWidgets.git] / src / msw / ole / automtn.cpp
CommitLineData
d980b3e1 1/////////////////////////////////////////////////////////////////////////////
11f104e5 2// Name: src/msw/ole/automtn.cpp
d980b3e1
JS
3// Purpose: OLE automation utilities
4// Author: Julian Smart
5// Modified by:
6// Created: 11/6/98
7// RCS-ID: $Id$
8// Copyright: (c) 1998, Julian Smart
65571936 9// Licence: wxWindows licence
d980b3e1
JS
10/////////////////////////////////////////////////////////////////////////////
11
d980b3e1
JS
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#if defined(__BORLANDC__)
7520f3da 16 #pragma hdrstop
d980b3e1
JS
17#endif
18
457e6c54 19// Watcom C++ gives a linker error if this is compiled in.
f6bcfd97 20// With Borland C++, all samples crash if this is compiled in.
6b12494d 21#if wxUSE_OLE && !(defined(__BORLANDC__) && (__BORLANDC__ < 0x520)) && !defined(__CYGWIN10__)
457e6c54 22
5283098e 23#define _FORCENAMELESSUNION
f6bcfd97 24#include "wx/log.h"
4676948b 25#include "wx/msw/private.h"
ed5317e5 26#include "wx/msw/ole/oleutils.h"
42e69d6b 27#include "wx/msw/ole/automtn.h"
b713f891 28#include "wx/math.h"
4676948b
JS
29
30#ifdef __WXWINCE__
31#include "wx/msw/wince/time.h"
32#else
f6bcfd97 33#include <time.h>
4676948b 34#endif
f6bcfd97 35
7dee726c
RS
36#include <wtypes.h>
37#include <unknwn.h>
4676948b 38
7dee726c
RS
39#include <ole2.h>
40#define _huge
4676948b
JS
41
42#ifndef __WXWINCE__
42e69d6b 43#include <ole2ver.h>
4676948b
JS
44#endif
45
42e69d6b 46#include <oleauto.h>
17b74d79 47
61bfe4b0
JS
48#if wxUSE_DATETIME
49#include "wx/datetime.h"
e421922f 50#endif // wxUSE_TIMEDATE
d980b3e1
JS
51
52static void ClearVariant(VARIANTARG *pvarg) ;
53static void ReleaseVariant(VARIANTARG *pvarg) ;
54// static void ShowException(LPOLESTR szMember, HRESULT hr, EXCEPINFO *pexcep, unsigned int uiArgErr);
55
56/*
57 * wxAutomationObject
58 */
59
60wxAutomationObject::wxAutomationObject(WXIDISPATCH* dispatchPtr)
61{
0a0e6a5b 62 m_dispatchPtr = dispatchPtr;
d980b3e1
JS
63}
64
65wxAutomationObject::~wxAutomationObject()
66{
0a0e6a5b
WS
67 if (m_dispatchPtr)
68 {
69 ((IDispatch*)m_dispatchPtr)->Release();
70 m_dispatchPtr = NULL;
71 }
d980b3e1
JS
72}
73
74#define INVOKEARG(i) (args ? args[i] : *(ptrArgs[i]))
75
76// For Put/Get, no named arguments are allowed.
77bool wxAutomationObject::Invoke(const wxString& member, int action,
78 wxVariant& retValue, int noArgs, wxVariant args[], const wxVariant* ptrArgs[]) const
79{
0a0e6a5b
WS
80 if (!m_dispatchPtr)
81 return false;
82
83 // nonConstMember is necessary because the wxString class doesn't have enough consts...
84 wxString nonConstMember(member);
85
86 int ch = nonConstMember.Find('.');
87 if (ch != -1)
88 {
89 // Use dot notation to get the next object
90 wxString member2(nonConstMember.Left((size_t) ch));
91 wxString rest(nonConstMember.Right(nonConstMember.Length() - ch - 1));
92 wxAutomationObject obj;
93 if (!GetObject(obj, member2))
94 return false;
95 return obj.Invoke(rest, action, retValue, noArgs, args, ptrArgs);
96 }
97
98 VARIANTARG vReturn;
99 ClearVariant(& vReturn);
100
101 VARIANTARG* vReturnPtr = & vReturn;
102
103 // Find number of names args
104 int namedArgCount = 0;
105 int i;
106 for (i = 0; i < noArgs; i++)
107 if (!INVOKEARG(i).GetName().IsNull())
12335fa6 108 {
0a0e6a5b
WS
109 namedArgCount ++;
110 }
111
112 int namedArgStringCount = namedArgCount + 1;
113 BSTR* argNames = new BSTR[namedArgStringCount];
114 argNames[0] = wxConvertStringToOle(member);
115
116 // Note that arguments are specified in reverse order
117 // (all totally logical; hey, we're dealing with OLE here.)
118
119 int j = 0;
120 for (i = 0; i < namedArgCount; i++)
121 {
122 if (!INVOKEARG(i).GetName().IsNull())
123 {
124 argNames[(namedArgCount-j)] = wxConvertStringToOle(INVOKEARG(i).GetName());
125 j ++;
126 }
127 }
128
129 // + 1 for the member name, + 1 again in case we're a 'put'
130 DISPID* dispIds = new DISPID[namedArgCount + 2];
131
132 HRESULT hr;
133 DISPPARAMS dispparams;
134 unsigned int uiArgErr;
135 EXCEPINFO excep;
136
137 // Get the IDs for the member and its arguments. GetIDsOfNames expects the
138 // member name as the first name, followed by argument names (if any).
139 hr = ((IDispatch*)m_dispatchPtr)->GetIDsOfNames(IID_NULL, argNames,
140 1 + namedArgCount, LOCALE_SYSTEM_DEFAULT, dispIds);
141 if (FAILED(hr))
142 {
143// ShowException(szMember, hr, NULL, 0);
144 delete[] argNames;
145 delete[] dispIds;
146 return false;
147 }
148
149 // if doing a property put(ref), we need to adjust the first argument to have a
150 // named arg of DISPID_PROPERTYPUT.
151 if (action & (DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF))
152 {
153 namedArgCount = 1;
154 dispIds[1] = DISPID_PROPERTYPUT;
155 vReturnPtr = (VARIANTARG*) NULL;
156 }
157
158 // Convert the wxVariants to VARIANTARGs
159 VARIANTARG* oleArgs = new VARIANTARG[noArgs];
160 for (i = 0; i < noArgs; i++)
161 {
162 // Again, reverse args
163 if (!wxConvertVariantToOle(INVOKEARG((noArgs-1) - i), oleArgs[i]))
164 {
165 delete[] argNames;
166 delete[] dispIds;
12335fa6 167 delete[] oleArgs;
0a0e6a5b
WS
168 return false;
169 }
170 }
171
172 dispparams.rgdispidNamedArgs = dispIds + 1;
173 dispparams.rgvarg = oleArgs;
174 dispparams.cArgs = noArgs;
175 dispparams.cNamedArgs = namedArgCount;
176
177 excep.pfnDeferredFillIn = NULL;
178
179 hr = ((IDispatch*)m_dispatchPtr)->Invoke(dispIds[0], IID_NULL, LOCALE_SYSTEM_DEFAULT,
5c519b6c 180 (WORD)action, &dispparams, vReturnPtr, &excep, &uiArgErr);
0a0e6a5b
WS
181
182 for (i = 0; i < namedArgStringCount; i++)
183 {
184 SysFreeString(argNames[i]);
185 }
186 delete[] argNames;
187 delete[] dispIds;
188
189 for (i = 0; i < noArgs; i++)
190 ReleaseVariant(& oleArgs[i]) ;
191 delete[] oleArgs;
192
193 if (FAILED(hr))
194 {
195 // display the exception information if appropriate:
196// ShowException((const char*) member, hr, &excep, uiArgErr);
197
198 // free exception structure information
199 SysFreeString(excep.bstrSource);
200 SysFreeString(excep.bstrDescription);
201 SysFreeString(excep.bstrHelpFile);
202
203 if (vReturnPtr)
204 ReleaseVariant(vReturnPtr);
205 return false;
206 }
207 else
208 {
209 if (vReturnPtr)
210 {
211 // Convert result to wxVariant form
212 wxConvertOleToVariant(vReturn, retValue);
213 // Mustn't release the dispatch pointer
214 if (vReturn.vt == VT_DISPATCH)
215 {
216 vReturn.pdispVal = (IDispatch*) NULL;
217 }
218 ReleaseVariant(& vReturn);
12335fa6 219 }
0a0e6a5b
WS
220 }
221 return true;
d980b3e1
JS
222}
223
224// Invoke a member function
225wxVariant wxAutomationObject::CallMethod(const wxString& member, int noArgs, wxVariant args[])
226{
0a0e6a5b
WS
227 wxVariant retVariant;
228 if (!Invoke(member, DISPATCH_METHOD, retVariant, noArgs, args))
229 {
230 retVariant.MakeNull();
231 }
232 return retVariant;
d980b3e1
JS
233}
234
24f4ad95
JS
235wxVariant wxAutomationObject::CallMethodArray(const wxString& member, int noArgs, const wxVariant **args)
236{
0a0e6a5b
WS
237 wxVariant retVariant;
238 if (!Invoke(member, DISPATCH_METHOD, retVariant, noArgs, NULL, args))
239 {
240 retVariant.MakeNull();
241 }
242 return retVariant;
24f4ad95
JS
243}
244
d980b3e1 245wxVariant wxAutomationObject::CallMethod(const wxString& member,
0a0e6a5b
WS
246 const wxVariant& arg1, const wxVariant& arg2,
247 const wxVariant& arg3, const wxVariant& arg4,
248 const wxVariant& arg5, const wxVariant& arg6)
d980b3e1 249{
0a0e6a5b
WS
250 const wxVariant** args = new const wxVariant*[6];
251 int i = 0;
252 if (!arg1.IsNull())
253 {
254 args[i] = & arg1;
255 i ++;
256 }
257 if (!arg2.IsNull())
258 {
259 args[i] = & arg2;
260 i ++;
261 }
262 if (!arg3.IsNull())
263 {
264 args[i] = & arg3;
265 i ++;
266 }
267 if (!arg4.IsNull())
268 {
269 args[i] = & arg4;
270 i ++;
271 }
272 if (!arg5.IsNull())
273 {
274 args[i] = & arg5;
275 i ++;
276 }
277 if (!arg6.IsNull())
278 {
279 args[i] = & arg6;
280 i ++;
281 }
282 wxVariant retVariant;
283 if (!Invoke(member, DISPATCH_METHOD, retVariant, i, NULL, args))
284 {
285 retVariant.MakeNull();
286 }
287 delete[] args;
288 return retVariant;
d980b3e1
JS
289}
290
291// Get/Set property
24f4ad95
JS
292wxVariant wxAutomationObject::GetPropertyArray(const wxString& property, int noArgs, const wxVariant **args) const
293{
0a0e6a5b
WS
294 wxVariant retVariant;
295 if (!Invoke(property, DISPATCH_PROPERTYGET, retVariant, noArgs, NULL, args))
296 {
297 retVariant.MakeNull();
298 }
299 return retVariant;
24f4ad95 300}
d980b3e1
JS
301wxVariant wxAutomationObject::GetProperty(const wxString& property, int noArgs, wxVariant args[]) const
302{
0a0e6a5b
WS
303 wxVariant retVariant;
304 if (!Invoke(property, DISPATCH_PROPERTYGET, retVariant, noArgs, args))
305 {
306 retVariant.MakeNull();
307 }
308 return retVariant;
d980b3e1
JS
309}
310
311wxVariant wxAutomationObject::GetProperty(const wxString& property,
0a0e6a5b
WS
312 const wxVariant& arg1, const wxVariant& arg2,
313 const wxVariant& arg3, const wxVariant& arg4,
314 const wxVariant& arg5, const wxVariant& arg6)
d980b3e1 315{
0a0e6a5b
WS
316 const wxVariant** args = new const wxVariant*[6];
317 int i = 0;
318 if (!arg1.IsNull())
319 {
320 args[i] = & arg1;
321 i ++;
322 }
323 if (!arg2.IsNull())
324 {
325 args[i] = & arg2;
326 i ++;
327 }
328 if (!arg3.IsNull())
329 {
330 args[i] = & arg3;
331 i ++;
332 }
333 if (!arg4.IsNull())
334 {
335 args[i] = & arg4;
336 i ++;
337 }
338 if (!arg5.IsNull())
339 {
340 args[i] = & arg5;
341 i ++;
342 }
343 if (!arg6.IsNull())
344 {
345 args[i] = & arg6;
346 i ++;
347 }
348 wxVariant retVariant;
349 if (!Invoke(property, DISPATCH_PROPERTYGET, retVariant, i, NULL, args))
350 {
351 retVariant.MakeNull();
352 }
353 delete[] args;
354 return retVariant;
d980b3e1
JS
355}
356
357bool wxAutomationObject::PutProperty(const wxString& property, int noArgs, wxVariant args[])
358{
0a0e6a5b
WS
359 wxVariant retVariant;
360 if (!Invoke(property, DISPATCH_PROPERTYPUT, retVariant, noArgs, args))
361 {
362 return false;
363 }
364 return true;
d980b3e1
JS
365}
366
24f4ad95
JS
367bool wxAutomationObject::PutPropertyArray(const wxString& property, int noArgs, const wxVariant **args)
368{
0a0e6a5b
WS
369 wxVariant retVariant;
370 if (!Invoke(property, DISPATCH_PROPERTYPUT, retVariant, noArgs, NULL, args))
371 {
372 return false;
373 }
374 return true;
24f4ad95
JS
375}
376
d980b3e1 377bool wxAutomationObject::PutProperty(const wxString& property,
0a0e6a5b
WS
378 const wxVariant& arg1, const wxVariant& arg2,
379 const wxVariant& arg3, const wxVariant& arg4,
380 const wxVariant& arg5, const wxVariant& arg6)
d980b3e1 381{
0a0e6a5b
WS
382 const wxVariant** args = new const wxVariant*[6];
383 int i = 0;
384 if (!arg1.IsNull())
385 {
386 args[i] = & arg1;
387 i ++;
388 }
389 if (!arg2.IsNull())
390 {
391 args[i] = & arg2;
392 i ++;
393 }
394 if (!arg3.IsNull())
395 {
396 args[i] = & arg3;
397 i ++;
398 }
399 if (!arg4.IsNull())
400 {
401 args[i] = & arg4;
402 i ++;
403 }
404 if (!arg5.IsNull())
405 {
406 args[i] = & arg5;
407 i ++;
408 }
409 if (!arg6.IsNull())
410 {
411 args[i] = & arg6;
412 i ++;
413 }
414 wxVariant retVariant;
415 bool ret = Invoke(property, DISPATCH_PROPERTYPUT, retVariant, i, NULL, args);
416 delete[] args;
417 return ret;
d980b3e1
JS
418}
419
420
421// Uses DISPATCH_PROPERTYGET
422// and returns a dispatch pointer. The calling code should call Release
423// on the pointer, though this could be implicit by constructing an wxAutomationObject
424// with it and letting the destructor call Release.
425WXIDISPATCH* wxAutomationObject::GetDispatchProperty(const wxString& property, int noArgs, wxVariant args[]) const
426{
0a0e6a5b
WS
427 wxVariant retVariant;
428 if (Invoke(property, DISPATCH_PROPERTYGET, retVariant, noArgs, args))
429 {
430 if (retVariant.GetType() == wxT("void*"))
431 {
432 return (WXIDISPATCH*) retVariant.GetVoidPtr();
433 }
434 }
435
436 return (WXIDISPATCH*) NULL;
d980b3e1
JS
437}
438
24f4ad95
JS
439// Uses DISPATCH_PROPERTYGET
440// and returns a dispatch pointer. The calling code should call Release
441// on the pointer, though this could be implicit by constructing an wxAutomationObject
442// with it and letting the destructor call Release.
443WXIDISPATCH* wxAutomationObject::GetDispatchProperty(const wxString& property, int noArgs, const wxVariant **args) const
444{
0a0e6a5b
WS
445 wxVariant retVariant;
446 if (Invoke(property, DISPATCH_PROPERTYGET, retVariant, noArgs, NULL, args))
447 {
448 if (retVariant.GetType() == wxT("void*"))
449 {
450 return (WXIDISPATCH*) retVariant.GetVoidPtr();
451 }
452 }
453
454 return (WXIDISPATCH*) NULL;
24f4ad95
JS
455}
456
457
d980b3e1
JS
458// A way of initialising another wxAutomationObject with a dispatch object
459bool wxAutomationObject::GetObject(wxAutomationObject& obj, const wxString& property, int noArgs, wxVariant args[]) const
460{
0a0e6a5b
WS
461 WXIDISPATCH* dispatch = GetDispatchProperty(property, noArgs, args);
462 if (dispatch)
463 {
464 obj.SetDispatchPtr(dispatch);
465 return true;
466 }
467 else
468 return false;
d980b3e1
JS
469}
470
24f4ad95
JS
471// A way of initialising another wxAutomationObject with a dispatch object
472bool wxAutomationObject::GetObject(wxAutomationObject& obj, const wxString& property, int noArgs, const wxVariant **args) const
473{
0a0e6a5b
WS
474 WXIDISPATCH* dispatch = GetDispatchProperty(property, noArgs, args);
475 if (dispatch)
476 {
477 obj.SetDispatchPtr(dispatch);
478 return true;
479 }
480 else
481 return false;
24f4ad95
JS
482}
483
d980b3e1
JS
484// Get a dispatch pointer from the current object associated
485// with a class id
486bool wxAutomationObject::GetInstance(const wxString& classId) const
487{
0a0e6a5b
WS
488 if (m_dispatchPtr)
489 return false;
490
491 CLSID clsId;
492 IUnknown * pUnk = NULL;
493
494 wxBasicString unicodeName(classId.mb_str());
495
496 if (FAILED(CLSIDFromProgID((BSTR) unicodeName, &clsId)))
497 {
498 wxLogWarning(wxT("Cannot obtain CLSID from ProgID"));
499 return false;
500 }
501
502 if (FAILED(GetActiveObject(clsId, NULL, &pUnk)))
503 {
504 wxLogWarning(wxT("Cannot find an active object"));
505 return false;
506 }
507
508 if (pUnk->QueryInterface(IID_IDispatch, (LPVOID*) &m_dispatchPtr) != S_OK)
509 {
510 wxLogWarning(wxT("Cannot find IDispatch interface"));
511 return false;
512 }
513
514 return true;
d980b3e1
JS
515}
516
517// Get a dispatch pointer from a new object associated
518// with the given class id
519bool wxAutomationObject::CreateInstance(const wxString& classId) const
520{
0a0e6a5b
WS
521 if (m_dispatchPtr)
522 return false;
523
524 CLSID clsId;
525
526 wxBasicString unicodeName(classId.mb_str());
527
528 if (FAILED(CLSIDFromProgID((BSTR) unicodeName, &clsId)))
529 {
530 wxLogWarning(wxT("Cannot obtain CLSID from ProgID"));
531 return false;
532 }
533
534 // start a new copy of Excel, grab the IDispatch interface
535 if (FAILED(CoCreateInstance(clsId, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void**)&m_dispatchPtr)))
536 {
537 wxLogWarning(wxT("Cannot start an instance of this class."));
538 return false;
539 }
540
541 return true;
d980b3e1
JS
542}
543
544
e2898549 545WXDLLEXPORT bool wxConvertVariantToOle(const wxVariant& variant, VARIANTARG& oleVariant)
d980b3e1 546{
0a0e6a5b
WS
547 ClearVariant(&oleVariant);
548 if (variant.IsNull())
549 {
550 oleVariant.vt = VT_NULL;
551 return true;
552 }
d980b3e1
JS
553
554 wxString type(variant.GetType());
555
6b978929
JS
556
557 if (type == wxT("long"))
d980b3e1
JS
558 {
559 oleVariant.vt = VT_I4;
560 oleVariant.lVal = variant.GetLong() ;
561 }
6b978929
JS
562 // cVal not always present
563#ifndef __GNUWIN32__
564 else if (type == wxT("char"))
565 {
0a0e6a5b 566 oleVariant.vt=VT_I1; // Signed Char
6b978929
JS
567 oleVariant.cVal=variant.GetChar();
568 }
569#endif
223d09f6 570 else if (type == wxT("double"))
d980b3e1
JS
571 {
572 oleVariant.vt = VT_R8;
573 oleVariant.dblVal = variant.GetDouble();
574 }
223d09f6 575 else if (type == wxT("bool"))
d980b3e1
JS
576 {
577 oleVariant.vt = VT_BOOL;
7c5dc04f 578 // 'bool' required for VC++ 4 apparently
6b12494d 579#if (defined(__VISUALC__) && (__VISUALC__ <= 1000))
7be1f0d9
JS
580 oleVariant.bool = variant.GetBool();
581#else
d980b3e1 582 oleVariant.boolVal = variant.GetBool();
7be1f0d9 583#endif
d980b3e1 584 }
223d09f6 585 else if (type == wxT("string"))
d980b3e1
JS
586 {
587 wxString str( variant.GetString() );
588 oleVariant.vt = VT_BSTR;
ed5317e5 589 oleVariant.bstrVal = wxConvertStringToOle(str);
d980b3e1 590 }
61bfe4b0
JS
591#if wxUSE_DATETIME
592 else if (type == wxT("datetime"))
593 {
594 wxDateTime date( variant.GetDateTime() );
595 oleVariant.vt = VT_DATE;
7520f3da 596
94113cc5 597 long dosDateTime = date.GetAsDOS();
11f104e5
WS
598 short dosDate = short((dosDateTime & 0xFFFF0000) >> 16);
599 short dosTime = short(dosDateTime & 0xFFFF);
7520f3da 600
94113cc5 601 DosDateTimeToVariantTime(dosDate, dosTime, & oleVariant.date);
61bfe4b0 602 }
457e6c54 603#endif
223d09f6 604 else if (type == wxT("void*"))
d980b3e1
JS
605 {
606 oleVariant.vt = VT_DISPATCH;
607 oleVariant.pdispVal = (IDispatch*) variant.GetVoidPtr();
608 }
223d09f6 609 else if (type == wxT("list") || type == wxT("stringlist"))
d980b3e1
JS
610 {
611 oleVariant.vt = VT_VARIANT | VT_ARRAY;
612
0a0e6a5b
WS
613 SAFEARRAY *psa;
614 SAFEARRAYBOUND saBound;
615 VARIANTARG *pvargBase;
616 VARIANTARG *pvarg;
617 int i, j;
d980b3e1
JS
618
619 int iCount = variant.GetCount();
0a0e6a5b
WS
620
621 saBound.lLbound = 0;
622 saBound.cElements = iCount;
623
624 psa = SafeArrayCreate(VT_VARIANT, 1, &saBound);
625 if (psa == NULL)
626 return false;
627
628 SafeArrayAccessData(psa, (void**)&pvargBase);
629
630 pvarg = pvargBase;
631 for (i = 0; i < iCount; i++)
632 {
633 // copy each string in the list of strings
d980b3e1 634 wxVariant eachVariant(variant[i]);
ed5317e5 635 if (!wxConvertVariantToOle(eachVariant, * pvarg))
d980b3e1 636 {
0a0e6a5b
WS
637 // memory failure: back out and free strings alloc'ed up to
638 // now, and then the array itself.
639 pvarg = pvargBase;
640 for (j = 0; j < i; j++)
641 {
642 SysFreeString(pvarg->bstrVal);
643 pvarg++;
644 }
645 SafeArrayDestroy(psa);
646 return false;
647 }
648 pvarg++;
649 }
650
651 SafeArrayUnaccessData(psa);
d980b3e1
JS
652
653 oleVariant.parray = psa;
654 }
655 else
656 {
657 oleVariant.vt = VT_NULL;
0a0e6a5b 658 return false;
d980b3e1 659 }
0a0e6a5b 660 return true;
d980b3e1
JS
661}
662
663#ifndef VT_TYPEMASK
664#define VT_TYPEMASK 0xfff
665#endif
666
e2898549 667WXDLLEXPORT bool wxConvertOleToVariant(const VARIANTARG& oleVariant, wxVariant& variant)
d980b3e1 668{
0a0e6a5b
WS
669 switch (oleVariant.vt & VT_TYPEMASK)
670 {
671 case VT_BSTR:
672 {
673 wxString str(wxConvertStringFromOle(oleVariant.bstrVal));
674 variant = str;
675 break;
676 }
677 case VT_DATE:
678 {
61bfe4b0 679#if wxUSE_DATETIME
94113cc5
JS
680 unsigned short dosDate = 0;
681 unsigned short dosTime = 0;
682 VariantTimeToDosDateTime(oleVariant.date, & dosDate, & dosTime);
7520f3da 683
94113cc5
JS
684 long dosDateTime = (dosDate << 16) || dosTime;
685 wxDateTime date;
686 date.SetFromDOS(dosDateTime);
0a0e6a5b 687 variant = date;
f6bcfd97 688#endif
f6bcfd97 689 break;
0a0e6a5b
WS
690 }
691 case VT_I4:
692 {
693 variant = (long) oleVariant.lVal;
694 break;
695 }
696 case VT_I2:
697 {
698 variant = (long) oleVariant.iVal;
699 break;
700 }
701
702 case VT_BOOL:
703 {
6b12494d 704#if (defined(_MSC_VER) && (_MSC_VER <= 1000) && !defined(__MWERKS__) ) //GC
25889d3c 705#ifndef HAVE_BOOL // Can't use bool operator if no native bool type
0a0e6a5b 706 variant = (long) (oleVariant.bool != 0);
25889d3c 707#else
0a0e6a5b 708 variant = (bool) (oleVariant.bool != 0);
25889d3c 709#endif
f6bcfd97
BP
710#else
711#ifndef HAVE_BOOL // Can't use bool operator if no native bool type
0a0e6a5b 712 variant = (long) (oleVariant.boolVal != 0);
7be1f0d9 713#else
0a0e6a5b 714 variant = (bool) (oleVariant.boolVal != 0);
f6bcfd97 715#endif
7be1f0d9 716#endif
0a0e6a5b
WS
717 break;
718 }
719 case VT_R8:
720 {
721 variant = oleVariant.dblVal;
722 break;
723 }
724 case VT_ARRAY:
725 {
726 variant.ClearList();
727
728 int cDims, cElements, i;
729 VARIANTARG* pvdata;
730
731 // Iterate the dimensions: number of elements is x*y*z
732 for (cDims = 0, cElements = 1;
733 cDims < oleVariant.parray->cDims; cDims ++)
734 cElements *= oleVariant.parray->rgsabound[cDims].cElements;
735
736 // Get a pointer to the data
737 HRESULT hr = SafeArrayAccessData(oleVariant.parray, (void HUGEP* FAR*) & pvdata);
738 if (hr != NOERROR)
739 return false;
740 // Iterate the data.
741 for (i = 0; i < cElements; i++)
742 {
743 VARIANTARG& oleElement = pvdata[i];
744 wxVariant vElement;
745 if (!wxConvertOleToVariant(oleElement, vElement))
746 return false;
747
748 variant.Append(vElement);
749 }
750 SafeArrayUnaccessData(oleVariant.parray);
751 break;
752 }
753 case VT_DISPATCH:
754 {
755 variant = (void*) oleVariant.pdispVal;
756 break;
757 }
758 case VT_NULL:
759 {
760 variant.MakeNull();
761 break;
762 }
763 case VT_EMPTY:
764 {
765 break; // Ignore Empty Variant, used only during destruction of objects
766 }
767 default:
768 {
769 wxLogError(wxT("wxAutomationObject::ConvertOleToVariant: Unknown variant value type"));
770 return false;
771 }
772 }
773 return true;
d980b3e1
JS
774}
775
d980b3e1
JS
776/*
777 * ClearVariant
778 *
779 * Zeros a variant structure without regard to current contents
780 */
781static void ClearVariant(VARIANTARG *pvarg)
782{
0a0e6a5b
WS
783 pvarg->vt = VT_EMPTY;
784 pvarg->wReserved1 = 0;
785 pvarg->wReserved2 = 0;
786 pvarg->wReserved3 = 0;
787 pvarg->lVal = 0;
d980b3e1
JS
788}
789
790/*
791 * ReleaseVariant
792 *
793 * Clears a particular variant structure and releases any external objects
794 * or memory contained in the variant. Supports the data types listed above.
795 */
796static void ReleaseVariant(VARIANTARG *pvarg)
797{
0a0e6a5b
WS
798 VARTYPE vt;
799 VARIANTARG _huge *pvargArray;
800 long lLBound, lUBound, l;
801
5c519b6c 802 vt = (VARTYPE)(pvarg->vt & 0xfff); // mask off flags
0a0e6a5b
WS
803
804 // check if an array. If so, free its contents, then the array itself.
805 if (V_ISARRAY(pvarg))
806 {
807 // variant arrays are all this routine currently knows about. Since a
808 // variant can contain anything (even other arrays), call ourselves
809 // recursively.
810 if (vt == VT_VARIANT)
811 {
812 SafeArrayGetLBound(pvarg->parray, 1, &lLBound);
813 SafeArrayGetUBound(pvarg->parray, 1, &lUBound);
814
815 if (lUBound > lLBound)
816 {
817 lUBound -= lLBound;
818
819 SafeArrayAccessData(pvarg->parray, (void**)&pvargArray);
820
821 for (l = 0; l < lUBound; l++)
822 {
823 ReleaseVariant(pvargArray);
824 pvargArray++;
825 }
826
827 SafeArrayUnaccessData(pvarg->parray);
828 }
829 }
830 else
831 {
832 wxLogWarning(wxT("ReleaseVariant: Array contains non-variant type"));
833 }
834
835 // Free the array itself.
836 SafeArrayDestroy(pvarg->parray);
837 }
838 else
839 {
840 switch (vt)
841 {
842 case VT_DISPATCH:
843 if (pvarg->pdispVal)
844 pvarg->pdispVal->Release();
845 break;
846
847 case VT_BSTR:
848 SysFreeString(pvarg->bstrVal);
849 break;
850
851 case VT_I2:
0a0e6932 852 case VT_I4:
0a0e6a5b
WS
853 case VT_BOOL:
854 case VT_R8:
855 case VT_ERROR: // to avoid erroring on an error return from Excel
0a0e6932 856 case VT_EMPTY:
0a0e6a5b
WS
857 // no work for these types
858 break;
859
860 default:
861 wxLogWarning(wxT("ReleaseVariant: Unknown type"));
862 break;
863 }
864 }
865
866 ClearVariant(pvarg);
d980b3e1
JS
867}
868
869#if 0
870
871void ShowException(LPOLESTR szMember, HRESULT hr, EXCEPINFO *pexcep, unsigned int uiArgErr)
872{
0a0e6a5b
WS
873 TCHAR szBuf[512];
874
875 switch (GetScode(hr))
876 {
877 case DISP_E_UNKNOWNNAME:
878 wsprintf(szBuf, L"%s: Unknown name or named argument.", szMember);
879 break;
880
881 case DISP_E_BADPARAMCOUNT:
882 wsprintf(szBuf, L"%s: Incorrect number of arguments.", szMember);
883 break;
884
885 case DISP_E_EXCEPTION:
886 wsprintf(szBuf, L"%s: Error %d: ", szMember, pexcep->wCode);
887 if (pexcep->bstrDescription != NULL)
888 lstrcat(szBuf, pexcep->bstrDescription);
889 else
890 lstrcat(szBuf, L"<<No Description>>");
891 break;
892
893 case DISP_E_MEMBERNOTFOUND:
894 wsprintf(szBuf, L"%s: method or property not found.", szMember);
895 break;
896
897 case DISP_E_OVERFLOW:
898 wsprintf(szBuf, L"%s: Overflow while coercing argument values.", szMember);
899 break;
900
901 case DISP_E_NONAMEDARGS:
902 wsprintf(szBuf, L"%s: Object implementation does not support named arguments.",
903 szMember);
904 break;
905
906 case DISP_E_UNKNOWNLCID:
907 wsprintf(szBuf, L"%s: The locale ID is unknown.", szMember);
908 break;
909
910 case DISP_E_PARAMNOTOPTIONAL:
911 wsprintf(szBuf, L"%s: Missing a required parameter.", szMember);
912 break;
913
914 case DISP_E_PARAMNOTFOUND:
915 wsprintf(szBuf, L"%s: Argument not found, argument %d.", szMember, uiArgErr);
916 break;
917
918 case DISP_E_TYPEMISMATCH:
919 wsprintf(szBuf, L"%s: Type mismatch, argument %d.", szMember, uiArgErr);
920 break;
921
922 default:
3103e8a9 923 wsprintf(szBuf, L"%s: Unknown error occurred.", szMember);
0a0e6a5b
WS
924 break;
925 }
926
927 wxLogWarning(szBuf);
d980b3e1
JS
928}
929
930#endif
931
6b12494d 932#endif // wxUSE_OLE && !(defined(__BORLANDC__) && (__BORLANDC__ < 0x520)) && !defined(__CYGWIN10__)