/*++ 
 
Copyright (c) 1996 Microsoft Corporation 
 
Module Name: 
 
    Util.h 
 
Abstract: 
 
    Definition of Utilities for use 
 
Author: 
 
Environment: 
 
    User mode 
 
Revision History : 
 
--*/ 
#ifndef _UTIL_H_ 
#define _UTIL_H_ 
 
#include "formtrck.h" 
 
//+--------------------------------------------------------------------- 
// 
//   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 InterlockedIncrement(plong) (++(*(plong))) 
#define InterlockedDecrement(plong) (--(*(plong))) 
 
#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(); } 
 
 
#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 
 
#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; 
 
#define OLEMISC_STREAMABLE 1024 
 
IsCompatibleOleVersion(WORD wMaj, WORD wMin); 
 
 
//#if DBG == 1 
#if 0 
STDAPI  CheckAndReturnResult( 
                HRESULT hr, 
                LPSTR   lpstrFile, 
                UINT    line, 
                int     cSuccess, 
                ...); 
 
STDAPI_(void)   CheckResult(HRESULT hr, LPSTR lpstrFile, UINT line); 
STDAPI_(void)   PrintIID(DWORD dwFlags, REFIID riid); 
STDAPI          PrintHRESULT(DWORD dwFlags, HRESULT hr); 
 
#define SRETURN(hr) \ 
    return CheckAndReturnResult((hr), __FILE__, __LINE__, -1) 
#define RRETURN(hr) \ 
    return CheckAndReturnResult((hr), __FILE__, __LINE__, 0) 
#define RRETURN1(hr, s1) \ 
    return CheckAndReturnResult((hr), __FILE__, __LINE__, 1, (s1)) 
#define RRETURN2(hr, s1, s2) \ 
    return CheckAndReturnResult((hr), __FILE__, __LINE__, 2, (s1), (s2)) 
#define RRETURN3(hr, s1, s2, s3) \ 
    return CheckAndReturnResult((hr), __FILE__, __LINE__, 3, (s1), (s2), (s3)) 
 
#define WARN_ERROR(hr)  CheckResult((hr), __FILE__, __LINE__) 
 
#define TRETURN(hr)         return PrintHRESULT(DEB_TRACE, (hr)) 
#define TRACEIID(iid)       PrintIID(DEB_TRACE, iid) 
#define TRACEHRESULT(hr)    PrintHRESULT(DEB_TRACE, (hr)) 
 
#else   // DBG == 0 
 
#define SRETURN(hr)                 return (hr) 
#define RRETURN(hr)                 return (hr) 
#define RRETURN1(hr, s1)            return (hr) 
#define RRETURN2(hr, s1, s2)        return (hr) 
#define RRETURN3(hr, s1, s2, s3)    return (hr) 
 
#define WARN_ERROR(hr) 
 
#define TRETURN(hr)     return (hr) 
#define TRACEIID(iid) 
#define TRACEHRESULT(hr) 
 
#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 //__UTILS_H_