/*
*********************************************************************
*
*	The Essence of OLE
*
*	Source code sample
*
*	Copyright (c) 1996, Rolling Thunder Computing, Ipswich MA
*
*	e-mail: essence@rollthunder.com
*	CompuServe: 73540,3430
*	Web: http://www.rollthunder.com
*
*	File Name: CELIZA.CPP
*
*	Purpose: Implementation of IEliza custom marshaling proxy
*
*********************************************************************
*/

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


CElizaProxy::CElizaProxy (void)
{
    m_RefCount = 1 ; 
    return;
}


CElizaProxy::~CElizaProxy(void)
{
/*
Object being destroyed, signal final release to the server
*/

	*(DWORD *) m_pSharedMem = 1 ;
	SetEvent (m_hComplaintEvent) ;


	UnmapViewOfFile (m_pSharedMem) ;
	CloseHandle (m_hMap) ;
	CloseHandle (m_hResponseEvent) ;
	CloseHandle (m_hComplaintEvent) ;

    return;
}



STDMETHODIMP CElizaProxy::QueryInterface(REFIID riid, LPVOID *ppv)
{
    if (IsEqualIID(riid, IID_IUnknown)
        || IsEqualIID(riid, IID_IEliza))
	{
        *ppv = (LPVOID)this;
		AddRef( ) ;
		return NOERROR;
	}
	else if (riid == IID_IMarshal)
	{
		*ppv = (LPMARSHAL) this ;
		AddRef( ) ;
		return NOERROR ;
	}
	else
	{
    	*ppv = NULL ;
    	return ResultFromScode(E_NOINTERFACE);
	}
        
}


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


STDMETHODIMP_(ULONG) CElizaProxy::Release(void)
{
	m_RefCount -- ;

    if (m_RefCount == 0)
	{
        delete this;
		return 0 ;
	}

    return m_RefCount ;
}





STDMETHODIMP CElizaProxy::Complain (LPOLESTR pIn, LPOLESTR pOut)
{

/*
Copy client's complaint into shared ram buffer.  Signal server by setting
an auto-reset event that the server ought to be waiting for.
*/

	lstrcpyn (m_pSharedMem+4, pIn, 128) ;
	SetEvent (m_hComplaintEvent) ;

/*
Wait for server to respond, timeout interval 1 second.  
If found, copy into output buffer.  
*/
	if (WaitForSingleObject (m_hResponseEvent, 1000) ==	WAIT_OBJECT_0)
	{
		lstrcpyn (pOut, m_pSharedMem+132, 128) ;
	}

/*
Otherwise, hem and haw.
*/
	else
	{
		lstrcpy (pOut, TEXT("I'm sorry, I spaced out.  What did you say ?")) ;
	}

	return NOERROR ;
}


STDMETHODIMP CElizaProxy::GetUnmarshalClass (REFIID riid, VOID* pVoid, DWORD dwDestCtx, VOID*, DWORD, 
	CLSID *pClsid )
{
	MessageBox (NULL, L"Unexpected GetUnmarshalClass in proxy", L"", 0) ;
	return S_OK ;

}

STDMETHODIMP CElizaProxy::GetMarshalSizeMax (REFIID riid, VOID* pv, DWORD dwDestCtx, 
	VOID* pvReserved, DWORD dwFlags, DWORD *pSize)
{
	MessageBox (NULL, L"Unexpected GetMarshalSizeMax in proxy", L"", 0) ;
	return S_OK ;
}

STDMETHODIMP CElizaProxy::MarshalInterface (IStream *pStream, REFIID riid, 
	VOID * pv, DWORD dwDestCtx, VOID *pvReserved, DWORD dwFlags)
{
	MessageBox (NULL, L"Unexpected MarshalInterface in proxy", L"", 0) ;
	return S_OK ;
}

STDMETHODIMP CElizaProxy::UnmarshalInterface (IStream *pStream, REFIID riid, VOID **ppv)
{

/*
Read file mapping name from pStream.  Create file mapping
and map memory pointer for that name.  Also open the events that the server
should have already created.
*/

	pStream->Read (m_ShareName, sizeof(m_ShareName), NULL) ;

	TCHAR out [256] ;
	wsprintf (out, TEXT("%sMap"), m_ShareName) ;
	
	m_hMap = OpenFileMapping (FILE_MAP_ALL_ACCESS, FALSE, out) ;
	m_pSharedMem = (LPTSTR) MapViewOfFile (m_hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0) ;
	
	wsprintf (out, TEXT("%sComplaintEvent"), m_ShareName) ;
	m_hComplaintEvent = OpenEvent (EVENT_MODIFY_STATE, FALSE, out) ;

	
	wsprintf (out, TEXT("%sResponseEvent"), m_ShareName) ;
	m_hResponseEvent = OpenEvent (EVENT_ALL_ACCESS, FALSE, out) ;

/*
If we couldn't open the file map or the events, fail construction of the
object.
*/

	if (!m_pSharedMem || !m_hComplaintEvent || !m_hResponseEvent)
	{
		*ppv = NULL ;
		return E_NOINTERFACE ;
	}
/*
Return pointer to IEliza interface
*/

	return QueryInterface (riid, ppv) ;
}

STDMETHODIMP CElizaProxy::ReleaseMarshalData (IStream *pStream)
{
	MessageBox (NULL, L"ReleaseMarshalData in proxy", L"", 0) ;
	return S_OK ;
}

STDMETHODIMP CElizaProxy::DisconnectObject (DWORD dwReserved)
{
	MessageBox (NULL, L"DisconnectObject in proxy", L"", 0) ;
	return S_OK ;
}
