ANIMAL.CPP

/* 
* ANIMAL.CPP
*
* Aggregatable Animal Object Implementation, Chapter 2
*
* Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
*
* Kraig Brockschmidt, Microsoft
* Internet : kraigb@microsoft.com
* Compuserve: >INTERNET:kraigb@microsoft.com
*/

#include <windows.h>
#include "reuse.h"
#include "animal.h"


/*
* CreateAnimal
*
* Purpose:
* Creates an instance of Animal returning a requested interface
* pointer.
*
* Parameters:
* pUnkOuter IUnknown * holding the outer unknown. Can
* be NULL.
* riid REFIID interface requested by the caller.
* ppv void ** in which to return the interface pointer.
*
* Return Value:
* HRESULT NOERROR if successful, CLASS_E_NOAGREGATION if
* IUnknown is not requested with non-NULL pUnkOuter,
* or other error as appropriate.
*/

HRESULT CreateAnimal(IUnknown *pUnkOuter, REFIID riid, void **ppv)
{
CAnimal *pObj;

//If aggregation is on, check riid==IID_IUnknown
if (NULL!=pUnkOuter && riid!=IID_IUnknown)
return ResultFromScode(CLASS_E_NOAGGREGATION);

pObj=new CAnimal(pUnkOuter);

if (NULL==pObj)
return E_OUTOFMEMORY;

if (!pObj->Init())
return E_FAIL;

return pObj->QueryInterface(riid, (PPVOID)ppv);
}





/*
* CAnimal::CAnimal
* CAnimal::~CAnimal
*
* Constructor Parameters:
* pUnkOuter IUnknown * holding the outer unknown. Can
* be NULL.
*/

CAnimal::CAnimal(IUnknown *pUnkOuter)
{
m_cRef=0;
m_pImpIAnimal=NULL;

//No AddRef necessary if non-NULL as we're nested.
m_pUnkOuter=pUnkOuter;
return;
}

CAnimal::~CAnimal(void)
{
DeleteInterfaceImp(m_pImpIAnimal);
return;
}



/*
* CAnimal::Init
*
* Purpose:
* Instantiates the interface implementations for this object.
*
* Parameters:
* None
*
* Return Value:
* BOOL TRUE if initialization succeeds, FALSE otherwise.
*/

BOOL CAnimal::Init(void)
{
IUnknown *pUnkOuter=m_pUnkOuter;

//Set up the right unknown for delegation
if (NULL==pUnkOuter)
pUnkOuter=this;

m_pImpIAnimal=new CImpIAnimal_A(this, pUnkOuter);

if (NULL==m_pImpIAnimal)
return FALSE;

return TRUE;
}






/*
* CAnimal::QueryInterface
* CAnimal::AddRef
* CAnimal::Release
*
* Purpose:
* Non-delegating IUnknown implementation.
*/

STDMETHODIMP CAnimal::QueryInterface(REFIID riid, PPVOID ppv)
{
*ppv=NULL;

if (IID_IUnknown==riid)
*ppv=this;

if (IID_IAnimal==riid)
*ppv=m_pImpIAnimal;

if (NULL==*ppv)
return ResultFromScode(E_NOINTERFACE);

((LPUNKNOWN)*ppv)->AddRef();
return NOERROR;
}


DWORD CAnimal::AddRef(void)
{
return ++m_cRef;
}

DWORD CAnimal::Release(void)
{
if (0!=--m_cRef)
return m_cRef;

delete this;
return 0;
}




//CImpIAnimal_A interface implementation


/*
* CImpIAnimal_A::CImpIAnimal_A
* CImpIAnimal_A::~CImpIAnimal_A
*
* Constructor Parameters:
* pObj PCAnimal to the outer object
* pUnkOuter IUnknown * to which to delegate.
*/

CImpIAnimal_A::CImpIAnimal_A(PCAnimal pObj, IUnknown *pUnkOuter)
{
m_cRef=0;
m_pObj=pObj;
m_pUnkOuter=pUnkOuter; //No AddRef, we're nested
return;
}

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



/*
* CImpIAnimal_A::QueryInterface
* CImpIAnimal_A::AddRef
* CImpIAnimal_A::Release
*
* IUnknown members that delegate to m_pUnkOuter, whatever it is.
*/

STDMETHODIMP CImpIAnimal_A::QueryInterface(REFIID riid, PPVOID ppv)
{
return m_pUnkOuter->QueryInterface(riid, ppv);
}

DWORD CImpIAnimal_A::AddRef(void)
{
++m_cRef;
return m_pUnkOuter->AddRef();
}

DWORD CImpIAnimal_A::Release(void)
{
--m_cRef;
return m_pUnkOuter->Release();
}



/*
* CImpIAnimal_A::Eat
* CImpIAnimal_A::Sleep
* CImpIAnimal_A::Procreate
*
* Purpose:
* Empty sample functions, no parameters, return NOERROR
*/

STDMETHODIMP CImpIAnimal_A::Eat(void)
{
ODS("Animal's IAnimal::Eat called");
return NOERROR;
}

STDMETHODIMP CImpIAnimal_A::Sleep(void)
{
ODS("Animal's IAnimal::Sleep called");
return NOERROR;
}

STDMETHODIMP CImpIAnimal_A::Procreate(void)
{
ODS("Animal's IAnimal::Procreate called");
return NOERROR;
}