⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 koala.cpp

📁 英文版的 想要的话可以下载了 为大家服务
💻 CPP
字号:
/*
 * KOALA.CPP
 * Koala Object with Custom Marshaling, Chapter 6
 *
 * Implementation of the CKoala object with a custom interface
 * to demonstrate local/remote transparency.
 *
 * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
 *
 * Kraig Brockschmidt, Microsoft
 * Internet  :  kraigb@microsoft.com
 * Compuserve:  >INTERNET:kraigb@microsoft.com
 */


#include "koala.h"


/*
 * CKoala::CKoala
 * CKoala::~CKoala
 *
 * Parameters (Constructor):
 *  pUnkOuter       LPUNKNOWN of a controlling unknown.
 *  pfnDestroy      PFNDESTROYED to call when an object
 *                  is destroyed.
 */

CKoala::CKoala(LPUNKNOWN pUnkOuter, PFNDESTROYED pfnDestroy)
    {
    m_cRef=0;
    m_pUnkOuter=pUnkOuter;
    m_pfnDestroy=pfnDestroy;

    m_pImpIAnimal=NULL;
    m_pImpIKoala=NULL;
    m_pImpIMarshal=NULL;

    m_fJustAte=FALSE;
    m_cSleepAfterEat=0;

    return;
    }


CKoala::~CKoala(void)
    {
    DeleteInterfaceImp(m_pImpIMarshal);
    DeleteInterfaceImp(m_pImpIKoala);
    DeleteInterfaceImp(m_pImpIAnimal);
    return;
    }



/*
 * CKoala::Init
 *
 * Purpose:
 *  Performs any intiailization of a CKoala that's prone to failure
 *  that we also use internally before exposing the object outside.
 *
 * Parameters:
 *  None
 *
 * Return Value:
 *  BOOL            TRUE if the function is successful,
 *                  FALSE otherwise.
 */

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

    if (NULL==pUnkOuter)
        pUnkOuter=this;

    m_pImpIAnimal=new CImpIAnimal(this, pUnkOuter);

    if (NULL==m_pImpIAnimal)
        return FALSE;

    m_pImpIKoala=new CImpIKoala(this, pUnkOuter);

    if (NULL==m_pImpIKoala)
        return FALSE;

    m_pImpIMarshal=new CImpIMarshal(this, pUnkOuter);

    if (NULL==m_pImpIMarshal)
        return FALSE;

    return TRUE;
    }




/*
 * CKoala::CallLocal
 *
 * Purpose:
 *  Sends or posts a message to the local object.
 *
 * Parameters:
 *  iMsg            UINT identifying the function to call
 *  lParam          LPARAM containing extra information
 *  fAsync          BOOL indicating if this is a Post (TRUE) or
 *                  a send (FALSE).
 *
 * Return Value:
 *  DWORD           Return value from the function or an HRESULT
 *                  on failure.
 */

DWORD CKoala::CallLocal(UINT iMsg, LPARAM lParam, BOOL fAsync)
    {
    DWORD   dwRet=0;

    if (fAsync)
        PostMessage(m_hWndLocal, WM_COMMAND, (WPARAM)iMsg, lParam);
    else
        {
        dwRet=SendMessage(m_hWndLocal, WM_COMMAND, (WPARAM)iMsg
            , lParam);
        }

    return dwRet;
    }




/*
 * CKoala::QueryInterface
 * CKoala::AddRef
 * CKoala::Release
 *
 * Purpose:
 *  IUnknown members for CKoala object.
 */

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

    /*
     * The only calls for IUnknown are either in a nonaggregated
     * case or when created in an aggregation, so in either case
     * always return our IUnknown for IID_IUnknown.
     */
    if (IID_IUnknown==riid)
        *ppv=this;

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

    if (IID_IKoala==riid)
        *ppv=m_pImpIKoala;

    if (IID_IMarshal==riid)
        *ppv=m_pImpIMarshal;

    if (NULL!=*ppv)
        {
        ((LPUNKNOWN)*ppv)->AddRef();
        return NOERROR;
        }

    return ResultFromScode(E_NOINTERFACE);
    }


STDMETHODIMP_(ULONG) CKoala::AddRef(void)
    {
    return ++m_cRef;
    }


STDMETHODIMP_(ULONG) CKoala::Release(void)
    {
    if (0L!=--m_cRef)
        return m_cRef;

    /*
     * If this is the last Release, then we have to tell
     * the server to free its object too.  This is an async
     * call as we don't need to hang around for it to quit.
     */
    CallLocal(MSG_RELEASE, 0, TRUE);

    if (NULL!=m_pfnDestroy)
        (*m_pfnDestroy)();

    delete this;
    return 0;
    }





//Proxy-side IAnimal implementation


/*
 * CImpIAnimal::CImpIAnimal
 * CImpIAnimal::~CImpIAnimal
 *
 * Constructor Parameters:
 *  pObj            PCKoala of the object containing us.
 *  pUnkOuter       LPUNKNOWN to which we blindly delegate
 *                  all IUnknown calls.
 */

CImpIAnimal::CImpIAnimal(PCKoala pObj, LPUNKNOWN pUnkOuter)
    {
    m_cRef=0;
    m_pObj=pObj;
    m_pUnkOuter=pUnkOuter;
    return;
    }

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



/*
 * CImpIAnimal::QueryInterface
 * CImpIAnimal::AddRef
 * CImpIAnimal::Release
 *
 * Purpose:
 *  Delegating IUnknown members for interface implementation.
 */

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

STDMETHODIMP_(ULONG) CImpIAnimal::AddRef(void)
    {
    ++m_cRef;
    return m_pUnkOuter->AddRef();
    }

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



/*
 * CImpIAnimal::Eat
 *
 * Purpose:
 *  Instructs the animal to eat something, returning what the animal
 *  actually ate which usually goes against recommendation (which is
 *  true for the human animal, too).
 *
 * Parameters:
 *  pszFoodRecommended  LPTSTR describing the food that the animal
 *                      should eat.
 *  pszFoodEaten        LPTSTR describing the food the animal actually
 *                      ate, which may not, of course, be the same as
 *                      what it should eat.
 *  cchEaten            short containing the lenght of pszFoodEaten.
 *
 * Return Value:
 *  HRESULT             NOERROR if food is eaten, S_FALSE if not.
 */

STDMETHODIMP CImpIAnimal::Eat(LPTSTR pszFoodRecommended
    , LPTSTR pszFoodEaten, short cchEaten)
    {
    /*
     * Koalas aren't don't care what you tell them, they eat one
     * thing.  We can handle the return string for the local
     * object, but we still need to tell it that this was
     * called.
     */

    _tcsncpy(pszFoodEaten, TEXT("Eucalyptus Leaves"), cchEaten);
    m_pObj->CallLocal(MSG_EAT, 0L, FALSE);
    return NOERROR;
    }



/*
 * CImpIAnimal::Sleep
 *
 * Purpose:
 *  Instructs the animal to sleep for a while.
 *
 * Parameters:
 *  pcMinutes      short * (in-out) containing the number of
 *                 minutes to sleep on entry, then number of
 *                 minutes actually slept on exit
 *
 * Return Value:
 *  HRESULT        NOERROR if sleep taken, S_FALSE if not, where
 *                 *pcMinutes should be zero.
 */

STDMETHODIMP CImpIAnimal::Sleep(short *pcMinutes)
    {
    DWORD       dwRet;

    //Pass the client's value
    dwRet=m_pObj->CallLocal(MSG_SLEEP, (LPARAM)*pcMinutes, FALSE);

    if (FAILED((HRESULT)dwRet))
        return (HRESULT)dwRet;

    //Store the return value in the client's variable.
    *pcMinutes=LOWORD(dwRet);
    return NOERROR;
    }



/*
 * CImpIAnimal::Procreate
 *
 * Purpose:
 *  Instructs the animal to procreate.  On entry, the number of
 *  offstring is unknown, so that's an out parameter.
 *
 * Parameters:
 *  pcOffspring     short * (out) in which to store the number
 *                  of new offspring.
 *
 * Return Value:
 *  HRESULT         NOERROR if offspring created, S_FALSE if not
 *                  where *pcOffspring should be zero.
 */

STDMETHODIMP CImpIAnimal::Procreate(short *pcOffspring)
    {
    DWORD       dwRet;

    dwRet=m_pObj->CallLocal(MSG_PROCREATE, 0, FALSE);

    if (FAILED((HRESULT)dwRet))
        return (HRESULT)dwRet;

    *pcOffspring=(short)LOWORD(dwRet);
    return ResultFromScode(0==dwRet ? S_FALSE : S_OK);
    }




/*
 * CImpIAnimal::WhatKindOfAnimal
 *
 * Purpose:
 *  Returns the IID of the specific animal interface that describes
 *  the type of animal this really is (a much more complex
 *  classification scheme might have IAnimal::WhatGenus and
 *  IGenus::WhatSpecies, etc., but we're just being simple here).
 *
 * Parameters:
 *  pIID            IID * in which to store the specific
 *                  animal IID.
 *
 * Return Value:
 *  HRESULT         NOERROR if the animal type is known,
 *                  S_FALSE if not with *pIID set to IID_NULL.
 */

STDMETHODIMP CImpIAnimal::WhatKindOfAnimal(IID *pIID)
    {
    //No need to ask the local object for something we know
    *pIID=IID_IKoala;
    return NOERROR;
    }





//IKoala implementation


/*
 * CImpIKoala::CImpIKoala
 * CImpIKoala::~CImpIKoala
 *
 * Constructor Parameters:
 *  pObj            PCKoala of the object containing us.
 *  pUnkOuter       LPUNKNOWN to which we blindly delegate
 *                  all IUnknown calls.
 */

CImpIKoala::CImpIKoala(PCKoala pObj, LPUNKNOWN pUnkOuter)
    {
    m_cRef=0;
    m_pObj=pObj;
    m_pUnkOuter=pUnkOuter;
    return;
    }

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



/*
 * CImpIKoala::QueryInterface
 * CImpIKoala::AddRef
 * CImpIKoala::Release
 *
 * Purpose:
 *  Delegating IUnknown members for interface implementation.
 */

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

STDMETHODIMP_(ULONG) CImpIKoala::AddRef(void)
    {
    ++m_cRef;
    return m_pUnkOuter->AddRef();
    }

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



/*
 * CImpIKoala::ClimbEucalyptusTree
 *
 * Purpose:
 *  Tells the Koala to go climb a tree, which means eating, which
 *  a koala is probably more than happy to do.
 *
 * Parameters:
 *  iTree           short identifying the tree to climb.
 *
 * Return Value:
 *  HRESULT         NOERROR if tree climbed, S_FALSE if not.
 */

STDMETHODIMP CImpIKoala::ClimbEucalyptusTree(short iTree)
    {
    //We know the server doesn't need this
    return NOERROR;
    }



/*
 * CImpIKoala::PouchOpensDown
 *
 * Purpose:
 *  Do-nothing function to demonstrate a void argument list.
 *
 * Parameters:
 *  None
 *
 * Return Value:
 *  HRESULT             NOERROR
 */

STDMETHODIMP CImpIKoala::PouchOpensDown(void)
    {
    //We know the server doesn't need this
    return NOERROR;
    }



/*
 * CImpIKoala::SleepAfterEating
 *
 * Purpose:
 *  Tells the Koala to sleep an additional number of minutes after
 *  eating.
 *
 * Parameters:
 *  cMinutes        short * (in) containing the number of
 *                  extra minutes to sleep after eating.
 *
 * Return Value:
 *  HRESULT         NOERROR
 */

STDMETHODIMP CImpIKoala::SleepAfterEating(short cMinutes)
    {
    DWORD   dwRet;

    dwRet=m_pObj->CallLocal(MSG_SLEEPAFTEREATING
        , (LPARAM)cMinutes, TRUE);

    if (FAILED((HRESULT)dwRet))
        return (HRESULT)dwRet;

    return NOERROR;
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -