home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / inole2 / chap06 / koalaprx / koala.cpp < prev    next >
C/C++ Source or Header  |  1995-05-03  |  11KB  |  518 lines

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