#include <windows.h>
#include "ctimedta.h"

extern UINT cfTimeData ;
extern SYSTEMTIME lt ;
extern int g_ObjectCount ;


FORMATETC feArray []= {
						{ CF_TEXT, NULL, DVASPECT_CONTENT,  -1, TYMED_HGLOBAL },
					  };
/*
constructor/destructor 
*/

CTimeDataDispatch::CTimeDataDispatch()
{
	m_RefCount = 1 ; 
	g_ObjectCount ++ ;

/*
Create inner contained IDispatch 
*/
	
	CLSID clsid ;
	CLSIDFromProgID (L"EssenceOfOle.HelloAutomation", &clsid) ;

	CoCreateInstance (
		clsid, NULL,
		CLSCTX_LOCAL_SERVER, IID_IDispatch,	
		(LPVOID *) &m_pInnerDispatch) ;	

    return;
}


CTimeDataDispatch::~CTimeDataDispatch(void)
{  
	g_ObjectCount -- ;

	/*
Release inner contained IDispatch
*/
	if (m_pInnerDispatch)
	{
		m_pInnerDispatch->Release( ) ;
	}

    return;
}


/*
IUnknown methods
*/

HRESULT CTimeDataDispatch::QueryInterface(REFIID riid, LPVOID FAR *ppv)
{
    if (IsEqualIID(riid, IID_IUnknown)
        || IsEqualIID(riid, IID_IDataObject))
    {
        *ppv = (LPVOID)this;  
        AddRef();
        return S_OK ;
    }
    else
    {
    	*ppv = NULL;       
    	return  E_NOINTERFACE ;
    }
}


STDMETHODIMP_(ULONG) CTimeDataDispatch::AddRef(void)
{
    m_RefCount ++ ;
    return m_RefCount ;
}


STDMETHODIMP_(ULONG) CTimeDataDispatch::Release(void)
{
    
    m_RefCount -- ;
    
    if (m_RefCount == 0L)
    {
        delete this;
    }	return 0 ;

    return m_RefCount ;
}


/*
GetData Method.  Caller is asking if we can supply data in a given 
format and medium
*/

STDMETHODIMP CTimeDataDispatch::GetData (LPFORMATETC lpfe, LPSTGMEDIUM lpstg) 
{


/*
We support a private clipboard format, identified by the UINT cfTimeData.
This is actually a structure of type SYSTEMTIME. 
Allocate a new global, copy our global system time into it, and fill in the 
elements of the STGMEDIUM structure that we were passed
*/

	if (lpfe->cfFormat == cfTimeData
		&& lpfe->tymed == TYMED_HGLOBAL
		&& lpfe->dwAspect == DVASPECT_CONTENT)
	{
		SYSTEMTIME *pSt ;
			
/*
If lindex == -1, then we are simply transferring a SYSTEMTIME structure.
Any other value means that we are doing a performance test.  In this
case, the value of lindex is the amount fo memory to allocate, while
the calling app measures response time.
*/
		if (lpfe->lindex == -1)
		{
			pSt = (SYSTEMTIME *)GlobalAlloc(GMEM_FIXED, sizeof (SYSTEMTIME));
		}
		else
		{
			pSt = (SYSTEMTIME *)GlobalAlloc(GMEM_FIXED, lpfe->lindex);
		}

		if (!pSt)
		{
    		return E_OUTOFMEMORY ;
		}	                                       
		
		memmove (pSt, &lt, sizeof (SYSTEMTIME)) ;
	    
	    lpstg->tymed = TYMED_HGLOBAL ;
    	lpstg->hGlobal = (HGLOBAL) pSt ;
	   	lpstg->pUnkForRelease = NULL ; ;
    	
    	return  S_OK ;

	}


/*
User asked for a format that we couldn't supply.  Return error code.
*/
	
	return DATA_E_FORMATETC ;
}



STDMETHODIMP CTimeDataDispatch::QueryGetData (LPFORMATETC lpfe) 
{

/*
We'll give you text, transferred through a global, with aspect
content.  If the user is asking for this, return success code.
*/

	if (lpfe->cfFormat == cfTimeData 
		&& lpfe->tymed == TYMED_HGLOBAL
		&& lpfe->dwAspect == DVASPECT_CONTENT)
	{
		return S_OK ;
	}


/*
But we won't give you anything else
*/
	return DATA_E_FORMATETC ;
    
}

/*
IDispatch members. Delegate to internal object. 
*/

STDMETHODIMP CTimeDataDispatch::GetIDsOfNames(REFIID riid, LPOLESTR *pNames,
	UINT cNames, LCID lcid, DISPID *pDispID)
{
	if (m_pInnerDispatch)
	{
		return m_pInnerDispatch->GetIDsOfNames (riid, pNames, cNames, lcid, pDispID) ;
	}
	else 
	{
		return E_FAIL ;
	} 
}


STDMETHODIMP CTimeDataDispatch::Invoke(DISPID dispidMember, REFIID riid,
	LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
	VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
	if (m_pInnerDispatch)
	{
		return m_pInnerDispatch->Invoke (dispidMember, riid, lcid, wFlags,
			pDispParams, pVarResult, pExcepInfo, puArgErr) ;
	}
	else 
	{
		return E_FAIL ;
	} 
}

STDMETHODIMP CTimeDataDispatch::GetTypeInfoCount(UINT *pNtypeInfo)
{
	if (m_pInnerDispatch)
	{
		return m_pInnerDispatch->GetTypeInfoCount (pNtypeInfo) ;
	}
	else 
	{
		return E_FAIL ;
	} 
}
        
STDMETHODIMP CTimeDataDispatch::GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo **pptinfo)
{
	if (m_pInnerDispatch)
	{
		return m_pInnerDispatch->GetTypeInfo (itinfo, lcid, pptinfo) ;
	}
	else 
	{
		return E_FAIL ;
	} 
}

/*
Unimplemented members
*/

STDMETHODIMP CTimeDataDispatch::EnumFormatEtc (DWORD dwDir, LPENUMFORMATETC FAR* lpEnum) 
{
	return E_NOTIMPL ;
}


STDMETHODIMP CTimeDataDispatch::DAdvise (FORMATETC FAR* lpfe, DWORD dw, LPADVISESINK lpas, 
	DWORD *lpdw) 
{
	return E_NOTIMPL ;
}

STDMETHODIMP CTimeDataDispatch::DUnadvise  (DWORD dw)
{
	return E_NOTIMPL ;
}

STDMETHODIMP CTimeDataDispatch::EnumDAdvise  (LPENUMSTATDATA *lpen)
{
	return E_NOTIMPL ;
}

STDMETHODIMP CTimeDataDispatch::GetDataHere (LPFORMATETC lpfe, LPSTGMEDIUM lpst)
{
	return E_NOTIMPL ;
}

STDMETHODIMP CTimeDataDispatch::GetCanonicalFormatEtc (LPFORMATETC lpout, LPFORMATETC lpin)
{
	return E_NOTIMPL ;
}

STDMETHODIMP CTimeDataDispatch::SetData (LPFORMATETC lpfe, STGMEDIUM FAR * lpst, BOOL fRelease)
{
	return E_NOTIMPL ;
}
