//+---------------------------------------------------------------------------
//
//  Microsoft Windows
//  Copyright (C) Microsoft Corporation, 1992 - 1992.
//
//  File:	stdobj.hxx
//
//  Contents:	Standard component object support
//
//  History:	3-June-93       MikeSe  Created
//
//  Notes:	The contents of this file provide a standard infrastructure
//		for implementing (aggregatable) component objects, an amalgam
//		or work done by JohnEls and DonCl.
//
//		The infrastructure supplies implementations of all the IUnknown
//		methods (both controlling and private), leaving the developer
//		to provide only the following:
//
//		- initialisation
//		- destruction
//		- non-IUnknown methods of supported interfaces.
//
//		The infrastructure assumes a static class factory object
//		(probably although not necessarily implemented using
//		CStdClassFactory) and a static description of the interfaces
//		supported or delegated through member variables.
//
//  Summary of usage:
//
//	1.	Declare your class as inheriting from CStdComponentObject.
//		Within the class definition, invoke the DECLARE_DELEGATED_UNKNOWN
//		macro to declare the required IUnknown methods. Do not include
//		IUnknown explicitly in the list of interface supported.
//
//	2. 	Use the BEGIN_CLASS, SUPPORTS(_EX), DELEGATES*
//		and END_CLASS macros to initialise the static class factory
//		and class descriptor for the class. This can be placed in any
//		convenient source file.
//
//		These macros assume the following naming conventions, for
//		an implementation class named <cls>:
//
//		- the class factory class is named <cls>CF.
//		- the class factory instance is named gcf<cls>Factory
//		- the class id for the class is named CLSID_<cls>
//		- the class descriptor for the class is named gcd<cls>Descriptor
//
//		If you do not adhere to these conventions you will need to
//		duplicate the effect of the BEGIN_CLASS macro by hand, or
//		provide #define's of the above names to the actual names.
//
//	3.	Implement class initialisation. A two-phase approach is used.
//		Any failure-free initialisation can be performed in the
//		constructor for the class, which *must* also invoke
//		the CStdComponentObject constructor, either through the
//		INIT_CLASS macro or an equivalent.
//
//		If any of the initialisation is failure prone, provide an
//		implementation of the _InitInstance method which performs
//		this initialisation and returns an appropriate result code
//		in the contract of IClassFactory::CreateInstance.
//
//	4.	Implement a destructor for your class, if you have any shutdown
//		requirements. The destructor should not assume that your
//		_InitInstance method (if any) has been called.
//
//	5.	Implement the CreateInstance method for your class factory
//		(or _CreateInstance if using CStdClassFactory). This should
//		issue a 'new' on your class, and then invoke the (inherited)
//		InitInstance method.
//
//		If you are using CStdClassFactory, you can use the
//		IMPLEMENT_CLASSFACTORY macro (defined in common\ih\stdclass.hxx)
//		to implement the _CreateInstance method, or in any case
//		you can look at the macro to get an idea of the general structure
//		you must follow.
//
//----------------------------------------------------------------------------

#ifndef __STDOBJ_HXX__
#define __STDOBJ_HXX__

#include <windows.h>
#include <ole2.h>
#include <otrack.hxx>

//+-------------------------------------------------------------------------
//
//  Class:      ITFDELTA
//
//  Purpose:    Defines an interface supported or delegated to.
//
//  Notes:      if piid is non-NULL
//		- a ulDelta with bit 31 set indicates a natively supported
//		  interface, and (ulDelta&0x7FFFFFFF) gives the value which
//		  must be added to the object's this pointer in order to
//		  transform into the required interface pointer.
//		  [in other words, the equivalent of doing (IFoo*)this]
//		- a ulDelta with bit 30 set indicates an interface pointer
//		  which can be loaded directly from a member variable
//		  at the offset (ulDelta&0x3FFFFFFF) from the object's this
//		  pointer.
//		- otherwise ulDelta indicates an offset from the object's
//		  this pointer to a member variable containing an IUnknown
//		  pointer (a delegatee) which can be QI'd to get the interface
//		  specified by piid.
//		if piid is NULL,
//		- ulDelta == 0x80000000L indicates the end of the table
//		  for the class.
//		- otherwise, ulDelta gives the offset to an "else" delegatee
//		  member variable. (See the DELEGATE_ELSE macro below).
//
//--------------------------------------------------------------------------

class ITFDELTA
{
public:
    const IID *			piid;
    ULONG			ulDelta;
};

#define ITF_SUPPORTED		0x80000000L
#define ITF_NO_QI		0x40000000L
#define ITF_END			0x80000000L

#define NOTDELEGATED(ulDelta)	((ulDelta & ITF_SUPPORTED)!=0)
#define QIREQUIRED(ulDelta)	((ulDelta & ITF_NO_QI)==0)
#define GETDELTA(ulDelta)	(ulDelta & 0x3FFFFFFFL)
#define MEMBEROFFSET(c,m)	((ULONG)&(((c *)0)->m))

//+---------------------------------------------------------------------------
//
// Macros:	SUPPORTS, SUPPORTS_EX, DELEGATES_DIRECT, DELEGATES_QI,
//		DELEGATES_ANY, END_INTERFACES
//
// These macros are used to declare ITFDELTA structures of various kinds.
// They are intended to be used in conjunction with the BEGIN_CLASS and
// END_CLASS macros (see below) and may not work correctly if used
// otherwise.
//
// SUPPORTS is used to specify an interface that is supported directly
// on the specified class.
//
// SUPPORTS_EX is used when an interface is inherited through more than one
// parent, and you need to express which one to use.
// SUPPORTS_EX(CFoo, IFoo, IPersist) says to use the IPersist inherited from
// IFoo (as opposed to the one inherited from IPersistFile, say).
//
// DELEGATES_DIRECT specifies a member variable of the class which contains an
// interface pointer to the specified interface.
// IE: DELEGATES_DIRECT(CFoo,IFoo,_pmem) implies that _pmem is of type IFoo*.
//
// DELEGATES_QI is similar, except it specifies that the interface must be
// obtained by issuing a QueryInterface on the pointer in the member variable.
// (Thus the member variable can be of any type deriving from IUnknown). The
// QueryInterface operation is permitted to fail.
//
// DELEGATES_ANY is similar to DELEGATES_QI except that any interface may
// be requested from the referred to member variable. Thus it is a kind of
// catchall.
//
// END_INTERFACES marks the end of the list. It is not used when END_CLASS
// (see below) is used.
//
// Do not put semicolons at the ends of these statements.
//
// The built-in implementation of QueryInterface processes the ITFDELTA array
// in the class descriptor in order, stopping as soon as the requested interface
// is obtained. Thus DELEGATES_ANY entries, of which there may be several,
// will normally appear last.
//
// If an interface which is part of a derivation chain is supported (eg:
// IPersistStream, deriving from IPersist) then all the interfaces, except
// IUnknown, must be listed. (i.e both IPersist and IPersistStream).
//
//----------------------------------------------------------------------------

#define SUPPORTS(clsname, itfname)  			\
    {							\
        &IID_##itfname, 				\
        ((ULONG)((VOID *) ((itfname *)(clsname *) ITF_SUPPORTED)))  \
    },

#define SUPPORTS_EX(clsname, itfprimary, itfname)	\
    {  							\
        &IID_##itfname, 				\
        ((ULONG)(VOID *)(itfname *)((itfprimary *)((clsname *) ITF_SUPPORTED))) \
    },

#define DELEGATES_DIRECT(clsname, itfname, iunkptr)  	\
    {  							\
        &IID_##itfname, 				\
        MEMBEROFFSET(clsname, iunkptr)|ITF_NO_QI	\
    },

#define DELEGATES_QI(clsname, itfname, iunkptr)  	\
    {  							\
        &IID_##itfname, 				\
        MEMBEROFFSET(clsname, iunkptr) 			\
    },

#define DELEGATES_ANY(clsname, iunkptr) 		\
{		                                     	\
    NULL, 						\
    MEMBEROFFSET(clsname, iunkptr) 			\
},

#define END_INTERFACES					\
    {							\
        NULL,						\
        ITF_END						\
    }

//+-------------------------------------------------------------------------
//
//  Class:      CLASSDESCRIPTION
//
//  Purpose:    Static description of class required by infrastructure.
//
//  Notes:      When creating a CLASSDESCRIPTOR, use the SUPPORTS etc.
//		macros to declare the entries in the aitfd array (or
//		better still, use BEGIN_CLASS etc to create the whole
//		descriptor).
//
//--------------------------------------------------------------------------

class CLASSDESCRIPTOR
{
public:
    const CLSID * 		pcls;		// the class id
    char *			pszClassName;	// for object tracking, the
                                                //  printable name of the class
    IClassFactory * 		pcf;		// the class factory for the
						//  class, assumed static

#pragma warning ( disable: 4200 )               // valid use of open struct
    ITFDELTA			aitfd[];	// supported/delegated interfaces
#pragma warning ( default: 4200 )
};

//+-------------------------------------------------------------------------
//
//  Macro:      CLASSFACTORY_NAME, CLASSDESCRIPTOR_NAME
//
//  Purpose:    These macros generate the standard names for the class factory
//		and class descriptor instances for a class.
//
//  Notes:
//
//--------------------------------------------------------------------------

#define CLASSFACTORY_NAME(cls)		gcf##cls##Factory
#define CLASSDESCRIPTOR_NAME(cls)	gcd##cls##Descriptor

//+-------------------------------------------------------------------------
//
//  Macro:      BEGIN_CLASS
//
//  Purpose:    Declare the class factory and the first part of the
//		class descriptor.
//
//  Notes:      This macro is usually followed by zero or more ITFDELTA
//		declaration macros (SUPPORTS, etc) and then END_CLASS.
//
//--------------------------------------------------------------------------

#define BEGIN_CLASS(cls)				\
	cls##CF CLASSFACTORY_NAME(cls);			\
							\
	CLASSDESCRIPTOR CLASSDESCRIPTOR_NAME(cls) = {	\
		&CLSID_##cls,				\
		#cls,    				\
		(IClassFactory*)&gcf##cls##Factory,	\
		{

//+-------------------------------------------------------------------------
//
//  Macro:      END_CLASS
//
//  Purpose:    Complete the declaration of the class descriptor.
//
//  Notes:
//
//--------------------------------------------------------------------------

#define END_CLASS					\
    END_INTERFACES					\
  }							\
};

//+-------------------------------------------------------------------------
//
//  Class:      CStdComponentObject
//
//  Purpose:    Standard base class from which to derive aggregatable component
//		classes.
//
//  Interface:  CStdComponentObject	[constructor]
//		InitInstance		[second phase initialisation,
//					 do not override].
//		~CStdComponentObject	[virtual destructor]
//		_InitInstance  		[virtual, override to provide
//					 class-specific second phase
//					 initialisation].
//		_QueryInterface		[virtual, override to provide last
//					 ditch QueryInterface operation ].
//		
//  Notes:      "Last ditch" QI operation means anything which cannot be
//		described in a static ITFDELTA. The _QueryInterface method
//		(if provided) is invoked only if the requested interface
//		cannot be satisfied via the ITFDELTA table.
//
//		The order of the method declarations is important, because
//		it allows us to safely cast a CStdComponentObject to an IUnknown
//		without actually deriving from it.
//
//--------------------------------------------------------------------------

class CStdComponentObject:	INHERIT_TRACKING
{
private:
    //
    //  pseudo-IUnknown methods
    //

    STDMETHOD(PrimaryQueryInterface)	(REFIID riid, void** ppv);
    STDMETHOD_(ULONG,PrimaryAddRef)	(void);
    STDMETHOD_(ULONG,PrimaryRelease)	(void);

    //
    //  Two-phase constructor.
    //

protected:
    			CStdComponentObject ( const CLASSDESCRIPTOR * pcd );
public:
    HRESULT		InitInstance (
                        	IUnknown* punkOuter,
                        	REFIID riid,
                        	void** ppv );

    //
    //  Destructor
    //

    virtual 		~CStdComponentObject(void);

protected:

    // Override the following method to provide last-ditch QueryInterface
    // behaviour.
    STDMETHOD(_QueryInterface) 		( REFIID riid, void** ppv );

    // Override the following method to provide class-specific failure-prone
    // initialisation. Status codes returned must be in the set defined
    // as valid for IClassFactory::CreateInstance.
    STDMETHOD(_InitInstance) 		( void );

    const CLASSDESCRIPTOR*	_pcd;
    IUnknown*           	_punkControlling;

};

//+-------------------------------------------------------------------------
//
//  Macro:      DECLARE_DELEGATED_UNKNOWN
//
//  Synopsis:   Implements IUnknown methods that simply delegate to the
//              corresponding methods on the controlling IUnknown object.
//
//  Note:       Use this macro when declaring a subclass of CStdComponentObject.
//              Invoke it anywhere within the public portion of your class
//		definition. If you sub-subclass, you must invoke this macro
//		at each level. EG:
//
//			class CMyMain: CStdComponentObject, IFoo
//
//			class CMySub: CMyMain, IBar
//
//		then both CMyMain and CMySub must DECLARE_DELEGATED_UNKNOWN.
//
//--------------------------------------------------------------------------

#define DECLARE_DELEGATED_UNKNOWN			\
                                              		\
STDMETHOD(QueryInterface) (REFIID riid, void** ppv)    	\
{                                                       \
    return _punkControlling->QueryInterface(riid, ppv);	\
};                                                      \
                                                        \
STDMETHOD_(ULONG,AddRef) ()                      	\
{                                                       \
    return _punkControlling->AddRef();                  \
};                                                      \
                                                        \
STDMETHOD_(ULONG,Release) ()				\
{                                                       \
    return _punkControlling->Release();                 \
};
	
//+-------------------------------------------------------------------------
//
//  Macro:      INIT_CLASS
//
//  Purpose:    Call constructor of base class correctly.
//
//  Notes:      This macro should be invoked in the initialisation
//		phase of the constructor for the component class
//		deriving from CStdComponentObject, viz:
//
//		CMyClass::CMyClass ()
//		    :INIT_CLASS(CMyClass)
//		     other initialisations
//		{...
//
//		Use of this macro requires the class descriptor to
//		be named according to the convention described previously.
//		If this is not so (eg: you didn't use BEGIN_CLASS) you
//		must write your own equivalent invocation.
//
//		If you sub-subclass, you must declare the constructor
//		for the subclass appropriately, so that the class descriptor
//		for the sub-subclass can be passed through to CStdComponentObject.
//
//--------------------------------------------------------------------------

#define INIT_CLASS(cls)	CStdComponentObject ( &CLASSDESCRIPTOR_NAME(cls) )

#endif	// of ifndef __STDOBJ_HXX__


