/****************************************************************************************


		MCCompObj.h

		Copyright: (c) 2001 Eovia Corp. All rights reserved.


		when		who			what & why
		==========	==========	======================================================
		3/23/99		Thierry		in TRefAddingPtr_ the AddRef is done when the ptr is assigned because
								it may be too late when the TRefAddingPtr_ is popped.
		3/4/99		tsh			fix syntax error
		3/3/99		Eml			Removed Ian last change, it is wrong in multiple inheritance cases
		3/3/99		Ian			When qUseInternalTypes is on, we test pointers passed to
								ReleaseIfNotNull_() to make sure they were allocated dynamically.
		10/29/98	cph			changed MCSCode.h to MCStatusCode.h
		7/5/98		Ian			Got rid of dependancy on MCOSConfig, it was more of a
								compiler dependancy. Also indented the #ifdefs to make it
								clearer.
		6/3/98		Eml			Added MCCOMAPIs

*****************************************************************************************/

#if !defined( __MCCOMPOBJ__ )
	#define __MCCOMPOBJ__

	#include "MCBasicTypes.h"

	/****** Linkage Definitions *************************************************/

	#ifdef qOLDCOMNAMES

		#ifndef STDMETHODIMP
		#define STDMETHODCALLTYPE       __stdcall
		#define STDAPICALLTYPE          __stdcall
		#define STDAPI                  extern "C" MCErr
		#define STDAPI_(type)           extern "C" type
		#define STDMETHODIMP            MCErr
		#define STDMETHODIMP_(type)     type
		#define STDMETHOD(method)       virtual MCErr method
		#define STDMETHOD_(type,method) virtual type method

	#endif

	#ifndef PURE
		#define PURE = 0
	#endif

	#ifndef THIS_
		#define THIS_
	#endif

	#ifndef THIS
		#define THIS void
	#endif

	#define DECLARE_INTERFACE	(iface) struct iface
	#define DECLARE_INTERFACE_	(iface, baseiface) struct iface : public baseiface

	#ifndef _REFIID_DEFINED
		#define _REFIID_DEFINED
		#define REFIID const MCIID&
	#endif

	#ifndef _REFCLSID_DEFINED
		#define _REFCLSID_DEFINED
		#define REFCLSID const MCCLSID&
	#endif

	#ifdef __MWERKS__
		#define __stdcall
	#endif

#endif

#if _MSC_VER
	#define MCCOMAPI __stdcall
#else
	#define MCCOMAPI
#endif

typedef MCErr MCCOMErr;

#include "MCStatusCode.h"

/****** Globally Unique Ids *************************************************/
 
/// Structure used to store a GUID (128 bit identifier)
///
struct MCGUID : public TMCObject
{
    uint32 Data1;
    uint16  Data2;
    uint16  Data3;
    uint8  Data4_0;
    uint8  Data4_1;
    uint8  Data4_2;
    uint8  Data4_3;
    uint8  Data4_4;
    uint8  Data4_5;
    uint8  Data4_6;
    uint8  Data4_7;

    boolean operator==	(const MCGUID& iidOther) const 
	{
			return Data1==iidOther.Data1 
					&&	*(long *)&Data2==*(long *)&iidOther.Data2
					&&	*(long *)&Data4_0==*(long *)&iidOther.Data4_0
					&&	*(long *)&Data4_4==*(long *)&iidOther.Data4_4;
	}

    boolean operator!=	(const MCGUID& iidOther) const
        { return !((*this) == iidOther); }

	MCGUID(	uint32	inData1, uint16 inData2, uint16 inData3,
			uint8	inData4_0, uint8 inData4_1, uint8 inData4_2, uint8 inData4_3,
			uint8	inData4_4, uint8 inData4_5, uint8 inData4_6, uint8 inData4_7)
			: Data1(inData1), Data2(inData2), Data3(inData3),
			  Data4_0(inData4_0), Data4_1(inData4_1), Data4_2(inData4_2), Data4_3(inData4_3),
			  Data4_4(inData4_4), Data4_5(inData4_5), Data4_6(inData4_6), Data4_7(inData4_7)
    {
	}
	MCGUID () {}
};

// macros to define byte pattern for a MCGUID.  
//      Example: DEFINE_GUID(MCGUID_XXX, a, b, c, ...);
//
// Each dll/exe must initialize the MCGUIDs once.  This is done in one of
// two ways.  If you are not using precompiled headers for the file(s) which
// initializes the MCGUIDs, define INITGUID before including compobj.h.

#define MCDEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) extern "C" const MCGUID name
#define MCDEFINE_GUID2(name, paramlist) extern "C" const MCGUID name

//Same as the above macros, except that the actual declaration will only be made if qDeclareSafeGuids is defined
//Should not be used anymore !! Use MCDEFINE_GUID_H and MCDEFINE_GUID_CPP instead (Charles 05/16/2005)
#define MCDEFINE_GUID_SAFELIB(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) extern "C" const MCGUID name
#define MCDEFINE_GUID_SAFELIB2(name, paramlist) extern "C" const MCGUID name


#define MCDEFINE_GUID_H(name) extern "C" const MCGUID name

#define MCDEFINE_GUID_CPP(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)  \
	extern "C" const MCGUID name(l, w1, w2, b1, b2,  b3,  b4,  b5,  b6,  b7,  b8)

#define MCDEFINE_GUID_CPP2(name, paramlist)  \
	extern "C" const MCGUID name(paramlist)

//***************************************************************************

#ifdef INITGUID
#include "MCInitGUID.h"
#endif

// Interface ID are just a kind of MCGUID
typedef MCGUID MCIID;
#define MCIsEqualIID(riid1, riid2) MCIsEqualGUID((const MCGUID&)riid1, (const MCGUID&)riid2)


// Class ID are just a kind of MCGUID
typedef MCGUID MCCLSID;
#define MCIsEqualCLSID(rclsid1, rclsid2) MCIsEqualGUID((const MCGUID&)rclsid1, (const MCGUID&)rclsid2)

#define MC_CLSCTX_INPROC_SERVER 0x1

/****** IMCUnknown Interface **************************************************/

#if defined(macintosh) && (defined(_MSC_VER) || !defined(__cplusplus)) && !defined(qEmulateSingleObject)
#define qEmulateSingleObject
#endif


#if defined(qEmulateSingleObject)
	//On the Mac it is very important to get the v-table in the following format
	//		NULL
	//		NULL  //as of 5.0
	//		&fn1
	//		&fn2
	//		&fn3
	//		...
	//which is the format agreed for SingleObject in Metrowerks and Apple CFront
	//In case a compiler uses this format by default, just don't do anything.
	//In case a compiler doesn't add a NULL entry, define EMULATE_SINGLEOBJECT.
	//In case a compiler as entry larger than 4 bytes, it WON'T work.

	#ifndef SINGLEOBJECT
		struct SingleObject
		{
		    virtual int32 PADMETHOD1() {return 0;}
		    virtual int32 PADMETHOD2() {return 0;}
		};
		#define SINGLEOBJECT SingleObject
	#endif

	struct IMCUnknown : public SingleObject
#else
/// \addtogroup BasicCOM
///
/// \{

/// Defines the basic methods that every COM object must implement. Every COM object
/// derives from it.
///
	struct IMCUnknown
#endif
{
	/// Check if the object supports a given interface and returns a pointer to that
	/// interface if it does.
	/// Note that QueryInterface will increment the reference count of the object
	/// by one if the interface is found.
	///
	/// \param riid GUID of the interface
	/// \param ppvObj A pointer to the pointer being returned.
	///
	virtual MCErr  MCCOMAPI QueryInterface	(const MCIID& riid, void** ppvObj) =0;

	/// Increments the reference count of the object
	///
	virtual uint32 MCCOMAPI AddRef			() = 0;

	/// Decrements the reference count of the object. If the reference count
	/// reaches zero, the object is destroyed.
	///
	virtual uint32 MCCOMAPI Release			() = 0;
};
/// \}

/// Defines a COM Class Factory. For internal use only.
///
struct IMCClassFactory: public IMCUnknown
{
    virtual MCErr MCCOMAPI CreateInstance	(IMCUnknown* pUnkOuter, const MCIID& riid, void** ppvObject) = 0;
    virtual MCErr MCCOMAPI LockServer		(boolean fLock) = 0;
};

inline boolean  MCInlineIsEqualGUID			(const MCGUID& rguid1, const MCGUID& rguid2)
{
   return (
      ((uint32*) &rguid1)[0] == ((uint32*) &rguid2)[0] &&
      ((uint32*) &rguid1)[1] == ((uint32*) &rguid2)[1] &&
      ((uint32*) &rguid1)[2] == ((uint32*) &rguid2)[2] &&
      ((uint32*) &rguid1)[3] == ((uint32*) &rguid2)[3]);
}

#define MCIsEqualGUID(rguid1, rguid2) MCInlineIsEqualGUID(rguid1, rguid2)

typedef MCErr (MCCOMAPI* MCLPFNGETCLASSOBJECT)	(const MCCLSID&, const MCIID&, void**);
typedef MCErr (MCCOMAPI* MCLPFNCANUNLOADNOW)	(void);

#endif