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 / tlbodl.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-27  |  52.2 KB  |  2,206 lines

  1. // tlbodl.cpp : implementation file
  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 "iviewers.h"
  16. #include "iview.h"
  17. #include "util.h"
  18. #include "iviewers.h"
  19. #include "iviewer.h"
  20. #include "typelib.h"
  21. #include "tree.h"
  22. #include "tlbodl.h"
  23.  
  24. #ifdef _DEBUG
  25. #undef THIS_FILE
  26. static char BASED_CODE THIS_FILE[] = __FILE__;
  27. #endif
  28.  
  29. #define MAX_NAMES   64     // max parameters to a function
  30.  
  31. IStream* CreateMemoryStream();
  32. int StringFromGUID2T(REFGUID rguid, LPTSTR lpszGUID, int cbMax);
  33.  
  34. // if defined, when typedefs are written out a tag is created
  35. // by concatinating "tag" with the typedef name.
  36. #define _WRITE_TAG 1
  37.  
  38. /////////////////////////////////////////////////////////////////////////////
  39. // CTypeLibODLView
  40.  
  41. IMPLEMENT_DYNCREATE(CTypeLibODLView, CEditView)
  42.  
  43. CTypeLibODLView::CTypeLibODLView()
  44. {
  45. }
  46.  
  47. CTypeLibODLView::~CTypeLibODLView()
  48. {
  49. }
  50.  
  51.  
  52. BEGIN_MESSAGE_MAP(CTypeLibODLView, CEditView)
  53.     //{{AFX_MSG_MAP(CTypeLibODLView)
  54.     ON_WM_DESTROY()
  55.     //}}AFX_MSG_MAP
  56. END_MESSAGE_MAP()
  57.  
  58.  
  59. /////////////////////////////////////////////////////////////////////////////
  60. // CTypeLibODLView drawing
  61.  
  62. void CTypeLibODLView::OnDraw(CDC* pDC)
  63. {
  64. }
  65.  
  66. /////////////////////////////////////////////////////////////////////////////
  67. // CTypeLibODLView diagnostics
  68.  
  69. #ifdef _DEBUG
  70. void CTypeLibODLView::AssertValid() const
  71. {
  72.     CEditView::AssertValid();
  73. }
  74.  
  75. void CTypeLibODLView::Dump(CDumpContext& dc) const
  76. {
  77.     CEditView::Dump(dc);
  78. }
  79. #endif //_DEBUG
  80.  
  81. /////////////////////////////////////////////////////////////////////////////
  82. // CTypeLibODLView message handlers
  83.  
  84. BOOL CTypeLibODLView::PreCreateWindow(CREATESTRUCT& cs)
  85. {
  86.     cs.style |= ES_READONLY | ES_MULTILINE | WS_VSCROLL | WS_HSCROLL ;
  87.  
  88.     return CEditView::PreCreateWindow(cs);
  89. }
  90.  
  91. void CTypeLibODLView::OnInitialUpdate()
  92. {
  93.     m_Font.CreateFont( -11, 0, 0, 0, 0, 0,
  94.                 0, 0, ANSI_CHARSET, 0, 0, 0,
  95.                 FIXED_PITCH | FF_DONTCARE, _T("Courier New") ) ;
  96.  
  97.     SetFont( &m_Font );
  98.     CEditView::OnInitialUpdate();
  99. }
  100.  
  101. void CTypeLibODLView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
  102. {
  103.     CTypeLibWnd* pFrame = (CTypeLibWnd*)GetParent()->GetParent() ;
  104.     ASSERT(pFrame->IsKindOf(RUNTIME_CLASS(CTypeLibWnd)));
  105.  
  106.     if (pFrame->m_pSelectedItem == NULL)
  107.     {
  108.         SetWindowText(_T("")) ;
  109.         return ;
  110.     }
  111.  
  112.     SetRedraw( FALSE ) ;
  113.     BeginWaitCursor() ;
  114.  
  115.     CString     sText;
  116.     HRESULT     hr = S_OK ;
  117.     IStream*    pstm = NULL ;
  118.  
  119.     TRY
  120.     {
  121.         pstm = CreateMemoryStream() ;
  122.  
  123.         switch(pFrame->m_pSelectedItem->m_Type)
  124.         {
  125.         case CTreeItem::typeTypeLib:
  126.         case CTreeItem::typeTypeLib2:
  127.              hr = DeCompileTypeLib( pstm, pFrame->m_pSelectedItem->GetTypeLib() ) ;
  128.         break ;
  129.  
  130.         case CTreeItem::typeEnum:
  131.         case CTreeItem::typeRecord:
  132.         case CTreeItem::typeModule:
  133.         case CTreeItem::typeInterface:
  134.         case CTreeItem::typeDispinterface:
  135.         case CTreeItem::typeCoClass:
  136.         case CTreeItem::typeAlias:
  137.         case CTreeItem::typeUnion:
  138.         case CTreeItem::typeTypeInfo:
  139.         case CTreeItem::typeTypeInfo2:
  140.             switch(pFrame->m_pSelectedItem->GetTypeKind())
  141.             {
  142.             case TKIND_ENUM:
  143.             case TKIND_RECORD:
  144.             case TKIND_UNION:
  145.             case TKIND_ALIAS:
  146.                  hr = DeCompileTypedef( pstm, pFrame->m_pSelectedItem->GetTypeInfo() ) ;
  147.             break ;
  148.  
  149.             case TKIND_MODULE:
  150.                  hr = DeCompileModule( pstm, pFrame->m_pSelectedItem->GetTypeInfo() ) ;
  151.             break ;
  152.  
  153.             case TKIND_INTERFACE:
  154.                  hr = DeCompileInterface( pstm, pFrame->m_pSelectedItem->GetTypeInfo() ) ;
  155.             break ;
  156.  
  157.             case TKIND_DISPATCH:
  158.                  hr = DeCompileDispinterface( pstm, pFrame->m_pSelectedItem->GetTypeInfo() ) ;
  159.             break ;
  160.  
  161.             case TKIND_COCLASS:
  162.                  hr = DeCompileCoClass( pstm, pFrame->m_pSelectedItem->GetTypeInfo() ) ;
  163.             break ;
  164.  
  165.             default:
  166.                 sText = _T("<<unclassified typeinfo>>");
  167.             break ;
  168.             }
  169.         break ;
  170.  
  171.         case CTreeItem::typeMethod:
  172.              hr = DeCompileFunc( pstm, pFrame->m_pSelectedItem->GetTypeInfo(), pFrame->m_pSelectedItem->m_uiMemid ) ;
  173.         break ;
  174.  
  175.         case CTreeItem::typeProperty:
  176.              hr = DeCompileVar( pstm, pFrame->m_pSelectedItem->GetTypeInfo(), pFrame->m_pSelectedItem->m_uiMemid ) ;
  177.         break ;
  178.  
  179.         case CTreeItem::typeConstant:
  180.              hr = DeCompileConst( pstm, pFrame->m_pSelectedItem->GetTypeInfo(), pFrame->m_pSelectedItem->m_uiMemid ) ;
  181.         break ;
  182.  
  183.         case CTreeItem::typeUnknown:
  184.         case CTreeItem::typeUnknown2:
  185.         case CTreeItem::typeEnums:
  186.         case CTreeItem::typeRecords:
  187.         case CTreeItem::typeModules:
  188.         case CTreeItem::typeInterfaces:
  189.         case CTreeItem::typeDispinterfaces:
  190.         case CTreeItem::typeCoClasses:
  191.         case CTreeItem::typeAliases:
  192.         case CTreeItem::typeUnions:
  193.         case CTreeItem::typeMethods:
  194.         case CTreeItem::typeMethods2:
  195.         case CTreeItem::typeProperties:
  196.         case CTreeItem::typeProperties2:
  197.         case CTreeItem::typeConstants:
  198.         case CTreeItem::typeConstants2:
  199.         case CTreeItem::typeImplTypes:
  200.         case CTreeItem::typeImplTypes2:
  201.         default:
  202.             //bstr = ::SysAllocString(OLESTR(""));
  203.         break ;
  204.         }
  205.  
  206.         if (hr != S_OK)
  207.             AfxThrowOleException( hr ) ;
  208.  
  209.         if (pstm)
  210.         {
  211.             STATSTG statstg ;
  212.             if (FAILED(hr = pstm->Stat( &statstg,STATFLAG_NONAME )))
  213.                 AfxThrowOleException( hr ) ;
  214.  
  215.             // Seek to beginning
  216.             LARGE_INTEGER li ;
  217.             LISet32( li, 0 ) ;
  218.             if (FAILED(hr = pstm->Seek( li, STREAM_SEEK_SET, NULL )))
  219.                 AfxThrowOleException( hr ) ;
  220.  
  221.             // Read into string
  222.             LPSTR lpszBuf = sText.GetBuffer(statstg.cbSize.LowPart+1);
  223.             if (FAILED(hr = pstm->Read( lpszBuf, statstg.cbSize.LowPart, NULL )))
  224.                 AfxThrowOleException( hr ) ;
  225.             lpszBuf[statstg.cbSize.LowPart] = '\0';
  226.             sText.ReleaseBuffer();
  227.         }
  228.         SetWindowText(sText);
  229.         pstm->Release() ;
  230.     }
  231.     CATCH(CException, pException)
  232.     {
  233.         SetWindowText( _T("// Could not decompile selected item") ) ;
  234.         if (pstm)
  235.             pstm->Release() ;
  236.  
  237.         if (pException->IsKindOf(RUNTIME_CLASS(COleException)))
  238.             hr = ((COleException*)pException)->m_sc ;
  239.         else if (pException->IsKindOf(RUNTIME_CLASS(COleException)))
  240.             hr = E_OUTOFMEMORY ;
  241.  
  242.         if (hr == S_OK)
  243.             hr = GetLastError() ;
  244.  
  245.         ErrorMessage( "Could not decompile selected item", hr ) ;
  246.     }
  247.     END_CATCH
  248.  
  249.     SetRedraw( TRUE ) ;
  250.     EndWaitCursor() ;
  251.     SendMessage(EM_SETSEL, 0, 0)  ;
  252. }
  253.  
  254. void CTypeLibODLView::OnDestroy()
  255. {
  256.     CEditView::OnDestroy();
  257.  
  258.     m_Font.DeleteObject() ;
  259. }
  260.  
  261. // Write string s with no indent and no CR
  262. #define WRITE( s )          WriteLine( pstm, s, 0, FALSE )
  263.  
  264. // Write string s with indent and no CR
  265. #define WRITE1( s )         WriteLine( pstm, s, uiIndent, FALSE )
  266. #define WRITE2( s, ui )     WriteLine( pstm, s, uiIndent+ui, FALSE )
  267.  
  268. // Write string s with indent and CR
  269. #define WRITELINE( s )      WriteLine( pstm, s, uiIndent, TRUE )
  270. #define WRITELINE2( s, ui ) WriteLine( pstm, s, uiIndent+ui, TRUE )
  271. #define WRITECR( s )        WriteLine( pstm, s, 0, TRUE )
  272.  
  273. #define WRITERAW( p, len )     WriteRaw( pstm, p, len )
  274. #define WRITEBSTR( p )         WriteBSTR( pstm, p )
  275.  
  276. inline void WriteRaw( IStream* pstm, const void* pv, UINT cb )
  277. {
  278.     HRESULT hr ;
  279.     if (FAILED(hr = pstm->Write( pv, cb, NULL )))
  280.         AfxThrowOleException( hr ) ;
  281. }
  282.  
  283. inline void WriteLine( IStream* pstm, const CString &rstr, UINT uiIndent, BOOL fNewLine )
  284. {
  285.     while(uiIndent--)
  286.     {
  287.         WriteRaw( pstm, _T("    "), 4 * sizeof(TCHAR));
  288.     }
  289.  
  290.     WriteRaw( pstm, rstr, rstr.GetLength() * sizeof(TCHAR)) ;
  291.  
  292.     if (fNewLine)
  293.         WriteRaw(pstm, _T("\r\n"), 2 * sizeof(TCHAR)) ;
  294. }
  295.  
  296. inline void WriteBSTR( IStream* pstm, BSTR bstr )
  297. {
  298.     UINT len = ::SysStringLen(bstr) ;
  299.     if (!len)
  300.         return ;
  301.  
  302.     USES_CONVERSION;
  303.     LPTSTR lpszSource = OLE2T(bstr);
  304.     TCHAR *pstrTemp = new TCHAR[((len + 1) * sizeof(TCHAR)) * 2];
  305.     LPTSTR lpD, lpS = lpszSource ;
  306.  
  307.     lpD = pstrTemp;
  308.     for (UINT n = 0 ; n < len ; n++)
  309.     {
  310.         if (!isprint(*lpS) || (*lpS) == '\"' || (*lpS) == '\\')
  311.         {
  312.             // \"  \\ \a  \b  \f  \n  \r  \t  \v
  313.             *lpD++ = '\\' ;
  314.             switch(*lpS)
  315.             {
  316.             case '\"':
  317.                 *lpD++ = '\"' ;
  318.             break ;
  319.             case '\\':
  320.                 *lpD++ = '\\' ;
  321.             break ;
  322.             case '\a':
  323.                 *lpD++ = 'a' ;
  324.             break ;
  325.             case '\b':
  326.                 *lpD++ = 'b' ;
  327.             break ;
  328.             case '\f':
  329.                 *lpD++ = 'f' ;
  330.             break ;
  331.             case '\n':
  332.                 *lpD++ = 'n' ;
  333.             break ;
  334.             case '\r':
  335.                 *lpD++ = 'r' ;
  336.             break ;
  337.             case '\t':
  338.                 *lpD++ = 't' ;
  339.             break ;
  340.             case '\v':
  341.                 *lpD++ = 'v' ;
  342.             break ;
  343.             case '\0':
  344.                 *lpD++ = '0' ;
  345.             break ;
  346.             default:
  347.                 lpD += wsprintf( lpD, _T("x%02X"), (UINT)*lpS );
  348.             break ;
  349.             }
  350.             lpS++;
  351.         }
  352.         else
  353.             *lpD++ = *lpS++;
  354.     }
  355.     *lpD = '\0';
  356.  
  357.     WriteRaw( pstm, pstrTemp, lstrlen(pstrTemp)*sizeof(TCHAR) ) ;
  358.     delete []pstrTemp ;
  359. }
  360.  
  361. //  // typelib.tlb
  362. //  [
  363. //    uuid(<00026b00-0000-0000-C000-000000000046>),
  364. //    version (<major>.<minor>),
  365. //    helpfile ("<helpfile.hlp>"),
  366. //    helpstring("<helpstring>"),
  367. //    helpcontext(<helpcontext>)
  368. //  ]
  369. //  library <libname>
  370. //  {
  371. //      importlib("<import.tlb>");
  372. //
  373. //  };
  374. HRESULT CTypeLibODLView::DeCompileTypeLib( IStream* pstm, ITypeLib* ptlb, UINT uiIndent /* = 0 */ )
  375. {
  376.     USES_CONVERSION;
  377.     HRESULT         hr = S_OK ;
  378.     BSTR            bstrName = NULL ;
  379.     BSTR            bstrDoc = NULL ;
  380.     BSTR            bstrHelp = NULL ;
  381.     DWORD           dwHelpID ;
  382.     TLIBATTR*       plibattr = NULL ;
  383.     ITypeInfo*      pti = NULL ;
  384.     TYPEATTR*       pattr = NULL ;
  385.  
  386.     ASSERT(ptlb) ;
  387.  
  388.     TRY
  389.     {
  390.         TCHAR szGUID[64] ;
  391.         CString str;
  392.         hr = ptlb->GetLibAttr(&plibattr);
  393.         if (FAILED(hr))
  394.             AfxThrowOleException( hr ) ;
  395.  
  396.         // write header with library filename
  397.         WRITELINE(_T("// Generated .ODL file (by Ole2View)"));
  398.         WRITELINE(_T("// "));
  399.         WRITE1(_T("// typelib filename: "));
  400.         hr = ::QueryPathOfRegTypeLib(plibattr->guid, plibattr->wMajorVerNum, plibattr->wMinorVerNum, plibattr->lcid, &bstrName);
  401.         if (SUCCEEDED(hr))
  402.         {
  403.             LPCTSTR lpszName = OLE2CT(bstrName);
  404.             ::SysFreeString(bstrName);
  405.             bstrName = NULL;
  406.  
  407.             LPTSTR p = _tcsrchr(lpszName, '\\');
  408.             if (p != NULL && *p && *(p+1))
  409.                 WRITECR( p+1 ) ;
  410.             else
  411.                 WRITECR( lpszName ) ;
  412.         }
  413.         else
  414.         {
  415.             // It's possible we're viewing a type lib that was never registered
  416.             WRITECR( _T("<could not determine filename>") ) ;
  417.         }
  418.  
  419.         WRITELINE( _T("[") ) ;
  420.  
  421.         StringFromGUID2T( plibattr->guid, szGUID, sizeof(szGUID) );
  422.         WRITE1(_T("  uuid(")) ; WRITE(szGUID); WRITECR(_T("),"))  ;
  423.  
  424.         str.Format( _T("  version(%d.%d)"), plibattr->wMajorVerNum, plibattr->wMinorVerNum ) ;
  425.         WRITE1(str) ;
  426.  
  427.         hr = ptlb->GetDocumentation( MEMBERID_NIL, &bstrName, &bstrDoc, &dwHelpID, &bstrHelp );
  428.         if (FAILED(hr))
  429.             AfxThrowOleException( hr ) ;
  430.  
  431.         if (bstrDoc && *bstrDoc)
  432.         {
  433.             WRITECR(_T(",")) ;
  434.             WRITE1(_T("  helpstring(\"")) ;
  435.             WRITEBSTR( bstrDoc ) ;
  436.             WRITE(_T("\")")) ;
  437.         }
  438.  
  439.         if (bstrHelp && *bstrHelp)
  440.         {
  441.             WRITECR(",") ;
  442.             LPCTSTR lpszHelp = OLE2CT(bstrHelp);
  443.             ::SysFreeString(bstrHelp);
  444.             bstrHelp = NULL;
  445.  
  446.             LPTSTR p = _tcsrchr(lpszHelp, '\\');
  447.             if (p != NULL && *p && *(p+1))
  448.                 str.Format( _T("  helpfile(\"%s\"),"), p+1 ) ;
  449.             else
  450.                 str.Format( _T("  helpfile(\"%s\"),"), lpszHelp ) ;
  451.             WRITELINE( str ) ;
  452.             str.Format( _T("  helpcontext(%#08.8x)"), dwHelpID ) ;
  453.             WRITE1( str ) ;
  454.         }
  455.  
  456.         WRITECR(_T("")) ;
  457.         WRITELINE(_T("]") ) ;
  458.  
  459.         WRITE1( _T("library ") ) ;
  460.         WRITEBSTR(bstrName) ;
  461.         WRITECR(_T("")) ;
  462.  
  463.         WRITELINE( _T("(") ) ;
  464.  
  465.         // TODO:  Grovel through all typeinfos for any referenced types
  466.         // that are defined in imported libs
  467.         //uiInfos = ptlb->GetTypeInfoCount() ;
  468.         //for (UINT n = 0 ; n < uiInfos ; n++)
  469.         //{
  470.         //}
  471.         WRITELINE(_T("// BUGBUG:  There most likely were \"importlib()\" statements in"));
  472.         WRITELINE(_T("//          in the source.  While it appears possible to be able"));
  473.         WRITELINE(_T("//          to identify them, it is non-trivial and is currently"));
  474.         WRITELINE(_T("//          not supported."));
  475.         WRITELINE(_T("// "));
  476.  
  477.         UINT uiInfos = ptlb->GetTypeInfoCount() ;
  478.         for (UINT n = 0 ; n < uiInfos ; n++)
  479.         {
  480.             if (FAILED(hr = ptlb->GetTypeInfo( n, &pti )))
  481.                 AfxThrowOleException(hr) ;
  482.  
  483.             if (FAILED(hr = pti->GetTypeAttr( &pattr )))
  484.                 AfxThrowOleException(hr) ;
  485.  
  486.             switch(pattr->typekind)
  487.             {
  488.             case TKIND_ENUM:
  489.             case TKIND_RECORD:
  490.             case TKIND_UNION:
  491.             case TKIND_ALIAS:
  492.                  hr = DeCompileTypedef( pstm, pti, uiIndent + 1 ) ;
  493.             break ;
  494.  
  495.             case TKIND_MODULE:
  496.                  hr = DeCompileModule( pstm, pti, uiIndent + 1 ) ;
  497.             break ;
  498.  
  499.             case TKIND_INTERFACE:
  500.                  hr = DeCompileInterface( pstm, pti, uiIndent + 1 ) ;
  501.             break ;
  502.  
  503.             case TKIND_DISPATCH:
  504.                  hr = DeCompileDispinterface( pstm, pti, uiIndent + 1 ) ;
  505.             break ;
  506.  
  507.             case TKIND_COCLASS:
  508.                  hr = DeCompileCoClass( pstm, pti, uiIndent + 1 ) ;
  509.             break ;
  510.             }
  511.  
  512.             if (n != uiInfos - 1)
  513.                 WRITECR(_T("")) ;
  514.  
  515.             pti->ReleaseTypeAttr( pattr ) ;
  516.             pti->Release() ;
  517.             pti = NULL ;
  518.             pattr = NULL ;
  519.         }
  520.         // Last line of the .ODL file
  521.         WRITELINE( ");" ) ;
  522.  
  523.         SysFreeString( bstrName ) ;
  524.         bstrName = NULL ;
  525.         SysFreeString( bstrDoc ) ;
  526.         bstrDoc = NULL ;
  527.         SysFreeString( bstrHelp ) ;
  528.         bstrHelp = NULL ;
  529.  
  530.         if (plibattr)
  531.             ptlb->ReleaseTLibAttr( plibattr ) ;
  532.     }
  533.     CATCH(CException, pException)
  534.     {
  535.         if (pti)
  536.         {
  537.             if (pattr)
  538.                 pti->ReleaseTypeAttr( pattr ) ;
  539.             pti->Release() ;
  540.         }
  541.         if (plibattr)
  542.             ptlb->ReleaseTLibAttr( plibattr ) ;
  543.         if (bstrName)
  544.             SysFreeString( bstrName ) ;
  545.         if (bstrDoc)
  546.             SysFreeString( bstrDoc ) ;
  547.         if (bstrHelp)
  548.             SysFreeString( bstrHelp ) ;
  549.  
  550.         THROW_LAST() ;
  551.     }
  552.     END_CATCH
  553.  
  554.     return hr ;
  555. }
  556.  
  557. // if typekind == TKIND_ALIAS
  558. //      typedef [attributes] basetype aliasname;
  559. //
  560. // if typekind == TKIND_ENUM
  561. //  typedef [attributes] enum [tag] {
  562. //      enumlist
  563. //  } enumname;
  564. // enumlist is made up of members of the form
  565. //      name = value,
  566. // or "= value" can be ommitted
  567. //
  568. // if typekind == TKIND_UNION or TKIND_RECORD
  569. // typedef [attributes] union/struct [tag] {
  570. //      memberlist
  571. // } union/structname;
  572. //
  573. // attributes can be
  574. //      [uuid(<00026b00-0000-0000-C000-000000000046>), version (<major>.<minor>),
  575. //       helpstring("<helpstring>"), helpcontext(<id), hidden, restricted,
  576. //       public]
  577. //
  578. // memberlist is made up of members of the form
  579. //      type name[bounds];
  580. //
  581. HRESULT CTypeLibODLView::DeCompileTypedef( IStream* pstm, ITypeInfo* pti, UINT uiIndent /* = 0 */ )
  582. {
  583.     USES_CONVERSION;
  584.     HRESULT     hr = S_OK ;
  585.     TYPEATTR*   pattr = NULL ;
  586.     BSTR            bstrName = NULL ;
  587.     BSTR            bstrDoc = NULL ;
  588.     BSTR            bstrHelp = NULL ;
  589.     DWORD           dwHelpID ;
  590.  
  591.     WRITE1("typedef ") ;
  592.  
  593.     TRY
  594.     {
  595.         if (FAILED(hr = pti->GetTypeAttr( &pattr)))
  596.             AfxThrowOleException( hr ) ;
  597.  
  598.         BOOL    fAttributes = FALSE ;      // any attributes?
  599.         BOOL    fAttribute = FALSE ;       // at least one (insert ",")
  600.  
  601.         // Was 'uuid' specified?
  602.         if (!IsEqualGUID( pattr->guid, GUID_NULL ))
  603.         {
  604.             TCHAR szGUID[64] ;
  605.             StringFromGUID2T( pattr->guid, szGUID, sizeof(szGUID) ) ;
  606.             fAttributes = TRUE ;
  607.             WRITE("[uuid(") ;
  608.             WRITE(szGUID) ;
  609.             WRITE(")") ;
  610.             fAttribute = TRUE ;
  611.         }
  612.  
  613.         // was version specified
  614.         if (pattr->wMajorVerNum || pattr->wMinorVerNum)
  615.         {
  616.             if (fAttributes == FALSE)
  617.                 WRITE("[") ;
  618.             fAttributes = TRUE ;
  619.             if (fAttribute)
  620.                 WRITE(", ") ;
  621.  
  622.             CString str ;
  623.             str.Format(_T("version(%d.%d)"), pattr->wMajorVerNum, pattr->wMinorVerNum) ;
  624.             WRITE(str) ;
  625.             fAttribute = TRUE ;
  626.         }
  627.  
  628.         if (SUCCEEDED(pti->GetDocumentation( MEMBERID_NIL, &bstrName, &bstrDoc, &dwHelpID, &bstrHelp )))
  629.         {
  630.             CString str ;
  631.             if (bstrDoc && *bstrDoc)
  632.             {
  633.                 if (fAttributes == FALSE) WRITE("[") ;
  634.                 fAttributes = TRUE ;
  635.                 if (fAttribute)
  636.                     WRITE(", ") ;
  637.                 LPCTSTR lpszDoc = OLE2CT(bstrDoc);
  638.                 ::SysFreeString(bstrDoc);
  639.                 bstrDoc = NULL;
  640.  
  641.                 str.Format( _T("helpstring(\"%s\")"), lpszDoc );
  642.                 WRITE( str ) ;
  643.                 if (dwHelpID > 0)
  644.                 {
  645.                     str.Format( _T(", helpcontext(%#08.8x)"), dwHelpID ) ;
  646.                     WRITE( str ) ;
  647.                 }
  648.             }
  649.             else if (dwHelpID > 0)
  650.             {
  651.                 if (fAttributes == FALSE) WRITE("[") ;
  652.                 fAttributes = TRUE ;
  653.                 if (fAttribute)
  654.                     WRITE(", ") ;
  655.                 str.Format( _T("helpcontext(%#08.8x)"), dwHelpID ) ;
  656.                 WRITE( str ) ;
  657.                 fAttribute = TRUE ;
  658.             }
  659.         }
  660.  
  661.         if (pattr->typekind == TKIND_ALIAS)
  662.         {
  663.             if (fAttributes == FALSE) WRITE("[") ;
  664.             fAttributes = TRUE ;
  665.             if (fAttribute)
  666.                 WRITE(", ") ;
  667.             WRITE("public") ;       // if it's in the tlb it had public
  668.         }
  669.  
  670.         if (fAttributes)
  671.             WRITE("] ") ;
  672.  
  673.         switch(pattr->typekind)
  674.         {
  675.         case TKIND_RECORD:
  676.             #ifdef _WRITE_TAG
  677.             WRITE("struct tag") ;
  678.             WRITEBSTR(bstrName) ;
  679.             #else
  680.             WRITE("struct ") ;
  681.             #endif
  682.             WRITECR(" {" );
  683.         break ;
  684.  
  685.         case TKIND_UNION:
  686.             #ifdef _WRITE_TAG
  687.             WRITE("union tag") ;
  688.             WRITEBSTR(bstrName) ;
  689.             #else
  690.             WRITE("union ") ;
  691.             #endif
  692.             WRITECR(" {" );
  693.         break ;
  694.  
  695.         case TKIND_ALIAS:  //typedef
  696.             // write base type
  697.             WRITE(TYPEDESCtoString( pti, &pattr->tdescAlias )) ;
  698.             WRITE(" ") ;
  699.  
  700.             // write aliasname
  701.         break ;
  702.  
  703.         case TKIND_ENUM:
  704.             WRITECR("enum {" );
  705.         break ;
  706.  
  707.         default:
  708.         ASSERT(0) ;
  709.         break ;
  710.         }
  711.  
  712.         if (pattr->typekind == TKIND_RECORD || pattr->typekind == TKIND_UNION)
  713.         {
  714.             for (UINT n = 0 ; n < pattr->cVars ; n++)
  715.                 DumpVar( pstm, pti, pattr, n, uiIndent + 1 ) ;
  716.             WRITE1("} ");
  717.         }
  718.  
  719.         if (pattr->typekind == TKIND_ENUM)
  720.         {
  721.             for (int n = 0 ; n < pattr->cVars ; n++)
  722.             {
  723.                 DumpConst( pstm, pti, pattr, n, uiIndent + 1, FALSE ) ;
  724.                 if (n < pattr->cVars-1)
  725.                     WRITECR(",") ;
  726.                 else
  727.                     WRITECR("") ;
  728.             }
  729.             WRITE1("} ");
  730.         }
  731.  
  732.         WRITEBSTR(bstrName) ;
  733.         WRITECR(";") ;
  734.  
  735.  
  736.         if (bstrName)
  737.             SysFreeString( bstrName ) ;
  738.         if (bstrDoc)
  739.             SysFreeString( bstrDoc ) ;
  740.         if (bstrHelp)
  741.             SysFreeString( bstrHelp ) ;
  742.  
  743.         pti->ReleaseTypeAttr( pattr ) ;
  744.     }
  745.     CATCH(CException, pException)
  746.     {
  747.         if (bstrName)
  748.             SysFreeString( bstrName ) ;
  749.         if (bstrDoc)
  750.             SysFreeString( bstrDoc ) ;
  751.         if (bstrHelp)
  752.             SysFreeString( bstrHelp ) ;
  753.         if (pattr)
  754.             pti->ReleaseTypeAttr( pattr ) ;
  755.  
  756.         THROW_LAST();
  757.     }
  758.     END_CATCH
  759.     return hr ;
  760. }
  761.  
  762. //  [
  763. //    attributes
  764. //  ]
  765. //  module modulename {
  766. //      elementlist
  767. //  };
  768. //  attributes are
  769. //      uuid, version, helpstring, helpcontext, dllname
  770. //      The dllname attribute is required.
  771. //
  772. //  [attributes] returntype [calling convention] funcname(params);
  773. //  [attributes] const constname = constval;
  774. //
  775. HRESULT CTypeLibODLView::DeCompileModule( IStream* pstm, ITypeInfo* pti, UINT uiIndent /* = 0 */ )
  776. {
  777.     HRESULT     hr = S_OK ;
  778.     TYPEATTR*   pattr = NULL ;
  779.     BSTR            bstrName = NULL ;
  780.     BSTR            bstrDoc = NULL ;
  781.     BSTR            bstrHelp = NULL ;
  782.     DWORD           dwHelpID ;
  783.  
  784.     TRY
  785.     {
  786.         if (FAILED(hr = pti->GetTypeAttr( &pattr)))
  787.             AfxThrowOleException( hr ) ;
  788.  
  789.         WRITELINE(_T("// BUGBUG:   There appears to be no way to retrieve the dllname of"));
  790.         WRITELINE(_T("//           a module via ITypeInfo in a reliable way. "));
  791.         WRITELINE(_T("//           ITypeInfo::GetDllEntry offers a possibility, but it will"));
  792.         WRITELINE(_T("//           only work if the module has entries in it."));
  793.         WRITELINE(_T("// "));
  794.  
  795.         WRITELINE(_T("[")) ;
  796.         WRITE1( _T("  dllname(")) ;
  797.  
  798.         /*
  799.         if (FAILED(hr = pti->GetDllEntry(MEMBERID_NIL, INVOKE_FUNC, &bstrName, NULL, NULL)))
  800.             AfxThrowOleException( hr ) ;
  801.  
  802.         WRITEBSTR(bstrName) ;
  803.         SysFreeString(bstrName) ;
  804.         bstrName = NULL ;
  805.         */
  806.  
  807.         WRITE(_T(")")) ;
  808.  
  809.         // Was 'uuid' specified?
  810.         if (!IsEqualGUID( pattr->guid, GUID_NULL ))
  811.         {
  812.             TCHAR szGUID[64] ;
  813.             StringFromGUID2T( pattr->guid, szGUID, sizeof(szGUID) ) ;
  814.             WRITECR(",") ;
  815.             WRITE1("  uuid(") ;
  816.             WRITE(szGUID) ;
  817.             WRITE(")") ;
  818.         }
  819.  
  820.         // was version specified
  821.         if (pattr->wMajorVerNum || pattr->wMinorVerNum)
  822.         {
  823.             WRITECR(",") ;
  824.             CString str ;
  825.             str.Format(_T("  version(%d.%d)"), pattr->wMajorVerNum, pattr->wMinorVerNum) ;
  826.             WRITE1(str) ;
  827.         }
  828.  
  829.         if (SUCCEEDED(pti->GetDocumentation( MEMBERID_NIL, &bstrName, &bstrDoc, &dwHelpID, &bstrHelp )))
  830.         {
  831.             CString str ;
  832.             if (bstrDoc && *bstrDoc)
  833.             {
  834.                 WRITECR(",") ;
  835.                 USES_CONVERSION;
  836.                 LPCTSTR lpszDoc = OLE2CT(bstrDoc);
  837.                 ::SysFreeString(bstrDoc);
  838.                 bstrDoc = NULL;
  839.                 str.Format( _T("  helpstring(\"%s\")"), lpszDoc ) ;
  840.                 WRITE1( str ) ;
  841.                 if (dwHelpID > 0)
  842.                 {
  843.                     WRITECR(",") ;
  844.                     str.Format( _T("  helpcontext(%#08.8x)"), dwHelpID ) ;
  845.                     WRITE1( str ) ;
  846.                 }
  847.             }
  848.             else if (dwHelpID > 0)
  849.             {
  850.                 WRITECR(",") ;
  851.                 str.Format( _T("  helpcontext(%#08.8x)"), dwHelpID ) ;
  852.                 WRITE1( str ) ;
  853.             }
  854.         }
  855.  
  856.         WRITECR("") ;
  857.         WRITELINE(_T("]")) ;
  858.         WRITE1(_T("module ")) ;
  859.         WRITEBSTR( bstrName ) ;
  860.         WRITECR( _T(" {")) ;
  861.  
  862.         for (int n = 0 ; n < pattr->cFuncs ; n++)
  863.             DumpFunc( pstm, pti, pattr, n, uiIndent + 1 ) ;
  864.  
  865.         for (n = 0 ; n < pattr->cVars ; n++)
  866.             DumpConst( pstm, pti, pattr, n, uiIndent + 1, TRUE ) ;
  867.  
  868.         WRITELINE("};") ;
  869.  
  870.  
  871.         if (bstrName)
  872.             SysFreeString( bstrName ) ;
  873.         if (bstrDoc)
  874.             SysFreeString( bstrDoc ) ;
  875.         if (bstrHelp)
  876.             SysFreeString( bstrHelp ) ;
  877.  
  878.         pti->ReleaseTypeAttr( pattr ) ;
  879.     }
  880.     CATCH(CException, pException)
  881.     {
  882.         if (bstrName)
  883.             SysFreeString( bstrName ) ;
  884.         if (bstrDoc)
  885.             SysFreeString( bstrDoc ) ;
  886.         if (bstrHelp)
  887.             SysFreeString( bstrHelp ) ;
  888.         if (pattr)
  889.             pti->ReleaseTypeAttr( pattr ) ;
  890.  
  891.         THROW_LAST();
  892.     }
  893.     END_CATCH
  894.     return hr ;
  895. }
  896.  
  897. //  [
  898. //    attributes
  899. //  ]
  900. //  interface interfacename  [:baseinterface] {
  901. //      functionlist
  902. //  };
  903. //
  904. //  attributes include source, default, and restricted
  905. //
  906. HRESULT CTypeLibODLView::DeCompileInterface( IStream* pstm, ITypeInfo* pti, UINT uiIndent /* = 0 */ )
  907. {
  908.     HRESULT     hr = S_OK ;
  909.     TYPEATTR*   pattr = NULL ;
  910.     BSTR            bstrName = NULL ;
  911.     BSTR            bstrDoc = NULL ;
  912.     BSTR            bstrHelp = NULL ;
  913.     DWORD           dwHelpID ;
  914.     ITypeInfo*      ptiImpl = NULL ;
  915.  
  916.     TRY
  917.     {
  918.         if (FAILED(hr = pti->GetTypeAttr( &pattr)))
  919.             AfxThrowOleException( hr ) ;
  920.  
  921.         WRITELINE(_T("[")) ;
  922.         WRITE1( _T("  odl")) ;
  923.  
  924.         TCHAR szGUID[64] ;
  925.         StringFromGUID2T( pattr->guid, szGUID, sizeof(szGUID) ) ;
  926.         WRITECR(",") ;
  927.         WRITE1("  uuid(") ;
  928.         WRITE(szGUID) ;
  929.         WRITE(")") ;
  930.  
  931.         // was version specified
  932.         if (pattr->wMajorVerNum || pattr->wMinorVerNum)
  933.         {
  934.             WRITECR(",") ;
  935.             CString str ;
  936.             str.Format(_T("  version(%d.%d)"), pattr->wMajorVerNum, pattr->wMinorVerNum) ;
  937.             WRITE1(str) ;
  938.         }
  939.  
  940.         if (SUCCEEDED(pti->GetDocumentation( MEMBERID_NIL, &bstrName, &bstrDoc, &dwHelpID, &bstrHelp )))
  941.         {
  942.             CString str ;
  943.             if (bstrDoc && *bstrDoc)
  944.             {
  945.                 WRITECR(",") ;
  946.                 USES_CONVERSION;
  947.                 LPCTSTR lpszDoc = OLE2CT(bstrDoc);
  948.                 ::SysFreeString(bstrDoc);
  949.                 bstrDoc = NULL;
  950.                 str.Format( _T("  helpstring(\"%s\")"), lpszDoc ) ;
  951.                 WRITE1( str ) ;
  952.                 if (dwHelpID > 0)
  953.                 {
  954.                     WRITECR(",") ;
  955.                     str.Format( _T("  helpcontext(%#08.8x)"), dwHelpID ) ;
  956.                     WRITE1( str ) ;
  957.                 }
  958.             }
  959.             else if (dwHelpID > 0)
  960.             {
  961.                 WRITECR(",") ;
  962.                 str.Format( _T("  helpcontext(%#08.8x)"), dwHelpID ) ;
  963.                 WRITE1( str ) ;
  964.             }
  965.         }
  966.  
  967.         // source, default, or restricted
  968.         if (pattr->wTypeFlags == TYPEFLAG_FHIDDEN)
  969.         {
  970.             WRITECR(",") ;
  971.             WRITE1("  hidden") ;
  972.         }
  973.  
  974.     /*
  975.         int    implflags = NULL ;
  976.         if (FAILED(hr = pti->GetImplTypeFlags(0, &implflags )))
  977.             AfxThrowOleException(hr) ;
  978.  
  979.         if (implflags & IMPLTYPEFLAG_FDEFAULT)
  980.         {
  981.             WRITECR(",") ;
  982.             WRITE1("  default") ;
  983.         }
  984.  
  985.         if (implflags & IMPLTYPEFLAG_FSOURCE)
  986.         {
  987.             WRITECR(",") ;
  988.             WRITE1("  source") ;
  989.         }
  990.  
  991.         if (implflags & IMPLTYPEFLAG_FRESTRICTED)
  992.         {
  993.             WRITECR(",") ;
  994.             WRITE1("  restricted") ;
  995.         }
  996.      */
  997.  
  998.         WRITECR("") ;
  999.         WRITELINE(_T("]")) ;
  1000.         WRITE1(_T("interface ")) ;
  1001.         // interface name
  1002.         WRITEBSTR( bstrName ) ;
  1003.  
  1004.         if (bstrName)
  1005.             SysFreeString( bstrName ) ;
  1006.         if (bstrDoc)
  1007.             SysFreeString( bstrDoc ) ;
  1008.         if (bstrHelp)
  1009.             SysFreeString( bstrHelp ) ;
  1010.         bstrName = bstrDoc = bstrHelp = NULL ;
  1011.  
  1012.         // is there a base interface?
  1013.         for (UINT n = 0 ; n <  pattr->cImplTypes; n++)
  1014.         {
  1015.             HREFTYPE href = NULL ;
  1016.             if (FAILED(hr = pti->GetRefTypeOfImplType(n, &href)))
  1017.                 AfxThrowOleException(hr) ;
  1018.  
  1019.             if (FAILED(hr = pti->GetRefTypeInfo( href, &ptiImpl )))
  1020.                 AfxThrowOleException(hr) ;
  1021.  
  1022.             if (FAILED(hr = ptiImpl->GetDocumentation( MEMBERID_NIL, &bstrName, &bstrDoc, &dwHelpID, &bstrHelp )))
  1023.                 AfxThrowOleException(hr) ;
  1024.  
  1025.             WRITE(_T(" : ")) ;
  1026.             WRITEBSTR( bstrName ) ;
  1027.  
  1028.             SysFreeString( bstrName ) ;
  1029.             bstrName = NULL ;
  1030.             SysFreeString( bstrDoc ) ;
  1031.             bstrDoc = NULL ;
  1032.             SysFreeString( bstrHelp ) ;
  1033.             bstrHelp = NULL ;
  1034.  
  1035.             ptiImpl->Release() ;
  1036.             ptiImpl = NULL ;
  1037.         }
  1038.  
  1039.         WRITECR(_T(" {")) ;
  1040.  
  1041.         for (n = 0 ; n < pattr->cFuncs ; n++)
  1042.             DumpFunc( pstm, pti, pattr, n, uiIndent + 1 ) ;
  1043.  
  1044.         WRITELINE("};") ;
  1045.  
  1046.         if (bstrName)
  1047.             SysFreeString( bstrName ) ;
  1048.         if (bstrDoc)
  1049.             SysFreeString( bstrDoc ) ;
  1050.         if (bstrHelp)
  1051.             SysFreeString( bstrHelp ) ;
  1052.  
  1053.         pti->ReleaseTypeAttr( pattr ) ;
  1054.     }
  1055.     CATCH(CException, pException)
  1056.     {
  1057.         if (ptiImpl)
  1058.             ptiImpl->Release() ;
  1059.  
  1060.         if (bstrName)
  1061.             SysFreeString( bstrName ) ;
  1062.         if (bstrDoc)
  1063.             SysFreeString( bstrDoc ) ;
  1064.         if (bstrHelp)
  1065.             SysFreeString( bstrHelp ) ;
  1066.         if (pattr)
  1067.             pti->ReleaseTypeAttr( pattr ) ;
  1068.  
  1069.         THROW_LAST();
  1070.     }
  1071.     END_CATCH
  1072.     return hr ;
  1073. }
  1074.  
  1075.  
  1076. //  Syntax 1
  1077. //
  1078. //  [
  1079. //    attributes
  1080. //  ]
  1081. //  dispinterface intfname {
  1082. //      properties:
  1083. //          proplist
  1084. //      methods:
  1085. //          methlist
  1086. //  };
  1087. //
  1088. //  Syntax 2
  1089. //
  1090. //  [
  1091. //    attributes
  1092. //  ]
  1093. //  dispinterface intfname {
  1094. //      interface interfacename
  1095. //  };
  1096. //
  1097. HRESULT CTypeLibODLView::DeCompileDispinterface( IStream* pstm, ITypeInfo* pti, UINT uiIndent /* = 0 */ )
  1098. {
  1099.     HRESULT     hr = S_OK ;
  1100.     TYPEATTR*   pattr = NULL ;
  1101.     BSTR            bstrName = NULL ;
  1102.     BSTR            bstrDoc = NULL ;
  1103.     BSTR            bstrHelp = NULL ;
  1104.     DWORD           dwHelpID ;
  1105.     ITypeInfo*      ptiImpl = NULL ;
  1106.  
  1107.     TRY
  1108.     {
  1109.         if (FAILED(hr = pti->GetTypeAttr( &pattr)))
  1110.             AfxThrowOleException( hr ) ;
  1111.  
  1112.         WRITELINE(_T("[")) ;
  1113.  
  1114.         TCHAR szGUID[64] ;
  1115.         StringFromGUID2T( pattr->guid, szGUID, sizeof(szGUID) ) ;
  1116.         WRITE1("  uuid(") ;
  1117.         WRITE(szGUID) ;
  1118.         WRITE(")") ;
  1119.  
  1120.         // was version specified
  1121.         if (pattr->wMajorVerNum || pattr->wMinorVerNum)
  1122.         {
  1123.             WRITECR(",") ;
  1124.             CString str ;
  1125.             str.Format(_T("  version(%d.%d)"), pattr->wMajorVerNum, pattr->wMinorVerNum) ;
  1126.             WRITE1(str) ;
  1127.         }
  1128.  
  1129.         if (SUCCEEDED(pti->GetDocumentation( MEMBERID_NIL, &bstrName, &bstrDoc, &dwHelpID, &bstrHelp )))
  1130.         {
  1131.             CString str ;
  1132.             if (bstrDoc && *bstrDoc)
  1133.             {
  1134.                 WRITECR(",") ;
  1135.                 USES_CONVERSION;
  1136.                 LPCTSTR lpszDoc = OLE2CT(bstrDoc);
  1137.                 ::SysFreeString(bstrDoc);
  1138.                 bstrDoc = NULL;
  1139.                 str.Format( _T("  helpstring(\"%s\")"), lpszDoc ) ;
  1140.                 WRITE1( str ) ;
  1141.                 if (dwHelpID > 0)
  1142.                 {
  1143.                     WRITECR(",") ;
  1144.                     str.Format( _T("  helpcontext(%#08.8x)"), dwHelpID ) ;
  1145.                     WRITE1( str ) ;
  1146.                 }
  1147.             }
  1148.             else if (dwHelpID > 0)
  1149.             {
  1150.                 WRITECR(",") ;
  1151.                 str.Format( _T("  helpcontext(%#08.8x)"), dwHelpID ) ;
  1152.                 WRITE1( str ) ;
  1153.             }
  1154.         }
  1155.  
  1156.         // source, default, or restricted
  1157.         if (pattr->wTypeFlags == TYPEFLAG_FHIDDEN)
  1158.         {
  1159.             WRITECR(",") ;
  1160.             WRITE1("  hidden") ;
  1161.         }
  1162.  
  1163.         if (pattr->wTypeFlags == TYPEFLAG_FDUAL)
  1164.         {
  1165.             WRITECR(",") ;
  1166.             WRITE1("  dual") ;
  1167.         }
  1168.  
  1169.         WRITECR("") ;
  1170.         WRITELINE(_T("]")) ;
  1171.         WRITE1(_T("dispinterface ")) ;
  1172.         // interface name
  1173.         WRITEBSTR( bstrName ) ;
  1174.  
  1175.         if (bstrName)
  1176.             SysFreeString( bstrName ) ;
  1177.         if (bstrDoc)
  1178.             SysFreeString( bstrDoc ) ;
  1179.         if (bstrHelp)
  1180.             SysFreeString( bstrHelp ) ;
  1181.         bstrName = bstrDoc = bstrHelp = NULL ;
  1182.  
  1183.         WRITECR(_T(" {")) ;
  1184.  
  1185.         WRITELINE2(_T("properties:"), 1) ;
  1186.         for (UINT n = 0 ; n < pattr->cVars ; n++)
  1187.             DumpVar( pstm, pti, pattr, n, uiIndent + 2 ) ;
  1188.  
  1189.         WRITELINE2(_T("methods:"), 1) ;
  1190.         for (n = 0 ; n < pattr->cFuncs ; n++)
  1191.             DumpFunc( pstm, pti, pattr, n, uiIndent + 2 ) ;
  1192.  
  1193.         WRITELINE("};") ;
  1194.  
  1195.         if (bstrName)
  1196.             SysFreeString( bstrName ) ;
  1197.         if (bstrDoc)
  1198.             SysFreeString( bstrDoc ) ;
  1199.         if (bstrHelp)
  1200.             SysFreeString( bstrHelp ) ;
  1201.  
  1202.         pti->ReleaseTypeAttr( pattr ) ;
  1203.     }
  1204.     CATCH(CException, pException)
  1205.     {
  1206.         if (ptiImpl)
  1207.             ptiImpl->Release() ;
  1208.  
  1209.         if (bstrName)
  1210.             SysFreeString( bstrName ) ;
  1211.         if (bstrDoc)
  1212.             SysFreeString( bstrDoc ) ;
  1213.         if (bstrHelp)
  1214.             SysFreeString( bstrHelp ) ;
  1215.         if (pattr)
  1216.             pti->ReleaseTypeAttr( pattr ) ;
  1217.     }
  1218.     END_CATCH
  1219.     return hr ;
  1220. }
  1221.  
  1222. //  [
  1223. //    attributes
  1224. //  ]
  1225. //  coclass classname {
  1226. //      [attributes2] [interface | dispinterface] interfacename;
  1227. //      ...
  1228. //  };
  1229. //
  1230. //  attributes
  1231. //      uuid, helpstring, helpcontext, licensed, version, and appobject
  1232. //
  1233. HRESULT CTypeLibODLView::DeCompileCoClass( IStream* pstm, ITypeInfo* pti, UINT uiIndent /* = 0 */ )
  1234. {
  1235.     HRESULT     hr = S_OK ;
  1236.     TYPEATTR*   pattr = NULL ;
  1237.     BSTR            bstrName = NULL ;
  1238.     BSTR            bstrDoc = NULL ;
  1239.     BSTR            bstrHelp = NULL ;
  1240.     DWORD           dwHelpID ;
  1241.     ITypeInfo*      ptiImpl = NULL ;
  1242.     TYPEATTR*       pattrImpl = NULL ;
  1243.  
  1244.     TRY
  1245.     {
  1246.         if (FAILED(hr = pti->GetTypeAttr( &pattr)))
  1247.             AfxThrowOleException( hr ) ;
  1248.  
  1249.         WRITELINE(_T("[")) ;
  1250.  
  1251.         TCHAR szGUID[64] ;
  1252.         StringFromGUID2T( pattr->guid, szGUID, sizeof(szGUID) ) ;
  1253.         WRITE1("  uuid(") ;
  1254.         WRITE(szGUID) ;
  1255.         WRITE(")") ;
  1256.  
  1257.         // was version specified
  1258.         if (pattr->wMajorVerNum || pattr->wMinorVerNum)
  1259.         {
  1260.             WRITECR(",") ;
  1261.             CString str ;
  1262.             str.Format(_T("  version(%d.%d)"), pattr->wMajorVerNum, pattr->wMinorVerNum) ;
  1263.             WRITE1(str) ;
  1264.         }
  1265.  
  1266.         if (SUCCEEDED(pti->GetDocumentation( MEMBERID_NIL, &bstrName, &bstrDoc, &dwHelpID, &bstrHelp )))
  1267.         {
  1268.             CString str ;
  1269.             if (bstrDoc && *bstrDoc)
  1270.             {
  1271.                 WRITECR(",") ;
  1272.                 USES_CONVERSION;
  1273.                 LPCTSTR lpszDoc = OLE2CT(bstrDoc);
  1274.                 ::SysFreeString(bstrDoc);
  1275.                 bstrDoc = NULL;
  1276.                 str.Format( _T("  helpstring(\"%s\")"), lpszDoc ) ;
  1277.                 WRITE1( str ) ;
  1278.                 if (dwHelpID > 0)
  1279.                 {
  1280.                     WRITECR(",") ;
  1281.                     str.Format( _T("  helpcontext(%#08.8x)"), dwHelpID ) ;
  1282.                     WRITE1( str ) ;
  1283.                 }
  1284.             }
  1285.             else if (dwHelpID > 0)
  1286.             {
  1287.                 WRITECR(",") ;
  1288.                 str.Format( _T("  helpcontext(%#08.8x)"), dwHelpID ) ;
  1289.                 WRITE1( str ) ;
  1290.             }
  1291.         }
  1292.  
  1293.         if (pattr->wTypeFlags == TYPEFLAG_FAPPOBJECT)
  1294.         {
  1295.             WRITECR(",") ;
  1296.             WRITE1("  appobject") ;
  1297.         }
  1298.         if (pattr->wTypeFlags == TYPEFLAG_FHIDDEN)
  1299.         {
  1300.             WRITECR(",") ;
  1301.             WRITE1("  hidden") ;
  1302.         }
  1303.         if (pattr->wTypeFlags == TYPEFLAG_FLICENSED)
  1304.         {
  1305.             WRITECR(",") ;
  1306.             WRITE1("  licensed") ;
  1307.         }
  1308.         if (pattr->wTypeFlags == TYPEFLAG_FCONTROL)
  1309.         {
  1310.             WRITECR(",") ;
  1311.             WRITE1("  control") ;
  1312.         }
  1313.  
  1314.         WRITECR("") ;
  1315.         WRITELINE(_T("]")) ;
  1316.         WRITE1(_T("coclass ")) ;
  1317.         // coclass name
  1318.         WRITEBSTR( bstrName ) ;
  1319.  
  1320.         if (bstrName)
  1321.             SysFreeString( bstrName ) ;
  1322.         if (bstrDoc)
  1323.             SysFreeString( bstrDoc ) ;
  1324.         if (bstrHelp)
  1325.             SysFreeString( bstrHelp ) ;
  1326.         bstrName = bstrDoc = bstrHelp = NULL ;
  1327.  
  1328.         WRITECR(_T(" {")) ;
  1329.  
  1330.         //  [attributes2] [interface | dispinterface] interfacename;
  1331.         for (UINT n = 0 ; n < pattr->cImplTypes ; n++)
  1332.         {
  1333.             HREFTYPE href = NULL ;
  1334.  
  1335.             int impltype = NULL ;
  1336.             if (FAILED(hr = pti->GetImplTypeFlags( n, &impltype )))
  1337.                 AfxThrowOleException(hr) ;
  1338.  
  1339.             if (FAILED(hr = pti->GetRefTypeOfImplType(n, &href)))
  1340.                 AfxThrowOleException(hr) ;
  1341.  
  1342.             if (FAILED(hr = pti->GetRefTypeInfo( href, &ptiImpl )))
  1343.                 AfxThrowOleException(hr) ;
  1344.  
  1345.             if (FAILED(hr = ptiImpl->GetDocumentation( MEMBERID_NIL, &bstrName, &bstrDoc, &dwHelpID, &bstrHelp )))
  1346.                 AfxThrowOleException(hr) ;
  1347.  
  1348.             if (FAILED(hr = ptiImpl->GetTypeAttr( &pattrImpl)))
  1349.                 AfxThrowOleException( hr ) ;
  1350.  
  1351.             WRITE2(_T(""), 1 ) ;
  1352.  
  1353.             if (impltype)
  1354.             {
  1355.                 WRITE(_T("[")) ;
  1356.                 BOOL    fComma = FALSE ;
  1357.                 if (impltype & IMPLTYPEFLAG_FDEFAULT)
  1358.                 {
  1359.                     WRITE(_T("default")) ;
  1360.                     fComma = TRUE ;
  1361.                 }
  1362.                 if (impltype & IMPLTYPEFLAG_FSOURCE)
  1363.                 {
  1364.                     if (fComma)
  1365.                         WRITE(_T(", ")) ;
  1366.                     WRITE(_T("source")) ;
  1367.                     fComma = TRUE ;
  1368.                 }
  1369.                 if (impltype & IMPLTYPEFLAG_FRESTRICTED)
  1370.                 {
  1371.                     if (fComma)
  1372.                         WRITE(_T(", ")) ;
  1373.                     WRITE(_T("restricted")) ;
  1374.                 }
  1375.  
  1376.                 WRITE(_T("] "));
  1377.             }
  1378.  
  1379.             if (pattrImpl->typekind == TKIND_INTERFACE)
  1380.                 WRITE(_T("interface ")) ;
  1381.  
  1382.             if (pattrImpl->typekind == TKIND_DISPATCH)
  1383.                 WRITE(_T("dispinterface ")) ;
  1384.  
  1385.             WRITE( bstrName ) ;
  1386.  
  1387.             WRITECR(_T(";")) ;
  1388.  
  1389.             SysFreeString( bstrName ) ;
  1390.             bstrName = NULL ;
  1391.             SysFreeString( bstrDoc ) ;
  1392.             bstrDoc = NULL ;
  1393.             SysFreeString( bstrHelp ) ;
  1394.             bstrHelp = NULL ;
  1395.  
  1396.             ptiImpl->ReleaseTypeAttr( pattrImpl ) ;
  1397.             pattrImpl = NULL ;
  1398.  
  1399.             ptiImpl->Release() ;
  1400.             ptiImpl = NULL ;
  1401.         }
  1402.  
  1403.         WRITELINE("};") ;
  1404.  
  1405.         if (bstrName)
  1406.             SysFreeString( bstrName ) ;
  1407.         if (bstrDoc)
  1408.             SysFreeString( bstrDoc ) ;
  1409.         if (bstrHelp)
  1410.             SysFreeString( bstrHelp ) ;
  1411.  
  1412.         pti->ReleaseTypeAttr( pattr ) ;
  1413.     }
  1414.     CATCH(CException, pException)
  1415.     {
  1416.         if (ptiImpl)
  1417.         {
  1418.             if (pattrImpl)
  1419.                 ptiImpl->ReleaseTypeAttr( pattrImpl ) ;
  1420.  
  1421.             ptiImpl->Release() ;
  1422.         }
  1423.         if (bstrName)
  1424.             SysFreeString( bstrName ) ;
  1425.         if (bstrDoc)
  1426.             SysFreeString( bstrDoc ) ;
  1427.         if (bstrHelp)
  1428.             SysFreeString( bstrHelp ) ;
  1429.         if (pattr)
  1430.             pti->ReleaseTypeAttr( pattr ) ;
  1431.  
  1432.         THROW_LAST();
  1433.     }
  1434.     END_CATCH
  1435.     return hr ;
  1436.  
  1437. }
  1438.  
  1439. HRESULT CTypeLibODLView::DeCompileFunc( IStream* pstm, ITypeInfo* pti, MEMBERID memid, UINT uiIndent /* = 0 */ )
  1440. {
  1441.     HRESULT     hr = S_OK ;
  1442.     TYPEATTR*   pattr = NULL ;
  1443.     ASSERT(pti) ;
  1444.  
  1445.     TRY
  1446.     {
  1447.         if (FAILED(hr = pti->GetTypeAttr( &pattr)))
  1448.             AfxThrowOleException( hr ) ;
  1449.  
  1450.         if (FAILED(hr = DumpFunc( pstm, pti, pattr, memid, uiIndent )))
  1451.             AfxThrowOleException( hr ) ;
  1452.  
  1453.         pti->ReleaseTypeAttr( pattr ) ;
  1454.     }
  1455.     CATCH(CException, pException)
  1456.     {
  1457.         if (pattr)
  1458.             pti->ReleaseTypeAttr( pattr ) ;
  1459.  
  1460.         THROW_LAST();
  1461.     }
  1462.     END_CATCH
  1463.  
  1464.     return hr ;
  1465. }
  1466.  
  1467. HRESULT CTypeLibODLView::DumpFunc( IStream* pstm, ITypeInfo* pti, TYPEATTR* pattr, MEMBERID memid, UINT uiIndent /* = 0 */ )
  1468. {
  1469.     HRESULT     hr = S_OK ;
  1470.     FUNCDESC*   pfuncdesc = NULL ;
  1471.     BSTR            rgbstrNames[MAX_NAMES] ;
  1472.     BSTR            bstrName = NULL ;
  1473.     BSTR            bstrDoc = NULL ;
  1474.     BSTR            bstrHelp = NULL ;
  1475.     DWORD           dwHelpID ;
  1476.     ASSERT(pti) ;
  1477.  
  1478.     for (UINT ui = 0 ; ui < MAX_NAMES ; ui++)
  1479.         rgbstrNames[ui] = NULL ;
  1480.  
  1481.     TRY
  1482.     {
  1483.         if (FAILED(hr = pti->GetFuncDesc( memid, &pfuncdesc )))
  1484.             AfxThrowOleException( hr ) ;
  1485.  
  1486.         // If pattr->typekind == TKIND_DISPATCH (dispinterface)
  1487.         //    [attributes] returntype methname(params);
  1488.         // where attributes can be
  1489.         //      id(<id>), propput, propget,
  1490.         //      propputref, bindable, defaultbind, displaybind,
  1491.         //      requestedit, source, vararg, hidden, helpstring("<helpstring>"),
  1492.         //      helpcontext(<id>)
  1493.         //
  1494.         // If pattr->typekind == TKIND_INTERFACE || TKIND_MODULE
  1495.         //  [attributes] returntype [calling convention]  funcname(params);
  1496.         // where attributes can be
  1497.         //      restricted, bindable, defaultbind, displaybind,
  1498.         //      requestedit, source, vararg, hidden, helpstring("<helpstring>"),
  1499.         //      helpcontext(<id>)
  1500.         // and calling convention can be
  1501.         //      pascal, cdecl, stdcall
  1502.         //
  1503.         // Write [attributes]
  1504.         //
  1505.         BOOL    fAttributes = FALSE ;      // any attributes?
  1506.         BOOL    fAttribute = FALSE ;       // at least one (insert ",")
  1507.         WRITE1("") ;    // indent
  1508.         CString str ;
  1509.         if (pattr->typekind == TKIND_DISPATCH)
  1510.         {
  1511.             fAttributes = TRUE ;
  1512.             fAttribute = TRUE ;
  1513.             str.Format(_T("[id(%d)"), memid) ;
  1514.             WRITE(str) ;
  1515.         }
  1516.         else if (pattr->typekind == TKIND_MODULE)
  1517.         {
  1518.             fAttributes = TRUE ;
  1519.             fAttribute = TRUE ;
  1520.             str.Format(_T("[entry(%d)"), memid) ;
  1521.             WRITE(str) ;
  1522.         }
  1523.         else
  1524.             // if there are some attributes
  1525.             if ((pfuncdesc->invkind > 1)|| pfuncdesc->wFuncFlags || pfuncdesc->cParamsOpt == -1)
  1526.             {
  1527.                 WRITE("[") ;
  1528.                 fAttributes = TRUE ;
  1529.             }
  1530.  
  1531.         if (pfuncdesc->invkind & INVOKE_PROPERTYGET)
  1532.         {
  1533.             if (fAttribute)
  1534.                 WRITE(", ") ;
  1535.             fAttribute = TRUE ;
  1536.             WRITE("propget") ;
  1537.         }
  1538.         if (pfuncdesc->invkind & INVOKE_PROPERTYPUT)
  1539.         {
  1540.             if (fAttribute)
  1541.                 WRITE(", ") ;
  1542.             fAttribute = TRUE ;
  1543.             WRITE("propput") ;
  1544.         }
  1545.         if (pfuncdesc->invkind & INVOKE_PROPERTYPUTREF)
  1546.         {
  1547.             if (fAttribute)
  1548.                 WRITE(", ") ;
  1549.             fAttribute = TRUE ;
  1550.             WRITE("propputref") ;
  1551.         }
  1552.         if (pfuncdesc->wFuncFlags & FUNCFLAG_FRESTRICTED)
  1553.         {
  1554.             if (fAttribute)
  1555.                 WRITE(", ") ;
  1556.             fAttribute = TRUE ;
  1557.             WRITE("restricted") ;
  1558.         }
  1559.         if (pfuncdesc->wFuncFlags & FUNCFLAG_FSOURCE)
  1560.         {
  1561.             if (fAttribute)
  1562.                 WRITE(", ") ;
  1563.             fAttribute = TRUE ;
  1564.             WRITE("source") ;
  1565.         }
  1566.         if (pfuncdesc->wFuncFlags & FUNCFLAG_FBINDABLE)
  1567.         {
  1568.             if (fAttribute)
  1569.                 WRITE(", ") ;
  1570.             fAttribute = TRUE ;
  1571.             WRITE("bindable") ;
  1572.         }
  1573.         if (pfuncdesc->wFuncFlags & FUNCFLAG_FREQUESTEDIT)
  1574.         {
  1575.             if (fAttribute)
  1576.                 WRITE(", ") ;
  1577.             fAttribute = TRUE ;
  1578.             WRITE("requestedit") ;
  1579.         }
  1580.         if (pfuncdesc->wFuncFlags & FUNCFLAG_FDISPLAYBIND)
  1581.         {
  1582.             if (fAttribute)
  1583.                 WRITE(", ") ;
  1584.             fAttribute = TRUE ;
  1585.             WRITE("displaybind") ;
  1586.         }
  1587.         if (pfuncdesc->wFuncFlags & FUNCFLAG_FDEFAULTBIND)
  1588.         {
  1589.             if (fAttribute)
  1590.                 WRITE(", ") ;
  1591.             fAttribute = TRUE ;
  1592.             WRITE("defaultbind") ;
  1593.         }
  1594.         if (pfuncdesc->wFuncFlags & FUNCFLAG_FHIDDEN)
  1595.         {
  1596.             if (fAttribute)
  1597.                 WRITE(", ") ;
  1598.             fAttribute = TRUE ;
  1599.             WRITE("hidden") ;
  1600.         }
  1601.         if (pfuncdesc->cParamsOpt == -1)    // cParamsOpt > 0 indicates VARIANT style
  1602.         {
  1603.             if (fAttribute)
  1604.                 WRITE(", ") ;
  1605.             fAttribute = TRUE ;
  1606.             WRITE("vararg") ;         // optional params
  1607.         }
  1608.  
  1609.         if (SUCCEEDED(pti->GetDocumentation( pfuncdesc->memid, &bstrName, &bstrDoc, &dwHelpID, &bstrHelp )))
  1610.         {
  1611.             CString str ;
  1612.             if (bstrDoc && *bstrDoc)
  1613.             {
  1614.                 if (fAttributes == FALSE) WRITE("[") ;
  1615.                 fAttributes = TRUE ;
  1616.                 if (fAttribute)
  1617.                     WRITE(", ") ;
  1618.                 USES_CONVERSION;
  1619.                 LPCTSTR lpszDoc = OLE2CT(bstrDoc);
  1620.                 ::SysFreeString(bstrDoc);
  1621.                 bstrDoc = NULL;
  1622.                 str.Format( _T("helpstring(\"%s\")"), lpszDoc ) ;
  1623.                 WRITE( str ) ;
  1624.                 if (dwHelpID > 0)
  1625.                 {
  1626.                     str.Format( _T(", helpcontext(%#08.8x)"), dwHelpID ) ;
  1627.                     WRITE( str ) ;
  1628.                 }
  1629.             }
  1630.             else if (dwHelpID > 0)
  1631.             {
  1632.                 if (fAttributes == FALSE) WRITE("[") ;
  1633.                 if (fAttribute)
  1634.                     WRITE(", ") ;
  1635.                 fAttributes = TRUE ;
  1636.                 str.Format( _T("helpcontext(%#08.8x)"), dwHelpID ) ;
  1637.                 WRITE( str ) ;
  1638.             }
  1639.         }
  1640.         if (fAttributes)
  1641.             WRITE("] ") ;
  1642.  
  1643.         // Write return type
  1644.         WRITE(TYPEDESCtoString( pti, &pfuncdesc->elemdescFunc.tdesc )) ;
  1645.         WRITE(" ") ;
  1646.  
  1647.         if (pattr->typekind != TKIND_DISPATCH)
  1648.         {   // Write calling convention
  1649.             switch(pfuncdesc->callconv)
  1650.             {
  1651.                 case CC_CDECL:      WRITE("_cdecl ") ;           break ;
  1652.                 //case CC_MSCPASCAL:  WRITE("_mspascal ") ;        break ;
  1653.                 case CC_PASCAL:     WRITE("_pascal ") ;          break ;
  1654.                 case CC_MACPASCAL:  WRITE("_macpascal ") ;       break ;
  1655.                 case CC_STDCALL :   WRITE("_stdcall ") ;          break ;
  1656.                 //case CC_RESERVED:   WRITE("_reserved ") ;         break ;
  1657.                 case CC_SYSCALL:    WRITE("_syscall ") ;          break ;
  1658.                 case CC_MPWCDECL:   WRITE("_mpwcdecl ") ;         break ;
  1659.                 case CC_MPWPASCAL:  WRITE("_mpwpascal ") ;        break ;
  1660.             }
  1661.         }
  1662.  
  1663.         // Write methodname
  1664.  
  1665.         // HACK:  If a property has the propput or propputref attributes the
  1666.         // 'right hand side' (rhs) is *always* the last parameter and MkTypeLib
  1667.         // strips the parameter name.  Thus you will always get 1 less name
  1668.         // back from ::GetNames than normal.
  1669.         //
  1670.         // Thus for the example below
  1671.         //  [propput] void Color([in] VARIANT rgb, [in] VARIANT rgb2 );
  1672.         // without taking this into consderation the output would be
  1673.         //  [propput] void Color([in] VARIANT rgb, [in] VARIANT );
  1674.         // when it should be
  1675.         //  [propput] void Color([in] VARIANT rgb, [in] VARIANT rhs );
  1676.         //
  1677.         // Another weirdness comes from a bug (which will never be fixed)
  1678.         // where optional parameters on property functions were allowed.
  1679.         // Because they were allowed by accident people used them, so they
  1680.         // are still allowed.
  1681.         //
  1682.  
  1683.         UINT cNames = 0 ;
  1684.         if (FAILED( hr = pti->GetNames( pfuncdesc->memid, rgbstrNames, MAX_NAMES, &cNames )))
  1685.             AfxThrowOleException( hr ) ;
  1686.  
  1687.         // fix for 'rhs' problem
  1688.         if ((int)cNames < pfuncdesc->cParams + 1)
  1689.         {
  1690.             rgbstrNames[cNames] = ::SysAllocString(OLESTR("rhs")) ;
  1691.             cNames++ ;
  1692.         }
  1693.  
  1694.         ASSERT((int)cNames == pfuncdesc->cParams+1) ;
  1695.         WRITEBSTR( rgbstrNames[0] ) ;
  1696.         WRITE("(") ;
  1697.  
  1698.         // params have the format
  1699.         //   [attributes] type paramname
  1700.         // where attributes can be
  1701.         //   in, out, optional, string   (string is not valid for TKIND_MODULE)
  1702.         //
  1703.         if (pfuncdesc->cParams > 1)
  1704.             WRITECR("") ;
  1705.         for ( int n = 0 ; n < pfuncdesc->cParams ; n++ )
  1706.         {
  1707.             if (pfuncdesc->cParams > 1)
  1708.                 WRITE2("", 4 ) ;    // indent 4
  1709.             fAttributes = FALSE ;
  1710.             fAttribute = FALSE ;
  1711.  
  1712.             if (pfuncdesc->lprgelemdescParam[n].idldesc.wIDLFlags)
  1713.             {
  1714.                 WRITE("[") ;
  1715.                 fAttributes = TRUE ;
  1716.             }
  1717.  
  1718.             if (pfuncdesc->lprgelemdescParam[n].idldesc.wIDLFlags & IDLFLAG_FIN)
  1719.             {
  1720.                 if (fAttribute)
  1721.                     WRITE(", ") ;
  1722.                 WRITE("in") ;
  1723.                 fAttribute = TRUE ;
  1724.             }
  1725.             if (pfuncdesc->lprgelemdescParam[n].idldesc.wIDLFlags & IDLFLAG_FOUT)
  1726.             {
  1727.                 if (fAttribute)
  1728.                     WRITE(", ") ;
  1729.                 WRITE("out") ;
  1730.                 fAttribute = TRUE ;
  1731.             }
  1732.             if (pfuncdesc->lprgelemdescParam[n].idldesc.wIDLFlags & IDLFLAG_FLCID)
  1733.             {
  1734.                 if (fAttribute)
  1735.                     WRITE(", ") ;
  1736.                 WRITE("lcid") ;
  1737.                 fAttribute = TRUE ;
  1738.             }
  1739.             if (pfuncdesc->lprgelemdescParam[n].idldesc.wIDLFlags & IDLFLAG_FRETVAL)
  1740.             {
  1741.                 if (fAttribute)
  1742.                     WRITE(", ") ;
  1743.                 WRITE("retval") ;
  1744.                 fAttribute = TRUE ;
  1745.             }
  1746.  
  1747.             // If we have an optional last parameter and we're on the last paramter
  1748.             // or we are into the optional parameters...
  1749.             if ((pfuncdesc->cParamsOpt == -1 && n == pfuncdesc->cParams - 1) ||
  1750.                 (n > (pfuncdesc->cParams - pfuncdesc->cParamsOpt)))
  1751.             {
  1752.                 if (fAttribute)
  1753.                     WRITE(", ") ;
  1754.                 if (!fAttributes)
  1755.                     WRITE("[") ;
  1756.                 WRITE("optional") ;
  1757.                 fAttributes = TRUE ;
  1758.                 fAttribute = TRUE ;
  1759.             }
  1760.  
  1761.             if (fAttributes)
  1762.                 WRITE("] ") ;
  1763.  
  1764.             // type
  1765.             CString str ;
  1766.             if ((pfuncdesc->lprgelemdescParam[n].tdesc.vt & 0x0FFF) == VT_CARRAY)
  1767.             {
  1768.                 // type name[n]
  1769.                 WRITE(TYPEDESCtoString( pti, &pfuncdesc->lprgelemdescParam[n].tdesc.lpadesc->tdescElem )) ;
  1770.                 WRITE(" ") ;
  1771.  
  1772.                 WRITEBSTR(rgbstrNames[n+1]) ;
  1773.  
  1774.                 // Allocate cDims * lstrlen("[123456]")
  1775.                 for (USHORT n = 0 ; n < pfuncdesc->lprgelemdescParam[n].tdesc.lpadesc->cDims ; n++)
  1776.                 {
  1777.                     str.Format( _T("[%d]"), pfuncdesc->lprgelemdescParam[n].tdesc.lpadesc->rgbounds[n].cElements ) ;
  1778.                     WRITE(str) ;
  1779.                 }
  1780.             }
  1781.             else
  1782.             {
  1783.                 WRITE(TYPEDESCtoString( pti, &pfuncdesc->lprgelemdescParam[n].tdesc ) + " " ) ;
  1784.                 WRITEBSTR(rgbstrNames[n+1]) ;
  1785.             }
  1786.             if (n < pfuncdesc->cParams - 1)
  1787.                 WRITECR(", ") ;
  1788.         }
  1789.  
  1790.         WRITECR(");") ;
  1791.  
  1792.         for (UINT ui = 0 ; ui < MAX_NAMES ; ui++)
  1793.             if (rgbstrNames[ui])
  1794.                 SysFreeString(rgbstrNames[ui]) ;
  1795.         if (bstrName)
  1796.             SysFreeString( bstrName ) ;
  1797.         if (bstrDoc)
  1798.             SysFreeString( bstrDoc ) ;
  1799.         if (bstrHelp)
  1800.             SysFreeString( bstrHelp ) ;
  1801.  
  1802.         pti->ReleaseFuncDesc( pfuncdesc ) ;
  1803.     }
  1804.     CATCH(CException, pException)
  1805.     {
  1806.         for (UINT ui = 0 ; ui < MAX_NAMES ; ui++)
  1807.             if (rgbstrNames[ui])
  1808.                 SysFreeString(rgbstrNames[ui]) ;
  1809.  
  1810.         if (bstrName)
  1811.             SysFreeString( bstrName ) ;
  1812.         if (bstrDoc)
  1813.             SysFreeString( bstrDoc ) ;
  1814.         if (bstrHelp)
  1815.             SysFreeString( bstrHelp ) ;
  1816.         if (pfuncdesc)
  1817.             pti->ReleaseFuncDesc( pfuncdesc ) ;
  1818.  
  1819.         THROW_LAST();
  1820.     }
  1821.     END_CATCH
  1822.  
  1823.     return hr ;
  1824. }
  1825.  
  1826. HRESULT CTypeLibODLView::DeCompileVar( IStream* pstm, ITypeInfo* pti, MEMBERID memid, UINT uiIndent /* = 0 */)
  1827. {
  1828.     HRESULT     hr = S_OK ;
  1829.     TYPEATTR*   pattr = NULL ;
  1830.     ASSERT(pti) ;
  1831.  
  1832.     TRY
  1833.     {
  1834.         if (FAILED(hr = pti->GetTypeAttr( &pattr)))
  1835.             AfxThrowOleException( hr ) ;
  1836.  
  1837.         if (FAILED(hr = DumpVar( pstm, pti, pattr, memid, uiIndent )))
  1838.             AfxThrowOleException( hr ) ;
  1839.  
  1840.         pti->ReleaseTypeAttr( pattr ) ;
  1841.     }
  1842.     CATCH(CException, pException)
  1843.     {
  1844.         if (pattr)
  1845.             pti->ReleaseTypeAttr( pattr ) ;
  1846.  
  1847.         THROW_LAST();
  1848.     }
  1849.     END_CATCH
  1850.  
  1851.     return hr ;
  1852. }
  1853.  
  1854. HRESULT CTypeLibODLView::DumpVar( IStream* pstm, ITypeInfo* pti, TYPEATTR* pattr, MEMBERID memid, UINT uiIndent /* = 0 */)
  1855. {
  1856.     HRESULT     hr = S_OK ;
  1857.     VARDESC*    pvardesc = NULL ;
  1858.     BSTR            rgbstrNames[1] ;
  1859.     BSTR            bstrName = NULL ;
  1860.     BSTR            bstrDoc = NULL ;
  1861.     BSTR            bstrHelp = NULL ;
  1862.     DWORD           dwHelpID ;
  1863.     ASSERT(pti) ;
  1864.  
  1865.     TRY
  1866.     {
  1867.         if (FAILED(hr = pti->GetVarDesc( memid, &pvardesc )))
  1868.             AfxThrowOleException( hr ) ;
  1869.  
  1870.         ASSERT(pvardesc->varkind != VAR_CONST) ;    // must not be a const
  1871.  
  1872.         // If pattr->typekind == TKIND_RECORD (struct) || TKIND_UNION
  1873.         //    type name[array];
  1874.         //
  1875.         // If pattr->typekind == TKIND_DISPATCH (dispinterface)
  1876.         //    [id(<id>), bindable, defaultbind, displaybind, readonly,
  1877.         //      requestedit, source, hidden, helpstring("<helpstring>"),
  1878.         //      helpcontext(<id>)] type name;
  1879.         //
  1880.         BOOL    fAttributes = FALSE ;
  1881.         WRITE1("") ;    // indent
  1882.         if (pattr->typekind == TKIND_DISPATCH)
  1883.         {
  1884.             CString str ;
  1885.             fAttributes = TRUE ;
  1886.             str.Format(_T("[id(%d)"), memid) ;
  1887.             WRITE(str) ;
  1888.  
  1889.             if (pvardesc->wVarFlags & VARFLAG_FREADONLY)
  1890.                 WRITE(", readonly") ;
  1891.             if (pvardesc->wVarFlags & VARFLAG_FSOURCE)
  1892.                 WRITE(", source") ;
  1893.             if (pvardesc->wVarFlags & VARFLAG_FBINDABLE)
  1894.                 WRITE(", bindable") ;
  1895.             if (pvardesc->wVarFlags & VARFLAG_FREQUESTEDIT)
  1896.                 WRITE(", requestedit") ;
  1897.             if (pvardesc->wVarFlags & VARFLAG_FDISPLAYBIND)
  1898.                 WRITE(", displaybind") ;
  1899.             if (pvardesc->wVarFlags & VARFLAG_FDEFAULTBIND)
  1900.                 WRITE(", defaultbind") ;
  1901.             if (pvardesc->wVarFlags & VARFLAG_FHIDDEN)
  1902.                 WRITE(", hidden") ;
  1903.         }
  1904.  
  1905.         if (SUCCEEDED(pti->GetDocumentation( pvardesc->memid, &bstrName, &bstrDoc, &dwHelpID, &bstrHelp )))
  1906.         {
  1907.             CString str ;
  1908.             if (bstrDoc && *bstrDoc)
  1909.             {
  1910.                 if (fAttributes == FALSE)
  1911.                     WRITE("[") ;
  1912.                 else
  1913.                     WRITE(", ") ;
  1914.                 fAttributes = TRUE ;
  1915.                 USES_CONVERSION;
  1916.                 LPCTSTR lpszDoc = OLE2CT(bstrDoc);
  1917.                 ::SysFreeString(bstrDoc);
  1918.                 bstrDoc = NULL;
  1919.                 str.Format( _T("helpstring(\"%s\")"), lpszDoc ) ;
  1920.                 WRITE( str ) ;
  1921.                 if (dwHelpID > 0)
  1922.                 {
  1923.                     str.Format( _T(", helpcontext(%#08.8x)"), dwHelpID ) ;
  1924.                     WRITE( str ) ;
  1925.                 }
  1926.             }
  1927.             else if (dwHelpID > 0)
  1928.             {
  1929.                 if (fAttributes == FALSE)
  1930.                     WRITE("[") ;
  1931.                 else
  1932.                     WRITE(", ") ;
  1933.                 fAttributes = TRUE ;
  1934.                 str.Format( _T("helpcontext(%#08.8x)"), dwHelpID ) ;
  1935.                 WRITE( str ) ;
  1936.             }
  1937.         }
  1938.  
  1939.         if (fAttributes)
  1940.             WRITE("] ") ;
  1941.         UINT cNames ;
  1942.         if (FAILED( hr = pti->GetNames( pvardesc->memid, rgbstrNames, 1, (UINT FAR*)&cNames )))
  1943.             AfxThrowOleException( hr ) ;
  1944.  
  1945.         CString str ;
  1946.         if ((pvardesc->elemdescVar.tdesc.vt & 0x0FFF) == VT_CARRAY)
  1947.         {
  1948.             // type name[n]
  1949.             WRITE(TYPEDESCtoString( pti, &pvardesc->elemdescVar.tdesc.lpadesc->tdescElem )) ;
  1950.             WRITE(" ") ;
  1951.             if (rgbstrNames[0])
  1952.                 WRITEBSTR(rgbstrNames[0]);
  1953.             else
  1954.                 WRITE(_T("(nameless)")) ;
  1955.             // Allocate cDims * lstrlen("[123456]")
  1956.             for (USHORT n = 0 ; n < pvardesc->elemdescVar.tdesc.lpadesc->cDims ; n++)
  1957.             {
  1958.                 str.Format( _T("[%d]"), pvardesc->elemdescVar.tdesc.lpadesc->rgbounds[n].cElements ) ;
  1959.                 WRITE(str) ;
  1960.             }
  1961.         }
  1962.         else
  1963.         {
  1964.             WRITE(TYPEDESCtoString( pti, &pvardesc->elemdescVar.tdesc ) + _T(" "));
  1965.             if (rgbstrNames[0])
  1966.                 WRITEBSTR(rgbstrNames[0]);
  1967.             else
  1968.                 WRITE(_T("(nameless)")) ;
  1969.         }
  1970.         WRITECR(";") ;
  1971.  
  1972.         if (bstrName)
  1973.             SysFreeString( bstrName ) ;
  1974.         if (bstrDoc)
  1975.             SysFreeString( bstrDoc ) ;
  1976.         if (bstrHelp)
  1977.             SysFreeString( bstrHelp ) ;
  1978.  
  1979.         pti->ReleaseVarDesc( pvardesc ) ;
  1980.     }
  1981.     CATCH(CException, pException)
  1982.     {
  1983.         if (bstrName)
  1984.             SysFreeString( bstrName ) ;
  1985.         if (bstrDoc)
  1986.             SysFreeString( bstrDoc ) ;
  1987.         if (bstrHelp)
  1988.             SysFreeString( bstrHelp ) ;
  1989.         if (pvardesc)
  1990.             pti->ReleaseVarDesc( pvardesc ) ;
  1991.  
  1992.         THROW_LAST();
  1993.     }
  1994.     END_CATCH
  1995.  
  1996.     return hr ;
  1997. }
  1998.  
  1999. // if fConst ==  TURE
  2000. //  const type name = value ;
  2001. // else
  2002. //  name = value  (no commas)
  2003. //
  2004. HRESULT CTypeLibODLView::DeCompileConst( IStream* pstm, ITypeInfo* pti, MEMBERID memid, UINT uiIndent /* = 0 */, BOOL fConst /* = TRUE */  )
  2005. {
  2006.     HRESULT     hr = S_OK ;
  2007.     TYPEATTR*       pattr = NULL ;
  2008.     ASSERT(pti) ;
  2009.  
  2010.     TRY
  2011.     {
  2012.         if (FAILED(hr = pti->GetTypeAttr( &pattr)))
  2013.             AfxThrowOleException( hr ) ;
  2014.  
  2015.         if (FAILED(hr = DumpConst( pstm, pti, pattr, memid, uiIndent, fConst )))
  2016.             AfxThrowOleException( hr ) ;
  2017.  
  2018.         pti->ReleaseTypeAttr( pattr ) ;
  2019.     }
  2020.     CATCH(CException, pException)
  2021.     {
  2022.         if (pattr)
  2023.             pti->ReleaseTypeAttr( pattr ) ;
  2024.         THROW_LAST();
  2025.     }
  2026.     END_CATCH
  2027.  
  2028.     return hr ;
  2029. }
  2030.  
  2031. HRESULT CTypeLibODLView::DumpConst( IStream* pstm, ITypeInfo* pti, TYPEATTR* pattr, MEMBERID memid, UINT uiIndent /* = 0 */, BOOL fConst /* = TRUE */  )
  2032. {
  2033.     USES_CONVERSION;
  2034.     HRESULT     hr = S_OK ;
  2035.     VARDESC*    pvardesc = NULL ;
  2036.     BSTR            rgbstrNames[1] ;
  2037.     BSTR            bstrName = NULL ;
  2038.     BSTR            bstrDoc = NULL ;
  2039.     BSTR            bstrHelp = NULL ;
  2040.     DWORD           dwHelpID ;
  2041.     ASSERT(pti) ;
  2042.     VARIANT varValue ;
  2043.     VariantInit( &varValue ) ;
  2044.  
  2045.     TRY
  2046.     {
  2047.         if (FAILED(hr = pti->GetVarDesc( memid, &pvardesc )))
  2048.             AfxThrowOleException( hr ) ;
  2049.  
  2050.         ASSERT(pvardesc->varkind == VAR_CONST) ;
  2051.  
  2052.         CString str = TYPEDESCtoString( pti, &pvardesc->elemdescVar.tdesc ) ;
  2053.         if (FAILED(hr = VariantChangeType( &varValue, pvardesc->lpvarValue, 0, VT_BSTR )))
  2054.         {
  2055.             if (pvardesc->lpvarValue->vt == VT_ERROR || pvardesc->lpvarValue->vt == VT_HRESULT)
  2056.             {
  2057.                 varValue.vt = VT_BSTR ;
  2058.                 varValue.bstrVal = ::SysAllocString(T2OLE(_GetScodeString(pvardesc->lpvarValue->scode))) ;
  2059.                 hr = S_OK ;
  2060.             }
  2061.             else
  2062.                 AfxThrowOleException( hr ) ;
  2063.         }
  2064.  
  2065.         BOOL fIndent = FALSE ;
  2066.         if (fConst)
  2067.         {
  2068.             CString str ;
  2069.             if (pattr->typekind == TKIND_MODULE)
  2070.             {
  2071.                 str.Format(_T("[entry(%d)"), memid) ;
  2072.                 WRITE1(str) ;
  2073.                 fIndent = TRUE ;
  2074.             }
  2075.  
  2076.             // [helpstring("<helpstring>"), helpcontext(<id>)] const type name = expression ;
  2077.             if (SUCCEEDED(pti->GetDocumentation( pvardesc->memid, &bstrName, &bstrDoc, &dwHelpID, &bstrHelp )))
  2078.             {
  2079.                 if (bstrDoc && *bstrDoc)
  2080.                 {
  2081.                     if (!fIndent)
  2082.                         WRITE1("[") ;
  2083.                     else
  2084.                         WRITE(", ") ;
  2085.                     LPCTSTR lpszDoc = OLE2CT(bstrDoc);
  2086.                     ::SysFreeString(bstrDoc);
  2087.                     bstrDoc = NULL;
  2088.                     str.Format( _T("helpstring(\"%s\")"), lpszDoc ) ;
  2089.                     WRITE( str ) ;
  2090.                     if (dwHelpID > 0)
  2091.                     {
  2092.                         str.Format( _T(", helpcontext(%#08.8x)"), dwHelpID ) ;
  2093.                         WRITE( str ) ;
  2094.                     }
  2095.                     WRITE("] ");
  2096.                     fIndent = TRUE ;
  2097.                 }
  2098.                 else if (dwHelpID > 0)
  2099.                 {
  2100.                     if (!fIndent)
  2101.                         WRITE1("[") ;
  2102.                     else
  2103.                         WRITE(", ") ;
  2104.                     str.Format( _T("helpcontext(%#08.8x)] "), dwHelpID ) ;
  2105.                     WRITE( str ) ;
  2106.                     fIndent = TRUE ;
  2107.                 }
  2108.             }
  2109.         }
  2110.  
  2111.         UINT cNames ;
  2112.         if (FAILED( hr = pti->GetNames( pvardesc->memid, rgbstrNames, 1, (UINT FAR*)&cNames )))
  2113.             AfxThrowOleException( hr ) ;
  2114.  
  2115.         if (fConst)
  2116.         {
  2117.             if (!fIndent)
  2118.                 WRITE1(_T("")) ;
  2119.             WRITE("const ") ; WRITE( str ) ; WRITE( " " ) ;
  2120.         }
  2121.         else
  2122.             WRITE1("") ;
  2123.  
  2124.         WRITEBSTR( rgbstrNames[0] ) ; WRITE( " = " ) ;
  2125.  
  2126.         if (pvardesc->lpvarValue->vt == VT_BSTR)
  2127.         {
  2128.             WRITE( "\"" ) ;
  2129.             WRITEBSTR( varValue.bstrVal ) ;
  2130.             WRITE( "\"" ) ;
  2131.         }
  2132.         else
  2133.             WRITEBSTR( varValue.bstrVal) ;
  2134.  
  2135.         if (fConst)
  2136.             WRITECR(";") ;
  2137.  
  2138.         VariantClear( &varValue ) ;
  2139.  
  2140.         if (bstrName)
  2141.             SysFreeString( bstrName ) ;
  2142.         if (bstrDoc)
  2143.             SysFreeString( bstrDoc ) ;
  2144.         if (bstrHelp)
  2145.             SysFreeString( bstrHelp ) ;
  2146.         pti->ReleaseVarDesc( pvardesc ) ;
  2147.     }
  2148.     CATCH(CException, pException)
  2149.     {
  2150.         VariantClear( &varValue ) ;
  2151.         if (bstrName)
  2152.             SysFreeString( bstrName ) ;
  2153.         if (bstrDoc)
  2154.             SysFreeString( bstrDoc ) ;
  2155.         if (bstrHelp)
  2156.             SysFreeString( bstrHelp ) ;
  2157.         if (pvardesc)
  2158.             pti->ReleaseVarDesc( pvardesc ) ;
  2159.  
  2160.         THROW_LAST();
  2161.     }
  2162.     END_CATCH
  2163.  
  2164.     return hr ;
  2165. }
  2166.  
  2167. IStream* CreateMemoryStream()
  2168. {
  2169.     LPSTREAM lpStream = NULL;
  2170.  
  2171.     // Create a stream object on a memory block.
  2172.     HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE, 0);
  2173.     if (hGlobal != NULL)
  2174.     {
  2175.         HRESULT hr ;
  2176.         if (FAILED(hr = CreateStreamOnHGlobal(hGlobal, TRUE, &lpStream)))
  2177.         {
  2178.             TRACE0("CreateStreamOnHGlobal failed.\n");
  2179.             GlobalFree(hGlobal);
  2180.             AfxThrowOleException( hr ) ;
  2181.         }
  2182.     }
  2183.     else
  2184.     {
  2185.         TRACE0("Failed to allocate memory for stream.\n");
  2186.         AfxThrowMemoryException() ;
  2187.     }
  2188.  
  2189.     return lpStream;
  2190. }
  2191.  
  2192. int StringFromGUID2T(REFGUID rguid, LPTSTR lpszGUID, int cbMax )
  2193. {
  2194.     USES_CONVERSION;
  2195.     OLECHAR* lpszOle = (OLECHAR*)_alloca(cbMax*sizeof(OLECHAR));
  2196.     int nCount = ::StringFromGUID2(rguid,lpszOle, cbMax*sizeof(OLECHAR));
  2197.     if (nCount == 0)
  2198.     {
  2199.         lpszGUID[0] = '\0';
  2200.         return 0; // buffer too small for the returned string
  2201.     }
  2202.     LPTSTR lpszRes = OLE2T(lpszOle);
  2203.     lstrcpy(lpszGUID, lpszRes);
  2204.     return 0;
  2205. }
  2206.