// Get.cpp: implementation of the CGet class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Test.h"
#include "Get.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CGet::CGet()
{
	m_Reference = 0;
	m_Data = 0;
	m_Length = 0;
	m_Place = 0;
	//	Create the event to indicate data is being added
	m_Added = CreateEvent(0, false, false, 0);
}

CGet::~CGet()
{
	ASSERT(m_Reference == 0);

	//	Delete m_Added
	CloseHandle(&m_Added);

	if (m_Data)
		delete[]m_Data;
}

STDMETHODIMP CGet::QueryInterface(REFIID riid, void**ppvObject)
{
	ASSERT(ppvObject);
	//	Set the return value (in case of error)
	*ppvObject = 0;

	//	The returned value
	IUnknown*Return = 0;

	//	The test for valid values
	if (riid == IID_IUnknown)
		Return = static_cast<IUnknown*>(static_cast<IGet*>(this));
	else if (riid == IID_IGet)
		Return = static_cast<IGet*>(this);
	else
		return E_NOINTERFACE;

	//	Set the value
	*ppvObject = Return;

	//	Increment the reference counter
	AddRef();

	return S_OK;
}

STDMETHODIMP_(ULONG)CGet::AddRef()
{
	return ++m_Reference;
}

STDMETHODIMP_(ULONG)CGet::Release()
{
	return --m_Reference;
}

STDMETHODIMP CGet::Get(UCHAR*aItem, UINT*aLength, UINT*aTimeout)
{
	UINT Length = *aLength;

	if (Length > (m_Length - m_Place))
		Length = m_Length - m_Place;

	if (Length > 0)
		memcpy(aItem, m_Data + m_Place, Length);

	m_Place += Length;

	*aLength = Length;

	return S_OK;
}

STDMETHODIMP CGet::Available(UINT*aLength, UINT*aTimeout)
{
	UINT Length = *aLength;

	if (Length > (m_Length - m_Place))
	{
		*aLength = m_Length - m_Place;

		//	Wait for data
		WaitForSingleObject(m_Added, 1000);

		*aTimeout = 0;
	}

	return S_OK;
}

STDMETHODIMP CGet::Clear()
{
	return S_OK;
}

STDMETHODIMP CGet::Interrupt()
{
	//	Signal that data is added
	SetEvent(m_Added);
	return S_OK;
}

STDMETHODIMP CGet::Used(UINT*aSize)
{
	*aSize = m_Length - m_Place;
	return S_OK;
}

HRESULT CGet::AddList(UCHAR*aList, UINT aLength)
{
	if (m_Data)
		delete[]m_Data;
	m_Place = 0;
	m_Length = aLength;
	m_Data = new UCHAR[m_Length];
	memcpy(m_Data, aList, m_Length);

	//	Signal that data is added
	SetEvent(m_Added);

	return S_OK;
}

