MYDISP.CPP
/************************************************************************* 
** 
**  This is a part of the Microsoft Source Code Samples. 
** 
**  Copyright 1992 - 1998 Microsoft Corporation. All rights reserved. 
** 
**  This source code is only intended as a supplement to Microsoft Development 
**  Tools and/or WinHelp documentation.  See these sources for detailed 
**  information regarding the Microsoft samples programs. 
** 
**  OLE Automation TypeLibrary Browse Helper Sample 
** 
**  mydisp.cpp 
** 
**  CMyDispatch implementation 
** 
**  Written by Microsoft Product Support Services, Windows Developer Support 
** 
**  The CMyDispatch object implement IUnknown & IDispatch for all the automation 
**  objects in this sample. All objects derive from CMyDispatch. 
** 
*************************************************************************/ 
 
#include <windows.h> 
#include <windowsx.h> 
#ifdef WIN16    
  #include <ole2.h> 
  #include <compobj.h>     
  #include <dispatch.h>  
  #include <variant.h> 
  #include <olenls.h>   
#endif  
#include "browseh.h"  
  
/* 
 * CMyDispatch::CMyDispatch 
 * 
 * Purpose: 
 *  Constructor for CMyDispatch object. Initializes members to NULL. 
 * 
 */ 
CMyDispatch::CMyDispatch() 
{     
    m_ptinfo = NULL; 
    m_cRef = 0; 
} 
 
/* 
 * CMyDispatch::~CMyDispatch 
 * 
 * Purpose: 
 *  Destructor for CMyDispatch object.  
 * 
 */ 
CMyDispatch::~CMyDispatch() 
{     
     if (m_ptinfo) m_ptinfo->Release();                    
} 
 
/* 
 * CMyDispatch::QueryInterface, AddRef, Release 
 * 
 * Purpose: 
 *  Implements IUnknown::QueryInterface, AddRef, Release 
 * 
 */ 
  
STDMETHODIMP 
CMyDispatch::QueryInterface(REFIID iid, void FAR* FAR* ppv)  
{    
    *ppv = NULL; 
         
    if (iid == IID_IUnknown)  
        *ppv = this;    
    else if (iid == IID_IDispatch) 
        *ppv = this;      
    else if (iid == GetInterfaceID()) 
        *ppv = this; 
    else return E_NOINTERFACE;  
 
    AddRef(); 
    return NOERROR;     
} 
 
 
STDMETHODIMP_(ULONG) 
CMyDispatch::AddRef(void) 
{ 
#ifdef _DEBUG   
    TCHAR ach[150]; 
    wsprintf(ach, TEXT("Ref = %ld, Object = %s\r\n"), m_cRef+1, m_szClassName);  
    OutputDebugString(ach);  
#endif     
    return ++m_cRef; 
} 
 
 
STDMETHODIMP_(ULONG) 
CMyDispatch::Release(void) 
{ 
#ifdef _DEBUG   
    TCHAR ach[150]; 
    wsprintf(ach, TEXT("Ref = %ld, Object = %s\r\n"), m_cRef-1, m_szClassName);  
    OutputDebugString(ach); 
#endif   
    if(--m_cRef == 0) 
    { 
        delete this; 
        return 0; 
    } 
    return m_cRef; 
}  
 
/* 
 * CMyDispatch::GetTypeInfoCount 
 * 
 * Purpose: 
 *  Implements IDispatch::GetTypeInfoCount. 
 * 
 */ 
STDMETHODIMP 
CMyDispatch::GetTypeInfoCount(UINT FAR* pctinfo) 
{ 
    *pctinfo = 1; 
    return NOERROR; 
} 
 
/* 
 * CMyDispatch::GetTypeInfo 
 * 
 * Purpose: 
 *  Implements IDispatch::GetTypeInfo.  
 * 
 */ 
STDMETHODIMP 
CMyDispatch::GetTypeInfo( 
      UINT itinfo, 
      LCID lcid, 
      ITypeInfo FAR* FAR* pptinfo) 
{     
    *pptinfo = NULL; 
      
    if(itinfo != 0) 
        return DISP_E_BADINDEX; 
     
    m_ptinfo->AddRef();  
    *pptinfo = m_ptinfo; 
     
    return NOERROR; 
} 
 
/* 
 * CMyDispatch::GetIDsOfNames 
 * 
 * Purpose: 
 *  Implements IDispatch::GetIDsOfNames.  The standard implementation, DispGetIDsOfNames, 
 *  is used. 
 * 
 */ 
STDMETHODIMP  
CMyDispatch::GetIDsOfNames( 
      REFIID riid, 
      OLECHAR FAR* FAR* rgszNames, 
      UINT cNames, 
      LCID lcid, 
      DISPID FAR* rgdispid) 
{ 
    return DispGetIDsOfNames(m_ptinfo, rgszNames, cNames, rgdispid); 
} 
 
/* 
 * CMyDispatch::Invoke 
 * 
 * Purpose: 
 *  Implements IDispatch::Invoke.  The standard implementation, DispInvoke, 
 *  is used. Properties and methods  will 
 *  set m_bRaiseException to raise an exception.  
 * 
 */ 
STDMETHODIMP 
CMyDispatch::Invoke( 
      DISPID dispidMember, 
      REFIID riid, 
      LCID lcid, 
      WORD wFlags, 
      DISPPARAMS FAR* pdispparams, 
      VARIANT FAR* pvarResult, 
      EXCEPINFO FAR* pexcepinfo, 
      UINT FAR* puArgErr) 
{   
    HRESULT hr; 
    
    m_bRaiseException = FALSE;          
    hr =  DispInvoke( 
        this, m_ptinfo, 
        dispidMember, wFlags, pdispparams, 
        pvarResult, pexcepinfo, puArgErr);  
    if (m_bRaiseException)  
    { 
       if (NULL != pexcepinfo) 
           _fmemcpy(pexcepinfo, &m_excepinfo, sizeof(EXCEPINFO));   
       return DISP_E_EXCEPTION;  
    } 
    else return hr;    
}  
 
/* 
 * CMyDispatch::LoadTypeInfo 
 * 
 *  Purpose: 
 *   Gets type information of an object's interface from type library. 
 * 
 * Parameters: 
 *  clsid               Interface id of object in type library.  
 * 
 * Return Value: 
 *  HRESULT 
 * 
 */ 
STDMETHODIMP 
CMyDispatch::LoadTypeInfo(REFCLSID clsid) 
{                           
    HRESULT hr; 
    LPTYPELIB ptlib = NULL; 
    LPTYPEINFO ptinfo = NULL; 
     
    // Load Type Library. If required, notify user on failure. 
    hr = LoadRegTypeLib(LIBID_BrowseHelper, 1, 0, 0x09, &ptlib); 
    if (FAILED(hr)) 
        return hr;  
     
    // Get type information for interface of the object.       
    hr = ptlib->GetTypeInfoOfGuid(clsid, &ptinfo); 
    if (FAILED(hr))   
    {  
        ptlib->Release(); 
        return hr; 
    }    
 
    ptlib->Release(); 
    m_ptinfo = ptinfo; 
    return NOERROR; 
} 
 
/* 
 * CMyDispatch::RaiseException 
 * 
 *  Purpose: 
 *   Raises exception so CMyDispatch::Invoke will return DISP_E_EXCEPTION 
 * 
 * Parameters: 
 *  nID               ID of exception to be raised. 
 * 
 */ 
STDMETHODIMP_(void) 
CMyDispatch::RaiseException(int nID) 
{    
    extern HINSTANCE g_hinst; 
    extern TCHAR g_szServerName[];      
    TCHAR szError[STR_LEN]; 
     
    _fmemset(&m_excepinfo, 0, sizeof(EXCEPINFO)); 
     
    m_excepinfo.wCode = nID; 
    if (LoadString(g_hinst, nID, szError, sizeof(szError))) 
        m_excepinfo.bstrDescription = SysAllocString(TO_OLE_STRING(szError));     
    m_excepinfo.bstrSource = SysAllocString(TO_OLE_STRING(g_szServerName)); 
     
    m_bRaiseException = TRUE;  
}