TYPELIB.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 
** 
**  typelib.cpp 
** 
**  CTypeLibrary implementation 
** 
**  Written by Microsoft Product Support Services, Windows Developer Support 
** 
*************************************************************************/ 
 
#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"   
 
/* 
 * CTypeLibrary::Create 
 * 
 * Purpose: 
 *  Creates an instance of the TypeLibrary automation object and initializes it. 
 * 
 * Parameters:        
 *  ptlib            ITypeLib interface that corresponds to this CTypeLibrary object. 
 *  ppTypeLibrary    Returns TypeLibrary automation object. 
 * 
 * Return Value: 
 *  HRESULT 
 * 
 */ 
HRESULT  
CTypeLibrary::Create(LPTYPELIB ptlib, CTypeLibrary FAR* FAR* ppTypeLibrary )  
{    
    HRESULT hr; 
    CTypeLibrary FAR* pTypeLibrary = NULL;     
    LPTLIBATTR ptlibattr; 
      
    *ppTypeLibrary = NULL; 
     
    // Create typelibrary object. 
    pTypeLibrary = new CTypeLibrary(); 
    if (pTypeLibrary == NULL) 
    { 
        hr = E_OUTOFMEMORY;  
        goto error; 
    } 
     
    // Load type information for the typelibrary object from type library.  
    hr = pTypeLibrary->LoadTypeInfo(IID_ITypeLibrary); 
    if (FAILED(hr)) 
        goto error; 
     
    hr = ptlib->GetDocumentation(-1, &pTypeLibrary->m_bstrName, &pTypeLibrary->m_bstrDocumentation, 
             &pTypeLibrary->m_ulHelpContext, &pTypeLibrary->m_bstrHelpFile);   
    if (FAILED(hr)) 
        goto error;     
         
    hr = ptlib->GetLibAttr(&ptlibattr); 
    if (FAILED(hr)) 
        goto error; 
    pTypeLibrary->m_guid = ptlibattr->guid; 
    pTypeLibrary->m_lcid = ptlibattr->lcid; 
    pTypeLibrary->m_wMajorVer = ptlibattr->wMajorVerNum;   
    pTypeLibrary->m_wMinorVer = ptlibattr->wMinorVerNum; 
    ptlib->ReleaseTLibAttr(ptlibattr); 
         
    ptlib->AddRef(); 
    pTypeLibrary->m_ptlib = ptlib;   
     
#ifdef _DEBUG   
    lstrcpyn(pTypeLibrary->m_szClassName, TEXT("TypeLibrary"), 100); 
#endif 
         
    *ppTypeLibrary = pTypeLibrary; 
    return NOERROR; 
     
error:                         
    if (pTypeLibrary == NULL) return E_OUTOFMEMORY; 
    if (pTypeLibrary->m_ptlib) pTypeLibrary->m_ptlib->Release(); 
    if (pTypeLibrary->m_bstrName) SysFreeString(pTypeLibrary->m_bstrName); 
    if (pTypeLibrary->m_bstrDocumentation) SysFreeString(pTypeLibrary->m_bstrDocumentation); 
    if (pTypeLibrary->m_bstrHelpFile) SysFreeString(pTypeLibrary->m_bstrHelpFile); 
          
    // Set to NULL to prevent destructor from attempting to free again   
    pTypeLibrary->m_ptlib = NULL; 
    pTypeLibrary->m_bstrName = NULL; 
    pTypeLibrary->m_bstrDocumentation = NULL; 
    pTypeLibrary->m_bstrHelpFile = NULL; 
     
    delete pTypeLibrary; 
    return hr; 
} 
 
/* 
 * CTypeLibrary::CTypeLibrary 
 * 
 * Purpose: 
 *  Constructor for CTypeLibrary object. Initializes members to NULL. 
 * 
 */ 
CTypeLibrary::CTypeLibrary() 
{   
    m_ptlib = NULL;  
    m_bstrName = NULL; 
    m_bstrDocumentation = NULL; 
    m_bstrHelpFile = NULL;    
    m_pdispTypeInfos = NULL; 
        m_pszGUID = NULL; 
} 
 
/* 
 * CTypeLibrary::~CTypeLibrary 
 * 
 * Purpose: 
 *  Destructor for CTypeLibrary object. Frees TypeLibrary message BSTR and default 
 *  IDispatch implementation. Closes the aplication. 
 * 
 */ 
CTypeLibrary::~CTypeLibrary() 
{     
    if (m_ptlib) m_ptlib->Release();     
    if (m_bstrName) SysFreeString(m_bstrName); 
    if (m_bstrDocumentation) SysFreeString(m_bstrDocumentation); 
    if (m_bstrHelpFile) SysFreeString(m_bstrHelpFile);   
    if (m_pdispTypeInfos) m_pdispTypeInfos->Release(); 
#ifdef WIN32 
    if (m_pszGUID) CoTaskMemFree(m_pszGUID); 
#else 
    HRESULT hr; 
    LPMALLOC pmalloc; 
    if (m_pszGUID) 
    { 
       hr = CoGetMalloc(MEMCTX_TASK, &pmalloc); 
       if (SUCCEEDED(hr)) 
       { 
           pmalloc->Free(m_pszGUID); 
           pmalloc->Release(); 
       } 
    } 
#endif  
     
}  
 
STDMETHODIMP_(REFCLSID) 
CTypeLibrary::GetInterfaceID() 
{ 
    return IID_ITypeLibrary; 
} 
  
STDMETHODIMP_(BSTR) 
CTypeLibrary::get_Name()      
{ 
    return SysAllocString(m_bstrName); 
}   
 
STDMETHODIMP_(BSTR) 
CTypeLibrary::get_Documentation()     
{ 
    return SysAllocString(m_bstrDocumentation); 
}   
 
STDMETHODIMP_(long) 
CTypeLibrary::get_HelpContext()      
{ 
    return (long)m_ulHelpContext; 
} 
 
STDMETHODIMP_(BSTR) 
CTypeLibrary::get_HelpFile()      
{ 
    return SysAllocString(m_bstrHelpFile); 
}   
 
STDMETHODIMP_(int) 
CTypeLibrary::get_MajorVersion()      
{ 
    return (int)m_wMajorVer; 
}  
 
STDMETHODIMP_(int) 
CTypeLibrary::get_MinorVersion()      
{ 
    return (int)m_wMinorVer; 
} 
 
STDMETHODIMP_(long) 
CTypeLibrary::get_LocaleID()      
{ 
    return (long)m_lcid; 
}  
 
STDMETHODIMP_(ICollection FAR*) 
CTypeLibrary::get_TypeInfos()      
{    
    HRESULT hr; 
    CTypeInfo FAR* pTypeInfo; 
    CInterface FAR* pInterface; 
    CDispinterface FAR* pDispinterface; 
    CModule FAR* pModule; 
    CCoClass FAR* pCoClass;     
    CEnum FAR* pEnum;    
    CAlias FAR* pAlias; 
    CStruct FAR* pStruct; 
    CUnion FAR* pUnion; 
    CCollection FAR* pCollection = NULL; 
    LPDISPATCH pdisp;  
    LPTYPEINFO ptinfo = NULL; 
    unsigned int cTypeInfo;     
    unsigned int n;       
    TYPEKIND typekind; 
     
    if (m_pdispTypeInfos == NULL) 
    { 
        cTypeInfo = m_ptlib->GetTypeInfoCount();      
        hr = CCollection::Create(cTypeInfo, 0, &pCollection); 
        if (FAILED(hr)) 
            {RaiseException(IDS_Unexpected); goto error;}   
         
        // Enumerate the typeinfos in this type library 
        for (n=0; n<cTypeInfo; n++) 
        { 
            hr = m_ptlib->GetTypeInfo(n, &ptinfo);   
            if (FAILED(hr)) 
                {RaiseException(IDS_Unexpected); goto error;}     
            hr = m_ptlib->GetTypeInfoType(n, &typekind); 
            if (FAILED(hr)) 
                {RaiseException(IDS_Unexpected); goto error;}       
            switch (typekind) 
            { 
                case TKIND_INTERFACE: 
                    hr = CInterface::Create(ptinfo, &pInterface);  
                    if (FAILED(hr)) 
                        {RaiseException(IDS_Unexpected); goto error;}   
                    pInterface->QueryInterface(IID_IDispatch, (void FAR* FAR*)&pdisp); 
                    break; 
              
                case TKIND_DISPATCH: 
                    hr = CDispinterface::Create(ptinfo, &pDispinterface);   
                    if (FAILED(hr)) 
                        {RaiseException(IDS_Unexpected); goto error;}    
                    pDispinterface->QueryInterface(IID_IDispatch, (void FAR* FAR*)&pdisp); 
                    break;   
                     
                case TKIND_MODULE: 
                    hr = CModule::Create(ptinfo, &pModule);   
                    if (FAILED(hr)) 
                        {RaiseException(IDS_Unexpected); goto error;}    
                    pModule->QueryInterface(IID_IDispatch, (void FAR* FAR*)&pdisp); 
                    break; 
                 
                case TKIND_COCLASS: 
                    hr = CCoClass::Create(ptinfo, &pCoClass);   
                    if (FAILED(hr)) 
                        {RaiseException(IDS_Unexpected); goto error;}     
                    pCoClass->QueryInterface(IID_IDispatch, (void FAR* FAR*)&pdisp); 
                    break;  
                     
                case TKIND_ENUM: 
                    hr = CEnum::Create(ptinfo, &pEnum);   
                    if (FAILED(hr)) 
                        {RaiseException(IDS_Unexpected); goto error;}     
                    pEnum->QueryInterface(IID_IDispatch, (void FAR* FAR*)&pdisp); 
                    break;   
                     
                case TKIND_ALIAS: 
                    hr = CAlias::Create(ptinfo, &pAlias);   
                    if (FAILED(hr)) 
                        {RaiseException(IDS_Unexpected); goto error;}     
                    pAlias->QueryInterface(IID_IDispatch, (void FAR* FAR*)&pdisp); 
                    break;  
                     
                 case TKIND_RECORD: 
                    hr = CStruct::Create(ptinfo, &pStruct);   
                    if (FAILED(hr)) 
                        {RaiseException(IDS_Unexpected); goto error;}     
                    pStruct->QueryInterface(IID_IDispatch, (void FAR* FAR*)&pdisp); 
                    break;  
                     
                 case TKIND_UNION: 
                    hr = CUnion::Create(ptinfo, &pUnion);   
                    if (FAILED(hr)) 
                        {RaiseException(IDS_Unexpected); goto error;}     
                    pUnion->QueryInterface(IID_IDispatch, (void FAR* FAR*)&pdisp); 
                    break;  
                     
                default:        
                    // Currently unsupported TKINDs 
                    hr = CTypeInfo::Create(ptinfo, &pTypeInfo);  
                    if (FAILED(hr)) 
                        {RaiseException(IDS_Unexpected); goto error;}   
                    pTypeInfo->QueryInterface(IID_IDispatch, (void FAR* FAR*)&pdisp); 
                    break; 
            }  
            // Add typeinfo to collection of typeinfos. 
            pCollection->Add(pdisp);   
            pdisp->Release(); 
            ptinfo->Release();    
            ptinfo = NULL; 
        }  
     
        pCollection->QueryInterface(IID_IDispatch, (void FAR* FAR*)&pdisp); 
        m_pdispTypeInfos = pdisp; 
    } 
    m_pdispTypeInfos->AddRef(); 
    return (ICollection FAR*)m_pdispTypeInfos; 
 
error:    
    if (ptinfo) ptinfo->Release();      
    if (pCollection) delete pCollection;     
    return NULL; 
} 
 
STDMETHODIMP_(BSTR) 
CTypeLibrary::get_GUIDAsString()      
{ 
        if (m_pszGUID == NULL) 
            StringFromCLSID(m_guid, &m_pszGUID); 
    return SysAllocString(m_pszGUID); 
}