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

  1. #include "StdAfx.H"
  2. #include "TestCon.H"
  3.  
  4. #ifdef _DEBUG
  5. #define new DEBUG_NEW
  6. #undef THIS_FILE
  7. static char THIS_FILE[] = __FILE__;
  8. #endif
  9.  
  10. CMethodParamInfo::CMethodParamInfo() :
  11.    m_vt( VT_EMPTY )
  12. {
  13. }
  14.  
  15. CMethodParamInfo::~CMethodParamInfo()
  16. {
  17. }
  18.  
  19. CString CMethodParamInfo::GetName() const
  20. {
  21.    return( m_strName );
  22. }
  23.  
  24. VARTYPE CMethodParamInfo::GetType() const
  25. {
  26.    return( m_vt );
  27. }
  28.  
  29. HRESULT CMethodParamInfo::Init( LPCOLESTR pszName, const ELEMDESC* pElemDesc )
  30. {
  31.    m_strName = pszName;
  32.    m_vt = pElemDesc->tdesc.vt;
  33.  
  34.    return( S_OK );
  35. }
  36.  
  37.  
  38. CMethodInfo::CMethodInfo() :
  39.    m_tLog( TRUE ),
  40.    m_tLogEditRequests( TRUE ),
  41.    m_eRequestEditResponse( REQUESTEDIT_ALWAYS )
  42. {
  43. }
  44.  
  45. CMethodInfo::~CMethodInfo()
  46. {
  47.    int iParam;
  48.  
  49.    for( iParam = 0; iParam < m_apParamInfo.GetSize(); iParam++ )
  50.    {
  51.       delete m_apParamInfo[iParam];
  52.    }
  53. }
  54.  
  55. void CMethodInfo::EnableEditRequestLogging( BOOL tEnable )
  56. {
  57.    m_tLogEditRequests = tEnable;
  58. }
  59.  
  60. void CMethodInfo::EnableLogging( BOOL tEnable )
  61. {
  62.    m_tLog = tEnable;
  63. }
  64.  
  65. DISPID CMethodInfo::GetID() const
  66. {
  67.    return( m_dispid );
  68. }
  69.  
  70. INVOKEKIND CMethodInfo::GetInvokeKind() const
  71. {
  72.    return( m_invkind );
  73. }
  74.  
  75. CString CMethodInfo::GetName() const
  76. {
  77.    return( m_strName );
  78. }
  79.  
  80. int CMethodInfo::GetNumParams() const
  81. {
  82.    return( m_apParamInfo.GetSize() );
  83. }
  84.  
  85. CMethodParamInfo* CMethodInfo::GetParam( int iParam ) const
  86. {
  87.    return( m_apParamInfo[iParam] );
  88. }
  89.  
  90. int CMethodInfo::GetRequestEditResponse() const
  91. {
  92.    return( m_eRequestEditResponse );
  93. }
  94.  
  95. HRESULT CMethodInfo::Init( ITypeInfo* pTypeInfo, const FUNCDESC* pFuncDesc )
  96. {
  97.    USES_CONVERSION;
  98.    HRESULT hResult;
  99.    BSTR* pbstrNames;
  100.    UINT nNames;
  101.    int iParam;
  102.    UINT iName;
  103.    LPCOLESTR pszParamName;
  104.    CString strPropertyValue;
  105.  
  106.    ASSERT( pTypeInfo != NULL );
  107.    ASSERT( pFuncDesc != NULL );
  108.  
  109.    m_dispid = pFuncDesc->memid;
  110.    m_invkind = pFuncDesc->invkind;
  111.    m_tBindable = pFuncDesc->wFuncFlags&FUNCFLAG_FBINDABLE;
  112.    m_tRequestEdit = pFuncDesc->wFuncFlags&FUNCFLAG_FREQUESTEDIT;
  113.  
  114.    m_apParamInfo.SetSize( pFuncDesc->cParams );
  115.    for( iParam = 0; iParam < m_apParamInfo.GetSize(); iParam++ )
  116.    {
  117.       m_apParamInfo[iParam] = new CMethodParamInfo;
  118.       if( m_apParamInfo[iParam] == NULL )
  119.       {
  120.          return( E_OUTOFMEMORY );
  121.       }
  122.    }
  123.  
  124.    pbstrNames = (BSTR*)alloca( (pFuncDesc->cParams+1)*sizeof( BSTR ) );
  125.    for( iName = 0; iName < UINT( pFuncDesc->cParams+1 ); iName++ )
  126.    {
  127.       pbstrNames[iName] = NULL;
  128.    }
  129.  
  130.    hResult = pTypeInfo->GetNames( m_dispid, pbstrNames, pFuncDesc->cParams+1,
  131.       &nNames );
  132.    if( FAILED( hResult ) )
  133.    {
  134.       return( hResult );
  135.    }
  136.    ASSERT( nNames > 0 );
  137.  
  138.    m_strName = pbstrNames[0];
  139.    TRACE( "  Method: %s ", LPCTSTR( m_strName ) );
  140.    switch( m_invkind )
  141.    {
  142.    case INVOKE_FUNC:
  143.       ASSERT( nNames == UINT( pFuncDesc->cParams+1 ) );
  144.       break;
  145.  
  146.    case INVOKE_PROPERTYGET:
  147.       ASSERT( nNames == UINT( pFuncDesc->cParams+1 ) );
  148.       break;
  149.  
  150.    case INVOKE_PROPERTYPUT:
  151.       ASSERT( nNames == UINT( pFuncDesc->cParams ) );
  152.       break;
  153.  
  154.    case INVOKE_PROPERTYPUTREF:
  155.       ASSERT( nNames == UINT( pFuncDesc->cParams ) );
  156.       break;
  157.  
  158.    default:
  159.       ASSERT( FALSE );
  160.       break;
  161.    }
  162.    for( iParam = 0; iParam < m_apParamInfo.GetSize(); iParam++ )
  163.    {
  164.       if( pbstrNames[iParam+1] == NULL )
  165.       {
  166.          // This must be the right-hand side of a property put or putref.
  167.          strPropertyValue.LoadString( IDS_PROPERTYVALUE );
  168.          pszParamName = T2OLE( LPCTSTR( strPropertyValue ) );
  169.       }
  170.       else
  171.       {
  172.          pszParamName = pbstrNames[iParam+1];
  173.       }
  174.       m_apParamInfo[iParam]->Init( pszParamName,
  175.          &pFuncDesc->lprgelemdescParam[iParam] );
  176.    }
  177.  
  178.    for( iName = 0; iName < UINT( pFuncDesc->cParams+1 ); iName++ )
  179.    {
  180.       if( pbstrNames[iName] != NULL )
  181.       {
  182.          ::SysFreeString( pbstrNames[iName] );
  183.       }
  184.    }
  185.  
  186.    return( S_OK );
  187. }
  188.  
  189. HRESULT CMethodInfo::InitPropertyGet( ITypeInfo* pTypeInfo,
  190.    const VARDESC* pVarDesc )
  191. {
  192.    HRESULT hResult;
  193.    BSTR bstrName;
  194.    UINT nNames;
  195.  
  196.    _ASSERTE( pTypeInfo != NULL );
  197.    _ASSERTE( pVarDesc != NULL );
  198.  
  199.    m_dispid = pVarDesc->memid;
  200.    m_invkind = INVOKE_PROPERTYGET;
  201.    m_tBindable = pVarDesc->wVarFlags&VARFLAG_FBINDABLE;
  202.    m_tRequestEdit = pVarDesc->wVarFlags&FUNCFLAG_FREQUESTEDIT;
  203.  
  204.    bstrName = NULL;
  205.    hResult = pTypeInfo->GetNames( m_dispid, &bstrName, 1, &nNames );
  206.    if( FAILED( hResult ) )
  207.    {
  208.       return( hResult );
  209.    }
  210.    ASSERT( nNames == 1 );
  211.  
  212.    m_strName = bstrName;
  213.    SysFreeString( bstrName );
  214.  
  215.    return( S_OK );
  216. }
  217.  
  218. HRESULT CMethodInfo::InitPropertyPut( ITypeInfo* pTypeInfo,
  219.    const VARDESC* pVarDesc )
  220. {
  221.    USES_CONVERSION;
  222.    CString strPropertyValue;
  223.    HRESULT hResult;
  224.    BSTR bstrName;
  225.    UINT nNames;
  226.  
  227.    _ASSERTE( pTypeInfo != NULL );
  228.    _ASSERTE( pVarDesc != NULL );
  229.  
  230.    m_dispid = pVarDesc->memid;
  231.    m_invkind = INVOKE_PROPERTYPUT;
  232.    m_tBindable = pVarDesc->wVarFlags&VARFLAG_FBINDABLE;
  233.    m_tRequestEdit = pVarDesc->wVarFlags&FUNCFLAG_FREQUESTEDIT;
  234.  
  235.    bstrName = NULL;
  236.    hResult = pTypeInfo->GetNames( m_dispid, &bstrName, 1, &nNames );
  237.    if( FAILED( hResult ) )
  238.    {
  239.       return( hResult );
  240.    }
  241.    ASSERT( nNames == 1 );
  242.  
  243.    m_strName = bstrName;
  244.    SysFreeString( bstrName );
  245.  
  246.    m_apParamInfo.SetSize( 1 );
  247.    m_apParamInfo[0] = new CMethodParamInfo;
  248.    if( m_apParamInfo[0] == NULL )
  249.    {
  250.       return( E_OUTOFMEMORY );
  251.    }
  252.  
  253.    strPropertyValue.LoadString( IDS_PROPERTYVALUE );
  254.  
  255.    m_apParamInfo[0]->Init( T2COLE( LPCTSTR( strPropertyValue ) ),
  256.       &pVarDesc->elemdescVar );
  257.  
  258.    return( S_OK );
  259. }
  260.  
  261. BOOL CMethodInfo::IsBindable() const
  262. {
  263.    return( m_tBindable );
  264. }
  265.  
  266. BOOL CMethodInfo::IsLogged() const
  267. {
  268.    return( m_tLog );
  269. }
  270.  
  271. BOOL CMethodInfo::LogEditRequests() const
  272. {
  273.    return( m_tLogEditRequests );
  274. }
  275.  
  276. void CMethodInfo::LogEvent( CLog& log, DISPPARAMS* pdpParams )
  277. {
  278.    int iParam;
  279.    CMethodParamInfo* pParamInfo;
  280.    COleVariant varParamValue;
  281.  
  282.    log<<m_strName<<_T( " " );
  283.  
  284.    if( pdpParams->cArgs != UINT( m_apParamInfo.GetSize() ) )
  285.    {
  286.       log<<_T( "(Wrong number of arguments)\n" );
  287.    }
  288.    else
  289.    {
  290.       for( iParam = 0; iParam < m_apParamInfo.GetSize(); iParam++ )
  291.       {
  292.          pParamInfo = m_apParamInfo[iParam];
  293.          log<<_T( "{" )<<pParamInfo->GetName()<<_T( "=" );
  294.        try
  295.        {
  296.            varParamValue = pdpParams->rgvarg[pdpParams->cArgs-iParam-1];
  297.          log<<varParamValue;
  298.        }
  299.        catch( COleException* pException )
  300.        {
  301.           pException->Delete();
  302.        }
  303.          log<<_T( "}" );
  304.       }
  305.       log<<_T( "\n" );
  306.    }
  307. }
  308.  
  309. BOOL CMethodInfo::RequestsEdit() const
  310. {
  311.    return( m_tRequestEdit );
  312. }
  313.  
  314. void CMethodInfo::SetRequestEditResponse( int eResponse )
  315. {
  316.    m_eRequestEditResponse = eResponse;
  317. }
  318.  
  319.  
  320. CInterfaceInfo::CInterfaceInfo() :
  321.    m_iid( IID_NULL )
  322. {
  323. }
  324.  
  325. CInterfaceInfo::~CInterfaceInfo()
  326. {
  327.    int iMethod;
  328.  
  329.    for( iMethod = 0; iMethod < m_apMethodInfo.GetSize(); iMethod++ )
  330.    {
  331.       delete m_apMethodInfo[iMethod];
  332.    }
  333. }
  334.  
  335. CMethodInfo* CInterfaceInfo::FindMethod( DISPID dispid ) const
  336. {
  337.    int iMethod;
  338.  
  339.    for( iMethod = 0; iMethod < m_apMethodInfo.GetSize(); iMethod++ )
  340.    {
  341.       if( m_apMethodInfo[iMethod]->GetID() == dispid )
  342.       {
  343.          return( m_apMethodInfo[iMethod] );
  344.       }
  345.    }
  346.  
  347.    return( NULL );
  348. }
  349.  
  350. CMethodInfo* CInterfaceInfo::FindPropertyGet( DISPID dispid ) const
  351. {
  352.    int iMethod;
  353.    CMethodInfo* pMethodInfo;
  354.  
  355.    for( iMethod = 0; iMethod < m_apMethodInfo.GetSize(); iMethod++ )
  356.    {
  357.       pMethodInfo = m_apMethodInfo[iMethod];
  358.       if( (pMethodInfo->GetID() == dispid) && (pMethodInfo->GetInvokeKind() ==
  359.          INVOKE_PROPERTYGET) )
  360.       {
  361.          return( pMethodInfo );
  362.       }
  363.    }
  364.  
  365.    return( NULL );
  366. }
  367.  
  368. IID CInterfaceInfo::GetIID() const
  369. {
  370.    return( m_iid );
  371. }
  372.  
  373. CMethodInfo* CInterfaceInfo::GetMethod( int iMethod ) const
  374. {
  375.    return( m_apMethodInfo[iMethod] );
  376. }
  377.  
  378. int CInterfaceInfo::GetNumMethods() const
  379. {
  380.    return( m_apMethodInfo.GetSize() );
  381. }
  382.  
  383. HRESULT CInterfaceInfo::Init( ITypeInfo* pTypeInfo )
  384. {
  385.    HRESULT hResult;
  386.    CSmartTypeAttr pTypeAttr( pTypeInfo );
  387.    CSmartFuncDesc pFuncDesc( pTypeInfo );
  388.    CSmartVarDesc pVarDesc( pTypeInfo );
  389.    int iVar;
  390.    int iMethod;
  391.    int iDestMethod;
  392.    BOOL tFound;
  393.  
  394.    ASSERT( pTypeInfo != NULL );
  395.  
  396.    hResult = pTypeInfo->GetTypeAttr( &pTypeAttr );
  397.    if( FAILED( hResult ) )
  398.    {
  399.       return( hResult );
  400.    }
  401.  
  402.    m_iid = pTypeAttr->guid;
  403.  
  404.    // Allocate enough space for the maximum number of methods that we could
  405.    // possibly have, plus room for two methods for each property in case the
  406.    // type info doesn't specify properties as put and set methods.
  407.    m_apMethodInfo.SetSize( pTypeAttr->cFuncs+(2*pTypeAttr->cVars) );
  408.  
  409.    iDestMethod = 0;
  410.    for( iMethod = 0; iMethod < pTypeAttr->cFuncs; iMethod++ )
  411.    {
  412.       hResult = pTypeInfo->GetFuncDesc( iMethod, &pFuncDesc );
  413.       if( FAILED( hResult ) )
  414.       {
  415.          return( hResult );
  416.       }
  417.  
  418.       // Only add the function to our list if it is at least at nesting level
  419.       // 2 (i.e. defined in an interface derived from IDispatch).
  420.       if( !(pFuncDesc->wFuncFlags&FUNCFLAG_FRESTRICTED) &&
  421.          (pFuncDesc->funckind == FUNC_DISPATCH) )
  422.       {
  423.          m_apMethodInfo[iDestMethod] = new CMethodInfo;
  424.          if( m_apMethodInfo[iDestMethod] == NULL )
  425.          {
  426.             return( E_OUTOFMEMORY );
  427.          }
  428.          hResult = m_apMethodInfo[iDestMethod]->Init( pTypeInfo, pFuncDesc );
  429.          if( FAILED( hResult ) )
  430.          {
  431.             return( hResult );
  432.          }
  433.          iDestMethod++;
  434.       }
  435.       pFuncDesc.Release();
  436.    }
  437.  
  438.    for( iVar = 0; iVar < pTypeAttr->cVars; iVar++ )
  439.    {
  440.       hResult = pTypeInfo->GetVarDesc( iVar, &pVarDesc );
  441.       if( FAILED( hResult ) )
  442.       {
  443.          return( hResult );
  444.       }
  445.  
  446.       if( (pVarDesc->varkind == VAR_DISPATCH) && !(pVarDesc->wVarFlags&
  447.          VARFLAG_FRESTRICTED) )
  448.       {
  449.          tFound = FALSE;
  450.          for( iMethod = 0; iMethod < iDestMethod; iMethod++ )
  451.          {
  452.             if( (m_apMethodInfo[iMethod]->GetID() == pVarDesc->memid) &&
  453.                (m_apMethodInfo[iMethod]->GetInvokeKind() ==
  454.                INVOKE_PROPERTYGET) )
  455.             {
  456.                tFound = TRUE;
  457.             }
  458.          }
  459.  
  460.          if( !tFound )
  461.          {
  462.             // We haven't already added this one as a method, so do it now.
  463.  
  464.             m_apMethodInfo[iDestMethod] = new CMethodInfo;
  465.             if( m_apMethodInfo[iDestMethod] == NULL )
  466.             {
  467.                return( E_OUTOFMEMORY );
  468.             }
  469.             hResult = m_apMethodInfo[iDestMethod]->InitPropertyGet( pTypeInfo,
  470.                pVarDesc );
  471.             if( FAILED( hResult ) )
  472.             {
  473.                return( hResult );
  474.             }
  475.             iDestMethod++;
  476.          }
  477.  
  478.          if( !(pVarDesc->wVarFlags&VARFLAG_FREADONLY) )
  479.          {
  480.             tFound = FALSE;
  481.             for( iMethod = 0; iMethod < iDestMethod; iMethod++ )
  482.             {
  483.                if( (m_apMethodInfo[iMethod]->GetID() == pVarDesc->memid) &&
  484.                   (m_apMethodInfo[iMethod]->GetInvokeKind() ==
  485.                   INVOKE_PROPERTYPUT) )
  486.                {
  487.                   tFound = TRUE;
  488.                }
  489.             }
  490.  
  491.             if( !tFound )
  492.             {
  493.                // We haven't already added this one as a method, so do it now.
  494.  
  495.                m_apMethodInfo[iDestMethod] = new CMethodInfo;
  496.                if( m_apMethodInfo[iDestMethod] == NULL )
  497.                {
  498.                   return( E_OUTOFMEMORY );
  499.                }
  500.                hResult = m_apMethodInfo[iDestMethod]->InitPropertyPut(
  501.                   pTypeInfo, pVarDesc );
  502.                if( FAILED( hResult ) )
  503.                {
  504.                   return( hResult );
  505.                }
  506.                iDestMethod++;
  507.             }
  508.          }
  509.       }
  510.  
  511.       pVarDesc.Release();
  512.    }
  513.  
  514.    // Trim the array down to the actual size.
  515.    m_apMethodInfo.SetSize( iDestMethod );
  516.  
  517.    return( S_OK );
  518. }
  519.