]>
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 // static void ShowException(LPOLESTR szMember, HRESULT hr, EXCEPINFO *pexcep, unsigned int uiArgErr);
59 #if wxUSE_OLE_AUTOMATION
65 wxAutomationObject::wxAutomationObject(WXIDISPATCH
* dispatchPtr
)
67 m_dispatchPtr
= dispatchPtr
;
70 wxAutomationObject::~wxAutomationObject()
74 ((IDispatch
*)m_dispatchPtr
)->Release();
79 #define INVOKEARG(i) (args ? args[i] : *(ptrArgs[i]))
81 // For Put/Get, no named arguments are allowed.
82 bool wxAutomationObject::Invoke(const wxString
& member
, int action
,
83 wxVariant
& retValue
, int noArgs
, wxVariant args
[], const wxVariant
* ptrArgs
[]) const
88 // nonConstMember is necessary because the wxString class doesn't have enough consts...
89 wxString
nonConstMember(member
);
91 int ch
= nonConstMember
.Find('.');
94 // Use dot notation to get the next object
95 wxString
member2(nonConstMember
.Left((size_t) ch
));
96 wxString
rest(nonConstMember
.Right(nonConstMember
.length() - ch
- 1));
97 wxAutomationObject obj
;
98 if (!GetObject(obj
, member2
))
100 return obj
.Invoke(rest
, action
, retValue
, noArgs
, args
, ptrArgs
);
104 VariantInit(& vReturn
);
106 VARIANTARG
* vReturnPtr
= & vReturn
;
108 // Find number of names args
109 int namedArgCount
= 0;
111 for (i
= 0; i
< noArgs
; i
++)
112 if (!INVOKEARG(i
).GetName().IsNull())
117 int namedArgStringCount
= namedArgCount
+ 1;
118 BSTR
* argNames
= new BSTR
[namedArgStringCount
];
119 argNames
[0] = wxConvertStringToOle(member
);
121 // Note that arguments are specified in reverse order
122 // (all totally logical; hey, we're dealing with OLE here.)
125 for (i
= 0; i
< namedArgCount
; i
++)
127 if (!INVOKEARG(i
).GetName().IsNull())
129 argNames
[(namedArgCount
-j
)] = wxConvertStringToOle(INVOKEARG(i
).GetName());
134 // + 1 for the member name, + 1 again in case we're a 'put'
135 DISPID
* dispIds
= new DISPID
[namedArgCount
+ 2];
138 DISPPARAMS dispparams
;
139 unsigned int uiArgErr
;
141 // Get the IDs for the member and its arguments. GetIDsOfNames expects the
142 // member name as the first name, followed by argument names (if any).
143 hr
= ((IDispatch
*)m_dispatchPtr
)->GetIDsOfNames(IID_NULL
, argNames
,
144 1 + namedArgCount
, LOCALE_SYSTEM_DEFAULT
, dispIds
);
147 // ShowException(szMember, hr, NULL, 0);
153 // if doing a property put(ref), we need to adjust the first argument to have a
154 // named arg of DISPID_PROPERTYPUT.
155 if (action
& (DISPATCH_PROPERTYPUT
| DISPATCH_PROPERTYPUTREF
))
158 dispIds
[1] = DISPID_PROPERTYPUT
;
162 // Convert the wxVariants to VARIANTARGs
163 VARIANTARG
* oleArgs
= new VARIANTARG
[noArgs
];
164 for (i
= 0; i
< noArgs
; i
++)
166 // Again, reverse args
167 if (!wxConvertVariantToOle(INVOKEARG((noArgs
-1) - i
), oleArgs
[i
]))
176 dispparams
.rgdispidNamedArgs
= dispIds
+ 1;
177 dispparams
.rgvarg
= oleArgs
;
178 dispparams
.cArgs
= noArgs
;
179 dispparams
.cNamedArgs
= namedArgCount
;
184 hr
= ((IDispatch
*)m_dispatchPtr
)->Invoke(dispIds
[0], IID_NULL
, LOCALE_SYSTEM_DEFAULT
,
185 (WORD
)action
, &dispparams
, vReturnPtr
, &excep
, &uiArgErr
);
187 for (i
= 0; i
< namedArgStringCount
; i
++)
189 SysFreeString(argNames
[i
]);
194 for (i
= 0; i
< noArgs
; i
++)
195 VariantClear(& oleArgs
[i
]) ;
200 // display the exception information if appropriate:
201 // ShowException((const char*) member, hr, &excep, uiArgErr);
203 // free exception structure information
204 SysFreeString(excep
.bstrSource
);
205 SysFreeString(excep
.bstrDescription
);
206 SysFreeString(excep
.bstrHelpFile
);
209 VariantClear(vReturnPtr
);
216 // Convert result to wxVariant form
217 wxConvertOleToVariant(vReturn
, retValue
);
218 // Mustn't release the dispatch pointer
219 if (vReturn
.vt
== VT_DISPATCH
)
221 vReturn
.pdispVal
= NULL
;
223 VariantClear(& vReturn
);
229 // Invoke a member function
230 wxVariant
wxAutomationObject::CallMethod(const wxString
& member
, int noArgs
, wxVariant args
[])
232 wxVariant retVariant
;
233 if (!Invoke(member
, DISPATCH_METHOD
, retVariant
, noArgs
, args
))
235 retVariant
.MakeNull();
240 wxVariant
wxAutomationObject::CallMethodArray(const wxString
& member
, int noArgs
, const wxVariant
**args
)
242 wxVariant retVariant
;
243 if (!Invoke(member
, DISPATCH_METHOD
, retVariant
, noArgs
, NULL
, args
))
245 retVariant
.MakeNull();
250 wxVariant
wxAutomationObject::CallMethod(const wxString
& member
,
251 const wxVariant
& arg1
, const wxVariant
& arg2
,
252 const wxVariant
& arg3
, const wxVariant
& arg4
,
253 const wxVariant
& arg5
, const wxVariant
& arg6
)
255 const wxVariant
** args
= new const wxVariant
*[6];
287 wxVariant retVariant
;
288 if (!Invoke(member
, DISPATCH_METHOD
, retVariant
, i
, NULL
, args
))
290 retVariant
.MakeNull();
297 wxVariant
wxAutomationObject::GetPropertyArray(const wxString
& property
, int noArgs
, const wxVariant
**args
) const
299 wxVariant retVariant
;
300 if (!Invoke(property
, DISPATCH_PROPERTYGET
, retVariant
, noArgs
, NULL
, args
))
302 retVariant
.MakeNull();
306 wxVariant
wxAutomationObject::GetProperty(const wxString
& property
, int noArgs
, wxVariant args
[]) const
308 wxVariant retVariant
;
309 if (!Invoke(property
, DISPATCH_PROPERTYGET
, retVariant
, noArgs
, args
))
311 retVariant
.MakeNull();
316 wxVariant
wxAutomationObject::GetProperty(const wxString
& property
,
317 const wxVariant
& arg1
, const wxVariant
& arg2
,
318 const wxVariant
& arg3
, const wxVariant
& arg4
,
319 const wxVariant
& arg5
, const wxVariant
& arg6
)
321 const wxVariant
** args
= new const wxVariant
*[6];
353 wxVariant retVariant
;
354 if (!Invoke(property
, DISPATCH_PROPERTYGET
, retVariant
, i
, NULL
, args
))
356 retVariant
.MakeNull();
362 bool wxAutomationObject::PutProperty(const wxString
& property
, int noArgs
, wxVariant args
[])
364 wxVariant retVariant
;
365 if (!Invoke(property
, DISPATCH_PROPERTYPUT
, retVariant
, noArgs
, args
))
372 bool wxAutomationObject::PutPropertyArray(const wxString
& property
, int noArgs
, const wxVariant
**args
)
374 wxVariant retVariant
;
375 if (!Invoke(property
, DISPATCH_PROPERTYPUT
, retVariant
, noArgs
, NULL
, args
))
382 bool wxAutomationObject::PutProperty(const wxString
& property
,
383 const wxVariant
& arg1
, const wxVariant
& arg2
,
384 const wxVariant
& arg3
, const wxVariant
& arg4
,
385 const wxVariant
& arg5
, const wxVariant
& arg6
)
387 const wxVariant
** args
= new const wxVariant
*[6];
419 wxVariant retVariant
;
420 bool ret
= Invoke(property
, DISPATCH_PROPERTYPUT
, retVariant
, i
, NULL
, args
);
426 // Uses DISPATCH_PROPERTYGET
427 // and returns a dispatch pointer. The calling code should call Release
428 // on the pointer, though this could be implicit by constructing an wxAutomationObject
429 // with it and letting the destructor call Release.
430 WXIDISPATCH
* wxAutomationObject::GetDispatchProperty(const wxString
& property
, int noArgs
, wxVariant args
[]) const
432 wxVariant retVariant
;
433 if (Invoke(property
, DISPATCH_PROPERTYGET
, retVariant
, noArgs
, args
))
435 if (retVariant
.GetType() == wxT("void*"))
437 return (WXIDISPATCH
*) retVariant
.GetVoidPtr();
444 // Uses DISPATCH_PROPERTYGET
445 // and returns a dispatch pointer. The calling code should call Release
446 // on the pointer, though this could be implicit by constructing an wxAutomationObject
447 // with it and letting the destructor call Release.
448 WXIDISPATCH
* wxAutomationObject::GetDispatchProperty(const wxString
& property
, int noArgs
, const wxVariant
**args
) const
450 wxVariant retVariant
;
451 if (Invoke(property
, DISPATCH_PROPERTYGET
, retVariant
, noArgs
, NULL
, args
))
453 if (retVariant
.GetType() == wxT("void*"))
455 return (WXIDISPATCH
*) retVariant
.GetVoidPtr();
463 // A way of initialising another wxAutomationObject with a dispatch object
464 bool wxAutomationObject::GetObject(wxAutomationObject
& obj
, const wxString
& property
, int noArgs
, wxVariant args
[]) const
466 WXIDISPATCH
* dispatch
= GetDispatchProperty(property
, noArgs
, args
);
469 obj
.SetDispatchPtr(dispatch
);
476 // A way of initialising another wxAutomationObject with a dispatch object
477 bool wxAutomationObject::GetObject(wxAutomationObject
& obj
, const wxString
& property
, int noArgs
, const wxVariant
**args
) const
479 WXIDISPATCH
* dispatch
= GetDispatchProperty(property
, noArgs
, args
);
482 obj
.SetDispatchPtr(dispatch
);
489 // Get a dispatch pointer from the current object associated
491 bool wxAutomationObject::GetInstance(const wxString
& classId
) const
497 IUnknown
* pUnk
= NULL
;
499 wxBasicString
unicodeName(classId
);
501 if (FAILED(CLSIDFromProgID((BSTR
) unicodeName
, &clsId
)))
503 wxLogWarning(wxT("Cannot obtain CLSID from ProgID"));
507 if (FAILED(GetActiveObject(clsId
, NULL
, &pUnk
)))
509 wxLogWarning(wxT("Cannot find an active object"));
513 if (pUnk
->QueryInterface(IID_IDispatch
, (LPVOID
*) &m_dispatchPtr
) != S_OK
)
515 wxLogWarning(wxT("Cannot find IDispatch interface"));
522 // Get a dispatch pointer from a new object associated
523 // with the given class id
524 bool wxAutomationObject::CreateInstance(const wxString
& classId
) const
531 wxBasicString
unicodeName(classId
);
533 if (FAILED(CLSIDFromProgID((BSTR
) unicodeName
, &clsId
)))
535 wxLogWarning(wxT("Cannot obtain CLSID from ProgID"));
539 // get the server IDispatch interface
541 // NB: using CLSCTX_INPROC_HANDLER results in failure when getting
542 // Automation interface for Microsoft Office applications so don't use
543 // CLSCTX_ALL which includes it
544 if (FAILED(CoCreateInstance(clsId
, NULL
, CLSCTX_SERVER
, IID_IDispatch
,
545 (void**)&m_dispatchPtr
)))
547 wxLogWarning(wxT("Cannot start an instance of this class."));
554 #endif // wxUSE_OLE_AUTOMATION
558 void ShowException(LPOLESTR szMember
, HRESULT hr
, EXCEPINFO
*pexcep
, unsigned int uiArgErr
)
562 switch (GetScode(hr
))
564 case DISP_E_UNKNOWNNAME
:
565 wsprintf(szBuf
, L
"%s: Unknown name or named argument.", szMember
);
568 case DISP_E_BADPARAMCOUNT
:
569 wsprintf(szBuf
, L
"%s: Incorrect number of arguments.", szMember
);
572 case DISP_E_EXCEPTION
:
573 wsprintf(szBuf
, L
"%s: Error %d: ", szMember
, pexcep
->wCode
);
574 if (pexcep
->bstrDescription
!= NULL
)
575 lstrcat(szBuf
, pexcep
->bstrDescription
);
577 lstrcat(szBuf
, L
"<<No Description>>");
580 case DISP_E_MEMBERNOTFOUND
:
581 wsprintf(szBuf
, L
"%s: method or property not found.", szMember
);
584 case DISP_E_OVERFLOW
:
585 wsprintf(szBuf
, L
"%s: Overflow while coercing argument values.", szMember
);
588 case DISP_E_NONAMEDARGS
:
589 wsprintf(szBuf
, L
"%s: Object implementation does not support named arguments.",
593 case DISP_E_UNKNOWNLCID
:
594 wsprintf(szBuf
, L
"%s: The locale ID is unknown.", szMember
);
597 case DISP_E_PARAMNOTOPTIONAL
:
598 wsprintf(szBuf
, L
"%s: Missing a required parameter.", szMember
);
601 case DISP_E_PARAMNOTFOUND
:
602 wsprintf(szBuf
, L
"%s: Argument not found, argument %d.", szMember
, uiArgErr
);
605 case DISP_E_TYPEMISMATCH
:
606 wsprintf(szBuf
, L
"%s: Type mismatch, argument %d.", szMember
, uiArgErr
);
610 wsprintf(szBuf
, L
"%s: Unknown error occurred.", szMember
);