#ifndef CLCOMHEADER_H
#define CLCOMHEADER_H

template <typename superClass, typename CType, typename IType, const CLSID* guid_ClsID, const IID* guid_IID>
class ATL_NO_VTABLE CLCOMBase : 
	public CComObjectRootEx<CComSingleThreadModel>,
	public CComCoClass<CType, guid_ClsID>,
	public ISupportErrorInfo,
	public IDispatchImpl<IType, guid_IID, &LIBID_CLcom, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
public:

DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CType)
	COM_INTERFACE_ENTRY(IType)
	COM_INTERFACE_ENTRY(IDispatch)
	COM_INTERFACE_ENTRY(ISupportErrorInfo)
END_COM_MAP()

	////////////////////////////////////////////////////////////////////////////////
	// COM methods
	////////////////////////////////////////////////////////////////////////////////

	// ISupportsErrorInfo
	STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid){
		for (int i=0; i < sizeof(guid_IID) / sizeof(guid_IID[0]); i++)
		{
			if (InlineIsEqualGUID(guid_IID[i],riid))
				return S_OK;
		}
		return S_FALSE;
	}

	static HRESULT WINAPI UpdateRegistry(BOOL bRegister) throw()
	{
		_ATL_REGMAP_ENTRY entries[4];
		entries[0].szKey = OLESTR("CLASSNAME");
		entries[1].szKey = OLESTR("COCLASSGUID");
		entries[2].szKey = OLESTR("INTERFACEGUID");
		entries[3].szKey = NULL;
		
		LPOLESTR lpsz=NULL;
		
		//INTERFACEGUID
		StringFromIID(*guid_IID, &lpsz);
		entries[2].szData = lpsz;

		//COCLASSGUID
		StringFromCLSID(*guid_ClsID, &lpsz);
		entries[1].szData = lpsz;

		//ProgID
		char* cn = CType::getClassName();
		TCHAR wcn[25];
		STRCPY_AtoT(wcn,cn,25);
		entries[0].szData = wcn;
		return ATL::_pAtlModule->UpdateRegistryFromResource(IDR_REGTEMPLATE, bRegister,entries);
	}
	
	superClass* __object;
	bool ownMemory;
	CLCOMBase(){
		__object = NULL;
		ownMemory=true; //this should normally be set to false to manage non ref counted objects
	}


	virtual HRESULT FinalConstruct(){
		return S_OK;
	}
	virtual void FinalRelease(){
		
	}
	void setObject(superClass* obj){
		__object = obj;
	}
};

#endif
