KOALA.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:10k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*
  2.  * KOALA.CPP
  3.  * Koala Object with Custom Interface, Chapter 6
  4.  *
  5.  * Implementation of the CKoala object with a custom interface
  6.  * to demonstrate local/remote transparency.
  7.  *
  8.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  9.  *
  10.  * Kraig Brockschmidt, Microsoft
  11.  * Internet  :  kraigb@microsoft.com
  12.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  13.  */
  14. #include "koala.h"
  15. /*
  16.  * CKoala::CKoala
  17.  * CKoala::~CKoala
  18.  *
  19.  * Parameters (Constructor):
  20.  *  pUnkOuter       LPUNKNOWN of a controlling unknown.
  21.  *  pfnDestroy      PFNDESTROYED to call when an object
  22.  *                  is destroyed.
  23.  */
  24. CKoala::CKoala(LPUNKNOWN pUnkOuter, PFNDESTROYED pfnDestroy)
  25.     {
  26.     m_cRef=0;
  27.     m_pUnkOuter=pUnkOuter;
  28.     m_pfnDestroy=pfnDestroy;
  29.     //CHAPTER6MOD
  30.     m_pImpIAnimal=NULL;
  31.     m_pImpIKoala=NULL;
  32.     m_fJustAte=FALSE;
  33.     m_cSleepAfterEat=0;
  34.     //End CHAPTER6MOD
  35.     return;
  36.     }
  37. CKoala::~CKoala(void)
  38.     {
  39.     //CHAPTER6MOD
  40.     DeleteInterfaceImp(m_pImpIKoala);
  41.     DeleteInterfaceImp(m_pImpIAnimal);
  42.     //End CHAPTER6MOD
  43.     return;
  44.     }
  45. /*
  46.  * CKoala::Init
  47.  *
  48.  * Purpose:
  49.  *  Performs any intiailization of a CKoala that's prone to failure
  50.  *  that we also use internally before exposing the object outside.
  51.  *
  52.  * Parameters:
  53.  *  None
  54.  *
  55.  * Return Value:
  56.  *  BOOL            TRUE if the function is successful,
  57.  *                  FALSE otherwise.
  58.  */
  59. BOOL CKoala::Init(void)
  60.     {
  61.     //CHAPTER6MOD
  62.     IUnknown   *pUnkOuter=m_pUnkOuter;
  63.     if (NULL==pUnkOuter)
  64.         pUnkOuter=this;
  65.     m_pImpIAnimal=new CImpIAnimal(this, pUnkOuter);
  66.     if (NULL==m_pImpIAnimal)
  67.         return FALSE;
  68.     m_pImpIKoala=new CImpIKoala(this, pUnkOuter);
  69.     if (NULL==m_pImpIKoala)
  70.         return FALSE;
  71.     //End CHAPTER6MOD
  72.     return TRUE;
  73.     }
  74. /*
  75.  * CKoala::QueryInterface
  76.  * CKoala::AddRef
  77.  * CKoala::Release
  78.  *
  79.  * Purpose:
  80.  *  IUnknown members for CKoala object.
  81.  */
  82. STDMETHODIMP CKoala::QueryInterface(REFIID riid, PPVOID ppv)
  83.     {
  84.     *ppv=NULL;
  85.     /*
  86.      * The only calls for IUnknown are either in a nonaggregated
  87.      * case or when created in an aggregation, so in either case
  88.      * always return our IUnknown for IID_IUnknown.
  89.      */
  90.     if (IID_IUnknown==riid)
  91.         *ppv=this;
  92.     //CHAPTER6MOD
  93.     if (IID_IAnimal==riid)
  94.         *ppv=m_pImpIAnimal;
  95.     if (IID_IKoala==riid)
  96.         *ppv=m_pImpIKoala;
  97.     //End CHAPTER6MOD
  98.     if (NULL!=*ppv)
  99.         {
  100.         ((LPUNKNOWN)*ppv)->AddRef();
  101.         return NOERROR;
  102.         }
  103.     return ResultFromScode(E_NOINTERFACE);
  104.     }
  105. STDMETHODIMP_(ULONG) CKoala::AddRef(void)
  106.     {
  107.     return ++m_cRef;
  108.     }
  109. STDMETHODIMP_(ULONG) CKoala::Release(void)
  110.     {
  111.     if (0L!=--m_cRef)
  112.         return m_cRef;
  113.     if (NULL!=m_pfnDestroy)
  114.         (*m_pfnDestroy)();
  115.     delete this;
  116.     return 0;
  117.     }
  118. //CHAPTER6MOD
  119. //IAnimal implementation
  120. /*
  121.  * CImpIAnimal::CImpIAnimal
  122.  * CImpIAnimal::~CImpIAnimal
  123.  *
  124.  * Constructor Parameters:
  125.  *  pObj            PCKoala of the object containing us.
  126.  *  pUnkOuter       LPUNKNOWN to which we blindly delegate
  127.  *                  all IUnknown calls.
  128.  */
  129. CImpIAnimal::CImpIAnimal(PCKoala pObj, LPUNKNOWN pUnkOuter)
  130.     {
  131.     m_cRef=0;
  132.     m_pObj=pObj;
  133.     m_pUnkOuter=pUnkOuter;
  134.     return;
  135.     }
  136. CImpIAnimal::~CImpIAnimal(void)
  137.     {
  138.     return;
  139.     }
  140. /*
  141.  * CImpIAnimal::QueryInterface
  142.  * CImpIAnimal::AddRef
  143.  * CImpIAnimal::Release
  144.  *
  145.  * Purpose:
  146.  *  Delegating IUnknown members for interface implementation.
  147.  */
  148. STDMETHODIMP CImpIAnimal::QueryInterface(REFIID riid
  149.     , LPVOID *ppv)
  150.     {
  151.     return m_pUnkOuter->QueryInterface(riid, ppv);
  152.     }
  153. STDMETHODIMP_(ULONG) CImpIAnimal::AddRef(void)
  154.     {
  155.     ++m_cRef;
  156.     return m_pUnkOuter->AddRef();
  157.     }
  158. STDMETHODIMP_(ULONG) CImpIAnimal::Release(void)
  159.     {
  160.     --m_cRef;
  161.     return m_pUnkOuter->Release();
  162.     }
  163. /*
  164.  * CImpIAnimal::Eat
  165.  *
  166.  * Purpose:
  167.  *  Instructs the animal to eat something, returning what the animal
  168.  *  actually ate which usually goes against recommendation (which is
  169.  *  true for the human animal, too).
  170.  *
  171.  * Parameters:
  172.  *  pszFoodRecommended  LPTSTR describing the food that the animal
  173.  *                      should eat.
  174.  *  pszFoodEaten        LPTSTR describing the food the animal actually
  175.  *                      ate, which may not, of course, be the same as
  176.  *                      what it should eat.
  177.  *  cchEaten            short containing the lenght of pszFoodEaten.
  178.  *
  179.  * Return Value:
  180.  *  HRESULT             NOERROR if food is eaten, S_FALSE if not.
  181.  */
  182. STDMETHODIMP CImpIAnimal::Eat(LPTSTR pszFoodRecommended
  183.     , LPTSTR pszFoodEaten, short cchEaten)
  184.     {
  185.     //Koalas aren't don't care what you tell them, they eat one thing
  186.    #ifdef WIN32ANSI
  187.     lstrcpyn(pszFoodEaten, "Eucalyptus Leaves", cchEaten);
  188.    #else
  189.     _tcsncpy(pszFoodEaten, TEXT("Eucalyptus Leaves"), cchEaten);
  190.    #endif
  191.     m_pObj->m_fJustAte=TRUE;
  192.     return NOERROR;
  193.     }
  194. /*
  195.  * CImpIAnimal::Sleep
  196.  *
  197.  * Purpose:
  198.  *  Instructs the animal to sleep for a while.
  199.  *
  200.  * Parameters:
  201.  *  pcMinutes      short * (in-out) containing the number of
  202.  *                 minutes to sleep on entry, then number of
  203.  *                 minutes actually slept on exit
  204.  *
  205.  * Return Value:
  206.  *  HRESULT        NOERROR if sleep taken, S_FALSE if not, where
  207.  *                 *pcMinutes should be zero.
  208.  */
  209. STDMETHODIMP CImpIAnimal::Sleep(short *pcMinutes)
  210.     {
  211.     /*
  212.      * Koalas welcome the opportunity to sleep, and will probably
  213.      * sleep longer than you tell them, so return more time than
  214.      * we were told based on IKoala::SleepAfterEating.
  215.      */
  216.     *pcMinutes=*pcMinutes+m_pObj->m_cSleepAfterEat;
  217.     m_pObj->m_fJustAte=FALSE;     //Probably want to eat again
  218.     return NOERROR;
  219.     }
  220. /*
  221.  * CImpIAnimal::Procreate
  222.  *
  223.  * Purpose:
  224.  *  Instructs the animal to procreate.  On entry, the number of
  225.  *  offstring is unknown, so that's an out parameter.
  226.  *
  227.  * Parameters:
  228.  *  pcOffspring     short * (out) in which to store the number
  229.  *                  of new offspring.
  230.  *
  231.  * Return Value:
  232.  *  HRESULT         NOERROR if offspring created, S_FALSE if not
  233.  *                  where *pcOffspring should be zero.
  234.  */
  235. STDMETHODIMP CImpIAnimal::Procreate(short *pcOffspring)
  236.     {
  237.     DWORD       dw;
  238.     SCODE       sc=S_FALSE;
  239.     /*
  240.      * Koalas like to reproduce when they damn well please and
  241.      * not when someone else tells them, so we'll just check
  242.      * the current time, and if it's appropriate, we'll reproduce.
  243.      * (Simulation:  use GetTickCount to get the system time, then
  244.      * divide by 100 to filter out resolution concerns, then see if
  245.      * the result is an even multiple of 10).
  246.      *
  247.      * Also, Koalas only produce one offspring at a time.  If
  248.      * this was a rabbit, we might get anywhere from 2-20 offspring.
  249.      */
  250.     dw=GetTickCount()/100;
  251.     if ((dw/10)*10==dw)
  252.         {
  253.         *pcOffspring=1;
  254.         sc=S_OK;
  255.         }
  256.     else
  257.         *pcOffspring=0;
  258.     return ResultFromScode(sc);
  259.     }
  260. /*
  261.  * CImpIAnimal::WhatKindOfAnimal
  262.  *
  263.  * Purpose:
  264.  *  Returns the IID of the specific animal interface that describes
  265.  *  the type of animal this really is (a much more complex
  266.  *  classification scheme might have IAnimal::WhatGenus and
  267.  *  IGenus::WhatSpecies, etc., but we're just being simple here).
  268.  *
  269.  * Parameters:
  270.  *  pIID            IID * in which to store the specific
  271.  *                  animal IID.
  272.  *
  273.  * Return Value:
  274.  *  HRESULT         NOERROR if the animal type is known,
  275.  *                  S_FALSE if not with *pIID set to IID_NULL.
  276.  */
  277. STDMETHODIMP CImpIAnimal::WhatKindOfAnimal(IID *pIID)
  278.     {
  279.     *pIID=IID_IKoala;
  280.     return NOERROR;
  281.     }
  282. //IKoala implementation
  283. /*
  284.  * CImpIKoala::CImpIKoala
  285.  * CImpIKoala::~CImpIKoala
  286.  *
  287.  * Constructor Parameters:
  288.  *  pObj            PCKoala of the object containing us.
  289.  *  pUnkOuter       LPUNKNOWN to which we blindly delegate
  290.  *                  all IUnknown calls.
  291.  */
  292. CImpIKoala::CImpIKoala(PCKoala pObj, LPUNKNOWN pUnkOuter)
  293.     {
  294.     m_cRef=0;
  295.     m_pObj=pObj;
  296.     m_pUnkOuter=pUnkOuter;
  297.     return;
  298.     }
  299. CImpIKoala::~CImpIKoala(void)
  300.     {
  301.     return;
  302.     }
  303. /*
  304.  * CImpIKoala::QueryInterface
  305.  * CImpIKoala::AddRef
  306.  * CImpIKoala::Release
  307.  *
  308.  * Purpose:
  309.  *  Delegating IUnknown members for interface implementation.
  310.  */
  311. STDMETHODIMP CImpIKoala::QueryInterface(REFIID riid
  312.     , LPVOID *ppv)
  313.     {
  314.     return m_pUnkOuter->QueryInterface(riid, ppv);
  315.     }
  316. STDMETHODIMP_(ULONG) CImpIKoala::AddRef(void)
  317.     {
  318.     ++m_cRef;
  319.     return m_pUnkOuter->AddRef();
  320.     }
  321. STDMETHODIMP_(ULONG) CImpIKoala::Release(void)
  322.     {
  323.     --m_cRef;
  324.     return m_pUnkOuter->Release();
  325.     }
  326. /*
  327.  * CImpIKoala::ClimbEucalyptusTree
  328.  *
  329.  * Purpose:
  330.  *  Tells the Koala to go climb a tree, which means eating, which
  331.  *  a koala is probably more than happy to do.
  332.  *
  333.  * Parameters:
  334.  *  iTree           short identifying the tree to climb.
  335.  *
  336.  * Return Value:
  337.  *  HRESULT         NOERROR if tree climbed, S_FALSE if not.
  338.  */
  339. STDMETHODIMP CImpIKoala::ClimbEucalyptusTree(short iTree)
  340.     {
  341.     //Nothing to demonstrate...
  342.     return NOERROR;
  343.     }
  344. /*
  345.  * CImpIKoala::PouchOpensDown
  346.  *
  347.  * Purpose:
  348.  *  Do-nothing function to demonstrate a void argument list.
  349.  *
  350.  * Parameters:
  351.  *  None
  352.  *
  353.  * Return Value:
  354.  *  HRESULT             NOERROR
  355.  */
  356. STDMETHODIMP CImpIKoala::PouchOpensDown(void)
  357.     {
  358.     //Nothing to demonstrate...
  359.     return NOERROR;
  360.     }
  361. /*
  362.  * CImpIKoala::SleepAfterEating
  363.  *
  364.  * Purpose:
  365.  *  Tells the Koala to sleep an additional number of minutes after
  366.  *  eating.
  367.  *
  368.  * Parameters:
  369.  *  cMinutes        short * (in) containing the number of
  370.  *                  extra minutes to sleep after eating.
  371.  *
  372.  * Return Value:
  373.  *  HRESULT         NOERROR
  374.  */
  375. STDMETHODIMP CImpIKoala::SleepAfterEating(short cMinutes)
  376.     {
  377.     m_pObj->m_cSleepAfterEat=cMinutes;
  378.     return NOERROR;
  379.     }
  380. //End CHAPTER6MOD