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