⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 atldispa.h

📁 remote debug and compile tools
💻 H
📖 第 1 页 / 共 2 页
字号:
   }
};


/////////////////////////////////////////////////////////////////////////////
// CComDynTypeInfoHolder

template< class T >
class CComDynTypeInfoHolder
{
// Should be 'protected' but can cause compiler to generate fat code.
public:
   const GUID* m_pguid;
   const GUID* m_plibid;
   WORD m_wMajor;
   WORD m_wMinor;
   ITypeInfo* m_pInfo;
   long m_dwRef;
   struct stringdispid
   {
      CComBSTR bstr;
      int nLen;
      DISPID id;
   };
   stringdispid* m_pCache;
   int m_nArgs;
   // The above members must be present in that order because they
   // are initialized by ATL (as a static member)
   INTERFACEDATA* m_pITF;

public:
   HRESULT GetTI(LCID lcid, ITypeInfo** ppInfo)
   {
      HRESULT Hr = S_OK;
      if( m_pInfo==NULL ) Hr = GetTI(lcid);
      *ppInfo = m_pInfo;
      if( m_pInfo!=NULL ) {
         m_pInfo->AddRef();
         Hr = S_OK;
      }
      return Hr;
   }
   HRESULT GetTI(LCID lcid);
   HRESULT EnsureTI(LCID lcid)
   {
      HRESULT Hr = S_OK;
      if( m_pInfo==NULL ) Hr = GetTI(lcid);
      return Hr;
   }

   // This function is called by the module on exit
   // It is registered through _Module.AddTermFunc()
   static void __stdcall Cleanup(DWORD dw)
   {
      CComDynTypeInfoHolder* p = (CComDynTypeInfoHolder*)dw;
      if( p->m_pInfo != NULL ) {
         p->m_pInfo->Release();
         p->m_pInfo = NULL;
         // Release internal interface block
         for( UINT i=0; i<p->m_pITF->cMembers; i++ ) delete [] p->m_pITF->pmethdata[i].ppdata;
         delete [] p->m_pITF->pmethdata;
         delete p->m_pITF;
      }
      if( p->m_pCache != NULL ) {
         delete [] p->m_pCache;
         p->m_pCache = NULL;
      }
   }

   HRESULT GetTypeInfo(UINT /*itinfo*/, LCID lcid, ITypeInfo** pptinfo)
   {
      HRESULT Hr = E_POINTER;
      if( pptinfo!=NULL ) Hr = GetTI(lcid, pptinfo);
      return Hr;
   }
   HRESULT GetIDsOfNames(REFIID /*riid*/, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid)
   {
      HRESULT Hr = EnsureTI(lcid);
      if( m_pInfo != NULL ) {
         for( int i=0; i<(int)cNames; i++ ) {
            int n = ocslen(rgszNames[i]);
            for( int j=0; j<m_nArgs; j++ ) {
               if( (n==m_pCache[j].nLen) &&
                   (memcmp(m_pCache[j].bstr, rgszNames[i], m_pCache[j].nLen * sizeof(OLECHAR)) == 0) )
               {
                  rgdispid[i] = m_pCache[j].id;
                  break;
               }
            }
            if( j==m_nArgs) {
               Hr = m_pInfo->GetIDsOfNames(rgszNames, cNames, rgdispid);
               if( FAILED(Hr) ) break;
            }
         }
      }
      return Hr;
   }

   HRESULT Invoke(IDispatch* p, DISPID dispidMember, REFIID /*riid*/,
      LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult,
      EXCEPINFO* /*pexcepinfo*/, UINT* /*puArgErr*/)
   {
      HRESULT Hr = EnsureTI(lcid);
      if( m_pInfo != NULL ) {
         // As Chris Sells so elegantly put it in his dispimpl2.h sample
         // the ATL library assumes that the methods are always placed on 
         // the IDispatch interface. So instead we implement our own Invoke(),
         // (much in dismay of the documentation of IDispatch::Invoke in Platform SDK).
/*
         Hr = m_pInfo->Invoke(p, dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);         
*/
/*
         T *pT = (T*)(p);
         Hr = m_pInfo->Invoke(pT, dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);         
*/
         if( (DISPATCH_PROPERTYPUT!=wFlags) && (pdispparams->cNamedArgs>0) ) return DISP_E_NONAMEDARGS;
         const _ATL_DISPATCH_ENTRY<T>* pMap = T::_GetDispMap();
         DISPID i = 1;
         while( pMap->pfn!=NULL ) {
            DISPID dispid = pMap->dispid==DISPID_UNKNOWN ? i : pMap->dispid;
            if( dispidMember==dispid ) {
               if( (DISPATCH_PROPERTYPUT==wFlags) && (DISPID_PROPERTYPUT==(pMap+1)->dispid) ) 
                  pMap++;
               VARTYPE* pArgs = (VARTYPE*) pMap->vtArgs;
               if( pArgs == NULL ) pArgs = (VARTYPE*) &pMap->vtSingle;
               UINT nArgs = pMap->nArgs;
               if( pdispparams->cArgs!=nArgs ) return DISP_E_BADPARAMCOUNT;
               VARIANTARG** ppVarArgs = nArgs ? (VARIANTARG**)_alloca(sizeof(VARIANTARG*)*nArgs) : NULL;
               VARIANTARG* pVarArgs = nArgs ? (VARIANTARG*)_alloca(sizeof(VARIANTARG)*nArgs) : NULL;
               UINT i;
               for( i=0; i<nArgs; i++ ) {
                  ppVarArgs[i] = &pVarArgs[i];
                  ::VariantInit(&pVarArgs[i]);
                  if( FAILED(::VariantCopyInd(&pVarArgs[i], &pdispparams->rgvarg[nArgs-i-1])) ) return DISP_E_TYPEMISMATCH;
                  if( FAILED(::VariantChangeType(&pVarArgs[i], &pVarArgs[i], 0, pArgs[i])) ) return DISP_E_TYPEMISMATCH;
               }
               T *pT = static_cast<T*>(p);
               CComStdCallThunk<T> thunk;
               thunk.Init(pMap->pfn, pT);
               CComVariant tmpResult;
               if( pvarResult==NULL ) pvarResult = &tmpResult;
               HRESULT Hr = ::DispCallFunc(
                  &thunk,
                  0,
                  CC_STDCALL,
                  pMap->vtReturn,
                  nArgs,
                  pArgs,
                  nArgs ? ppVarArgs : NULL,
                  pvarResult);
               for( i=0; i<nArgs; i++ ) ::VariantClear(&pVarArgs[i]);
               return Hr;
            }
            i++;
            pMap++;
         }
         return DISP_E_MEMBERNOTFOUND;
      }
      return Hr;
   }
   HRESULT LoadNameCache(ITypeInfo* /*pTypeInfo*/)
   {
      // A name cache is really not useful here since we already have
      // a fine map of the names. Oh well...
      const _ATL_DISPATCH_ENTRY<T>* pTemp, *pMap = T::_GetDispMap();
      pTemp = pMap;
      m_nArgs = 0;      
      while( pTemp->pfn!=NULL ) {
         m_nArgs++;
         pTemp++;
      }
      m_pCache = m_nArgs==0 ? NULL : new stringdispid[m_nArgs];
      DISPID i = 0;
      while( pMap->pfn!=NULL ) {
         m_pCache[i].bstr = pMap->szName;
         m_pCache[i].nLen = ::SysStringLen(m_pCache[i].bstr);
         m_pCache[i].id = pMap->dispid==DISPID_UNKNOWN ? i+1 : pMap->dispid;
         // NOTE: In case of DISPID_PROPERTYPUT we assume that a name entry 
         // exists before it, which will have the correct DISPID.
         pMap++;
         i++;
      }
      return S_OK;
   }
};

template< class T >
inline HRESULT CComDynTypeInfoHolder<T>::GetTI(LCID lcid)
{   
   const _ATL_DISPATCH_ENTRY<T>* pTemp, *pMap = T::_GetDispMap();
   pTemp = pMap;
   UINT nArgs = 0;
   while( pTemp->pfn!=NULL ) {
      nArgs++;
      pTemp++;
   }
   // Create INTERFACEDATA structures.
   // HACK: They cannot be created on the stack. Seems that the ancient
   //       CreateDispTypeInfo() method uses weak references?!
   m_pITF = new INTERFACEDATA;
   m_pITF->cMembers = nArgs;
   METHODDATA* pM = m_pITF->pmethdata = new METHODDATA[nArgs];
   DISPID dispid = 1;
   DISPID oldid = 0;
   LONG i = 0; // Method index
   while( pMap->pfn!=NULL ) {
      pM->szName = pMap->szName;
      pM->dispid = pMap->dispid==DISPID_UNKNOWN ? dispid : pMap->dispid;
      if( pMap->dispid==DISPID_PROPERTYPUT ) pM->dispid = oldid; // Support hack in our DISP_PROP macro
      pM->iMeth = i;
      pM->cc = CC_STDCALL;
      pM->ppdata = NULL;
      pM->cArgs = pMap->nArgs;
      if( pMap->nArgs>0 ) {
         PARAMDATA* pParams = pM->ppdata = new PARAMDATA[pMap->nArgs];
         for( UINT j=0; j<pMap->nArgs; j++ ) {
            pParams->szName = NULL;
            pParams->vt = pMap->vtArgs != NULL ? pMap->vtArgs[j] : pMap->vtSingle;
            pParams++;
         }
      }
      pM->wFlags = (USHORT) pMap->wFlags;
      pM->vtReturn = pMap->vtReturn;
      // Next entry..
      oldid = pM->dispid;
      dispid++;
      i++;
      pM++;
      pMap++;
   }
   HRESULT Hr = ::CreateDispTypeInfo(m_pITF, lcid, &m_pInfo);
   // The result of CreateDispTypeInfo() is very disappointing. It
   // doesn't create a full ITypeInfo object, so calling ITypeInfo::GetTypeAttr()
   // claims that there are NO methods and properties in the list (?).
   // This basically renders the idea of creating a CComTypeInfoHolder clone
   // useless. I might as well have done a better IDispatch impl instead.
   if( SUCCEEDED(Hr) ) {
      LoadNameCache(m_pInfo);
      _Module.AddTermFunc(Cleanup, (DWORD)this);
   }
   return Hr;
};


#endif // !defined(AFX_ATLDISPA_H__20010608_7B20_BD08_5EED_0080AD509054__INCLUDED_)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -