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

Windows编程

开发平台:

Visual C++

  1. /*
  2.  * KOALA.CPP
  3.  * Koala Object with Custom Marshaling, 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.     m_pImpIAnimal=NULL;
  30.     m_pImpIKoala=NULL;
  31.     m_pImpIMarshal=NULL;
  32.     m_fJustAte=FALSE;
  33.     m_cSleepAfterEat=0;
  34.     return;
  35.     }
  36. CKoala::~CKoala(void)
  37.     {
  38.     DeleteInterfaceImp(m_pImpIMarshal);
  39.     DeleteInterfaceImp(m_pImpIKoala);
  40.     DeleteInterfaceImp(m_pImpIAnimal);
  41.     return;
  42.     }
  43. /*
  44.  * CKoala::Init
  45.  *
  46.  * Purpose:
  47.  *  Performs any intiailization of a CKoala that's prone to failure
  48.  *  that we also use internally before exposing the object outside.
  49.  *
  50.  * Parameters:
  51.  *  None
  52.  *
  53.  * Return Value:
  54.  *  BOOL            TRUE if the function is successful,
  55.  *                  FALSE otherwise.
  56.  */
  57. BOOL CKoala::Init(void)
  58.     {
  59.     IUnknown   *pUnkOuter=m_pUnkOuter;
  60.     if (NULL==pUnkOuter)
  61.         pUnkOuter=this;
  62.     m_pImpIAnimal=new CImpIAnimal(this, pUnkOuter);
  63.     if (NULL==m_pImpIAnimal)
  64.         return FALSE;
  65.     m_pImpIKoala=new CImpIKoala(this, pUnkOuter);
  66.     if (NULL==m_pImpIKoala)
  67.         return FALSE;
  68.     m_pImpIMarshal=new CImpIMarshal(this, pUnkOuter);
  69.     if (NULL==m_pImpIMarshal)
  70.         return FALSE;
  71.     return TRUE;
  72.     }
  73. /*
  74.  * CKoala::CallLocal
  75.  *
  76.  * Purpose:
  77.  *  Sends or posts a message to the local object.
  78.  *
  79.  * Parameters:
  80.  *  iMsg            UINT identifying the function to call
  81.  *  lParam          LPARAM containing extra information
  82.  *  fAsync          BOOL indicating if this is a Post (TRUE) or
  83.  *                  a send (FALSE).
  84.  *
  85.  * Return Value:
  86.  *  DWORD           Return value from the function or an HRESULT
  87.  *                  on failure.
  88.  */
  89. DWORD CKoala::CallLocal(UINT iMsg, LPARAM lParam, BOOL fAsync)
  90.     {
  91.     DWORD   dwRet=0;
  92.     if (fAsync)
  93.         PostMessage(m_hWndLocal, WM_COMMAND, (WPARAM)iMsg, lParam);
  94.     else
  95.         {
  96.         dwRet=SendMessage(m_hWndLocal, WM_COMMAND, (WPARAM)iMsg
  97.             , lParam);
  98.         }
  99.     return dwRet;
  100.     }
  101. /*
  102.  * CKoala::QueryInterface
  103.  * CKoala::AddRef
  104.  * CKoala::Release
  105.  *
  106.  * Purpose:
  107.  *  IUnknown members for CKoala object.
  108.  */
  109. STDMETHODIMP CKoala::QueryInterface(REFIID riid, PPVOID ppv)
  110.     {
  111.     *ppv=NULL;
  112.     /*
  113.      * The only calls for IUnknown are either in a nonaggregated
  114.      * case or when created in an aggregation, so in either case
  115.      * always return our IUnknown for IID_IUnknown.
  116.      */
  117.     if (IID_IUnknown==riid)
  118.         *ppv=this;
  119.     if (IID_IAnimal==riid)
  120.         *ppv=m_pImpIAnimal;
  121.     if (IID_IKoala==riid)
  122.         *ppv=m_pImpIKoala;
  123.     if (IID_IMarshal==riid)
  124.         *ppv=m_pImpIMarshal;
  125.     if (NULL!=*ppv)
  126.         {
  127.         ((LPUNKNOWN)*ppv)->AddRef();
  128.         return NOERROR;
  129.         }
  130.     return ResultFromScode(E_NOINTERFACE);
  131.     }
  132. STDMETHODIMP_(ULONG) CKoala::AddRef(void)
  133.     {
  134.     return ++m_cRef;
  135.     }
  136. STDMETHODIMP_(ULONG) CKoala::Release(void)
  137.     {
  138.     if (0L!=--m_cRef)
  139.         return m_cRef;
  140.     /*
  141.      * If this is the last Release, then we have to tell
  142.      * the server to free its object too.  This is an async
  143.      * call as we don't need to hang around for it to quit.
  144.      */
  145.     CallLocal(MSG_RELEASE, 0, TRUE);
  146.     if (NULL!=m_pfnDestroy)
  147.         (*m_pfnDestroy)();
  148.     delete this;
  149.     return 0;
  150.     }
  151. //Proxy-side IAnimal implementation
  152. /*
  153.  * CImpIAnimal::CImpIAnimal
  154.  * CImpIAnimal::~CImpIAnimal
  155.  *
  156.  * Constructor Parameters:
  157.  *  pObj            PCKoala of the object containing us.
  158.  *  pUnkOuter       LPUNKNOWN to which we blindly delegate
  159.  *                  all IUnknown calls.
  160.  */
  161. CImpIAnimal::CImpIAnimal(PCKoala pObj, LPUNKNOWN pUnkOuter)
  162.     {
  163.     m_cRef=0;
  164.     m_pObj=pObj;
  165.     m_pUnkOuter=pUnkOuter;
  166.     return;
  167.     }
  168. CImpIAnimal::~CImpIAnimal(void)
  169.     {
  170.     return;
  171.     }
  172. /*
  173.  * CImpIAnimal::QueryInterface
  174.  * CImpIAnimal::AddRef
  175.  * CImpIAnimal::Release
  176.  *
  177.  * Purpose:
  178.  *  Delegating IUnknown members for interface implementation.
  179.  */
  180. STDMETHODIMP CImpIAnimal::QueryInterface(REFIID riid
  181.     , LPVOID *ppv)
  182.     {
  183.     return m_pUnkOuter->QueryInterface(riid, ppv);
  184.     }
  185. STDMETHODIMP_(ULONG) CImpIAnimal::AddRef(void)
  186.     {
  187.     ++m_cRef;
  188.     return m_pUnkOuter->AddRef();
  189.     }
  190. STDMETHODIMP_(ULONG) CImpIAnimal::Release(void)
  191.     {
  192.     --m_cRef;
  193.     return m_pUnkOuter->Release();
  194.     }
  195. /*
  196.  * CImpIAnimal::Eat
  197.  *
  198.  * Purpose:
  199.  *  Instructs the animal to eat something, returning what the animal
  200.  *  actually ate which usually goes against recommendation (which is
  201.  *  true for the human animal, too).
  202.  *
  203.  * Parameters:
  204.  *  pszFoodRecommended  LPTSTR describing the food that the animal
  205.  *                      should eat.
  206.  *  pszFoodEaten        LPTSTR describing the food the animal actually
  207.  *                      ate, which may not, of course, be the same as
  208.  *                      what it should eat.
  209.  *  cchEaten            short containing the lenght of pszFoodEaten.
  210.  *
  211.  * Return Value:
  212.  *  HRESULT             NOERROR if food is eaten, S_FALSE if not.
  213.  */
  214. STDMETHODIMP CImpIAnimal::Eat(LPTSTR pszFoodRecommended
  215.     , LPTSTR pszFoodEaten, short cchEaten)
  216.     {
  217.     /*
  218.      * Koalas aren't don't care what you tell them, they eat one
  219.      * thing.  We can handle the return string for the local
  220.      * object, but we still need to tell it that this was
  221.      * called.
  222.      */
  223.     _tcsncpy(pszFoodEaten, TEXT("Eucalyptus Leaves"), cchEaten);
  224.     m_pObj->CallLocal(MSG_EAT, 0L, FALSE);
  225.     return NOERROR;
  226.     }
  227. /*
  228.  * CImpIAnimal::Sleep
  229.  *
  230.  * Purpose:
  231.  *  Instructs the animal to sleep for a while.
  232.  *
  233.  * Parameters:
  234.  *  pcMinutes      short * (in-out) containing the number of
  235.  *                 minutes to sleep on entry, then number of
  236.  *                 minutes actually slept on exit
  237.  *
  238.  * Return Value:
  239.  *  HRESULT        NOERROR if sleep taken, S_FALSE if not, where
  240.  *                 *pcMinutes should be zero.
  241.  */
  242. STDMETHODIMP CImpIAnimal::Sleep(short *pcMinutes)
  243.     {
  244.     DWORD       dwRet;
  245.     //Pass the client's value
  246.     dwRet=m_pObj->CallLocal(MSG_SLEEP, (LPARAM)*pcMinutes, FALSE);
  247.     if (FAILED((HRESULT)dwRet))
  248.         return (HRESULT)dwRet;
  249.     //Store the return value in the client's variable.
  250.     *pcMinutes=LOWORD(dwRet);
  251.     return NOERROR;
  252.     }
  253. /*
  254.  * CImpIAnimal::Procreate
  255.  *
  256.  * Purpose:
  257.  *  Instructs the animal to procreate.  On entry, the number of
  258.  *  offstring is unknown, so that's an out parameter.
  259.  *
  260.  * Parameters:
  261.  *  pcOffspring     short * (out) in which to store the number
  262.  *                  of new offspring.
  263.  *
  264.  * Return Value:
  265.  *  HRESULT         NOERROR if offspring created, S_FALSE if not
  266.  *                  where *pcOffspring should be zero.
  267.  */
  268. STDMETHODIMP CImpIAnimal::Procreate(short *pcOffspring)
  269.     {
  270.     DWORD       dwRet;
  271.     dwRet=m_pObj->CallLocal(MSG_PROCREATE, 0, FALSE);
  272.     if (FAILED((HRESULT)dwRet))
  273.         return (HRESULT)dwRet;
  274.     *pcOffspring=(short)LOWORD(dwRet);
  275.     return ResultFromScode(0==dwRet ? S_FALSE : S_OK);
  276.     }
  277. /*
  278.  * CImpIAnimal::WhatKindOfAnimal
  279.  *
  280.  * Purpose:
  281.  *  Returns the IID of the specific animal interface that describes
  282.  *  the type of animal this really is (a much more complex
  283.  *  classification scheme might have IAnimal::WhatGenus and
  284.  *  IGenus::WhatSpecies, etc., but we're just being simple here).
  285.  *
  286.  * Parameters:
  287.  *  pIID            IID * in which to store the specific
  288.  *                  animal IID.
  289.  *
  290.  * Return Value:
  291.  *  HRESULT         NOERROR if the animal type is known,
  292.  *                  S_FALSE if not with *pIID set to IID_NULL.
  293.  */
  294. STDMETHODIMP CImpIAnimal::WhatKindOfAnimal(IID *pIID)
  295.     {
  296.     //No need to ask the local object for something we know
  297.     *pIID=IID_IKoala;
  298.     return NOERROR;
  299.     }
  300. //IKoala implementation
  301. /*
  302.  * CImpIKoala::CImpIKoala
  303.  * CImpIKoala::~CImpIKoala
  304.  *
  305.  * Constructor Parameters:
  306.  *  pObj            PCKoala of the object containing us.
  307.  *  pUnkOuter       LPUNKNOWN to which we blindly delegate
  308.  *                  all IUnknown calls.
  309.  */
  310. CImpIKoala::CImpIKoala(PCKoala pObj, LPUNKNOWN pUnkOuter)
  311.     {
  312.     m_cRef=0;
  313.     m_pObj=pObj;
  314.     m_pUnkOuter=pUnkOuter;
  315.     return;
  316.     }
  317. CImpIKoala::~CImpIKoala(void)
  318.     {
  319.     return;
  320.     }
  321. /*
  322.  * CImpIKoala::QueryInterface
  323.  * CImpIKoala::AddRef
  324.  * CImpIKoala::Release
  325.  *
  326.  * Purpose:
  327.  *  Delegating IUnknown members for interface implementation.
  328.  */
  329. STDMETHODIMP CImpIKoala::QueryInterface(REFIID riid
  330.     , LPVOID *ppv)
  331.     {
  332.     return m_pUnkOuter->QueryInterface(riid, ppv);
  333.     }
  334. STDMETHODIMP_(ULONG) CImpIKoala::AddRef(void)
  335.     {
  336.     ++m_cRef;
  337.     return m_pUnkOuter->AddRef();
  338.     }
  339. STDMETHODIMP_(ULONG) CImpIKoala::Release(void)
  340.     {
  341.     --m_cRef;
  342.     return m_pUnkOuter->Release();
  343.     }
  344. /*
  345.  * CImpIKoala::ClimbEucalyptusTree
  346.  *
  347.  * Purpose:
  348.  *  Tells the Koala to go climb a tree, which means eating, which
  349.  *  a koala is probably more than happy to do.
  350.  *
  351.  * Parameters:
  352.  *  iTree           short identifying the tree to climb.
  353.  *
  354.  * Return Value:
  355.  *  HRESULT         NOERROR if tree climbed, S_FALSE if not.
  356.  */
  357. STDMETHODIMP CImpIKoala::ClimbEucalyptusTree(short iTree)
  358.     {
  359.     //We know the server doesn't need this
  360.     return NOERROR;
  361.     }
  362. /*
  363.  * CImpIKoala::PouchOpensDown
  364.  *
  365.  * Purpose:
  366.  *  Do-nothing function to demonstrate a void argument list.
  367.  *
  368.  * Parameters:
  369.  *  None
  370.  *
  371.  * Return Value:
  372.  *  HRESULT             NOERROR
  373.  */
  374. STDMETHODIMP CImpIKoala::PouchOpensDown(void)
  375.     {
  376.     //We know the server doesn't need this
  377.     return NOERROR;
  378.     }
  379. /*
  380.  * CImpIKoala::SleepAfterEating
  381.  *
  382.  * Purpose:
  383.  *  Tells the Koala to sleep an additional number of minutes after
  384.  *  eating.
  385.  *
  386.  * Parameters:
  387.  *  cMinutes        short * (in) containing the number of
  388.  *                  extra minutes to sleep after eating.
  389.  *
  390.  * Return Value:
  391.  *  HRESULT         NOERROR
  392.  */
  393. STDMETHODIMP CImpIKoala::SleepAfterEating(short cMinutes)
  394.     {
  395.     DWORD   dwRet;
  396.     dwRet=m_pObj->CallLocal(MSG_SLEEPAFTEREATING
  397.         , (LPARAM)cMinutes, TRUE);
  398.     if (FAILED((HRESULT)dwRet))
  399.         return (HRESULT)dwRet;
  400.     return NOERROR;
  401.     }