home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / mfc / ole / oleview / iviewers / tree.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-27  |  27.7 KB  |  1,082 lines

  1. // tree.cpp
  2. //
  3.  
  4. // This is a part of the Microsoft Foundation Classes C++ library.
  5. // Copyright (C) 1992-1998 Microsoft Corporation
  6. // All rights reserved.
  7. //
  8. // This source code is only intended as a supplement to the
  9. // Microsoft Foundation Classes Reference and related
  10. // electronic documentation provided with the library.
  11. // See these sources for detailed information regarding the
  12. // Microsoft Foundation Classes product.
  13.  
  14. #include "stdafx.h"
  15. #include "tree.h"
  16. #include "util.h"
  17.  
  18. #define MAX_NAMES   64
  19.  
  20. IMPLEMENT_DYNCREATE(CTreeItem, CObject)
  21. CTreeItem::CTreeItem(CTreeCtrl* pTree )
  22. {
  23.     ASSERT(pTree) ;
  24.     m_pTree = pTree ;
  25.     m_punk = NULL ;
  26.     m_Type = typeUnknown ;
  27.     m_uiMemid = 0 ;
  28. }
  29.  
  30. CTreeItem::~CTreeItem()
  31. {
  32.     if (m_punk )
  33.         m_punk->Release()  ;
  34. }
  35.  
  36. BOOL CTreeItem::Expand( HTREEITEM hitem )
  37. {
  38.     BOOL fExpand = FALSE ;
  39.  
  40.     switch(m_Type)
  41.     {
  42.     case typeUnknown:
  43.     case typeUnknown2:
  44.     break ;
  45.  
  46.     case typeTypeLib:
  47.         fExpand = ExpandTypeLib( hitem );
  48.     break ;
  49.  
  50.     case typeTypeLib2:
  51.     {
  52.         // CTypeLibWnd::m_fGroupByType == TRUE
  53.         CTreeItem* pItem ;
  54.  
  55.         TV_INSERTSTRUCT tvis ;
  56.         tvis.hParent = hitem ;
  57.         tvis.hInsertAfter = TVI_LAST ;
  58.         tvis.item.mask = TVIF_TEXT | TVIF_CHILDREN | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE ;
  59.         tvis.item.iImage = CTreeItem::typeUnknown ;
  60.         tvis.item.iSelectedImage = tvis.item.iImage + 1 ;
  61.         tvis.item.cChildren = 1 ;
  62.  
  63.         pItem = new CTreeItem(m_pTree) ;
  64.         pItem->SetTypeLib( GetTypeLib() ) ;
  65.         GetTypeLib()->AddRef() ;
  66.         pItem->m_Type = CTreeItem::typeEnums ;
  67.         tvis.item.lParam = (LPARAM)pItem ;
  68.         tvis.item.pszText = _T("Enums") ;
  69.         m_pTree->InsertItem(&tvis) ;
  70.  
  71.         pItem = new CTreeItem(m_pTree) ;
  72.         pItem->SetTypeLib( GetTypeLib() ) ;
  73.         GetTypeLib()->AddRef() ;
  74.         pItem->m_Type = CTreeItem::typeRecords ;
  75.         tvis.item.lParam = (LPARAM)pItem ;
  76.         tvis.item.pszText = _T("Structs") ;
  77.         m_pTree->InsertItem(&tvis) ;
  78.  
  79.         pItem = new CTreeItem(m_pTree) ;
  80.         pItem->SetTypeLib( GetTypeLib() ) ;
  81.         GetTypeLib()->AddRef() ;
  82.         pItem->m_Type = CTreeItem::typeModules ;
  83.         tvis.item.lParam = (LPARAM)pItem ;
  84.         tvis.item.pszText = _T("Modules") ;
  85.         m_pTree->InsertItem(&tvis) ;
  86.  
  87.         pItem = new CTreeItem(m_pTree) ;
  88.         pItem->SetTypeLib( GetTypeLib() ) ;
  89.         GetTypeLib()->AddRef() ;
  90.         pItem->m_Type = CTreeItem::typeInterfaces ;
  91.         tvis.item.lParam = (LPARAM)pItem ;
  92.         tvis.item.pszText = _T("Interfaces") ;
  93.         m_pTree->InsertItem(&tvis) ;
  94.  
  95.         pItem = new CTreeItem(m_pTree) ;
  96.         pItem->SetTypeLib( GetTypeLib() ) ;
  97.         GetTypeLib()->AddRef() ;
  98.         pItem->m_Type = CTreeItem::typeDispinterfaces ;
  99.         tvis.item.lParam = (LPARAM)pItem ;
  100.         tvis.item.pszText = _T("Dispinterfaces") ;
  101.         m_pTree->InsertItem(&tvis) ;
  102.  
  103.         pItem = new CTreeItem(m_pTree) ;
  104.         pItem->SetTypeLib( GetTypeLib() ) ;
  105.         GetTypeLib()->AddRef() ;
  106.         pItem->m_Type = CTreeItem::typeCoClasses ;
  107.         tvis.item.lParam = (LPARAM)pItem ;
  108.         tvis.item.pszText = _T("CoClasses") ;
  109.         m_pTree->InsertItem(&tvis) ;
  110.  
  111.         pItem = new CTreeItem(m_pTree) ;
  112.         pItem->SetTypeLib( GetTypeLib() ) ;
  113.         GetTypeLib()->AddRef() ;
  114.         pItem->m_Type = CTreeItem::typeAliases ;
  115.         tvis.item.lParam = (LPARAM)pItem ;
  116.         tvis.item.pszText = _T("Typedefs") ;
  117.         m_pTree->InsertItem(&tvis) ;
  118.  
  119.         pItem = new CTreeItem(m_pTree) ;
  120.         pItem->SetTypeLib( GetTypeLib() ) ;
  121.         GetTypeLib()->AddRef() ;
  122.         pItem->m_Type = CTreeItem::typeUnions ;
  123.         tvis.item.lParam = (LPARAM)pItem ;
  124.         tvis.item.pszText = _T("Unions") ;
  125.         m_pTree->InsertItem(&tvis) ;
  126.  
  127.         fExpand = TRUE ;
  128.     }
  129.     break ;
  130.  
  131.     case typeEnums:
  132.     case typeRecords:
  133.     case typeModules:
  134.     case typeInterfaces:
  135.     case typeDispinterfaces:
  136.     case typeCoClasses:
  137.     case typeAliases:
  138.     case typeUnions:
  139.         fExpand = ExpandTypeLib( hitem ) ;
  140.     break ;
  141.  
  142.     case typeTypeInfo:
  143.     case typeTypeInfo2:
  144.     case typeEnum:
  145.     case typeRecord:
  146.     case typeModule:
  147.     case typeInterface:
  148.     case typeDispinterface:
  149.     case typeCoClass:
  150.     case typeAlias:
  151.     case typeUnion:
  152.         fExpand = ExpandTypeInfo( hitem ) ;
  153.     break ;
  154.  
  155.     case typeMethods:
  156.     case typeMethods2:
  157.         fExpand = ExpandFuncs( hitem ) ;
  158.     break ;
  159.  
  160.     case typeProperties:
  161.     case typeProperties2:
  162.     case typeConstants:
  163.     case typeConstants2:
  164.         fExpand = ExpandVars( hitem ) ;
  165.     break ;
  166.  
  167.     case typeImplTypes:
  168.     case typeImplTypes2:
  169.         fExpand = ExpandImplTypes( hitem ) ;
  170.     break ;
  171.  
  172.     case typeMethod:
  173.     case typeProperty:
  174.     case typeConstant:
  175.     default:
  176.     break ;
  177.     }
  178.  
  179.     return fExpand ;
  180. }
  181.  
  182. BOOL CTreeItem::ExpandTypeLib( HTREEITEM hitem )
  183. {
  184.     ASSERT(hitem) ;
  185.     CTreeItem*  pNewItem = NULL ;
  186.  
  187.     UINT            uiTypeInfoCount = GetTypeLib()->GetTypeInfoCount() ;
  188.     HRESULT         hr = S_OK ;
  189.     TV_INSERTSTRUCT tvis ;
  190.     CString         strError = "Enumerating typeinfos";
  191.     TYPEATTR*       pattr = NULL ;
  192.     BOOL            fExpand = FALSE ;
  193.  
  194.     tvis.hParent = hitem  ;
  195.     tvis.hInsertAfter = TVI_LAST ;
  196.     tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN ;
  197.     tvis.item.cChildren = 1 ;
  198.     TRY
  199.     {
  200.         for (UINT n = 0 ; n < uiTypeInfoCount ; n++)
  201.         {
  202.             pNewItem = new CTreeItem( m_pTree ) ;
  203.             pNewItem->m_Type = typeTypeInfo ;
  204.             ASSERT(pNewItem) ;
  205.  
  206.             tvis.item.lParam = (LPARAM)pNewItem ;
  207.             hr = GetTypeLib()->GetTypeInfo( n, (ITypeInfo**)&pNewItem->m_punk ) ;
  208.             if (FAILED(hr))
  209.             {
  210.                 strError.Format(_T("Could not get TypeInfo #%u"), n ) ;
  211.                 AfxThrowOleException(hr) ;
  212.             }
  213.             ASSERT(pNewItem->m_punk) ;
  214.  
  215.             hr = pNewItem->GetTypeInfo()->GetTypeAttr(&pattr) ;
  216.             if FAILED(hr)
  217.             {
  218.                 strError.Format(_T("ITypeInfo::GetTypeAttr() failed") ) ;
  219.                 AfxThrowOleException(hr) ;
  220.             }
  221.  
  222.             if ((m_Type == typeTypeLib) ||
  223.                 (m_Type == (TypeKindToItemType(pattr->typekind) + 8)))
  224.             {
  225.                 tvis.item.iImage = pattr->typekind + typeEnum ;
  226.                 tvis.item.iSelectedImage = tvis.item.iImage ;
  227.                 CString sName;
  228.                 pNewItem->GetName(sName, TRUE );
  229.                 tvis.item.pszText = sName.GetBuffer(0);
  230.                 m_pTree->InsertItem( &tvis ) ;
  231.                 sName.ReleaseBuffer();
  232.                 pNewItem->GetTypeInfo()->ReleaseTypeAttr( pattr ) ;
  233.                 fExpand = TRUE ;
  234.             }
  235.             else
  236.             {
  237.                 pNewItem->GetTypeInfo()->ReleaseTypeAttr( pattr ) ;
  238.                 delete pNewItem ;
  239.             }
  240.        }
  241.     }
  242.     CATCH(CException, pException)
  243.     {
  244.         if (pException->IsKindOf(RUNTIME_CLASS(COleException)))
  245.             ErrorMessage( strError, ((COleException*)pException)->m_sc ) ;
  246.         else
  247.             ErrorMessage( strError, hr ) ;
  248.  
  249.         if (pNewItem)
  250.             delete pNewItem ;
  251.         return FALSE ;
  252.     }
  253.     END_CATCH
  254.  
  255.     return fExpand ;
  256. }
  257.  
  258.  
  259. BOOL CTreeItem::ExpandTypeInfo( HTREEITEM hitem )
  260. {
  261.     ASSERT(m_pTree) ;
  262.     ASSERT(hitem) ;
  263.  
  264.     CTreeItem*  pNewItem = NULL ;
  265.     HRESULT         hr = S_OK ;
  266.     TV_INSERTSTRUCT tvis ;
  267.     CString         strError = "Enumerating TypeInfo" ;
  268.     TYPEATTR*       pattr = NULL ;
  269.     ITypeInfo*      pti = GetTypeInfo() ;
  270.     ASSERT(pti) ;
  271.     BOOL            fExpand = FALSE ;
  272.  
  273.     tvis.hParent = hitem  ;
  274.     tvis.hInsertAfter = TVI_LAST ;
  275.     tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN ;
  276.     tvis.item.iImage = typeUnknown ;
  277.     tvis.item.iSelectedImage = tvis.item.iImage + 1 ;
  278.  
  279.     TRY
  280.     {
  281.         hr = pti->GetTypeAttr(&pattr) ;
  282.         if FAILED(hr)
  283.         {
  284.             strError.Format(_T("ITypeInfo::GetTypeAttr() failed"), hr ) ;
  285.             AfxThrowMemoryException() ;
  286.         }
  287.  
  288.         switch(pattr->typekind)
  289.         {
  290.         // typedef [attributes] enum [tag] {
  291.         //      enumlist
  292.         // } enumname;
  293.         //
  294.         // "typedef enum enumname"
  295.         case TKIND_ENUM:
  296.             fExpand = ExpandVars( hitem ) ;
  297.         break ;
  298.  
  299.         // typedef [attributes]
  300.         //  struct [tag] {
  301.         //      memberlist
  302.         //  } structname;
  303.         //
  304.         // "typedef struct structname"
  305.         case TKIND_RECORD:
  306.             fExpand = ExpandVars( hitem ) ;
  307.         break ;
  308.  
  309.         // [attributes]
  310.         //  module modulename {
  311.         //      elementlist
  312.         // };
  313.         case TKIND_MODULE:
  314.             if (pattr->cVars)
  315.             {
  316.                 // Add "Constants" folder
  317.                 //
  318.                 pNewItem = new CTreeItem(m_pTree) ;
  319.                 pNewItem->m_Type = typeProperties ;
  320.                 pNewItem->SetTypeInfo(pti) ;
  321.                 pti->AddRef() ;
  322.                 tvis.item.cChildren = pattr->cVars ;
  323.                 tvis.item.lParam = (LPARAM)pNewItem ;
  324.                 tvis.item.pszText = _T("Constants") ;
  325.                 tvis.item.iImage = typeConstants ;
  326.                 tvis.item.iSelectedImage = tvis.item.iImage + 1 ;
  327.                 m_pTree->InsertItem( &tvis ) ;
  328.                 fExpand = TRUE ;
  329.             }
  330.             if (pattr->cFuncs)
  331.             {
  332.                 pNewItem = new CTreeItem(m_pTree) ;
  333.                 pNewItem->m_Type = typeMethods ;
  334.                 pNewItem->SetTypeInfo(pti) ;
  335.                 pti->AddRef() ;
  336.                 tvis.item.cChildren = pattr->cFuncs ;
  337.                 tvis.item.lParam = (LPARAM)pNewItem ;
  338.                 tvis.item.pszText = _T("Functions") ;
  339.                 tvis.item.iImage = typeMethods ;
  340.                 tvis.item.iSelectedImage = tvis.item.iImage + 1 ;
  341.                 m_pTree->InsertItem( &tvis ) ;
  342.                 fExpand = TRUE ;
  343.             }
  344.         break ;
  345.  
  346.         // [attributes]
  347.         //  interface interfacename  [:baseinterface] {
  348.         //      functionlist
  349.         // };
  350.         case TKIND_INTERFACE:
  351.             fExpand = ExpandFuncs( hitem) ;
  352.             if (pattr->cImplTypes)
  353.             {
  354.                 pNewItem = new CTreeItem(m_pTree) ;
  355.                 pNewItem->m_Type = typeImplTypes ;
  356.                 pNewItem->SetTypeInfo(pti) ;
  357.                 pti->AddRef() ;
  358.                 tvis.item.pszText = _T("Inherited Interfaces") ;
  359.                 tvis.item.iImage = typeInterface ;
  360.                 tvis.item.cChildren = pattr->cImplTypes ;
  361.                 tvis.item.lParam = (LPARAM)pNewItem ;
  362.                 tvis.item.iSelectedImage = tvis.item.iImage ;
  363.                 m_pTree->InsertItem( &tvis ) ;
  364.                 fExpand = TRUE ;
  365.             }
  366.         break ;
  367.  
  368.         // [attributes]
  369.         //  dispinterface intfname {
  370.         //      interface interfacename
  371.         // };
  372.         case TKIND_DISPATCH :
  373.             if (pattr->cVars)
  374.             {
  375.                 // Add "Constants" folder
  376.                 //
  377.                 pNewItem = new CTreeItem(m_pTree) ;
  378.                 pNewItem->m_Type = typeConstants ;
  379.                 pNewItem->SetTypeInfo(pti) ;
  380.                 pti->AddRef() ;
  381.                 tvis.item.cChildren = pattr->cVars ;
  382.                 tvis.item.lParam = (LPARAM)pNewItem ;
  383.                 tvis.item.pszText = _T("Constants") ;
  384.                 tvis.item.iImage = typeConstants ;
  385.                 tvis.item.iSelectedImage = tvis.item.iImage + 1 ;
  386.                 m_pTree->InsertItem( &tvis ) ;
  387.  
  388.                 // Add "Properties" folder
  389.                 //
  390.                 pNewItem = new CTreeItem(m_pTree) ;
  391.                 pNewItem->m_Type = typeProperties ;
  392.                 pNewItem->SetTypeInfo(pti) ;
  393.                 pti->AddRef() ;
  394.                 tvis.item.cChildren = pattr->cVars ;
  395.                 tvis.item.lParam = (LPARAM)pNewItem ;
  396.                 tvis.item.pszText = _T("Properties") ;
  397.                 tvis.item.iImage = typeProperties ;
  398.                 tvis.item.iSelectedImage = tvis.item.iImage + 1 ;
  399.                 m_pTree->InsertItem( &tvis ) ;
  400.                 fExpand = TRUE ;
  401.              }
  402.             if (pattr->cFuncs)
  403.             {
  404.                 pNewItem = new CTreeItem(m_pTree) ;
  405.                 pNewItem->m_Type = typeMethods ;
  406.                 pNewItem->SetTypeInfo(pti) ;
  407.                 pti->AddRef() ;
  408.                 tvis.item.cChildren = pattr->cFuncs ;
  409.                 tvis.item.lParam = (LPARAM)pNewItem ;
  410.                 tvis.item.pszText = _T("Methods") ;
  411.                 tvis.item.iImage = typeMethods ;
  412.                 tvis.item.iSelectedImage = tvis.item.iImage + 1 ;
  413.                 m_pTree->InsertItem( &tvis ) ;
  414.                 fExpand = TRUE ;
  415.             }
  416.             if (pattr->cImplTypes)
  417.             {
  418.                 pNewItem = new CTreeItem(m_pTree) ;
  419.                 pNewItem->m_Type = typeImplTypes ;
  420.                 pNewItem->SetTypeInfo(pti) ;
  421.                 pti->AddRef() ;
  422.                 tvis.item.pszText = _T("Inherited Interfaces") ;
  423.                 tvis.item.iImage = typeInterface ;
  424.                 tvis.item.cChildren = pattr->cImplTypes ;
  425.                 tvis.item.lParam = (LPARAM)pNewItem ;
  426.                 tvis.item.iSelectedImage = tvis.item.iImage ;
  427.                 m_pTree->InsertItem( &tvis ) ;
  428.                 fExpand = TRUE ;
  429.             }
  430.         break ;
  431.  
  432.         // [attributes]
  433.         //  coclass classname {
  434.         //      [attributes2] [interface | dispinterface] interfacename;
  435.         //      ...
  436.         // };
  437.         case TKIND_COCLASS:
  438.             fExpand = ExpandImplTypes( hitem ) ;
  439.         break ;
  440.  
  441.         // typedef [attributes] basetype aliasname;
  442.         case TKIND_ALIAS:
  443.             if (pattr->tdescAlias.vt == VT_USERDEFINED)
  444.             {
  445.                 ITypeInfo* ptiRefType = NULL ;
  446.                 HRESULT hr = pti->GetRefTypeInfo( pattr->tdescAlias.hreftype, &ptiRefType ) ;
  447.                 if (FAILED(hr))
  448.                     AfxThrowOleException( hr ) ;
  449.  
  450.                 CTreeItem* pNewItem = new CTreeItem(m_pTree) ;
  451.                 pNewItem->SetTypeInfo( ptiRefType ) ;
  452.                 pNewItem->m_Type = TypeKindToItemType( pNewItem->GetTypeKind() ) ;
  453.                 tvis.item.iImage = TypeKindToItemType( pNewItem->GetTypeKind() ) ;
  454.                 tvis.item.cChildren = 1 ;
  455.                 tvis.item.lParam = (LPARAM)pNewItem ;
  456.                 tvis.item.iSelectedImage = tvis.item.iImage ;
  457.                 CString sName;
  458.                 pNewItem->GetName(sName, TRUE );
  459.                 tvis.item.pszText = sName.GetBuffer(0) ;
  460.                 m_pTree->InsertItem( &tvis ) ;
  461.                 sName.ReleaseBuffer();
  462.                 fExpand = TRUE ;
  463.             }
  464.         break ;
  465.  
  466.         // typedef [attributes] union [tag] {
  467.         //      memberlist
  468.         // } unionname;
  469.         case TKIND_UNION:
  470.             fExpand = ExpandVars( hitem ) ;
  471.         break ;
  472.  
  473.         default:
  474.         break ;
  475.         }
  476.  
  477.         if (pattr)
  478.             pti->ReleaseTypeAttr( pattr ) ;
  479.     }
  480.     CATCH(CException, pException)
  481.     {
  482.         ErrorMessage( strError, hr ) ;
  483.         if (pNewItem)
  484.             delete pNewItem ;
  485.  
  486.         if (pattr)
  487.             pti->ReleaseTypeAttr( pattr ) ;
  488.  
  489.         return FALSE ;
  490.     }
  491.     END_CATCH
  492.     return fExpand ;
  493. }
  494.  
  495. BOOL CTreeItem::ExpandFuncs( HTREEITEM hitem )
  496. {
  497.     ASSERT(hitem) ;
  498.  
  499.     CTreeItem*  pNewItem = NULL ;
  500.     HRESULT         hr = S_OK ;
  501.     TV_INSERTSTRUCT tvis ;
  502.     CString         strError ;
  503.     TYPEATTR*       pattr = NULL ;
  504.     ITypeInfo*      pti = GetTypeInfo() ;
  505.     ASSERT(pti) ;
  506.     FUNCDESC*       pfuncdesc = NULL ;
  507.     BSTR            bstrParams = NULL ;
  508.     BOOL            fExpand = FALSE ;
  509.  
  510.     tvis.hParent = hitem  ;
  511.     tvis.hInsertAfter = TVI_LAST ;
  512.     tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN ;
  513.  
  514.     TRY
  515.     {
  516.         hr = pti->GetTypeAttr(&pattr) ;
  517.         if FAILED(hr)
  518.         {
  519.             strError.Format(_T("ITypeInfo::GetTypeAttr() failed: %x"), hr);
  520.             AfxThrowMemoryException() ;
  521.         }
  522.  
  523.         BSTR  rgbstrNames[MAX_NAMES] ;
  524.         int   cNames ;
  525.  
  526.         //
  527.         // Enumerate through all FUNCDESCS
  528.         for ( int iIndex = 0 ; iIndex < pattr->cFuncs ; iIndex++)
  529.         {
  530.             hr = pti->GetFuncDesc( iIndex, &pfuncdesc ) ;
  531.             if (FAILED(hr))
  532.             {
  533.                 strError.Format(_T("GetVarDesc failed for function #%u"), iIndex) ;
  534.                 AfxThrowMemoryException() ;
  535.             }
  536.  
  537.             //int cParams = pfuncdesc->cParams ;
  538.             //int cParamsOpt = abs(pfuncdesc->cParamsOpt) ;
  539.  
  540.             // Get the names of the function and it's parameters into rgbstrNames.
  541.             // cNames gets the number of parameters + 1.
  542.             //
  543.             hr = pti->GetNames( pfuncdesc->memid, rgbstrNames, 1, (UINT*)&cNames) ; //MAX_NAMES, (UINT FAR*)&cNames );
  544.             if (FAILED(hr))
  545.             {
  546.                 strError.Format(_T("GetNames failed for function #%u"), iIndex) ;
  547.                 AfxThrowMemoryException() ;
  548.             }
  549.  
  550.             // rgbstrNames[0] is the name of the function
  551.             if (cNames > 0)
  552.             {
  553.                 USES_CONVERSION;
  554.                 pNewItem = new CTreeItem(m_pTree) ;
  555.                 pNewItem->SetTypeInfo(pti) ;
  556.                 pti->AddRef() ;
  557.                 pNewItem->m_Type = typeMethod ;
  558.                 pNewItem->m_uiMemid = iIndex ;
  559.                 tvis.item.lParam = (LPARAM)pNewItem ;
  560.                 tvis.item.iImage = typeMethod ;
  561.                 tvis.item.iSelectedImage = tvis.item.iImage ;
  562.                 tvis.item.cChildren = 0 ;
  563.                 LPTSTR lpszText = OLE2T(rgbstrNames[0]);
  564.                 tvis.item.pszText = lpszText;
  565.                 m_pTree->InsertItem( &tvis ) ;
  566.                 SysFreeString( rgbstrNames[0] ) ;
  567.             }
  568.  
  569.             SysFreeString( bstrParams ) ;
  570.  
  571.             pti->ReleaseFuncDesc( pfuncdesc ) ;
  572.             fExpand = TRUE ;
  573.         }
  574.         if (pattr)
  575.             pti->ReleaseTypeAttr( pattr ) ;
  576.     }
  577.     CATCH(CException, pException)
  578.     {
  579.         ErrorMessage( strError, hr ) ;
  580.         if (pNewItem)
  581.             delete pNewItem ;
  582.  
  583.         if (pattr)
  584.             pti->ReleaseTypeAttr( pattr ) ;
  585.  
  586.         if (pfuncdesc)
  587.             pti->ReleaseFuncDesc( pfuncdesc ) ;
  588.  
  589.         if (bstrParams)
  590.             SysFreeString(bstrParams) ;
  591.  
  592.         return FALSE ;
  593.     }
  594.     END_CATCH
  595.     return fExpand ;
  596. }
  597.  
  598. BOOL CTreeItem::ExpandVars( HTREEITEM hitem )
  599. {
  600.     USES_CONVERSION;
  601.     ASSERT(hitem) ;
  602.     CTreeItem*  pNewItem = NULL ;
  603.     HRESULT         hr = S_OK ;
  604.     TV_INSERTSTRUCT tvis ;
  605.     CString         strError ;
  606.     TYPEATTR*       pattr = NULL ;
  607.     ITypeInfo*      pti = GetTypeInfo() ;
  608.     ASSERT(pti) ;
  609.     LPVARDESC pvardesc = NULL ;
  610.     BSTR            rgbstrNames[MAX_NAMES] ;
  611.     int             cNames ;
  612.     BOOL            fProperties = FALSE ;
  613.     BOOL            fExpand = FALSE ;
  614.     tvis.hParent = hitem  ;
  615.     tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN ;
  616.     tvis.item.cChildren = 0 ;
  617.  
  618.     TRY
  619.     {
  620.         hr = pti->GetTypeAttr(&pattr) ;
  621.         if FAILED(hr)
  622.         {
  623.             strError.Format(_T("ITypeInfo::GetTypeAttr() failed"), hr ) ;
  624.             AfxThrowMemoryException() ;
  625.         }
  626.  
  627.         // if it's a struct or an enum, order is important
  628.         //
  629.         if (pattr->typekind == TKIND_RECORD || pattr->typekind == TKIND_ENUM || pattr->typekind == TKIND_UNION)
  630.             tvis.hInsertAfter = TVI_LAST ;
  631.         else
  632.         {
  633.             tvis.hInsertAfter = TVI_LAST ;
  634.  
  635.             // are we doing constants or properties?
  636.             TV_ITEM tvi ;
  637.             TCHAR szBuf[80] ;
  638.             tvi.hItem = hitem ;
  639.             tvi.mask = TVIF_TEXT ;
  640.             tvi.cchTextMax = 80 ;
  641.             tvi.pszText = szBuf ;
  642.             m_pTree->GetItem(&tvi) ;
  643.             if (lstrcmpi(tvi.pszText, _T("Properties")) == 0)
  644.                 fProperties = TRUE ;
  645.         }
  646.  
  647.         for (int iIndex = 0 ; iIndex < pattr->cVars ; iIndex++)
  648.         {
  649.             hr = pti->GetVarDesc( iIndex, &pvardesc ) ;
  650.             if (FAILED(hr))
  651.             {
  652.                 strError.Format(_T("GetVarDesc failed for variable #%u"), iIndex) ;
  653.                 AfxThrowMemoryException() ;
  654.             }
  655.             hr = pti->GetNames( pvardesc->memid, rgbstrNames, 1, (UINT FAR*)&cNames );
  656.             if (FAILED(hr))
  657.             {
  658.                 strError.Format(_T("GetNames failed for variable #%u"), iIndex) ;
  659.                 AfxThrowMemoryException() ;
  660.             }
  661.             if (pvardesc->varkind == VAR_CONST && fProperties == FALSE)
  662.             {
  663.                 CString str = TYPEDESCtoString( &pvardesc->elemdescVar.tdesc ) ;
  664.  
  665.                 VARIANT varValue ;
  666.                 VariantInit( &varValue ) ;
  667.                 if (FAILED(hr = VariantChangeType( &varValue, pvardesc->lpvarValue, 0, VT_BSTR )))
  668.                 {
  669.                     if (pvardesc->lpvarValue->vt == VT_ERROR || pvardesc->lpvarValue->vt == VT_HRESULT)
  670.                     {
  671.                         varValue.vt = VT_BSTR ;
  672.                         varValue.bstrVal = SysAllocString(T2OLE(_GetScodeString(pvardesc->lpvarValue->scode))) ;
  673.                         hr = S_OK ;
  674.                     }
  675.                     else
  676.                         AfxThrowOleException( hr ) ;
  677.                 }
  678.  
  679.                 // const type name = expression
  680.                 UINT len = SysStringLen( varValue.bstrVal ) ;
  681.                 LPTSTR lpszSource = OLE2T(varValue.bstrVal);
  682.                 TCHAR* pstrExpand = new TCHAR[(len+1) * sizeof(TCHAR) * 2] ;
  683.                 LPTSTR lpD, lpS = lpszSource ;
  684.                 lpD = pstrExpand;
  685.                 for (UINT n = 0 ; n < len ; n++)
  686.                 {
  687.                     if (!isprint(*lpS) || (*lpS) == '\"' || (*lpS) == '\\')
  688.                     {
  689.                         // \"  \\ \a  \b  \f  \n  \r  \t  \v
  690.                         *lpD++ = '\\' ;
  691.                         switch(*lpS)
  692.                         {
  693.                         case '\"':
  694.                             *lpD++ = '\"' ;
  695.                         break ;
  696.                         case '\\':
  697.                             *lpD++ = '\\' ;
  698.                         break ;
  699.                         case '\a':
  700.                             *lpD++ = 'a' ;
  701.                         break ;
  702.                         case '\b':
  703.                             *lpD++ = 'b' ;
  704.                         break ;
  705.                         case '\f':
  706.                             *lpD++ = 'f' ;
  707.                         break ;
  708.                         case '\n':
  709.                             *lpD++ = 'n' ;
  710.                         break ;
  711.                         case '\r':
  712.                             *lpD++ = 'r' ;
  713.                         break ;
  714.                         case '\t':
  715.                             *lpD++ = 't' ;
  716.                         break ;
  717.                         case '\v':
  718.                             *lpD++ = 'v' ;
  719.                         break ;
  720.                         case '\0':
  721.                             *lpD++ = '0' ;
  722.                         break ;
  723.                         default:
  724.                             lpD += wsprintf( lpD, _T("x%02X"), (UINT)*lpS );
  725.                         break ;
  726.                         }
  727.                         lpS++;
  728.                     }
  729.                     else
  730.                         *lpD++ = *lpS++;
  731.                 }
  732.                 *lpD = '\0';
  733.  
  734.                 if (pvardesc->lpvarValue->vt == VT_BSTR)
  735.                     strError.Format(_T("const %s %s = \"%s\""), (LPCTSTR)str, OLE2CT(rgbstrNames[0]), pstrExpand) ;
  736.                 else
  737.                     strError.Format(_T("const %s %s = %s"), (LPCTSTR)str, OLE2CT(rgbstrNames[0]), pstrExpand);
  738.                 delete []pstrExpand ;
  739.                 VariantClear( &varValue ) ;
  740.                 tvis.item.iImage = typeConstant ;
  741.                 tvis.item.iSelectedImage = tvis.item.iImage ;
  742.                 pNewItem = new CTreeItem(m_pTree) ;
  743.                 pNewItem->SetTypeInfo(pti) ;
  744.                 pti->AddRef() ;
  745.                 pNewItem->m_Type = typeConstant ;
  746.                 pNewItem->m_uiMemid = iIndex ;
  747.                 tvis.item.lParam = (LPARAM)pNewItem ;
  748.                 tvis.item.pszText = strError.GetBuffer(0) ;
  749.                 m_pTree->InsertItem( &tvis ) ;
  750.                 strError.ReleaseBuffer(-1) ;
  751.                 fExpand = TRUE ;
  752.             }
  753.             else if (fProperties == TRUE ||
  754.                     (pattr->typekind == TKIND_RECORD ||
  755.                      pattr->typekind == TKIND_UNION  ))
  756.             {
  757.                 CString str ;
  758.                 static TCHAR szNameless[] = _T("(nameless)");
  759.                 if ((pvardesc->elemdescVar.tdesc.vt & 0x0FFF) == VT_CARRAY)
  760.                 {
  761.                     // type name[n]
  762.                     strError.Format(_T("%s "), TYPEDESCtoString( &pvardesc->elemdescVar.tdesc.lpadesc->tdescElem) );
  763.                     if (rgbstrNames[0])
  764.                         strError += OLE2CT(rgbstrNames[0]);
  765.                     else
  766.                         strError += szNameless;
  767.                     // Allocate cDims * lstrlen("[123456]")
  768.                     for (USHORT n = 0 ; n < pvardesc->elemdescVar.tdesc.lpadesc->cDims ; n++)
  769.                     {
  770.                         str.Format( _T("[%d]"), pvardesc->elemdescVar.tdesc.lpadesc->rgbounds[n].cElements ) ;
  771.                         strError += str ;
  772.                     }
  773.                 }
  774.                 else
  775.                 {
  776.                     // type name
  777.                     strError.Format(_T("%s "),strError = TYPEDESCtoString( &pvardesc->elemdescVar.tdesc ));
  778.                     if (rgbstrNames[0])
  779.                         strError += OLE2CT(rgbstrNames[0]);
  780.                     else
  781.                         strError += szNameless;
  782.                 }
  783.                 tvis.item.iImage = typeProperty ;
  784.                 tvis.item.iSelectedImage = tvis.item.iImage ;
  785.                 pNewItem = new CTreeItem(m_pTree) ;
  786.                 pNewItem->SetTypeInfo(pti) ;
  787.                 pti->AddRef() ;
  788.                 pNewItem->m_Type = typeProperty ;
  789.                 pNewItem->m_uiMemid = iIndex ;
  790.                 tvis.item.lParam = (LPARAM)pNewItem ;
  791.                 tvis.item.pszText = strError.GetBuffer(0) ;
  792.                 m_pTree->InsertItem( &tvis ) ;
  793.                 strError.ReleaseBuffer(-1) ;
  794.                 fExpand = TRUE ;
  795.             }
  796.             SysFreeString( rgbstrNames[0] ) ;
  797.             pti->ReleaseVarDesc( pvardesc ) ;
  798.         }
  799.  
  800.         if (pattr)
  801.             pti->ReleaseTypeAttr( pattr ) ;
  802.     }
  803.     CATCH(CException, pException)
  804.     {
  805.         ErrorMessage( strError, hr ) ;
  806.         if (pNewItem)
  807.             delete pNewItem ;
  808.  
  809.         if (pattr)
  810.             pti->ReleaseTypeAttr( pattr ) ;
  811.  
  812.         if (pvardesc)
  813.             pti->ReleaseVarDesc( pvardesc ) ;
  814.  
  815.         return FALSE ;
  816.     }
  817.     END_CATCH
  818.     return fExpand ;
  819. }
  820.  
  821. BOOL CTreeItem::ExpandImplTypes( HTREEITEM hitem )
  822. {
  823.     ASSERT(hitem) ;
  824.  
  825.     USES_CONVERSION;
  826.     BOOL fExpand = FALSE ;
  827.     CTreeItem*  pNewItem = NULL ;
  828.     HRESULT         hr = S_OK ;
  829.     BSTR            bstrName = NULL ;
  830.     BSTR            bstrDoc = NULL ;
  831.     BSTR            bstrHelp = NULL ;
  832.     DWORD           dwHelpID ;
  833.     TV_INSERTSTRUCT tvis ;
  834.     CString         strError ;
  835.     TYPEATTR*       pattr = NULL ;
  836.     ITypeInfo*      pti = GetTypeInfo() ;
  837.  
  838.     tvis.hParent = hitem  ;
  839.     tvis.hInsertAfter = TVI_LAST ;
  840.     tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN ;
  841.     tvis.item.cChildren = 1 ;
  842.     TRY
  843.     {
  844.         hr = pti->GetTypeAttr(&pattr) ;
  845.         if FAILED(hr)
  846.         {
  847.             strError.Format(_T("ITypeInfo::GetTypeAttr() failed"), hr ) ;
  848.             AfxThrowMemoryException() ;
  849.         }
  850.  
  851.         for (UINT n = 0 ; n <  pattr->cImplTypes; n++)
  852.         {
  853.             pNewItem = new CTreeItem( m_pTree ) ;
  854.             pNewItem->m_uiMemid = n ;
  855.             ASSERT(pNewItem) ;
  856.  
  857.             tvis.item.lParam = (LPARAM)pNewItem ;
  858.             HREFTYPE href = NULL ;
  859.             hr = pti->GetRefTypeOfImplType(n, &href) ;
  860.             if (FAILED(hr))
  861.             {
  862.                 strError.Format(_T("Could not get RefTypeOfImplType #%u"), n ) ;
  863.                 AfxThrowMemoryException() ;
  864.             }
  865.             hr = pti->GetRefTypeInfo( href, (ITypeInfo**)&pNewItem->m_punk ) ;
  866.             if (FAILED(hr))
  867.             {
  868.                 strError.Format(_T("Could not get RefTypeInfo") ) ;
  869.                 AfxThrowMemoryException() ;
  870.             }
  871.  
  872.             ASSERT(pNewItem->m_punk) ;
  873.  
  874.             TYPEATTR* pattrNew ;
  875.             hr = pNewItem->GetTypeInfo()->GetTypeAttr(&pattrNew) ;
  876.             if FAILED(hr)
  877.             {
  878.                 strError.Format(_T("ITypeInfo::GetTypeAttr() failed") ) ;
  879.                 AfxThrowMemoryException() ;
  880.             }
  881.             pNewItem->m_Type = TypeKindToItemType( pNewItem->GetTypeKind() ) ;
  882.             tvis.item.iImage = TypeKindToItemType( pNewItem->GetTypeKind() ) ;
  883.             tvis.item.iSelectedImage = tvis.item.iImage ;
  884.             pNewItem->GetTypeInfo()->ReleaseTypeAttr( pattrNew ) ;
  885.  
  886.             hr = pNewItem->GetTypeInfo()->GetDocumentation( MEMBERID_NIL, &bstrName, &bstrDoc, &dwHelpID, &bstrHelp ) ;
  887.             if (FAILED(hr))
  888.             {
  889.                 strError.Format(_T("ITypeInfo::GetDocumentation() failed")) ;
  890.                 AfxThrowMemoryException() ;
  891.             }
  892.             LPTSTR lpszName = OLE2T(bstrName);
  893.             tvis.item.pszText = lpszName  ;
  894.             m_pTree->InsertItem( &tvis ) ;
  895.  
  896.             SysFreeString( bstrName ) ;
  897.             bstrName = NULL ;
  898.             SysFreeString( bstrDoc ) ;
  899.             bstrDoc = NULL ;
  900.             SysFreeString( bstrHelp ) ;
  901.             bstrHelp = NULL ;
  902.  
  903.             fExpand = TRUE ;
  904.         }
  905.     }
  906.     CATCH(CException, pException)
  907.     {
  908.         ErrorMessage( strError, hr ) ;
  909.         if (pNewItem)
  910.             delete pNewItem ;
  911.         if (bstrName)
  912.             SysFreeString( bstrName ) ;
  913.         if (bstrDoc)
  914.             SysFreeString( bstrDoc ) ;
  915.         if (bstrHelp)
  916.             SysFreeString( bstrHelp ) ;
  917.         return FALSE ;
  918.     }
  919.     END_CATCH
  920.  
  921.     if (pti && pattr)
  922.         pti->ReleaseTypeAttr( pattr );
  923.     return fExpand ;
  924. }
  925.  
  926. CString CTreeItem::TYPEDESCtoString( TYPEDESC* ptdesc )
  927. {
  928.     ASSERT(GetTypeInfo()) ;
  929.     return ::TYPEDESCtoString( GetTypeInfo(), ptdesc ) ;
  930. }
  931.  
  932. void CTreeItem::GetName(CString& szReturn, BOOL fIDLStyle /*= FALSE*/)
  933. {
  934.     BSTR    bstrName = NULL ;
  935.     BSTR    bstrDoc = NULL ;
  936.     BSTR    bstrHelp = NULL ;
  937.     DWORD   dwHelpID ;
  938.     HRESULT hr ;
  939.  
  940.     TRY
  941.     {
  942.         hr = GetTypeInfo()->GetDocumentation( MEMBERID_NIL, &bstrName, &bstrDoc, &dwHelpID, &bstrHelp ) ;
  943.         if (FAILED(hr))
  944.             AfxThrowOleException( hr ) ;
  945.  
  946.         SysFreeString( bstrDoc ) ;
  947.         bstrDoc = NULL ;
  948.         SysFreeString( bstrHelp ) ;
  949.         bstrHelp = NULL ;
  950.         USES_CONVERSION;
  951.         LPCTSTR lpszName = OLE2CT(bstrName);
  952.         ::SysFreeString(bstrName);
  953.         bstrName = NULL;
  954.         if (fIDLStyle)
  955.         {
  956.             TYPEATTR* pattr ;
  957.             hr = GetTypeInfo()->GetTypeAttr(&pattr) ;
  958.             if FAILED(hr)
  959.                 AfxThrowOleException(hr) ;
  960.  
  961.             switch(pattr->typekind)
  962.             {
  963.             // typedef [attributes] enum [tag] {
  964.             //      enumlist
  965.             // } enumname;
  966.             //
  967.             // "typedef enum enumname"
  968.             case TKIND_ENUM:
  969.                 szReturn.Format(_T("typedef enum %s"), lpszName ) ;
  970.             break ;
  971.  
  972.             // typedef [attributes]
  973.             //  struct [tag] {
  974.             //      memberlist
  975.             //  } structname;
  976.             //
  977.             // "typedef struct structname"
  978.             case TKIND_RECORD:
  979.                 szReturn.Format(_T("typedef struct %s"), lpszName ) ;
  980.             break ;
  981.  
  982.             // [attributes]
  983.             //  module modulename {
  984.             //      elementlist
  985.             // };
  986.             case TKIND_MODULE:
  987.                 szReturn.Format(_T("module %s"), lpszName ) ;
  988.             break ;
  989.  
  990.             // [attributes]
  991.             //  interface interfacename  [:baseinterface] {
  992.             //      functionlist
  993.             // };
  994.             case TKIND_INTERFACE:
  995.                 // TODO:  enum base interfaces and append
  996.                 szReturn.Format(_T("interface %s"), lpszName ) ;
  997.             break ;
  998.  
  999.             // [attributes]
  1000.             //  dispinterface intfname {
  1001.             //      interface interfacename
  1002.             // };
  1003.             case TKIND_DISPATCH :
  1004.                 szReturn.Format(_T("dispinterface %s"), lpszName ) ;
  1005.             break ;
  1006.  
  1007.             // [attributes]
  1008.             //  coclass classname {
  1009.             //      [attributes2] [interface | dispinterface] interfacename;
  1010.             //      ...
  1011.             // };
  1012.             case TKIND_COCLASS:
  1013.                 szReturn.Format(_T("coclass %s"), lpszName ) ;
  1014.             break ;
  1015.  
  1016.             // typedef [attributes] basetype aliasname;
  1017.             case TKIND_ALIAS:
  1018.                 szReturn.Format(_T("typedef %s %s"),
  1019.                     ::TYPEDESCtoString(GetTypeInfo(), &pattr->tdescAlias), lpszName);
  1020.             break ;
  1021.  
  1022.             // typedef [attributes] union [tag] {
  1023.             //      memberlist
  1024.             // } unionname;
  1025.             case TKIND_UNION:
  1026.                 szReturn.Format(_T("typedef union %s"), lpszName ) ;
  1027.             break ;
  1028.  
  1029.             default:
  1030.             break ;
  1031.             }
  1032.             GetTypeInfo()->ReleaseTypeAttr( pattr ) ;
  1033.         }
  1034.     }
  1035.     CATCH(CException, pException)
  1036.     {
  1037.         if (bstrName)
  1038.             SysFreeString( bstrName ) ;
  1039.         if (bstrDoc)
  1040.             SysFreeString( bstrDoc ) ;
  1041.         if (bstrHelp)
  1042.             SysFreeString( bstrHelp ) ;
  1043.         THROW_LAST();
  1044.     }
  1045.     END_CATCH
  1046.  
  1047. }
  1048.  
  1049. TYPEKIND CTreeItem::GetTypeKind()
  1050. {
  1051.     TYPEATTR* pattr ;
  1052.     TYPEKIND kind ;
  1053.  
  1054.     HRESULT hr = GetTypeInfo()->GetTypeAttr(&pattr) ;
  1055.     if FAILED(hr)
  1056.         AfxThrowOleException(hr) ;
  1057.     kind = pattr->typekind ;
  1058.     GetTypeInfo()->ReleaseTypeAttr(pattr) ;
  1059.  
  1060.     return kind ;
  1061. }
  1062.  
  1063. CTreeItem::ITEM_TYPE CTreeItem::TypeKindToItemType( TYPEKIND tkind )
  1064. {
  1065.     ITEM_TYPE t ;
  1066.  
  1067.     switch(tkind)
  1068.     {
  1069.     case TKIND_ENUM:        t = typeEnum ; break ;
  1070.     case TKIND_RECORD:      t = typeRecord ; break ;
  1071.     case TKIND_MODULE:      t = typeModule ;break ;
  1072.     case TKIND_INTERFACE:   t = typeInterface ;break ;
  1073.     case TKIND_DISPATCH :   t = typeDispinterface ; break ;
  1074.     case TKIND_COCLASS:     t = typeCoClass ; break ;
  1075.     case TKIND_ALIAS:       t = typeAlias ; break ;
  1076.     case TKIND_UNION:       t = typeUnion ; break ;
  1077.     default:                t = typeUnknown ; break ;
  1078.     }
  1079.  
  1080.     return t ;
  1081. }
  1082.