FireBreath  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Pages
JSAPI_IDispatchEx.h
1 /**********************************************************\
2 Original Author: Richard Bateman (taxilian)
3 
4 Created: Oct 30, 2009
5 License: Dual license model; choose one of two:
6  New BSD License
7  http://www.opensource.org/licenses/bsd-license.php
8  - or -
9  GNU Lesser General Public License, version 2.1
10  http://www.gnu.org/licenses/lgpl-2.1.html
11 
12 Copyright 2009 Richard Bateman, Firebreath development team
13 \**********************************************************/
14 
15 #pragma once
16 #ifndef H_JSAPI_IDISPATCHEX
17 #define H_JSAPI_IDISPATCHEX
18 
19 #include "ActiveXBrowserHost.h"
20 #include "APITypes.h"
21 #include "JSAPI.h"
22 #include "TypeIDMap.h"
23 #include "utf8_tools.h"
24 #include "JSFunction.h"
25 #include "axutil.h"
26 
27 #include "IDispatchAPI.h"
28 #include "dispex.h"
29 #include <map>
30 #include "logging.h"
31 #include <mshtmdid.h>
32 
33 MIDL_INTERFACE("a7f89004-620a-56e0-aeea-ec0e8da18fb3")
34 IFireBreathObject : public IUnknown
35 {
36 };
37 #define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
38  const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
39 // Global interface for all firebreath plugins
40 MIDL_DEFINE_GUID(IID, IID_IFireBreathObject,0xa7f89004,0x620a,0x56e0,0xae,0xea,0xec,0x0e,0x8d,0xa1,0x8f,0xb3);
41 #undef MIDL_DEFINE_GUID
42 
43 namespace FB { namespace ActiveX {
44  class JSAPI_IDispatchExBase : public IFireBreathObject
45  {
46  public:
47  FB_FORWARD_PTR(IDisp_AttachEvent);
48  FB_FORWARD_PTR(IDisp_DetachEvent);
49  FB_FORWARD_PTR(IDisp_GetLastException);
50  class IDisp_GetLastException : public FB::JSFunction
51  {
52  public:
53  IDisp_GetLastException()
54  : FB::JSFunction(FB::JSAPIPtr(), "getLastException", FB::SecurityScope_Public) { }
55  FB::variant exec(const std::vector<variant>& args) {
56  return m_msg;
57  }
58  void setMessage(const FB::variant& msg) { m_msg = msg; }
59  private:
60  static FB::variant m_msg;
61  };
62  class IDisp_AttachEvent : public FB::JSFunction
63  {
64  public:
65  IDisp_AttachEvent(JSAPI_IDispatchExBase* ptr)
66  : FB::JSFunction(FB::JSAPIPtr(), "attachEvent", FB::SecurityScope_Public), obj(ptr) { }
67  FB::variant exec(const std::vector<variant>& args) {
68  if (args.size() >=2 && args.size() <= 3) {
69  try {
70  std::string evtName = args[0].convert_cast<std::string>();
71  FB::JSObjectPtr method(args[1].convert_cast<FB::JSObjectPtr>());
72  obj->getAPI()->registerEventMethod(evtName, method);
73  return FB::variant();
74  } catch (const std::bad_cast& e) {
75  throw FB::invalid_arguments(e.what());
76  }
77  } else {
78  throw FB::invalid_arguments();
79  }
80  }
81  private:
82  JSAPI_IDispatchExBase* obj;
83  };
84  class IDisp_DetachEvent : public FB::JSFunction
85  {
86  public:
87  IDisp_DetachEvent(JSAPI_IDispatchExBase* ptr)
88  : FB::JSFunction(FB::JSAPIPtr(), "detachEvent", FB::SecurityScope_Public), obj(ptr) { }
89  FB::variant exec(const std::vector<variant>& args) {
90  if (args.size() >=2 && args.size() <= 3) {
91  try {
92  std::string evtName = args[0].convert_cast<std::string>();
93  FB::JSObjectPtr method(args[1].convert_cast<FB::JSObjectPtr>());
94  obj->getAPI()->unregisterEventMethod(evtName, method);
95  return FB::variant();
96  } catch (const std::bad_cast& e) {
97  throw FB::invalid_arguments(e.what());
98  }
99  } else {
100  throw FB::invalid_arguments();
101  }
102  }
103  private:
104  JSAPI_IDispatchExBase* obj;
105  };
106  public:
107  JSAPI_IDispatchExBase()
108  : m_attachFunc(boost::make_shared<IDisp_AttachEvent>(this)),
109  m_detachFunc(boost::make_shared<IDisp_DetachEvent>(this)),
110  m_getLastExceptionFunc(boost::make_shared<IDisp_GetLastException>())
111  { }
112  void setAPI(FB::JSAPIWeakPtr api, const ActiveXBrowserHostPtr& host)
113  {
114  m_api = api;
115  m_host = host;
116  }
117 
118  FB::JSAPIPtr getAPI()
119  {
120  FB::JSAPIPtr api(m_api.lock());
121  if (!api)
122  throw std::bad_cast();
123  return api;
124  }
125  ActiveXBrowserHostPtr getHost() const {
126  return m_host.lock();
127  }
128 
129  friend class IDisp_AttachEvent;
130  friend class IDisp_DetachEvent;
131 
132  protected:
133  FB::JSAPIWeakPtr m_api;
134  IDisp_AttachEventPtr m_attachFunc;
135  IDisp_DetachEventPtr m_detachFunc;
136  IDisp_GetLastExceptionPtr m_getLastExceptionFunc;
137 
138  ActiveXBrowserHostWeakPtr m_host;
139  };
140 
141  template <class T, class IDISP, const IID* piid>
142  class JSAPI_IDispatchEx :
143  public JSAPI_IDispatchExBase,
144  public IDISP,
145  public IConnectionPointContainer,
146  public IConnectionPoint
147  {
148  typedef CComEnum<IEnumConnectionPoints, &__uuidof(IEnumConnectionPoints), IConnectionPoint*,
149  _CopyInterface<IConnectionPoint> > CComEnumConnectionPoints;
150  typedef std::map<DWORD, IDispatchAPIPtr> ConnectionPointMap;
151 
152  public:
153  JSAPI_IDispatchEx(const std::string& mimetype) : m_mimetype(mimetype), m_readyState(READYSTATE_LOADING) { };
154  virtual ~JSAPI_IDispatchEx(void) { };
155  void setReadyState(READYSTATE newState)
156  {
157  m_readyState = newState;
158  if (m_propNotify)
159  m_propNotify->OnChanged(DISPID_READYSTATE);
160  }
161 
162  private:
163  const std::string m_mimetype;
164 
165  protected:
166  ConnectionPointMap m_connPtMap;
167 
168  READYSTATE m_readyState;
169  CComQIPtr<IPropertyNotifySink, &IID_IPropertyNotifySink> m_propNotify;
170 
171  bool m_valid;
172  std::vector<std::wstring> m_memberList;
173 
174  virtual bool callSetEventListener(const std::vector<FB::variant> &args, bool add);
175 
176  public:
177  /* IConnectionPointContainer members */
178  HRESULT STDMETHODCALLTYPE EnumConnectionPoints(IEnumConnectionPoints **ppEnum);
179  HRESULT STDMETHODCALLTYPE FindConnectionPoint(REFIID riid, IConnectionPoint **ppCP);
180 
181  /* IConnectionPoint members */
182  HRESULT STDMETHODCALLTYPE GetConnectionInterface(IID *pIID);
183  HRESULT STDMETHODCALLTYPE GetConnectionPointContainer(IConnectionPointContainer **ppCPC);
184  HRESULT STDMETHODCALLTYPE Advise(IUnknown *pUnkSink, DWORD *pdwCookie);
185  HRESULT STDMETHODCALLTYPE Unadvise(DWORD dwCookie);
186  HRESULT STDMETHODCALLTYPE EnumConnections(IEnumConnections **ppEnum);
187 
188  /* IDispatch members */
189  HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT *pctinfo);
190  HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo);
191  HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid,
192  DISPID *rgDispId);
193  HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
194  DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr);
195 
196  /* IDispatchEx members */
197  HRESULT STDMETHODCALLTYPE GetDispID(BSTR bstrName, DWORD grfdex, DISPID *pid);
198  HRESULT STDMETHODCALLTYPE InvokeEx(DISPID id, LCID lcid, WORD wFlags,
199  DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller);
200  HRESULT STDMETHODCALLTYPE DeleteMemberByName(BSTR bstrName, DWORD grfdex);
201  HRESULT STDMETHODCALLTYPE DeleteMemberByDispID(DISPID id);
202  HRESULT STDMETHODCALLTYPE GetMemberProperties(DISPID id, DWORD grfdexFetch,
203  DWORD *pgrfdex);
204  HRESULT STDMETHODCALLTYPE GetMemberName(DISPID id, BSTR *pbstrName);
205  HRESULT STDMETHODCALLTYPE GetNextDispID(DWORD grfdex, DISPID id, DISPID *pid);
206  HRESULT STDMETHODCALLTYPE GetNameSpaceParent(IUnknown **ppunk);
207  };
208 
209  /* IConnectionPointContainer methods */
210  template <class T, class IDISP, const IID* piid>
211  HRESULT JSAPI_IDispatchEx<T,IDISP,piid>::EnumConnectionPoints(IEnumConnectionPoints **ppEnum)
212  {
213  if (ppEnum == NULL)
214  return E_POINTER;
215  *ppEnum = NULL;
216  CComEnumConnectionPoints* pEnum = NULL;
217 
218  pEnum = new CComObject<CComEnumConnectionPoints>;
219  if (pEnum == NULL)
220  return E_OUTOFMEMORY;
221 
222  IConnectionPoint *connectionPoint[1] = { NULL };
223  static_cast<T*>(this)->QueryInterface(IID_IConnectionPoint, (void **)connectionPoint);
224 
225  HRESULT hRes = pEnum->Init(connectionPoint, &connectionPoint[1],
226  reinterpret_cast<IConnectionPointContainer*>(this), AtlFlagCopy);
227 
228  connectionPoint[0]->Release();
229 
230  if (FAILED(hRes))
231  {
232  delete pEnum;
233  return hRes;
234  }
235  hRes = pEnum->QueryInterface(__uuidof(IEnumConnectionPoints), (void**)ppEnum);
236  if (FAILED(hRes))
237  delete pEnum;
238  return hRes;
239  }
240 
241  template <class T, class IDISP, const IID* piid>
242  HRESULT JSAPI_IDispatchEx<T,IDISP,piid>::FindConnectionPoint(REFIID riid, IConnectionPoint **ppCP)
243  {
244  if (ppCP == NULL)
245  return E_POINTER;
246  *ppCP = NULL;
247  HRESULT hRes = CONNECT_E_NOCONNECTION;
248 
249  if (InlineIsEqualGUID(*piid, riid)) {
250  hRes = static_cast<T*>(this)->QueryInterface(__uuidof(IConnectionPoint), (void**)ppCP);
251  }
252 
253  return hRes;
254  }
255 
256  /* IConnectionPoint methods */
257  template <class T, class IDISP, const IID* piid>
258  HRESULT JSAPI_IDispatchEx<T,IDISP,piid>::GetConnectionInterface(IID *pIID)
259  {
260  *pIID = *piid;
261  return S_OK;
262  }
263 
264  template <class T, class IDISP, const IID* piid>
265  HRESULT JSAPI_IDispatchEx<T,IDISP,piid>::GetConnectionPointContainer(IConnectionPointContainer **ppCPC)
266  {
267  if (ppCPC == NULL)
268  return E_POINTER;
269 
270  return static_cast<T*>(this)->QueryInterface(__uuidof(IConnectionPointContainer), (void**)ppCPC);
271  }
272 
273  template <class T, class IDISP, const IID* piid>
274  HRESULT JSAPI_IDispatchEx<T,IDISP,piid>::Advise(IUnknown *pUnkSink, DWORD *pdwCookie)
275  {
276  try {
277  CComQIPtr<IDispatch> disp(pUnkSink);
278  if (disp) {
279  IDispatchAPIPtr obj(IDispatchAPI::create(disp, getHost()));
280  m_connPtMap[(DWORD)obj.get()] = obj;
281  *pdwCookie = (DWORD)obj.get();
282  getAPI()->registerEventInterface(obj);
283  return S_OK;
284  } else {
285  return CONNECT_E_CANNOTCONNECT;
286  }
287  } catch (const std::exception&) {
288  return CONNECT_E_CANNOTCONNECT;
289  }
290  }
291 
292  template <class T, class IDISP, const IID* piid>
293  HRESULT JSAPI_IDispatchEx<T,IDISP,piid>::Unadvise(DWORD dwCookie)
294  {
295  try {
296  ConnectionPointMap::iterator fnd = m_connPtMap.find(dwCookie);
297  if (fnd == m_connPtMap.end()) {
298  return E_UNEXPECTED;
299  } else {
300  getAPI()->unregisterEventInterface(fnd->second);
301  m_connPtMap.erase(fnd);
302  return S_OK;
303  }
304  } catch (const std::exception&) {
305  return S_OK;
306  }
307  }
308 
309  template <class T, class IDISP, const IID* piid>
310  HRESULT JSAPI_IDispatchEx<T,IDISP,piid>::EnumConnections(IEnumConnections **ppEnum)
311  {
312  return E_NOTIMPL;
313  }
314 
315  /* IDispatch methods */
316  template <class T, class IDISP, const IID* piid>
317  HRESULT JSAPI_IDispatchEx<T,IDISP,piid>::GetTypeInfoCount(UINT *pctinfo)
318  {
319  return E_NOTIMPL;
320  }
321 
322  template <class T, class IDISP, const IID* piid>
323  HRESULT JSAPI_IDispatchEx<T,IDISP,piid>::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
324  {
325  return E_NOTIMPL;
326  }
327 
328  template <class T, class IDISP, const IID* piid>
329  HRESULT JSAPI_IDispatchEx<T,IDISP,piid>::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames,
330  UINT cNames, LCID lcid,
331  DISPID *rgDispId)
332  {
333  HRESULT rv = S_OK;
334  for (UINT i = 0; i < cNames; i++) {
335  CComBSTR bstr(rgszNames[i]);
336  rv = GetDispID(bstr, 0, &rgDispId[i]);
337  if (!SUCCEEDED(rv)) {
338  return rv;
339  }
340  }
341  return rv;
342  }
343 
344  template <class T, class IDISP, const IID* piid>
345  HRESULT JSAPI_IDispatchEx<T,IDISP,piid>::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
346  WORD wFlags, DISPPARAMS *pDispParams,
347  VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
348  UINT *puArgErr)
349  {
350  return InvokeEx(dispIdMember, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, NULL);
351  }
352 
353 
354  /* IDispatchEx members */
355  template <class T, class IDISP, const IID* piid>
356  HRESULT JSAPI_IDispatchEx<T,IDISP,piid>::GetDispID(BSTR bstrName, DWORD grfdex, DISPID *pid)
357  {
358  std::wstring wsName(bstrName);
359 
360  try {
361  FB::JSAPIPtr api(getAPI());
362  if ((wsName == L"attachEvent") || (wsName == L"detachEvent") || (wsName == L"getLastException")) {
363  *pid = AxIdMap.getIdForValue(wsName);
364  } else if (api->HasProperty(wsName) || api->HasMethod(wsName)) {
365  *pid = AxIdMap.getIdForValue(wsName);
366  } else {
367  *pid = -1;
368  return DISP_E_UNKNOWNNAME;
369  }
370  return S_OK;
371  } catch (const std::exception &e) {
372  e;
373  *pid = -1;
374  return DISP_E_UNKNOWNNAME;
375  }
376  }
377 
378  // helper method for Invoke
379  template <class T, class IDISP, const IID* piid>
380  bool JSAPI_IDispatchEx<T,IDISP,piid>::callSetEventListener(const std::vector<FB::variant> &args, bool add)
381  {
382  if (args.size() < 2 || args.size() > 3) {
383  throw FB::invalid_arguments();
384  }
385 
386  try {
387  std::string evtName = args[0].convert_cast<std::string>();
388  FB::JSObjectPtr method(args[1].convert_cast<FB::JSObjectPtr>());
389  if (add) {
390  getAPI()->registerEventMethod(evtName, method);
391  } else {
392  getAPI()->unregisterEventMethod(evtName, method);
393  }
394  } catch(const std::bad_cast&) {
395  throw FB::invalid_arguments();
396  }
397 
398  return true;
399  }
400 
401  template <class T, class IDISP, const IID* piid>
402  HRESULT JSAPI_IDispatchEx<T,IDISP,piid>::InvokeEx(DISPID id, LCID lcid, WORD wFlags,
403  DISPPARAMS *pdp, VARIANT *pvarRes,
404  EXCEPINFO *pei,
405  IServiceProvider *pspCaller)
406  {
407  FB::JSAPIPtr api;
408  try {
409  api = getAPI();
410  } catch (...) {
411  return DISP_E_MEMBERNOTFOUND;
412  }
413  if (!AxIdMap.idExists(id)) {
414  return DISP_E_MEMBERNOTFOUND;
415  }
416 
417  std::wstring wsName;
418 
419  try
420  {
421  wsName = AxIdMap.getValueForId<std::wstring>(id);
422  ActiveXBrowserHostPtr host(getHost());
423 
424  if (wFlags & DISPATCH_PROPERTYGET) {
425  if(!pvarRes)
426  return E_INVALIDARG;
427 
428  switch(id) {
429  case DISPID_READYSTATE:
430  CComVariant(this->m_readyState).Detach(pvarRes);
431  return S_OK;
432  case DISPID_ENABLED:
433  CComVariant(true).Detach(pvarRes);
434  return S_OK;
435  case DISPID_SECURITYCTX:
436  return E_NOTIMPL;
437  }
438  }
439 
440  if (wsName == L"getLastException") {
441  if (wFlags & DISPATCH_METHOD) {
442  FB::VariantList params;
443  FB::variant rVal;
444  rVal = m_getLastExceptionFunc->exec(params);
445 
446  if(pvarRes)
447  host->getComVariant(pvarRes, rVal);
448  } else if (wFlags & DISPATCH_PROPERTYGET) {
449  FB::variant rVal(m_getLastExceptionFunc);
450  host->getComVariant(pvarRes, rVal);
451  }
452  } else if (wsName == L"attachEvent" || wsName == L"detachEvent") {
453  if (wFlags & DISPATCH_METHOD) {
454  std::vector<FB::variant> params;
455  for (int i = pdp->cArgs - 1; i >= 0; i--) {
456  params.push_back(host->getVariant(&pdp->rgvarg[i]));
457  }
458 
459  if (wsName[0] == L'a') {
460  m_attachFunc->exec(params);
461  } else {
462  m_detachFunc->exec(params);
463  }
464  } else if (wFlags & DISPATCH_PROPERTYGET) {
465  FB::variant rVal;
466  if (wsName[0] == L'a') {
467  rVal = m_attachFunc;
468  } else {
469  rVal = m_detachFunc;
470  }
471  host->getComVariant(pvarRes, rVal);
472  }
473 
474  } else if (wFlags & DISPATCH_METHOD && (api->HasMethod(wsName) || !id) ) {
475 
476  std::vector<FB::variant> params;
477  if (pdp->cNamedArgs > 0 && pdp->rgdispidNamedArgs[0] == DISPID_THIS) {
478  if (id == 0)
479  wsName = L"";
480  for (int i = pdp->cArgs - 1; i >= 1; i--) {
481  params.push_back(host->getVariant(&pdp->rgvarg[i]));
482  }
483  } else {
484  for (int i = pdp->cArgs - 1; i >= 0; i--) {
485  params.push_back(host->getVariant(&pdp->rgvarg[i]));
486  }
487  }
488  FB::variant rVal;
489  rVal = api->Invoke(wsName, params);
490 
491  if(pvarRes)
492  host->getComVariant(pvarRes, rVal);
493 
494  } else if (wFlags & DISPATCH_CONSTRUCT) {
495 
496  std::vector<FB::variant> params;
497  if (pdp->cNamedArgs > 0 && pdp->rgdispidNamedArgs[0] == DISPID_THIS) {
498  if (id == 0)
499  wsName = L"";
500  for (int i = pdp->cArgs - 1; i >= 1; i--) {
501  params.push_back(host->getVariant(&pdp->rgvarg[i]));
502  }
503  } else {
504  for (int i = pdp->cArgs - 1; i >= 0; i--) {
505  params.push_back(host->getVariant(&pdp->rgvarg[i]));
506  }
507  }
508  FB::variant rVal;
509  rVal = api->Construct(params);
510 
511  if(pvarRes)
512  host->getComVariant(pvarRes, rVal);
513 
514 
515  } else if (wFlags & DISPATCH_PROPERTYGET && api->HasMethod(wsName)) {
516 
517  FB::variant rVal;
518  if (api->HasMethodObject(wsName))
519  rVal = api->GetMethodObject(wsName);
520  else
521  rVal = true;
522  host->getComVariant(pvarRes, rVal);
523 
524  } else if (wFlags & DISPATCH_PROPERTYGET && api->HasProperty(wsName)) {
525 
526  if(!pvarRes)
527  return E_INVALIDARG;
528 
529  FB::variant rVal = api->GetProperty(wsName);
530 
531  host->getComVariant(pvarRes, rVal);
532 
533  } else if ((wFlags & DISPATCH_PROPERTYPUT || wFlags & DISPATCH_PROPERTYPUTREF) && api->HasProperty(wsName)) {
534 
535  FB::variant newVal = host->getVariant(&pdp->rgvarg[0]);
536  api->SetProperty(wsName, newVal);
537 
538  } else {
539  throw FB::invalid_member("Invalid method or property name");
540  }
541  } catch (const FB::invalid_member& se) {
542  FBLOG_INFO("JSAPI_IDispatchEx", "No such member: \"" << FB::wstring_to_utf8(wsName) << "\"");
543  m_getLastExceptionFunc->setMessage(se.what());
544  return DISP_E_MEMBERNOTFOUND;
545  } catch (const FB::script_error& se) {
546  FBLOG_INFO("JSAPI_IDispatchEx", "Script error for \"" << FB::wstring_to_utf8(wsName) << "\": " << se.what());
547  m_getLastExceptionFunc->setMessage(se.what());
548  if (pei != NULL) {
549  pei->bstrSource = CComBSTR(m_mimetype.c_str()).Detach();
550  pei->bstrDescription = CComBSTR(se.what()).Detach();
551  pei->bstrHelpFile = NULL;
552  pei->pfnDeferredFillIn = NULL;
553  pei->scode = E_NOTIMPL;
554  }
555  return DISP_E_EXCEPTION;
556  } catch (...) {
557  return E_NOTIMPL;
558  }
559 
560  return S_OK;
561  }
562 
563  template <class T, class IDISP, const IID* piid>
564  HRESULT JSAPI_IDispatchEx<T,IDISP,piid>::DeleteMemberByName(BSTR bstrName, DWORD grfdex)
565  {
566  return E_NOTIMPL;
567  }
568 
569  template <class T, class IDISP, const IID* piid>
570  HRESULT JSAPI_IDispatchEx<T,IDISP,piid>::DeleteMemberByDispID(DISPID id)
571  {
572  FB::JSAPIPtr api;
573  try {
574  api = getAPI();
575  } catch (...) {
576  return S_FALSE;
577  }
578  if (!AxIdMap.idExists(id)) {
579  return S_FALSE;
580  }
581 
582  std::wstring wsName;
583  try
584  {
585  wsName = AxIdMap.getValueForId<std::wstring>(id);
586  api->RemoveProperty(wsName);
587  } catch (const FB::script_error& se) {
588  FBLOG_INFO("JSAPI_IDispatchEx", "Script error for \"" << FB::wstring_to_utf8(wsName) << "\": " << se.what());
589  m_getLastExceptionFunc->setMessage(se.what());
590  return S_FALSE;
591  } catch (...) {
592  return S_FALSE;
593  }
594 
595  return S_OK;
596  }
597 
598  template <class T, class IDISP, const IID* piid>
599  HRESULT JSAPI_IDispatchEx<T,IDISP,piid>::GetMemberProperties(DISPID id, DWORD grfdexFetch,
600  DWORD *pgrfdex)
601  {
602  return E_NOTIMPL;
603  }
604 
605  template <class T, class IDISP, const IID* piid>
606  HRESULT JSAPI_IDispatchEx<T,IDISP,piid>::GetMemberName(DISPID id, BSTR *pbstrName)
607  {
608  try {
609  CComBSTR outStr(AxIdMap.getValueForId<std::wstring>(id).c_str());
610 
611  *pbstrName = outStr.Detach();
612  return S_OK;
613  } catch (...) {
614  return DISP_E_UNKNOWNNAME;
615  }
616  return E_NOTIMPL;
617  }
618 
619  template <class T, class IDISP, const IID* piid>
620  HRESULT JSAPI_IDispatchEx<T,IDISP,piid>::GetNextDispID(DWORD grfdex, DISPID id, DISPID *pid)
621  {
622  FB::JSAPIPtr api;
623  try {
624  api = getAPI();
625  } catch (...) {
626  return S_FALSE;
627  }
628 
629  if (m_memberList.size() != api->getMemberCount()) {
630  m_memberList.clear();
631  api->getMemberNames(m_memberList);
632  m_memberList.push_back(L"attachEvent");
633  m_memberList.push_back(L"detachEvent");
634  m_memberList.push_back(L"getLastException");
635  }
636  if (m_memberList.size() == 0)
637  return S_FALSE;
638 
639  if (id == DISPID_STARTENUM) {
640  *pid = AxIdMap.getIdForValue(m_memberList[0]);
641  return S_OK;
642  }
643  std::wstring wStr = AxIdMap.getValueForId<std::wstring>(id);
644 
645  std::vector<std::wstring>::iterator it;
646  for (it = m_memberList.begin(); it != m_memberList.end(); it++) {
647  if (wStr == *it) {
648  it++;
649  break;
650  }
651  }
652  if (it != m_memberList.end()) {
653  *pid = AxIdMap.getIdForValue(*it);
654  } else {
655  return S_FALSE;
656  }
657  return S_OK;
658  }
659 
660  template <class T, class IDISP, const IID* piid>
661  HRESULT JSAPI_IDispatchEx<T,IDISP,piid>::GetNameSpaceParent(IUnknown **ppunk)
662  {
663  return E_NOTIMPL;
664  }
665 } }
666 #endif // H_JSAPI_IDISPATCHEX
667 
boost::shared_ptr< FB::JSObject > JSObjectPtr
Defines an alias representing a JSObject shared_ptr (you should never use a JSObject* directly) ...
Definition: APITypes.h:109
Accepts any datatype, used in all interactions with javascript. Provides tools for getting back out t...
Definition: variant.h:198
Thrown by a JSAPI object when the argument(s) provided to a SetProperty or Invoke call are found to b...
Definition: JSExceptions.h:47
std::vector< variant > VariantList
Defines an alias representing list of variants.
Definition: APITypes.h:64
boost::weak_ptr< FB::JSAPI > JSAPIWeakPtr
Defines an alias for a JSAPI weak_ptr (you should never use a JSAPI* directly)
Definition: APITypes.h:88
boost::shared_ptr< FB::JSAPI > JSAPIPtr
Defines an alias for a JSAPI shared_ptr (you should never use a JSAPI* directly)
Definition: APITypes.h:94
Exception type; when thrown in a JSAPI method, a javascript exception will be thrown.
Definition: JSExceptions.h:28
std::string wstring_to_utf8(const std::wstring &src)
Accepts a std::wstring and returns a UTF8-encoded std::string.
Definition: utf8_tools.cpp:37
Thrown when an Invoke, SetProperty, or GetProperty call is made for a member that is invalid (does no...
Definition: JSExceptions.h:83