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

		BasicCOMExtImplementations.cpp

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

		Author:	Alec
		Date:	2/25/98

		Revision History

		when		who			what & why
		==========	==========	======================================================
		02/26/99	cph			added include for MCBasicDefines.h
		02/25/99	Alec		seperated the extension DLL calls from 
									BasicCOMImplementations so it can be used in shell
		
*****************************************************************************************/

#include "BasicCOMExtImplementations.h"
#include "COMSafeUtilities.h"
#include "MCBasicDefines.h"
#include "MCBasicGUID.h"
#include "MCCountedPtrHelper.h"



//**************************************************************************************************
//  Implementation of exported functions
//**************************************************************************************************

extern "C" MCCOMErr MCCOMAPI MCDLLEXPORT MCDllGetClassObject(const MCCLSID& rclsid, const MCIID& riid, void** ppv)
{
	TMCCountedPtr<TBasicObjectFactory> objectFactory;
	TMCCountedCreateHelper<TBasicObjectFactory> ofCreator(&objectFactory);
	ofCreator = new TBasicObjectFactory(rclsid);
	MCCOMErr res = objectFactory->QueryInterface(riid, ppv);
	return res;
}

extern "C" MCCOMErr MCCOMAPI MCDLLEXPORT MCDllCanUnloadNow(void)
{
	return gBasicComRefCount <= 0 ? MC_S_OK : MC_S_FALSE;
}

#if MAC
#ifndef qMacho
extern void MCInitializeLibrary(IMCUnknown* utilities);//implemeted in StartupMCExtension.cpp
extern pascal void __terminate(void);
#endif
#endif

extern "C" MCCOMErr MCCOMAPI MCDLLEXPORT MCDllInit(IMCUnknown* utilities)
{
	InitSafeUtilities(utilities);
//	InitUtilities(utilities);
#if MAC
	#ifndef qMacho
		MCInitializeLibrary(utilities);
	#endif
#endif
#if WIN
	CatchPlatformException(true);
#endif
	ExtensionInit(utilities);
	return MC_S_OK;
}

boolean gCleanUpHasBeenDone=false;

extern "C" MCCOMErr MCCOMAPI MCDLLEXPORT MCDllCleanUp()
{
	if (!gCleanUpHasBeenDone)
	{
		ExtensionCleanup();
//		CleanUpUtilities();
		CleanUpSafeUtilities();
		
//Arnaud: no way, this is already called by code warrior when you put __terminate in the linker settings...
//#if MAC
//	__terminate();
//#endif		
#if WIN
		CatchPlatformException(false);
#endif
		gCleanUpHasBeenDone=true;
	}
	return MC_S_OK;
}

#if WIN
extern "C" MCCOMErr MCCOMAPI MCDllInitExceptionTranslator()
{
	CatchPlatformException(true);
	return MC_S_OK;
}

extern "C" MCCOMErr MCCOMAPI MCDllCleanUpExceptionTranslator()
{
	CatchPlatformException(false);
	return MC_S_OK;
}

#endif

//**************************************************************************************************
//  Implementation of TBasicObjectFactory
//**************************************************************************************************

TBasicObjectFactory::TBasicObjectFactory(const MCCLSID& classId)
{
	fClassId = classId;
}

MCCOMErr TBasicObjectFactory::QueryInterface(const MCIID& riid, void** ppvObj)
{
	if (MCIsEqualIID(riid, IID_IMCClassFactory))
	{
		TMCCountedGetHelper<IMCClassFactory> result(ppvObj);
		result = this;
		return MC_S_OK;
	}
	return TBasicUnknown::QueryInterface(riid, ppvObj);
}

MCCOMErr TBasicObjectFactory::CreateInstance(IMCUnknown* pUnkOuter, const MCIID& riid, void** ppvObj)
{
	MCCOMErr res = MC_E_UNEXPECTED;
	TBasicUnknown* newObject = MakeCOMObject(fClassId); //__psq__
	if (newObject)
	{
		newObject->SetControllingUnknown(pUnkOuter);
		res = newObject->QueryInterface(riid, ppvObj);
		if (MCVerify(res == MC_S_OK))
		{
			// the QueryInterface suceeded but it incremented the refcount of the external instance
			// but when attaching to an internal instance, the refcount used will be
			// the one of the pUnkOuter
		}
		else
		{
			newObject->SetControllingUnknown(NULL);
		}
		newObject->Release(); //__psq__
	}

	return res;
}

MCCOMErr TBasicObjectFactory::LockServer(boolean fLock)
{
	return MC_S_OK;
}