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 / chap14 / beeper5 / beeper.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  8.2 KB  |  358 lines

  1. /*
  2.  * BEEPER.CPP
  3.  * Simple Automation Object #5 Chapter 14
  4.  *
  5.  * Implementation of the CBeeper class demonstrating the use of
  6.  * CreateStdDispatch instead of DispInvoke, DispGetIDOfNames, and
  7.  * a custom IDispatch implementation.  In this case we don't have
  8.  * our own IDispatch at all, which CreateStdDispatch provides for
  9.  * us, but at the loss of multiple language support and the ability
  10.  * to define exception.
  11.  *
  12.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  13.  *
  14.  * Kraig Brockschmidt, Microsoft
  15.  * Internet  :  kraigb@microsoft.com
  16.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  17.  */
  18.  
  19.  
  20. #include "beeper.h"
  21.  
  22.  
  23. /*
  24.  * CBeeper::CBeeper
  25.  * CBeeper::~CBeeper
  26.  *
  27.  * Parameters (Constructor):
  28.  *  pUnkOuter       LPUNKNOWN of a controlling unknown.
  29.  *  pfnDestroy      PFNDESTROYED to call when an object
  30.  *                  is destroyed.
  31.  */
  32.  
  33. CBeeper::CBeeper(LPUNKNOWN pUnkOuter, PFNDESTROYED pfnDestroy)
  34.     {
  35.     m_cRef=0;
  36.     m_pUnkOuter=pUnkOuter;
  37.     m_pfnDestroy=pfnDestroy;
  38.  
  39.     m_lSound=0;
  40.     m_pITINeutral=NULL;
  41.     m_pIUnkStdDisp=NULL;
  42.     return;
  43.     }
  44.  
  45.  
  46. CBeeper::~CBeeper(void)
  47.     {
  48.     ReleaseInterface(m_pIUnkStdDisp);
  49.     ReleaseInterface(m_pITINeutral);
  50.     return;
  51.     }
  52.  
  53.  
  54.  
  55. /*
  56.  * CBeeper::Init
  57.  *
  58.  * Purpose:
  59.  *  Performs any intiailization of a CBeeper that's prone to failure
  60.  *  that we also use internally before exposing the object outside.
  61.  *
  62.  * Parameters:
  63.  *  None
  64.  *
  65.  * Return Value:
  66.  *  BOOL            TRUE if the function is successful,
  67.  *                  FALSE otherwise.
  68.  */
  69.  
  70. BOOL CBeeper::Init(void)
  71.     {
  72.     LPUNKNOWN       pIUnknown=this;
  73.     ITypeLib       *pITypeLib;
  74.     HRESULT         hr;
  75.  
  76.     if (NULL!=m_pUnkOuter)
  77.         pIUnknown=m_pUnkOuter;
  78.  
  79.     /*
  80.      * Load our type library.  Since this sample uses
  81.      * CreateStdDispatch we can only support one locale,
  82.      * which is neutral (English) in this case.
  83.      */
  84.  
  85.     if (FAILED(LoadRegTypeLib(LIBID_BeeperTypeLibrary, 1, 0
  86.         , LANG_NEUTRAL, &pITypeLib)))
  87.         {
  88.         /*
  89.          * If LoadRegTypeLib fails, try loading directly with
  90.          * LoadTypeLib, which will register the library for us.
  91.          *
  92.          * NOTE:  You should prepend your DIR registry key to the
  93.          * .TLB name so you don't depend on it being it the PATH.
  94.          * This sample will be updated later to reflect this.
  95.          */
  96.         if (FAILED(LoadTypeLib(OLETEXT("BEEP0000.TLB"), &pITypeLib)))
  97.             return FALSE;
  98.         }
  99.  
  100.     //Get the type information out of the type library.
  101.     hr=pITypeLib->GetTypeInfoOfGuid(DIID_DIBeeper, &m_pITINeutral);
  102.  
  103.     if (FAILED(hr))
  104.         {
  105.         pITypeLib->Release();
  106.         return FALSE;
  107.         }
  108.  
  109.     m_pImpIProvideCI=new CImpIProvideClassInfo(this, pITypeLib);
  110.     pITypeLib->Release();
  111.  
  112.     if (FAILED(hr))
  113.         return FALSE;
  114.  
  115.     /*
  116.      * CreateStdDispatch always returns an IUnknown pointer
  117.      * because such is required in aggregation, which is
  118.      * involved here.  In other words, the Beeper is aggregating
  119.      * on the OLE-provided "StdDispatch" object in order to
  120.      * directly expose IDispatch from that object.  See the
  121.      * implementation of QueryInterface.
  122.      */
  123.     hr=CreateStdDispatch(pIUnknown, (IBeeper *)this, m_pITINeutral
  124.         , &m_pIUnkStdDisp);
  125.  
  126.     if (FAILED(hr))
  127.         return FALSE;
  128.  
  129.     return TRUE;
  130.     }
  131.  
  132.  
  133.  
  134. /*
  135.  * CBeeper::QueryInterface
  136.  * CBeeper::AddRef
  137.  * CBeeper::Release
  138.  *
  139.  * Purpose:
  140.  *  IUnknown members for CBeeper object.
  141.  */
  142.  
  143. STDMETHODIMP CBeeper::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 || IID_IBeeper==riid)
  153.         *ppv=this;
  154.  
  155.     /*
  156.      * We specifically have to ask the object returned from
  157.      * CreateStdDispatch for our dispinterface.  Note that
  158.      * it only understands IID_IDispatch and not DIID_DIBeeper,
  159.      * so we convert requests for DIID_DIBeeper into IID_IDispatch
  160.      * which amounts to exactly the same thing.
  161.      */
  162.     if (IID_IDispatch==riid || DIID_DIBeeper==riid)
  163.         return m_pIUnkStdDisp->QueryInterface(IID_IDispatch, ppv);
  164.  
  165.     //AddRef any interface we'll return.
  166.     if (NULL!=*ppv)
  167.         {
  168.         ((LPUNKNOWN)*ppv)->AddRef();
  169.         return NOERROR;
  170.         }
  171.  
  172.     return ResultFromScode(E_NOINTERFACE);
  173.     }
  174.  
  175.  
  176. STDMETHODIMP_(ULONG) CBeeper::AddRef(void)
  177.     {
  178.     return ++m_cRef;
  179.     }
  180.  
  181.  
  182. STDMETHODIMP_(ULONG) CBeeper::Release(void)
  183.     {
  184.     if (0L!=--m_cRef)
  185.         return m_cRef;
  186.  
  187.     //Inform the server about destruction so it can handle shutdown
  188.     if (NULL!=m_pfnDestroy)
  189.         (*m_pfnDestroy)();
  190.  
  191.     delete this;
  192.     return 0L;
  193.     }
  194.  
  195.  
  196.  
  197. //IBeeper interface functions
  198.  
  199. /*
  200.  * CBeeper::get_Sound
  201.  * CBeeper::put_Sound
  202.  *
  203.  * Purpose:
  204.  *  Functions called from DispInvoke to handle the Sound property.
  205.  *
  206.  * Parameters (Set only):
  207.  *  lSound          long, new sound to save after validation.
  208.  *
  209.  * Return Value: (Get only):
  210.  *  ULONG           Current sound.
  211.  */
  212.  
  213. STDMETHODIMP_(long) CBeeper::get_Sound(void)
  214.     {
  215.     return m_lSound;
  216.     }
  217.  
  218.  
  219. STDMETHODIMP_(void) CBeeper::put_Sound(long lSound)
  220.     {
  221.     if (MB_OK!=lSound && MB_ICONEXCLAMATION!=lSound
  222.         && MB_ICONQUESTION!=lSound && MB_ICONHAND!=lSound
  223.         && MB_ICONASTERISK!=lSound)
  224.         {
  225.         /*
  226.          * We cannot return error information to the StdDispatch
  227.          * given the way we've defined the return value of this
  228.          * methods, so we can't raise an exception.
  229.          */
  230.         return;
  231.         }
  232.  
  233.     m_lSound=lSound;
  234.     return;
  235.     }
  236.  
  237.  
  238.  
  239. /*
  240.  * CBeeper::Beep
  241.  *
  242.  * Purpose:
  243.  *  Function called from DispInvoke to invoke the Beep method.
  244.  *
  245.  * Return Value:
  246.  *  long            The sound played.
  247.  */
  248.  
  249. STDMETHODIMP_(long) CBeeper::Beep(void)
  250.     {
  251.     MessageBeep((UINT)m_lSound);
  252.     return m_lSound;
  253.     }
  254.  
  255.  
  256.  
  257.  
  258. /*
  259.  * Since CreateStdDispatch provides an IDispatch implementation
  260.  * for us, there's no specific code for that interface needed here.
  261.  *
  262.  * So to not get rid of too much code, we'll add an
  263.  * IProvideClassInfo
  264.  */
  265.  
  266.  
  267.  
  268. /*
  269.  * CImpIProvideClassInfo::CImpIProvideClassInfo
  270.  * CImpIProvideClassInfo::~CImpIProvideClassInfo
  271.  *
  272.  * Parameters (Constructor):
  273.  *  pUnkOuter       LPUNKNOWN of a controlling unknown.
  274.  *  pITypeLib       ITypeLib * to return from this interface.
  275.  */
  276.  
  277. CImpIProvideClassInfo::CImpIProvideClassInfo(LPUNKNOWN pUnkOuter
  278.     , ITypeLib *pITypeLib)
  279.     {
  280.     m_cRef=0;
  281.     m_pUnkOuter=pUnkOuter;
  282.  
  283.     /*
  284.      * Get the coclass type info.  If this fails then we'll
  285.      * just fail GetClassInfo below.
  286.      */
  287.     m_pITI=NULL;
  288.     pITypeLib->GetTypeInfoOfGuid(CLSID_Beeper, &m_pITI);
  289.     return;
  290.     }
  291.  
  292.  
  293. CImpIProvideClassInfo::~CImpIProvideClassInfo(void)
  294.     {
  295.     ReleaseInterface(m_pITI);
  296.     return;
  297.     }
  298.  
  299.  
  300. /*
  301.  * CImpIProvideClassInfo::QueryInterface
  302.  * CImpIProvideClassInfo::AddRef
  303.  * CImpIProvideClassInfo::Release
  304.  *
  305.  * Purpose:
  306.  *  IUnknown members for CImpIProvideClassInfo object.
  307.  */
  308.  
  309. STDMETHODIMP CImpIProvideClassInfo::QueryInterface(REFIID riid, PPVOID ppv)
  310.     {
  311.     return m_pUnkOuter->QueryInterface(riid, ppv);
  312.     }
  313.  
  314.  
  315. STDMETHODIMP_(ULONG) CImpIProvideClassInfo::AddRef(void)
  316.     {
  317.     return m_pUnkOuter->AddRef();
  318.     }
  319.  
  320.  
  321. STDMETHODIMP_(ULONG) CImpIProvideClassInfo::Release(void)
  322.     {
  323.     return m_pUnkOuter->Release();
  324.     }
  325.  
  326.  
  327.  
  328.  
  329. /*
  330.  * CImpIProvideClassInfo::GetClassInfo
  331.  *
  332.  * Purpose:
  333.  *  Returns the type information for this coclass.
  334.  *
  335.  * Parameters:
  336.  *  ppITI           ITypeInfo ** in which to store the ITypeInfo
  337.  *                  for this coclass.
  338.  *
  339.  * Return Value:
  340.  *  HRESULT         NOERROR on success, error otherwise.
  341.  */
  342.  
  343. STDMETHODIMP CImpIProvideClassInfo::GetClassInfo(ITypeInfo **ppITI)
  344.     {
  345.     if (NULL==ppITI)
  346.         return ResultFromScode(E_POINTER);
  347.  
  348.     *ppITI=m_pITI;
  349.  
  350.     if (NULL!=m_pITI)
  351.         {
  352.         m_pITI->AddRef();
  353.         return NOERROR;
  354.         }
  355.  
  356.     return ResultFromScode(E_FAIL);
  357.     }
  358.