#ifndef _ImplementQI_h_included #define _ImplementQI_h_included #if _MSC_VER > 1000 template struct InterfaceIID { static const IID &iid() { return __uuidof(T); } }; #ifndef ATL_NO_VTABLE #ifdef _ATL_DISABLE_NO_VTABLE #define ATL_NO_VTABLE #else #define ATL_NO_VTABLE __declspec(novtable) #endif #endif // ifndef ATL_NO_VTABLE #else template struct InterfaceIID { static const IID &iid(); }; #ifndef ATL_NO_VTABLE #define ATL_NO_VTABLE #endif // ifndef ATL_NO_VTABLE #endif template struct InterfaceBase { typedef IUnknown Type; }; template struct IIDFinder { static bool HasIID(REFIID riid) { if(riid == InterfaceIID::iid()) return true; return IIDFinder::Type>::HasIID(riid); } }; // Specialisation for IUnknown to terminate the recursive template above template<> struct IIDFinder { static bool HasIID(REFIID riid) { return false; } }; // Within this namespace are templates you probably // aren't interested in. namespace _ImplementQIImplementation { struct Dummy { }; template struct ATL_NO_VTABLE Interface1 : public T { void *SupportsInterface(REFIID riid) { if(IIDFinder::HasIID(riid)) return static_cast(this); return 0; } }; struct ATL_NO_VTABLE Interface1 { void *SupportsInterface(REFIID) { return 0; } }; template struct ATL_NO_VTABLE splitter : public Interface1, _right { void *SupportsInterface(REFIID riid) { void *retval = Interface1::SupportsInterface(riid); return retval ? retval : _right::SupportsInterface(riid); } }; template struct ATL_NO_VTABLE Interface2 : public splitter > { }; struct ATL_NO_VTABLE Interface2 : public Interface1 { }; template struct ATL_NO_VTABLE Interface3 : public splitter > { }; struct ATL_NO_VTABLE Interface3 : public Interface1 { }; template struct ATL_NO_VTABLE Interface4 : public splitter > { }; struct ATL_NO_VTABLE Interface4 : public Interface1 { }; template struct ATL_NO_VTABLE Interface5 : public splitter > { }; struct ATL_NO_VTABLE Interface5 : public Interface1 { }; template struct ATL_NO_VTABLE Interface6 : public splitter > { }; struct ATL_NO_VTABLE Interface6 : public Interface1 { }; template struct ATL_NO_VTABLE Interface7 : public splitter > { }; struct ATL_NO_VTABLE Interface7 : public Interface1 { }; template struct ATL_NO_VTABLE Interface8 : public splitter > { }; struct ATL_NO_VTABLE Interface8 : public Interface1 { }; } // namespace _ImplementQIImplementation template class ATL_NO_VTABLE ImplementQI : public _ImplementQIImplementation::Interface8 { public: STDMETHOD(QueryInterface)(REFIID riid, void **ppv) { using _ImplementQIImplementation::Interface8; *ppv = Interface8::SupportsInterface(riid); if(!*ppv && riid == InterfaceIID::iid()) *ppv = this; if(*ppv) { static_cast(*ppv)->AddRef(); return S_OK; } else return E_NOINTERFACE; } template HRESULT QueryInterface(Interface** pp) { return QueryInterface(InterfaceIID::iid(), reinterpret_cast(pp)); } }; // class CClass : public ImplementQI // { // // Implement everything, including AddRef() and Release(), except for QueryInterface() // }; // Two macros to make explicit how you declare that one interface is a base of another: // DECLARE_BASE // Specify that Interface is derived from DerivedFrom // as in // interface IInterface : IDerivedFrom // // For example, if I had the following IDL // // interface IPrinter : IDevice // { // }; // Then you should have in the header files: // // DECLARE_BASE(IPrinter, IDevice) // // If you forget to declare the base, then // QueryInterface for the base interface will return E_NOINTERFACE. // By default interfaces are derived from IUnknown // so you don't need to specify this. #define DECLARE_BASE(__xyzqInterface, __xyzqDerivedFrom)\ template<>\ struct InterfaceBase<__xyzqInterface>\ {\ typedef __xyzqDerivedFrom Type;\ }; // DECLARE_IID // Associate an IID with an interface. // Defaults to __xyzquuidof() // You generally don't need to use this // macro if you use MIDL or #import // to get the interface. // // But if you don't like declspec(uuid()) // then you can use it like so: // DECLARE_IID(IPrinter, IID_IPrinter) #define DECLARE_IID(__xyzqInterface, __xyzqinterfaceIID)\ template<>\ struct InterfaceIID<__xyzqInterface>\ {\ static const IID &iid() { return __xyzqinterfaceIID; }\ }; template class ATL_NO_VTABLE HeapObject : public T { private: LONG m_dwRef; protected: HeapObject() : m_dwRef(0) {} // Ensure destructor is virtual virtual ~HeapObject() {} public: STDMETHOD_(ULONG, AddRef)() { return ThreadModelT::Increment(&m_dwRef); } STDMETHOD_(ULONG, Release)() { LONG retval = ThreadModelT::Decrement(&m_dwRef); if(retval == 0) delete this; return retval; } }; // struct containing classes that might vary their implementation // depending on threading model. struct MultiThreaded { // Mixin class that // adds Heap lifetime semantics. When created with new, // the object has 0 references. // When the reference count drops down to zero again, // the object deletes itself. template class ATL_NO_VTABLE HeapCounter : public HeapObject { }; inline static LONG Increment(LONG *pLong) { return ::InterlockedIncrement(pLong); } inline static LONG Decrement(LONG *pLong) { return ::InterlockedDecrement(pLong); } }; struct SingleThreaded { template class ATL_NO_VTABLE HeapCounter : public HeapObject { }; inline static LONG Increment(LONG *pLong) { return ++(*pLong); } inline static LONG Decrement(LONG *pLong) { return --(*pLong); } }; template struct ATL_NO_VTABLE StaticCounter : public T { STDMETHOD_(ULONG, AddRef)() { return 2; } STDMETHOD_(ULONG, Release)() { return 1; } }; // 06-July-2000 SimpleHeapObject1 is no longer any more efficient // than the general implementation. It is merely preserved here for // backward compatibility. You'll make the code more "general" by simply // using // HeapObject, ThreadModel> // or // ThreadModel::HeapCounter > // Same applies for SimpleHeapObject2. There will never be // a SimpleHeapObject3. template struct ATL_NO_VTABLE SimpleHeapObject1 : public HeapObject, ThreadModelT> { }; template struct ATL_NO_VTABLE SimpleHeapObject2 : public HeapObject, ThreadModelT> { }; #endif // ImplementQI