/** \file * Provides dispatch driver via wrap_t< ::IDispatch> * Provides dynamic implementation of IDispatch via dynamic_dispatch. */ /* * Copyright © 2001 Sofus Mortensen * * This material is provided "as is", with absolutely no warranty * expressed or implied. Any use is at your own risk. Permission to * use or copy this software for any purpose is hereby granted without * fee, provided the above notices are retained on all copies. * Permission to modify the code and to distribute modified code is * granted, provided the above notices are retained, and a notice that * the code was modified is included with the above copyright notice. * * This header is part of Comet version 2. * https://github.com/alamaison/comet */ #ifndef COMET_DISPATCH_H #define COMET_DISPATCH_H #include #include namespace comet { /*! \addtogroup Interfaces */ //@{ /** Specialisation of wrap_t for IDispatch. * Implements wrappers for the call-by name and call-by dispid for IDispatch methods * and properties. The wrapper supports properties with up to 3 arguments and methods * with up to 4 arguments. * \code com_ptr disp( my_dual_interface); variant_t val = disp->get(L"Name"); * \endcode * See \ref cometcomptrsmartwrapper for details on wrap_t. */ template<> struct wrap_t< ::IDispatch> { /** Get property by dispid. */ variant_t get(DISPID id) { VARIANT result; VARIANT* vars = 0; DISPPARAMS disp = { vars, 0, 0, 0 }; HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &disp, &result, 0, 0); if (FAILED(hr)) throw_com_error(raw(this), hr); return auto_attach(result); } /** Get property by name. */ variant_t get(const wchar_t* name) { DISPID id; HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast(&name), 1, LOCALE_USER_DEFAULT, &id); if (FAILED(hr)) throw_com_error(raw(this), hr); return get(id); } /** Get property by dispid with 1 argument. */ variant_t get(DISPID id, const variant_t& a0) { VARIANT result; VARIANT vars[1]; vars[0] = a0.in(); DISPPARAMS disp = { vars, 0, 1, 0 }; HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &disp, &result, 0, 0); if (FAILED(hr)) throw_com_error(raw(this), hr); return auto_attach(result); } /** Get property by name with 1 argument. */ variant_t get(const wchar_t* name, const variant_t& a0) { DISPID id; HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast(&name), 1, LOCALE_USER_DEFAULT, &id); if (FAILED(hr)) throw_com_error(raw(this), hr); return get(id, a0); } /** Get property by dispid with 2 arguments. */ variant_t get(DISPID id, const variant_t& a1, const variant_t& a0) { VARIANT result; VARIANT vars[2]; vars[0] = a0.in(); vars[1] = a1.in(); DISPPARAMS disp = { vars, 0, 2, 0 }; HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &disp, &result, 0, 0); if (FAILED(hr)) throw_com_error(raw(this), hr); return auto_attach(result); } /** Get property by name with 2 arguments. */ variant_t get(const wchar_t* name, const variant_t& a1, const variant_t& a0) { DISPID id; HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast(&name), 1, LOCALE_USER_DEFAULT, &id); if (FAILED(hr)) throw_com_error(raw(this), hr); return get(id, a1, a0); } /** Get property by dispid with 3 arguments. */ variant_t get(DISPID id, const variant_t& a2, const variant_t& a1, const variant_t& a0) { VARIANT result; VARIANT vars[3]; vars[0] = a0.in(); vars[1] = a1.in(); vars[2] = a2.in(); DISPPARAMS disp = { vars, 0, 3, 0 }; HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &disp, &result, 0, 0); if (FAILED(hr)) throw_com_error(raw(this), hr); return auto_attach(result); } /** Get property by name with 3 arguments. */ variant_t get(const wchar_t* name, const variant_t& a2, const variant_t& a1, const variant_t& a0) { DISPID id; HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast(&name), 1, LOCALE_USER_DEFAULT, &id); if (FAILED(hr)) throw_com_error(raw(this), hr); return get(id, a2, a1, a0); } /** Put property by dispid. */ void put(DISPID id, const variant_t& val) { VARIANT vars[1]; vars[0] = val.in(); DISPID did = DISPID_PROPERTYPUT; DISPPARAMS disp = { vars, &did, 1, 1 }; HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &disp, 0, 0, 0); if (FAILED(hr)) throw_com_error(raw(this), hr); } /** Put property by name. */ void put(const wchar_t* name, const variant_t& val) { DISPID id; HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast(&name), 1, LOCALE_USER_DEFAULT, &id); if (FAILED(hr)) throw_com_error(raw(this), hr); put(id, val); } /** Put property with 1 argument by dispid. */ void put(DISPID id, const variant_t& a1, const variant_t& val) { VARIANT vars[2]; vars[0] = val.in(); vars[1] = a1.in(); DISPID did = DISPID_PROPERTYPUT; DISPPARAMS disp = { vars, &did, 2, 1 }; HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &disp, 0, 0, 0); if (FAILED(hr)) throw_com_error(raw(this), hr); } /** Put property with 1 argument by name. */ void put(const wchar_t* name, const variant_t& a1, const variant_t& val) { DISPID id; HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast(&name), 1, LOCALE_USER_DEFAULT, &id); if (FAILED(hr)) throw_com_error(raw(this), hr); put(id, a1, val); } /** Put property with 2 arguments by dispid. */ void put(DISPID id, const variant_t& a2, const variant_t& a1, const variant_t& val) { VARIANT vars[3]; vars[0] = val.in(); vars[1] = a1.in(); vars[2] = a2.in(); DISPID did = DISPID_PROPERTYPUT; DISPPARAMS disp = { vars, &did, 3, 1 }; HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &disp, 0, 0, 0); if (FAILED(hr)) throw_com_error(raw(this), hr); } /** Put property with 2 arguments by name. */ void put(const wchar_t* name, const variant_t& a2, const variant_t& a1, const variant_t& val) { DISPID id; HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast(&name), 1, LOCALE_USER_DEFAULT, &id); if (FAILED(hr)) throw_com_error(raw(this), hr); put(id, a2, a1, val); } /** Put property with 3 arguments by dispid. */ void put(DISPID id, const variant_t& a3, const variant_t& a2, const variant_t& a1, const variant_t& val) { VARIANT vars[4]; vars[0] = val.in(); vars[1] = a1.in(); vars[2] = a2.in(); vars[3] = a3.in(); DISPID did = DISPID_PROPERTYPUT; DISPPARAMS disp = { vars, &did, 4, 1 }; HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &disp, 0, 0, 0); if (FAILED(hr)) throw_com_error(raw(this), hr); } /** Put property with 3 arguments by name. */ void put(const wchar_t* name, const variant_t& a3, const variant_t& a2, const variant_t& a1, const variant_t& val) { DISPID id; HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast(&name), 1, LOCALE_USER_DEFAULT, &id); if (FAILED(hr)) throw_com_error(raw(this), hr); put(id, a3, a2, a1, val); } /** Put property by reference by dispid. */ void putref(DISPID id, const variant_t& val) { VARIANT vars[1]; vars[0] = val.in(); DISPID did = DISPID_PROPERTYPUT; DISPPARAMS disp = { vars, &did, 1, 1 }; HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF, &disp, 0, 0, 0); if (FAILED(hr)) throw_com_error(raw(this), hr); } /** Put property by reference by name. */ void putref(const wchar_t* name, const variant_t& val) { DISPID id; HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast(&name), 1, LOCALE_USER_DEFAULT, &id); if (FAILED(hr)) throw_com_error(raw(this), hr); putref(id, val); } void putref(DISPID id, const variant_t& a1, const variant_t& val) { VARIANT vars[2]; vars[0] = val.in(); vars[1] = a1.in(); DISPID did = DISPID_PROPERTYPUT; DISPPARAMS disp = { vars, &did, 2, 1 }; HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF, &disp, 0, 0, 0); if (FAILED(hr)) throw_com_error(raw(this), hr); } void putref(const wchar_t* name, const variant_t& a1, const variant_t& val) { DISPID id; HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast(&name), 1, LOCALE_USER_DEFAULT, &id); if (FAILED(hr)) throw_com_error(raw(this), hr); putref(id, a1, val); } void putref(DISPID id, const variant_t& a2, const variant_t& a1, const variant_t& val) { VARIANT vars[3]; vars[0] = val.in(); vars[1] = a1.in(); vars[2] = a2.in(); DISPID did = DISPID_PROPERTYPUT; DISPPARAMS disp = { vars, &did, 3, 1 }; HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF, &disp, 0, 0, 0); if (FAILED(hr)) throw_com_error(raw(this), hr); } void putref(const wchar_t* name, const variant_t& a2, const variant_t& a1, const variant_t& val) { DISPID id; HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast(&name), 1, LOCALE_USER_DEFAULT, &id); if (FAILED(hr)) throw_com_error(raw(this), hr); putref(id, a2, a1, val); } void putref(DISPID id, const variant_t& a3, const variant_t& a2, const variant_t& a1, const variant_t& val) { VARIANT vars[4]; vars[0] = val.in(); vars[1] = a1.in(); vars[2] = a2.in(); vars[3] = a3.in(); DISPID did = DISPID_PROPERTYPUT; DISPPARAMS disp = { vars, &did, 4, 1 }; HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF, &disp, 0, 0, 0); if (FAILED(hr)) throw_com_error(raw(this), hr); } void putref(const wchar_t* name, const variant_t& a3, const variant_t& a2, const variant_t& a1, const variant_t& val) { DISPID id; HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast(&name), 1, LOCALE_USER_DEFAULT, &id); if (FAILED(hr)) throw_com_error(raw(this), hr); putref(id, a3, a2, a1, val); } /** Call method by dispid. */ variant_t call(DISPID id) { VARIANT result; VARIANT* vars = 0; DISPPARAMS disp = { vars, 0, 0, 0 }; HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &result, 0, 0); if (FAILED(hr)) throw_com_error(raw(this), hr); return auto_attach(result); } /** Call method by name. */ variant_t call(const wchar_t* name) { DISPID id; HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast(&name), 1, LOCALE_USER_DEFAULT, &id); if (FAILED(hr)) throw_com_error(raw(this), hr); return call(id); } variant_t call(DISPID id, const variant_t& a0) { VARIANT result; VARIANT vars[1]; vars[0] = a0.in(); DISPPARAMS disp = { vars, 0, 1, 0 }; HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &result, 0, 0); if (FAILED(hr)) throw_com_error(raw(this), hr); return auto_attach(result); } variant_t call(const wchar_t* name, const variant_t& a0) { DISPID id; HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast(&name), 1, LOCALE_USER_DEFAULT, &id); if (FAILED(hr)) throw_com_error(raw(this), hr); return call(id, a0); } variant_t call(DISPID id, const variant_t& a1, const variant_t& a0) { VARIANT result; VARIANT vars[2]; vars[0] = a0.in(); vars[1] = a1.in(); DISPPARAMS disp = { vars, 0, 2, 0 }; HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &result, 0, 0); if (FAILED(hr)) throw_com_error(raw(this), hr); return auto_attach(result); } variant_t call(const wchar_t* name, const variant_t& a1, const variant_t& a0) { DISPID id; HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast(&name), 1, LOCALE_USER_DEFAULT, &id); if (FAILED(hr)) throw_com_error(raw(this), hr); return call(id, a1, a0); } variant_t call(DISPID id, const variant_t& a2, const variant_t& a1, const variant_t& a0) { VARIANT result; VARIANT vars[3]; vars[0] = a0.in(); vars[1] = a1.in(); vars[2] = a2.in(); DISPPARAMS disp = { vars, 0, 3, 0 }; HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &result, 0, 0); if (FAILED(hr)) throw_com_error(raw(this), hr); return auto_attach(result); } variant_t call(const wchar_t* name, const variant_t& a2, const variant_t& a1, const variant_t& a0) { DISPID id; HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast(&name), 1, LOCALE_USER_DEFAULT, &id); if (FAILED(hr)) throw_com_error(raw(this), hr); return call(id, a2, a1, a0); } variant_t call(DISPID id, const variant_t& a3, const variant_t& a2, const variant_t& a1, const variant_t& a0) { VARIANT result; VARIANT vars[4]; vars[0] = a0.in(); vars[1] = a1.in(); vars[2] = a2.in(); vars[3] = a3.in(); DISPPARAMS disp = { vars, 0, 4, 0 }; HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &result, 0, 0); if (FAILED(hr)) throw_com_error(raw(this), hr); return auto_attach(result); } variant_t call(const wchar_t* name, const variant_t& a3, const variant_t& a2, const variant_t& a1, const variant_t& a0) { DISPID id; HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast(&name), 1, LOCALE_USER_DEFAULT, &id); if (FAILED(hr)) throw_com_error(raw(this), hr); return call(id, a3, a2, a1, a0); } variant_t call(DISPID id, const variant_t& a4, const variant_t& a3, const variant_t& a2, const variant_t& a1, const variant_t& a0) { VARIANT result; VARIANT vars[5]; vars[0] = a0.in(); vars[1] = a1.in(); vars[2] = a2.in(); vars[3] = a3.in(); vars[4] = a4.in(); DISPPARAMS disp = { vars, 0, 5, 0 }; HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &result, 0, 0); if (FAILED(hr)) throw_com_error(raw(this), hr); return auto_attach(result); } variant_t call(const wchar_t* name, const variant_t& a4, const variant_t& a3, const variant_t& a2, const variant_t& a1, const variant_t& a0) { DISPID id; HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast(&name), 1, LOCALE_USER_DEFAULT, &id); if (FAILED(hr)) throw_com_error(raw(this), hr); return call(id, a4, a3, a2, a1, a0); } }; /** \class dynamic_dispatch dispatch.h comet/dispatch.h * Implementation of a dynamic IDispatch, allowing methods to be added to * an IDispatch implementation. * The class needs to be inherited from to be able to add methods. * Each method can have up to 4 parameters. */ template class ATL_NO_VTABLE dynamic_dispatch : public ::IDispatch { struct method_ptr { bool has_retval; union { void (BASE::*pm00)(); void (BASE::*pm01)(const variant_t&); void (BASE::*pm02)(const variant_t&, const variant_t&); void (BASE::*pm03)(const variant_t&, const variant_t&, const variant_t&); void (BASE::*pm04)(const variant_t&, const variant_t&, const variant_t&, const variant_t&); variant_t (BASE::*pm10)(); variant_t (BASE::*pm11)(const variant_t&); variant_t (BASE::*pm12)(const variant_t&, const variant_t&); variant_t (BASE::*pm13)(const variant_t&, const variant_t&, const variant_t&); variant_t (BASE::*pm14)(const variant_t&, const variant_t&, const variant_t&, const variant_t&); }; }; typedef std::map NAMEMAP; NAMEMAP name_map_; // Workaround VC internal compiler error struct wrap_map_t { std::map m; }; typedef std::map MAP; MAP map_; void add_method(const wchar_t* name, method_ptr p, DISPID id, int type) { if (id == flag_value) { NAMEMAP::const_iterator it = name_map_.find(name); if (it == name_map_.end()) { id = 100000 + map_.size(); while (map_.find(id) != map_.end()) ++id; } else { id = it->second; } } name_map_[name] = id; map_[id].m[type] = p; } enum { flag_value = MINLONG }; public: typedef ::IDispatch interface_is; protected: void remove(const wchar_t* name) { NAMEMAP::iterator it = name_map_.find(name); if (it != name_map_.end()) { DISPID id = it->second; name_map_.erase(it); map_.erase(id); } } void add_method(const wchar_t* name, void (BASE::*pm)(), DISPID id = flag_value) { method_ptr p; p.has_retval = false; p.pm00 = pm; add_method( name, p, id, 0 << 16 | DISPATCH_METHOD ); } void add_method(const wchar_t* name, void (BASE::*pm)(const variant_t&), DISPID id = flag_value) { method_ptr p; p.has_retval = false; p.pm01 = pm; add_method( name, p, id, 1 << 16 | DISPATCH_METHOD ); } void add_method(const wchar_t* name, void (BASE::*pm)(const variant_t&, const variant_t&), DISPID id = flag_value) { method_ptr p; p.has_retval = false; p.pm02 = pm; add_method( name, p, id, 2 << 16 | DISPATCH_METHOD ); } void add_method(const wchar_t* name, void (BASE::*pm)(const variant_t&, const variant_t&, const variant_t&), DISPID id = flag_value) { method_ptr p; p.has_retval = false; p.pm03 = pm; add_method( name, p, id, 3 << 16 | DISPATCH_METHOD ); } void add_method(const wchar_t* name, void (BASE::*pm)(const variant_t&, const variant_t&, const variant_t&, const variant_t&), DISPID id = flag_value) { method_ptr p; p.has_retval = false; p.pm04 = pm; add_method( name, p, id, 4 << 16 | DISPATCH_METHOD ); } void add_method(const wchar_t* name, variant_t (BASE::*pm)(), DISPID id = flag_value) { method_ptr p; p.has_retval = true; p.pm10 = pm; add_method( name, p, id, 0 << 16 | DISPATCH_METHOD ); } void add_method(const wchar_t* name, variant_t (BASE::*pm)(const variant_t&), DISPID id = flag_value) { method_ptr p; p.has_retval = true; p.pm11 = pm; add_method( name, p, id, 1 << 16 | DISPATCH_METHOD ); } void add_method(const wchar_t* name, variant_t (BASE::*pm)(const variant_t&, const variant_t&), DISPID id = flag_value) { method_ptr p; p.has_retval = true; p.pm12 = pm; add_method( name, p, id, 2 << 16 | DISPATCH_METHOD ); } void add_method(const wchar_t* name, variant_t (BASE::*pm)(const variant_t&, const variant_t&, const variant_t&), DISPID id = flag_value) { method_ptr p; p.has_retval = true; p.pm13 = pm; add_method( name, p, id, 3 << 16 | DISPATCH_METHOD ); } void add_method(const wchar_t* name, variant_t (BASE::*pm)(const variant_t&, const variant_t&, const variant_t&, const variant_t&), DISPID id = flag_value) { method_ptr p; p.has_retval = true; p.pm14 = pm; add_method( name, p, id, 4 << 16 | DISPATCH_METHOD ); } void add_put_property(const wchar_t* name, void (BASE::*pm)(const variant_t&), DISPID id = flag_value) { method_ptr p; p.has_retval = false; p.pm01 = pm; add_method( name, p, id, 1 << 16 | DISPATCH_PROPERTYPUT ); } void add_put_property(const wchar_t* name, void (BASE::*pm)(const variant_t&, const variant_t&), DISPID id = flag_value) { method_ptr p; p.has_retval = false; p.pm02 = pm; add_method( name, p, id, 2 << 16 | DISPATCH_PROPERTYPUT ); } void add_put_property(const wchar_t* name, void (BASE::*pm)(const variant_t&, const variant_t&, const variant_t&), DISPID id = flag_value) { method_ptr p; p.has_retval = false; p.pm03 = pm; add_method( name, p, id, 3 << 16 | DISPATCH_PROPERTYPUT ); } void add_put_property(const wchar_t* name, void (BASE::*pm)(const variant_t&, const variant_t&, const variant_t&, const variant_t&), DISPID id = flag_value) { method_ptr p; p.has_retval = false; p.pm04 = pm; add_method( name, p, id, 4 << 16 | DISPATCH_PROPERTYPUT ); } void add_putref_property(const wchar_t* name, void (BASE::*pm)(const variant_t&), DISPID id = flag_value) { method_ptr p; p.has_retval = false; p.pm01 = pm; add_method( name, p, id, 1 << 16 | DISPATCH_PROPERTYPUTREF ); } void add_putref_property(const wchar_t* name, void (BASE::*pm)(const variant_t&, const variant_t&), DISPID id = flag_value) { method_ptr p; p.has_retval = false; p.pm02 = pm; add_method( name, p, id, 2 << 16 | DISPATCH_PROPERTYPUTREF ); } void add_putref_property(const wchar_t* name, void (BASE::*pm)(const variant_t&, const variant_t&, const variant_t&), DISPID id = flag_value) { method_ptr p; p.has_retval = false; p.pm03 = pm; add_method( name, p, id, 3 << 16 | DISPATCH_PROPERTYPUTREF ); } void add_putref_property(const wchar_t* name, void (BASE::*pm)(const variant_t&, const variant_t&, const variant_t&, const variant_t&), DISPID id = flag_value) { method_ptr p; p.has_retval = false; p.pm04 = pm; add_method( name, p, id, 4 << 16 | DISPATCH_PROPERTYPUTREF ); } void add_get_property(const wchar_t* name, variant_t (BASE::*pm)(), DISPID id = flag_value) { method_ptr p; p.has_retval = true; p.pm10 = pm; add_method( name, p, id, 0 << 16 | DISPATCH_PROPERTYGET ); } void add_get_property(const wchar_t* name, variant_t (BASE::*pm)(const variant_t&), DISPID id = flag_value) { method_ptr p; p.has_retval = true; p.pm11 = pm; add_method( name, p, id, 1 << 16 | DISPATCH_PROPERTYGET ); } void add_get_property(const wchar_t* name, variant_t (BASE::*pm)(const variant_t&, const variant_t&), DISPID id = flag_value) { method_ptr p; p.has_retval = true; p.pm12 = pm; add_method( name, p, id, 2 << 16 | DISPATCH_PROPERTYGET ); } void add_get_property(const wchar_t* name, variant_t (BASE::*pm)(const variant_t&, const variant_t&, const variant_t&), DISPID id = flag_value) { method_ptr p; p.has_retval = true; p.pm13 = pm; add_method( name, p, id, 3 << 16 | DISPATCH_PROPERTYGET ); } void add_get_property(const wchar_t* name, variant_t (BASE::*pm)(const variant_t&, const variant_t&, const variant_t&, const variant_t&), DISPID id = flag_value) { method_ptr p; p.has_retval = true; p.pm14 = pm; add_method( name, p, id, 4 << 16 | DISPATCH_PROPERTYGET ); } private: STDMETHOD(Invoke)(DISPID id, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pd, VARIANT* pVarResult, EXCEPINFO* pe, UINT* pu) { unsigned type = pd->cArgs << 16 | (wFlags & 15); typename MAP::const_iterator it2 = map_.find(id); if (it2 == map_.end()) return DISP_E_MEMBERNOTFOUND; typename std::map::const_iterator it = it2->second.m.find(type); if (it == it2->second.m.end()) return DISP_E_BADPARAMCOUNT; try { if (pd->cNamedArgs > 1) return DISP_E_NONAMEDARGS; if (pd->cNamedArgs == 1) { if ((wFlags & 15) != DISPATCH_PROPERTYPUT && (wFlags & 15) != DISPATCH_PROPERTYPUTREF) return DISP_E_NONAMEDARGS; if (pd->rgdispidNamedArgs[0] != DISPID_PROPERTYPUT) return DISP_E_NONAMEDARGS; switch (pd->cArgs) { case 1: (static_cast(this)->*it->second.pm01)(variant_t::create_reference(pd->rgvarg[0])); break; case 2: (static_cast(this)->*it->second.pm02)(variant_t::create_reference(pd->rgvarg[1]), variant_t::create_reference(pd->rgvarg[0])); break; case 3: (static_cast(this)->*it->second.pm03)(variant_t::create_reference(pd->rgvarg[2]), variant_t::create_reference(pd->rgvarg[1]), variant_t::create_reference(pd->rgvarg[0])); break; case 4: (static_cast(this)->*it->second.pm04)(variant_t::create_reference(pd->rgvarg[3]), variant_t::create_reference(pd->rgvarg[2]), variant_t::create_reference(pd->rgvarg[1]), variant_t::create_reference(pd->rgvarg[0])); break; default: return DISP_E_MEMBERNOTFOUND; } } else { variant_t rv; if (it->second.has_retval) { switch (pd->cArgs) { case 0: rv = (static_cast(this)->*it->second.pm10)(); break; case 1: rv = (static_cast(this)->*it->second.pm11)(variant_t::create_reference(pd->rgvarg[0])); break; case 2: rv = (static_cast(this)->*it->second.pm12)(variant_t::create_reference(pd->rgvarg[1]), variant_t::create_reference(pd->rgvarg[0])); break; case 3: rv = (static_cast(this)->*it->second.pm13)(variant_t::create_reference(pd->rgvarg[2]), variant_t::create_reference(pd->rgvarg[1]), variant_t::create_reference(pd->rgvarg[1])); break; case 4: rv = (static_cast(this)->*it->second.pm14)(variant_t::create_reference(pd->rgvarg[3]), variant_t::create_reference(pd->rgvarg[1]), variant_t::create_reference(pd->rgvarg[2]), variant_t::create_reference(pd->rgvarg[0])); break; default: return DISP_E_MEMBERNOTFOUND; } } else { switch (pd->cArgs) { case 0: (static_cast(this)->*it->second.pm00)(); break; case 1: (static_cast(this)->*it->second.pm01)(variant_t::create_reference(pd->rgvarg[0])); break; case 2: (static_cast(this)->*it->second.pm02)(variant_t::create_reference(pd->rgvarg[1]), variant_t::create_reference(pd->rgvarg[0])); break; case 3: (static_cast(this)->*it->second.pm03)(variant_t::create_reference(pd->rgvarg[2]), variant_t::create_reference(pd->rgvarg[1]), variant_t::create_reference(pd->rgvarg[0])); break; case 4: (static_cast(this)->*it->second.pm04)(variant_t::create_reference(pd->rgvarg[3]), variant_t::create_reference(pd->rgvarg[2]), variant_t::create_reference(pd->rgvarg[1]), variant_t::create_reference(pd->rgvarg[0])); break; default: return DISP_E_MEMBERNOTFOUND; } } if (pVarResult) *pVarResult = rv.detach(); } } catch (com_error& err) { return impl::return_com_error(err); } catch (const std::exception& err) { return impl::return_com_error(err); } catch (HRESULT hr) { return hr; } catch (...) { return E_FAIL; } return S_OK; } STDMETHOD(GetIDsOfNames)(REFIID, WCHAR** names, unsigned int c, LCID, DISPID* dispid) { bool failed = false; for (size_t i=0; isecond; } } return failed ? DISP_E_UNKNOWNNAME : S_OK; } STDMETHOD(GetTypeInfo)(UINT, LCID, ITypeInfo**) { return E_NOTIMPL; } STDMETHOD(GetTypeInfoCount)(UINT *it) { *it = 0; return S_OK; } }; //@} } #endif