482 lines
21 KiB
C++
482 lines
21 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// 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 <formtrck.hxx>
|
|
|
|
//+---------------------------------------------------------------------
|
|
//
|
|
// 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_
|