#ifndef __CFactory_h__
#define __CFactory_h__
///////////////////////////////////////////////////////////
// 
//
//	CFactory.h	-	Header file for the IClassFactory implementation.
//
//

#include "CUnknown.h"
///////////////////////////////////////////////////////////
// 
// Forward reference.
//
class CFactoryData ;

// Global data used by CFactory.
extern CFactoryData g_FactoryDataArray[] ;
extern int g_cFactoryDataEntries;

//////////////////////////////////////////////////////////////////////////////////////
//
//  Component creation function pointer.
//
typedef HRESULT (*FPCREATEINSTANCE)(IUnknown*, CUnknown**) ;

//////////////////////////////////////////////////////////////////////////////////////
//
// typedefs
//
// The special registration function is used to add custom registration and
// unregistration code to the component. It takes a single parameter.
// TRUE = Reg and FALSE = UnReg.
typedef void (*FPSPECIALREGISTRATION)(BOOL) ;

//////////////////////////////////////////////////////////////////////////////////////
//
// CFactoryData -
//
// Information CFactory needs to create a component supported
// by the DLL.
//
//
class CFactoryData
{
public:
	// The class ID for the component
	const CLSID* m_pCLSID;

	// Pointer to the function that creates it
	FPCREATEINSTANCE CreateInstance ;

	// Name of the component to register in the registry
	const char* m_RegistryName ;

	// ProgID
	const char* m_szProgID ;

	// Version independent ProgID
	const char* m_szVerIndProgID ;

	// Helper function for finding the class id
	BOOL IsClassID(const CLSID& clsid) const
		{return (*m_pCLSID == clsid) ;}

	// Function for performing special registration
	FPSPECIALREGISTRATION SpecialRegistration ;

	//----- Out of process server support -----
	
	// Pointer running class factory associated with this component.
	IClassFactory* m_pIClassFactory ;

	// Magic cookie to identify running object
	DWORD m_dwRegister ;
} ;


///////////////////////////////////////////////////////////
//
// Class Factory
//
class CFactory : public IClassFactory
{
public:
	// IUnknown
	virtual HRESULT __stdcall QueryInterface(	const IID& iid,
												void** ppv) ;
	virtual ULONG   __stdcall AddRef() ;
	virtual ULONG   __stdcall Release() ;
	
	// IClassFactory
	virtual HRESULT __stdcall CreateInstance(	IUnknown* pUnkOuter,
												const IID& iid,
												void** ppv) ;
	virtual HRESULT __stdcall LockServer(BOOL bLock); 

	// Constructor - Pass pointer to data of component to create.
	CFactory(const CFactoryData* pFactoryData) ;

	// Destructor
	~CFactory() {/*empty*/ }

	// ----- static FactoryData support functions. -----

	// DllGetClassObject Support
	static HRESULT GetClassObject(	const CLSID& clsid, 
									const IID& iid, 
									void** ppv);
	
	// Helper function for DllCanUnloadNow 
	static BOOL IsLocked()
		{ return (s_cServerLocks > 0) ; }

	// Functions to [Un]Register all components.
	static HRESULT RegisterAll();
	static HRESULT UnregisterAll();

	// Functions to determine if component can be unloaded.
	static HRESULT CanUnloadNow();


#ifdef _OUTPROC_SERVER_
	// ----- Out of process server support -----

	static BOOL StartFactories() ;
	static void StopFactories() ;

	static DWORD s_dwThreadID;

	// Shut down the application.
	static void CloseExe()
	{
		if (CanUnloadNow() == S_OK)
		{
			::PostThreadMessage(s_dwThreadID, WM_QUIT, 0, 0);
		}
	}
#else
	// CloseExe doesn't do anything if we are in process.
	static void CloseExe() {/*Empty*/} 
#endif

public:
	// Reference Count
	LONG m_cRef;

	// Pointer to information about class this factory creates.
	const CFactoryData* m_pFactoryData;

	// Count of locks
	static LONG s_cServerLocks ;   

	// Module handle
	static HMODULE s_hModule ;
};

#endif