]>
git.saurik.com Git - wxWidgets.git/blob - src/msw/ole/automtn.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/ole/automtn.cpp
3 // Purpose: OLE automation utilities
4 // Author: Julian Smart
8 // Copyright: (c) 1998, Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
15 #if defined(__BORLANDC__)
19 // With Borland C++, all samples crash if this is compiled in.
20 #if (defined(__BORLANDC__) && (__BORLANDC__ < 0x520)) || defined(__CYGWIN10__)
21 #undef wxUSE_OLE_AUTOMATION
22 #define wxUSE_OLE_AUTOMATION 0
30 #define _FORCENAMELESSUNION
31 #include "wx/msw/private.h"
32 #include "wx/msw/ole/oleutils.h"
33 #include "wx/msw/ole/automtn.h"
36 #include "wx/msw/wince/time.h"
54 #include "wx/datetime.h"
55 #endif // wxUSE_DATETIME
57 #if wxUSE_OLE_AUTOMATION
59 // Report an OLE error to the user via wxLog.
61 ShowException(const wxString
& member
,
64 unsigned int uiArgErr
);
68 wxAutomationObject::wxAutomationObject(WXIDISPATCH
* dispatchPtr
)
70 m_dispatchPtr
= dispatchPtr
;
73 wxAutomationObject::~wxAutomationObject()
77 ((IDispatch
*)m_dispatchPtr
)->Release();
82 #define INVOKEARG(i) (args ? args[i] : *(ptrArgs[i]))
84 // For Put/Get, no named arguments are allowed.
85 bool wxAutomationObject::Invoke(const wxString
& member
, int action
,
86 wxVariant
& retValue
, int noArgs
, wxVariant args
[], const wxVariant
* ptrArgs
[]) const
91 // nonConstMember is necessary because the wxString class doesn't have enough consts...
92 wxString
nonConstMember(member
);
94 int ch
= nonConstMember
.Find('.');
97 // Use dot notation to get the next object
98 wxString
member2(nonConstMember
.Left((size_t) ch
));
99 wxString
rest(nonConstMember
.Right(nonConstMember
.length() - ch
- 1));
100 wxAutomationObject obj
;
101 if (!GetObject(obj
, member2
))
103 return obj
.Invoke(rest
, action
, retValue
, noArgs
, args
, ptrArgs
);
107 VariantInit(& vReturn
);
109 VARIANTARG
* vReturnPtr
= & vReturn
;
111 // Find number of names args
112 int namedArgCount
= 0;
114 for (i
= 0; i
< noArgs
; i
++)
115 if (!INVOKEARG(i
).GetName().IsNull())
120 int namedArgStringCount
= namedArgCount
+ 1;
121 BSTR
* argNames
= new BSTR
[namedArgStringCount
];
122 argNames
[0] = wxConvertStringToOle(member
);
124 // Note that arguments are specified in reverse order
125 // (all totally logical; hey, we're dealing with OLE here.)
128 for (i
= 0; i
< namedArgCount
; i
++)
130 if (!INVOKEARG(i
).GetName().IsNull())
132 argNames
[(namedArgCount
-j
)] = wxConvertStringToOle(INVOKEARG(i
).GetName());
137 // + 1 for the member name, + 1 again in case we're a 'put'
138 DISPID
* dispIds
= new DISPID
[namedArgCount
+ 2];
141 DISPPARAMS dispparams
;
142 unsigned int uiArgErr
;
144 // Get the IDs for the member and its arguments. GetIDsOfNames expects the
145 // member name as the first name, followed by argument names (if any).
146 hr
= ((IDispatch
*)m_dispatchPtr
)->GetIDsOfNames(IID_NULL
, argNames
,
147 1 + namedArgCount
, LOCALE_SYSTEM_DEFAULT
, dispIds
);
150 ShowException(member
, hr
, NULL
, 0);
156 // if doing a property put(ref), we need to adjust the first argument to have a
157 // named arg of DISPID_PROPERTYPUT.
158 if (action
& (DISPATCH_PROPERTYPUT
| DISPATCH_PROPERTYPUTREF
))
161 dispIds
[1] = DISPID_PROPERTYPUT
;
165 // Convert the wxVariants to VARIANTARGs
166 VARIANTARG
* oleArgs
= new VARIANTARG
[noArgs
];
167 for (i
= 0; i
< noArgs
; i
++)
169 // Again, reverse args
170 if (!wxConvertVariantToOle(INVOKEARG((noArgs
-1) - i
), oleArgs
[i
]))
179 dispparams
.rgdispidNamedArgs
= dispIds
+ 1;
180 dispparams
.rgvarg
= oleArgs
;
181 dispparams
.cArgs
= noArgs
;
182 dispparams
.cNamedArgs
= namedArgCount
;
187 hr
= ((IDispatch
*)m_dispatchPtr
)->Invoke(dispIds
[0], IID_NULL
, LOCALE_SYSTEM_DEFAULT
,
188 (WORD
)action
, &dispparams
, vReturnPtr
, &excep
, &uiArgErr
);
190 for (i
= 0; i
< namedArgStringCount
; i
++)
192 SysFreeString(argNames
[i
]);
197 for (i
= 0; i
< noArgs
; i
++)
198 VariantClear(& oleArgs
[i
]) ;
203 // display the exception information if appropriate:
204 ShowException(member
, hr
, &excep
, uiArgErr
);
206 // free exception structure information
207 SysFreeString(excep
.bstrSource
);
208 SysFreeString(excep
.bstrDescription
);
209 SysFreeString(excep
.bstrHelpFile
);
212 VariantClear(vReturnPtr
);
219 // Convert result to wxVariant form
220 wxConvertOleToVariant(vReturn
, retValue
);
221 // Mustn't release the dispatch pointer
222 if (vReturn
.vt
== VT_DISPATCH
)
224 vReturn
.pdispVal
= NULL
;
226 VariantClear(& vReturn
);
232 // Invoke a member function
233 wxVariant
wxAutomationObject::CallMethod(const wxString
& member
, int noArgs
, wxVariant args
[])
235 wxVariant retVariant
;
236 if (!Invoke(member
, DISPATCH_METHOD
, retVariant
, noArgs
, args
))
238 retVariant
.MakeNull();
243 wxVariant
wxAutomationObject::CallMethodArray(const wxString
& member
, int noArgs
, const wxVariant
**args
)
245 wxVariant retVariant
;
246 if (!Invoke(member
, DISPATCH_METHOD
, retVariant
, noArgs
, NULL
, args
))
248 retVariant
.MakeNull();
253 wxVariant
wxAutomationObject::CallMethod(const wxString
& member
,
254 const wxVariant
& arg1
, const wxVariant
& arg2
,
255 const wxVariant
& arg3
, const wxVariant
& arg4
,
256 const wxVariant
& arg5
, const wxVariant
& arg6
)
258 const wxVariant
** args
= new const wxVariant
*[6];
290 wxVariant retVariant
;
291 if (!Invoke(member
, DISPATCH_METHOD
, retVariant
, i
, NULL
, args
))
293 retVariant
.MakeNull();
300 wxVariant
wxAutomationObject::GetPropertyArray(const wxString
& property
, int noArgs
, const wxVariant
**args
) const
302 wxVariant retVariant
;
303 if (!Invoke(property
, DISPATCH_PROPERTYGET
, retVariant
, noArgs
, NULL
, args
))
305 retVariant
.MakeNull();
309 wxVariant
wxAutomationObject::GetProperty(const wxString
& property
, int noArgs
, wxVariant args
[]) const
311 wxVariant retVariant
;
312 if (!Invoke(property
, DISPATCH_PROPERTYGET
, retVariant
, noArgs
, args
))
314 retVariant
.MakeNull();
319 wxVariant
wxAutomationObject::GetProperty(const wxString
& property
,
320 const wxVariant
& arg1
, const wxVariant
& arg2
,
321 const wxVariant
& arg3
, const wxVariant
& arg4
,
322 const wxVariant
& arg5
, const wxVariant
& arg6
)
324 const wxVariant
** args
= new const wxVariant
*[6];
356 wxVariant retVariant
;
357 if (!Invoke(property
, DISPATCH_PROPERTYGET
, retVariant
, i
, NULL
, args
))
359 retVariant
.MakeNull();
365 bool wxAutomationObject::PutProperty(const wxString
& property
, int noArgs
, wxVariant args
[])
367 wxVariant retVariant
;
368 if (!Invoke(property
, DISPATCH_PROPERTYPUT
, retVariant
, noArgs
, args
))
375 bool wxAutomationObject::PutPropertyArray(const wxString
& property
, int noArgs
, const wxVariant
**args
)
377 wxVariant retVariant
;
378 if (!Invoke(property
, DISPATCH_PROPERTYPUT
, retVariant
, noArgs
, NULL
, args
))
385 bool wxAutomationObject::PutProperty(const wxString
& property
,
386 const wxVariant
& arg1
, const wxVariant
& arg2
,
387 const wxVariant
& arg3
, const wxVariant
& arg4
,
388 const wxVariant
& arg5
, const wxVariant
& arg6
)
390 const wxVariant
** args
= new const wxVariant
*[6];
422 wxVariant retVariant
;
423 bool ret
= Invoke(property
, DISPATCH_PROPERTYPUT
, retVariant
, i
, NULL
, args
);
429 // Uses DISPATCH_PROPERTYGET
430 // and returns a dispatch pointer. The calling code should call Release
431 // on the pointer, though this could be implicit by constructing an wxAutomationObject
432 // with it and letting the destructor call Release.
433 WXIDISPATCH
* wxAutomationObject::GetDispatchProperty(const wxString
& property
, int noArgs
, wxVariant args
[]) const
435 wxVariant retVariant
;
436 if (Invoke(property
, DISPATCH_PROPERTYGET
, retVariant
, noArgs
, args
))
438 if (retVariant
.GetType() == wxT("void*"))
440 return (WXIDISPATCH
*) retVariant
.GetVoidPtr();
447 // Uses DISPATCH_PROPERTYGET
448 // and returns a dispatch pointer. The calling code should call Release
449 // on the pointer, though this could be implicit by constructing an wxAutomationObject
450 // with it and letting the destructor call Release.
451 WXIDISPATCH
* wxAutomationObject::GetDispatchProperty(const wxString
& property
, int noArgs
, const wxVariant
**args
) const
453 wxVariant retVariant
;
454 if (Invoke(property
, DISPATCH_PROPERTYGET
, retVariant
, noArgs
, NULL
, args
))
456 if (retVariant
.GetType() == wxT("void*"))
458 return (WXIDISPATCH
*) retVariant
.GetVoidPtr();
466 // A way of initialising another wxAutomationObject with a dispatch object
467 bool wxAutomationObject::GetObject(wxAutomationObject
& obj
, const wxString
& property
, int noArgs
, wxVariant args
[]) const
469 WXIDISPATCH
* dispatch
= GetDispatchProperty(property
, noArgs
, args
);
472 obj
.SetDispatchPtr(dispatch
);
479 // A way of initialising another wxAutomationObject with a dispatch object
480 bool wxAutomationObject::GetObject(wxAutomationObject
& obj
, const wxString
& property
, int noArgs
, const wxVariant
**args
) const
482 WXIDISPATCH
* dispatch
= GetDispatchProperty(property
, noArgs
, args
);
485 obj
.SetDispatchPtr(dispatch
);
492 // Get a dispatch pointer from the current object associated
494 bool wxAutomationObject::GetInstance(const wxString
& classId
) const
501 IUnknown
* pUnk
= NULL
;
503 wxBasicString
unicodeName(classId
);
505 hr
= CLSIDFromProgID((BSTR
) unicodeName
, &clsId
);
508 ShowException(classId
, hr
, NULL
, 0);
509 wxLogWarning(wxT("Cannot obtain CLSID from ProgID"));
513 hr
= GetActiveObject(clsId
, NULL
, &pUnk
);
516 ShowException(classId
, hr
, NULL
, 0);
517 wxLogWarning(wxT("Cannot find an active object"));
521 hr
= pUnk
->QueryInterface(IID_IDispatch
, (LPVOID
*) &m_dispatchPtr
);
524 ShowException(classId
, hr
, NULL
, 0);
525 wxLogWarning(wxT("Cannot find IDispatch interface"));
532 // Get a dispatch pointer from a new object associated
533 // with the given class id
534 bool wxAutomationObject::CreateInstance(const wxString
& classId
) const
542 wxBasicString
unicodeName(classId
);
544 hr
= CLSIDFromProgID((BSTR
) unicodeName
, &clsId
);
547 ShowException(classId
, hr
, NULL
, 0);
548 wxLogWarning(wxT("Cannot obtain CLSID from ProgID"));
552 // get the server IDispatch interface
554 // NB: using CLSCTX_INPROC_HANDLER results in failure when getting
555 // Automation interface for Microsoft Office applications so don't use
556 // CLSCTX_ALL which includes it
557 hr
= CoCreateInstance(clsId
, NULL
, CLSCTX_SERVER
, IID_IDispatch
,
558 (void**)&m_dispatchPtr
);
561 ShowException(classId
, hr
, NULL
, 0);
562 wxLogWarning(wxT("Could not start an instance of this class."));
570 ShowException(const wxString
& member
,
573 unsigned int uiArgErr
)
576 switch (GetScode(hr
))
578 case DISP_E_UNKNOWNNAME
:
579 message
= wxT("Unknown name or named argument.");
582 case DISP_E_BADPARAMCOUNT
:
583 message
= wxT("Incorrect number of arguments.");
586 case DISP_E_EXCEPTION
:
588 message
= wxT("Error Code (");
589 message
<< pexcep
->wCode
;// unsigned short
591 if (pexcep
->bstrDescription
!= NULL
)
592 message
+= pexcep
->bstrDescription
;
594 message
+= wxT("<<No Description>>");
598 case DISP_E_MEMBERNOTFOUND
:
599 message
= wxT("Method or property not found.");
602 case DISP_E_OVERFLOW
:
603 message
= wxT("Overflow while coercing argument values.");
606 case DISP_E_NONAMEDARGS
:
607 message
= wxT("Object implementation does not support named arguments.");
610 case DISP_E_UNKNOWNLCID
:
611 message
= wxT("The locale ID is unknown.");
614 case DISP_E_PARAMNOTOPTIONAL
:
615 message
= wxT("Missing a required parameter.");
618 case DISP_E_PARAMNOTFOUND
:
619 message
= wxT("Argument not found, argument.");
623 case DISP_E_TYPEMISMATCH
:
624 message
= wxT("Type mismatch, argument.");
628 case ERROR_FILE_NOT_FOUND
:
629 message
= wxT("The system cannot find the file specified.");
632 case REGDB_E_CLASSNOTREG
:
633 message
= wxT("Class not registered.");
637 message
= wxT("Unknown error occurred. Return value is ");
642 wxLogDebug("OLE Automation error in %s: %s", member
, message
);
645 #endif // wxUSE_OLE_AUTOMATION