#include <windows.h>
#include <initguid.h>
#include "ieliza.h"
#include "cmarshal.h"


DWORD __stdcall ThreadFunc (LPVOID lpVoid)
{
	CMarshal *pMarsh = (CMarshal *) lpVoid ;

	for (;;)
	{

		MessageBeep (0) ;
/*
Wait for client to set event
*/
		WaitForSingleObject (pMarsh->m_hEvent, INFINITE) ;
		MessageBox (NULL, "Clear wait in Server", "", 0) ;

/*
Event set, check first DWORD of shared file mapping.  If set to 1,
then that's the release.
*/

		if (*(DWORD *) pMarsh->m_pSharedMem == 1)
		{
			MessageBeep (0) ;
			SetEvent (pMarsh->m_hEvent) ;
			pMarsh->Release ( ) ;
			return 0 ;
		}
	}
	return 0 ;
}


CMarshal::CMarshal (LPUNKNOWN pUnkOuter)
{
	m_pUnkOuter = pUnkOuter ;
    return;
}


CMarshal::~CMarshal(void)
{
    return;
}



STDMETHODIMP CMarshal::QueryInterface(REFIID riid, LPVOID *ppv)
{
	return m_pUnkOuter->QueryInterface (riid, ppv) ;
}


STDMETHODIMP_(ULONG) CMarshal::AddRef(void)
{
	return m_pUnkOuter->AddRef ( ) ;
}


STDMETHODIMP_(ULONG) CMarshal::Release(void)
{
	return m_pUnkOuter->Release ( ) ;
}

STDMETHODIMP CMarshal::GetUnmarshalClass (REFIID riid, VOID* pVoid, DWORD dwDestCtx, VOID*, DWORD, 
	CLSID *pClsid )
{

/*
We only know how to marshall the IEliza interface.  Anything else is
an error.
*/
	if (riid != IID_IEliza)
	{
		*pClsid = IID_NULL ;
		return ResultFromScode (E_INVALIDARG) ;
	}
/*
This marshalling depends on running on the same machine.  If not,
fail with an error
*/

	if (dwDestCtx != MSHCTX_LOCAL)
	{
		*pClsid = IID_NULL ;
		return ResultFromScode (E_INVALIDARG) ;
	}
	 
/*
Return the class ID of the server that provides our proxy DLL
*/

	*pClsid = CLSID_ElizaStub ;

	return S_OK ;

}

STDMETHODIMP CMarshal::GetMarshalSizeMax (REFIID riid, VOID* pv, DWORD dwDestCtx, 
	VOID* pvReserved, DWORD dwFlags, DWORD *pSize)
{
	*pSize = sizeof(m_ShareName) ;
	return S_OK ;
}

STDMETHODIMP CMarshal::MarshalInterface (IStream *pStream, REFIID riid, 
	VOID * pv, DWORD dwDestCtx, VOID *pvReserved, DWORD dwFlags)
{

/*
Write the name we will use for the file mapping and event into the
stream provided.  This is the marshaling packet that will be passed
to the client proxy.
*/

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

/*
Additional AddRef( ) on this object to make up for the lack of
a system-supplied stub.
*/

	AddRef( ) ;

/*
Create file mapping and map it into our address space
*/

	char out [256] ;
	wsprintf (out, "%sMap", m_ShareName) ;

	m_hMap = CreateFileMapping ((HANDLE)-1, NULL, PAGE_READWRITE, 0, 1000, out) ;
	m_pSharedMem = (LPTSTR) MapViewOfFile (m_hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0) ;

/*
Create an event that the client proxy will set to signal us that 
data has been placed in the shared RAM buffer.  Create a thread to
wait on the event.
*/

	wsprintf (out, "%sEvent", m_ShareName) ;

	m_hEvent = CreateEvent (NULL, FALSE, FALSE, out) ;
	m_hThread = CreateThread (NULL, 0, ThreadFunc, (LPVOID)this, 0, &m_ThreadID) ;

	if (!m_hEvent)
	{
		MessageBox (NULL, "Couldn't create event", "", 0) ;
	}

	return S_OK ;
}

STDMETHODIMP CMarshal::UnmarshalInterface (IStream *pStream, REFIID riid, VOID **ppv)
{
	MessageBox (NULL, "Unexpected UnmarshalInterface", "Server", 0) ;
	return S_OK ;
}

STDMETHODIMP CMarshal::ReleaseMarshalData (IStream *pStream)
{
	MessageBox (NULL, "Unexpected ReleaseMarshalData", "Server", 0) ;
	return S_OK ;
}

STDMETHODIMP CMarshal::DisconnectObject (DWORD dwReserved)
{
	MessageBox (NULL, "Unexpected DisconnectObject", "Server", 0) ;
	return S_OK ;
}

