//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1995. // // File: NOUTIL.hxx // // Contents: Definitions of utility stuff for use // // Classes: StdClassFactory // // Functions: // // Macros: // // History: // //---------------------------------------------------------------------------- #ifndef _NOUTIL_HXX_ #define _NOUTIL_HXX_ #include //+--------------------------------------------------------------------- // // Generally useful #defines and inline functions for OLE2. // //------------------------------------------------------------------------ // These are the major and minor version returned by OleBuildVersion #define OLE_MAJ_VER 0x0003 #define OLE_MIN_VER 0x003A //--------------------------------------------------------------- // SCODE and HRESULT macros //--------------------------------------------------------------- #define OK(r) (SUCCEEDED(r)) #define NOTOK(r) (FAILED(r)) //--------------------------------------------------------------- // IUnknown //--------------------------------------------------------------- #define ADsIncrement(__ul) InterlockedIncrement((long *) &__ul) #define ADsDecrement(__ul) InterlockedDecrement((long *) &__ul) #define DECLARE_ADs_IUNKNOWN_METHODS \ STDMETHOD(QueryInterface) (REFIID riid, LPVOID * ppv); \ STDMETHOD_(ULONG, AddRef) (void); \ STDMETHOD_(ULONG, Release) (void); #define DECLARE_ADs_STANDARD_IUNKNOWN(cls) \ STDMETHOD(QueryInterface) (REFIID riid, LPVOID * ppv); \ ULONG _ulRefs; \ STDMETHOD_(ULONG, AddRef) (void) \ { \ ADsIncrement(_ulRefs); \ return _ulRefs; \ } \ STDMETHOD_(ULONG, Release) (void) \ { \ if (!ADsDecrement(_ulRefs)) \ { \ ADsIncrement(_ulRefs); \ delete this; \ return 0; \ } \ return _ulRefs; \ } #define DECLARE_ADs_DELEGATING_IUNKNOWN(cls) \ IUnknown * _pUnkOuter; \ STDMETHOD(QueryInterface) (REFIID iid, LPVOID * ppv) \ { return _pUnkOuter->QueryInterface(iid, ppv); } \ STDMETHOD_(ULONG, AddRef) (void) \ { return _pUnkOuter->AddRef(); } \ STDMETHOD_(ULONG, Release) (void) \ { return _pUnkOuter->Release(); } #define DECLARE_DELEGATING_REFCOUNTING \ IUnknown * _pUnkOuter; \ STDMETHOD_(ULONG, AddRef) (void) \ { return _pUnkOuter->AddRef(); } \ STDMETHOD_(ULONG, Release) (void) \ { return _pUnkOuter->Release(); } #if DBG == 0 // // Retail versions of these macros // #define DECLARE_ADs_PRIVATE_IUNKNOWN(cls) \ class PrivateUnknown : public IUnknown \ { \ private: \ ULONG _ulRefs; \ cls * My##cls(void) \ { return CONTAINING_RECORD(this, cls, _PrivUnk); } \ \ public: \ PrivateUnknown(void) \ { _ulRefs = 1; } \ \ DECLARE_ADs_IUNKNOWN_METHODS \ }; \ friend class PrivateUnknown; \ PrivateUnknown _PrivUnk; #define IMPLEMENT_ADs_PRIVATE_IUNKNOWN(cls) \ STDMETHODIMP_(ULONG) cls::PrivateUnknown::AddRef( ) \ { \ ADsIncrement(_ulRefs); \ return _ulRefs; \ } \ STDMETHODIMP_(ULONG) cls::PrivateUnknown::Release( ) \ { \ if (!ADsDecrement(_ulRefs)) \ { \ ADsIncrement(_ulRefs); \ delete My##cls(); \ return 0; \ } \ return _ulRefs; \ } #define DECLARE_ADs_COMPOUND_IUNKNOWN(cls) \ class PrivateUnknown : public IUnknown \ { \ friend class cls; \ \ public: \ PrivateUnknown(void) \ { _ulRefs = 1; _ulAllRefs = 1; } \ \ DECLARE_ADs_IUNKNOWN_METHODS \ \ private: \ ULONG _ulRefs; \ ULONG _ulAllRefs; \ \ cls * My##cls(void) \ { return CONTAINING_RECORD(this, cls, _PrivUnk); } \ }; \ friend class PrivateUnknown; \ PrivateUnknown _PrivUnk; \ \ ULONG SubAddRef(void); \ ULONG SubRelease(void); #define IMPLEMENT_ADs_COMPOUND_IUNKNOWN(cls) \ STDMETHODIMP_(ULONG) cls::PrivateUnknown::AddRef( ) \ { \ ADsIncrement(_ulAllRefs); \ ADsIncrement(_ulRefs); \ return _ulRefs; \ } \ STDMETHODIMP_(ULONG) cls::PrivateUnknown::Release( ) \ { \ if (!ADsDecrement(_ulRefs)) \ { \ My##cls()->Passivate(); \ } \ if (!ADsDecrement(_ulAllRefs)) \ { \ ADsIncrement(_ulAllRefs); \ delete My##cls(); \ return 0; \ } \ return _ulRefs; \ } \ ULONG cls::SubAddRef( ) \ { \ return ADsIncrement(_PrivUnk._ulAllRefs); \ } \ ULONG cls::SubRelease( ) \ { \ ULONG ul; \ \ ul = ADsDecrement(_PrivUnk._ulAllRefs); \ if (!ul) \ { \ ADsIncrement(_PrivUnk._ulAllRefs); \ delete this; \ } \ \ return ul; \ } #else // DBG == 0 // // Debug versions of these macros // #define DECLARE_ADs_PRIVATE_IUNKNOWN(cls) \ class PrivateUnknown : protected ObjectTracker, \ public IUnknown \ { \ private: \ cls * My##cls(void) \ { return CONTAINING_RECORD(this, cls, _PrivUnk); } \ \ public: \ PrivateUnknown(void) \ { _ulRefs = 1; TrackClassName(#cls); } \ \ DECLARE_ADs_IUNKNOWN_METHODS \ }; \ friend class PrivateUnknown; \ PrivateUnknown _PrivUnk; #define IMPLEMENT_ADs_PRIVATE_IUNKNOWN(cls) \ STDMETHODIMP_(ULONG) cls::PrivateUnknown::AddRef( ) \ { \ StdAddRef(); \ return _ulRefs; \ } \ STDMETHODIMP_(ULONG) cls::PrivateUnknown::Release( ) \ { \ if (!StdRelease()) \ { \ ADsIncrement(_ulRefs); \ delete My##cls(); \ return 0; \ } \ return _ulRefs; \ } #define DECLARE_ADs_COMPOUND_IUNKNOWN(cls) \ class PrivateUnknown : protected ObjectTracker, \ public IUnknown \ { \ friend class cls; \ \ public: \ PrivateUnknown(void) \ { _ulNRefs = 1; _ulRefs = 1; TrackClassName(#cls); } \ \ DECLARE_ADs_IUNKNOWN_METHODS \ \ private: \ ULONG _ulNRefs; \ \ cls * My##cls(void) \ { return CONTAINING_RECORD(this, cls, _PrivUnk); } \ }; \ friend class PrivateUnknown; \ PrivateUnknown _PrivUnk; \ \ ULONG SubAddRef(void); \ ULONG SubRelease(void); #define IMPLEMENT_ADs_COMPOUND_IUNKNOWN(cls) \ STDMETHODIMP_(ULONG) cls::PrivateUnknown::AddRef( ) \ { \ StdAddRef(); \ ADsIncrement(_ulNRefs); \ return _ulNRefs; \ } \ STDMETHODIMP_(ULONG) cls::PrivateUnknown::Release( ) \ { \ if (!ADsDecrement(_ulNRefs)) \ { \ My##cls()->Passivate(); \ } \ if (!StdRelease()) \ { \ ADsIncrement(_ulRefs); \ delete My##cls(); \ return 0; \ } \ return _ulNRefs; \ } \ ULONG cls::SubAddRef( ) \ { \ return _PrivUnk.StdAddRef(); \ } \ ULONG cls::SubRelease( ) \ { \ ULONG ul; \ \ ul = _PrivUnk.StdRelease(); \ if (!ul) \ { \ ADsIncrement(_PrivUnk._ulRefs); \ delete this; \ } \ \ return ul; \ } #endif // DBG == 0 // The Detach method is no longer useful, now that we've // removed the parent class pointer #define DECLARE_ADs_SUBOBJECT_IUNKNOWN(cls, parent_cls, member) \ DECLARE_ADs_IUNKNOWN_METHODS \ parent_cls * My##parent_cls(void); \ void Detach(void) \ { ; } #define IMPLEMENT_ADs_SUBOBJECT_IUNKNOWN(cls, parent_cls, member) \ inline parent_cls * cls::My##parent_cls(void) \ { \ return CONTAINING_RECORD(this, parent_cls, member); \ } \ STDMETHODIMP_(ULONG) cls::AddRef( ) \ { return My##parent_cls()->SubAddRef(); } \ STDMETHODIMP_(ULONG) cls::Release( ) \ { return My##parent_cls()->SubRelease(); } //+------------------------------------------------------------------------ // // NO_COPY *declares* the constructors and assignment operator for copying. // By not *defining* these functions, you can prevent your class from // accidentally being copied or assigned -- you will be notified by // a linkage error. // //------------------------------------------------------------------------- #define NO_COPY(cls) \ cls(const cls&); \ cls& operator=(const cls&); //+--------------------------------------------------------------------- // // Miscellaneous useful OLE helper and debugging functions // //---------------------------------------------------------------------- // // Some convenient OLE-related definitions and declarations // typedef unsigned short far * LPUSHORT; //REVIEW we are experimenting with a non-standard OLEMISC flag. #define OLEMISC_STREAMABLE 1024 #include "misc.hxx" #if DBG == 1 STDAPI_(void) PrintIID(DWORD dwFlags, REFIID riid); #define TRACEIID(iid) PrintIID(DEB_TRACE, iid) #else // DBG == 0 #define TRACEIID(iid) #endif // DBG //+--------------------------------------------------------------------- // // Interface wrapper for tracing method invocations // //---------------------------------------------------------------------- #if DBG == 1 LPVOID WatchInterface(REFIID riid, LPVOID pv, LPWSTR lpstr); #define WATCHINTERFACE(iid, p, lpstr) WatchInterface(iid, p, lpstr) #else // DBG == 0 #define WATCHINTERFACE(iid, p, lpstr) (p) #endif // DBG //+--------------------------------------------------------------------- // // Standard IClassFactory implementation // //---------------------------------------------------------------------- //+--------------------------------------------------------------- // // Class: StdClassFactory // // Purpose: Standard implementation of a class factory object // // Notes: **************!!!!!!!!!!!!!!!!!************* // TAKE NOTE --- The implementation of Release on this // class does not perform a delete. This is so you can // make the class factory a global static variable. // Use the CDynamicCF class below for an object // which is not global static data. // // ALSO - The refcount is initialized to 0, NOT 1! // //--------------------------------------------------------------- class StdClassFactory: public IClassFactory { public: StdClassFactory(void) : _ulRefs(1) {}; // IUnknown methods DECLARE_ADs_IUNKNOWN_METHODS; // IClassFactory methods STDMETHOD(LockServer) (BOOL fLock); // CreateInstance is left pure virtual. protected: ULONG _ulRefs; }; //+--------------------------------------------------------------------------- // // Class: CDynamicCF (DYNCF) // // Purpose: Class factory which exists on the heap, and whose Release // method does the normal thing. // // Interface: DECLARE_ADs_STANDARD_IUNKNOWN -- IUnknown methods // // LockServer -- Per IClassFactory. // CDynamicCF -- ctor. // ~CDynamicCF -- dtor. // // History: 6-22-94 adams Created // 7-13-94 adams Moved from ADs\inc\dyncf.hxx // //---------------------------------------------------------------------------- class CDynamicCF: public IClassFactory { public: // IUnknown methods DECLARE_ADs_STANDARD_IUNKNOWN(CDynamicCF) // IClassFactory methods STDMETHOD(LockServer) (BOOL fLock); protected: CDynamicCF(void); virtual ~CDynamicCF(void); }; #endif //__NOUTILS_HXX_