dspsprt.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 9k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. #include "priv.h"
  2. #include "dspsprt.h"
  3. /*
  4.  * CImpIDispatch::CImpIDispatch
  5.  * CImpIDispatch::~CImpIDispatch
  6.  *
  7.  * Parameters (Constructor):
  8.  *  piid    guid this IDispatch implementation is for
  9.  *          we call QueryInterface to get the interface
  10.  */
  11. CImpIDispatch::CImpIDispatch(const IID *plibid, USHORT wVerMajor, USHORT wVerMinor, const IID * piid)
  12. {
  13.     m_piid = piid;
  14.     m_plibid = plibid;
  15.     m_wVerMajor = wVerMajor;
  16.     m_wVerMinor = wVerMinor;
  17.     m_pITINeutral = NULL;
  18.     return;
  19. }
  20. CImpIDispatch::~CImpIDispatch(void)
  21. {
  22.     if (m_pITINeutral)
  23.     {
  24.         m_pITINeutral->Release();
  25.         m_pITINeutral = NULL;
  26.     }
  27.     return;
  28. }
  29. /*
  30.  * CImpIDispatch::GetTypeInfoCount
  31.  *
  32.  * Purpose:
  33.  *  Returns the number of type information (ITypeInfo) interfaces
  34.  *  that the object provides (0 or 1).
  35.  *
  36.  * Parameters:
  37.  *  pctInfo         UINT * to the location to receive
  38.  *                  the count of interfaces.
  39.  *
  40.  * Return Value:
  41.  *  HRESULT         NOERROR or a general error code.
  42.  */
  43. STDMETHODIMP CImpIDispatch::GetTypeInfoCount(UINT *pctInfo)
  44. {
  45.     //We implement GetTypeInfo so return 1
  46.     *pctInfo=1;
  47.     return NOERROR;
  48. }
  49. //
  50. // helper function for pulling ITypeInfo out of our typelib
  51. //
  52. HRESULT GetTypeInfoFromLibId(LCID lcid, UUID libid, USHORT wVerMajor, USHORT wVerMinor, 
  53.                              UUID uuid, ITypeInfo **ppITypeInfo)
  54. {
  55.     HRESULT    hr;
  56.     ITypeLib  *pITypeLib;
  57.     // Just in case we can't find the type library anywhere
  58.     *ppITypeInfo = NULL;
  59.     /*
  60.      * The type libraries are registered under 0 (neutral),
  61.      * 7 (German), and 9 (English) with no specific sub-
  62.      * language, which would make them 407 or 409 and such.
  63.      * If you are sensitive to sub-languages, then use the
  64.      * full LCID instead of just the LANGID as done here.
  65.      */
  66.     hr=LoadRegTypeLib(libid, wVerMajor, wVerMinor, PRIMARYLANGID(lcid), &pITypeLib);
  67.     /*
  68.      * If LoadRegTypeLib fails, try loading directly with
  69.      * LoadTypeLib, which will register the library for us.
  70.      * Note that there's no default case here because the
  71.      * prior switch will have filtered lcid already.
  72.      *
  73.      * NOTE:  You should prepend your DIR registry key to the
  74.      * .TLB name so you don't depend on it being it the PATH.
  75.      * This sample will be updated later to reflect this.
  76.      */
  77.     if (FAILED(hr))
  78.     {
  79.         OLECHAR wszPath[MAX_PATH];
  80. #ifdef UNICODE
  81.         GetModuleFileName(HINST_THISDLL, wszPath, ARRAYSIZE(wszPath));
  82. #else
  83.         TCHAR szPath[MAX_PATH];
  84.         GetModuleFileName(HINST_THISDLL, szPath, ARRAYSIZE(szPath));
  85.         MultiByteToWideChar(CP_ACP, 0, szPath, -1, wszPath, ARRAYSIZE(wszPath));
  86. #endif
  87.         switch (PRIMARYLANGID(lcid))
  88.         {
  89.         case LANG_NEUTRAL:
  90.         case LANG_ENGLISH:
  91.             hr=LoadTypeLib(wszPath, &pITypeLib);
  92.             break;
  93.         }
  94.     }
  95.     if (SUCCEEDED(hr))
  96.     {
  97.         //Got the type lib, get type info for the interface we want
  98.         hr=pITypeLib->GetTypeInfoOfGuid(uuid, ppITypeInfo);
  99.         pITypeLib->Release();
  100.     }
  101.     return(hr);
  102. }
  103. /*
  104.  * CImpIDispatch::GetTypeInfo
  105.  *
  106.  * Purpose:
  107.  *  Retrieves type information for the automation interface.  This
  108.  *  is used anywhere that the right ITypeInfo interface is needed
  109.  *  for whatever LCID is applicable.  Specifically, this is used
  110.  *  from within GetIDsOfNames and Invoke.
  111.  *
  112.  * Parameters:
  113.  *  itInfo          UINT reserved.  Must be zero.
  114.  *  lcid            LCID providing the locale for the type
  115.  *                  information.  If the object does not support
  116.  *                  localization, this is ignored.
  117.  *  ppITypeInfo     ITypeInfo ** in which to store the ITypeInfo
  118.  *                  interface for the object.
  119.  *
  120.  * Return Value:
  121.  *  HRESULT         NOERROR or a general error code.
  122.  */
  123. STDMETHODIMP CImpIDispatch::GetTypeInfo(UINT itInfo, LCID lcid
  124.     , ITypeInfo **ppITypeInfo)
  125. {
  126.     ITypeInfo **ppITI;
  127.     *ppITypeInfo=NULL;
  128.     if (0!=itInfo)
  129.         return(TYPE_E_ELEMENTNOTFOUND);
  130.     // docs say we can ignore lcid if we support only one LCID
  131.     // we don't have to return DISP_E_UNKNOWNLCID if we're *ignoring* it
  132.     ppITI = &m_pITINeutral;
  133.     //Load a type lib if we don't have the information already.
  134.     if (NULL==*ppITI)
  135.     {
  136.         HRESULT    hr;
  137.         ITypeInfo *pITIDisp;
  138.         hr = GetTypeInfoFromLibId(lcid, *m_plibid, m_wVerMajor, m_wVerMinor, *m_piid, &pITIDisp);
  139.         if (SUCCEEDED(hr))
  140.         {
  141.             HRESULT hrT;
  142.             HREFTYPE hrefType;
  143.             // All our IDispatch implementations are DUAL. GetTypeInfoOfGuid
  144.             // returns the ITypeInfo of the IDispatch-part only. We need to
  145.             // find the ITypeInfo for the dual interface-part.
  146.             //
  147.             hrT = pITIDisp->GetRefTypeOfImplType(0xffffffff, &hrefType);
  148.             if (SUCCEEDED(hrT))
  149.             {
  150.                 hrT = pITIDisp->GetRefTypeInfo(hrefType, ppITI);
  151.             }
  152.             if (FAILED(hrT))
  153.             {
  154.                 // I suspect GetRefTypeOfImplType may fail if someone uses
  155.                 // CImpIDispatch on a non-dual interface. In this case the
  156.                 // ITypeInfo we got above is just fine to use.
  157.                 //
  158.                 *ppITI = pITIDisp;
  159.             }
  160.             else
  161.             {
  162.                 pITIDisp->Release();
  163.             }
  164.         }
  165.         if (FAILED(hr))
  166.             return hr;
  167.     }
  168.     /*
  169.      * Note:  the type library is still loaded since we have
  170.      * an ITypeInfo from it.
  171.      */
  172.     (*ppITI)->AddRef();
  173.     *ppITypeInfo=*ppITI;
  174.     return NOERROR;
  175. }
  176. /*
  177.  * CImpIDispatch::GetIDsOfNames
  178.  *
  179.  * Purpose:
  180.  *  Converts text names into DISPIDs to pass to Invoke
  181.  *
  182.  * Parameters:
  183.  *  riid            REFIID reserved.  Must be IID_NULL.
  184.  *  rgszNames       OLECHAR ** pointing to the array of names to be
  185.  *                  mapped.
  186.  *  cNames          UINT number of names to be mapped.
  187.  *  lcid            LCID of the locale.
  188.  *  rgDispID        DISPID * caller allocated array containing IDs
  189.  *                  corresponging to those names in rgszNames.
  190.  *
  191.  * Return Value:
  192.  *  HRESULT         NOERROR or a general error code.
  193.  */
  194. STDMETHODIMP CImpIDispatch::GetIDsOfNames(REFIID riid
  195.     , OLECHAR **rgszNames, UINT cNames, LCID lcid, DISPID *rgDispID)
  196. {
  197.     HRESULT     hr;
  198.     ITypeInfo  *pTI;
  199.     if (IID_NULL!=riid)
  200.         return(DISP_E_UNKNOWNINTERFACE);
  201.     //Get the right ITypeInfo for lcid.
  202.     hr=GetTypeInfo(0, lcid, &pTI);
  203.     if (SUCCEEDED(hr))
  204.     {
  205.         hr=pTI->GetIDsOfNames(rgszNames, cNames, rgDispID);
  206.         pTI->Release();
  207.     }
  208.     return hr;
  209. }
  210. /*
  211.  * CImpIDispatch::Invoke
  212.  *
  213.  * Purpose:
  214.  *  Calls a method in the dispatch interface or manipulates a
  215.  *  property.
  216.  *
  217.  * Parameters:
  218.  *  dispID          DISPID of the method or property of interest.
  219.  *  riid            REFIID reserved, must be IID_NULL.
  220.  *  lcid            LCID of the locale.
  221.  *  wFlags          USHORT describing the context of the invocation.
  222.  *  pDispParams     DISPPARAMS * to the array of arguments.
  223.  *  pVarResult      VARIANT * in which to store the result.  Is
  224.  *                  NULL if the caller is not interested.
  225.  *  pExcepInfo      EXCEPINFO * to exception information.
  226.  *  puArgErr        UINT * in which to store the index of an
  227.  *                  invalid parameter if DISP_E_TYPEMISMATCH
  228.  *                  is returned.
  229.  *
  230.  * Return Value:
  231.  *  HRESULT         NOERROR or a general error code.
  232.  */
  233. STDMETHODIMP CImpIDispatch::Invoke(DISPID dispID, REFIID riid
  234.     , LCID lcid, unsigned short wFlags, DISPPARAMS *pDispParams
  235.     , VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
  236. {
  237.     ITypeInfo  *pTI;
  238.     HRESULT hr;
  239.     //riid is supposed to be IID_NULL always
  240.     if (IID_NULL!=riid)
  241.         return(DISP_E_UNKNOWNINTERFACE);
  242.     IDispatch *pdisp;
  243.     hr=QueryInterface(*m_piid, (LPVOID*)&pdisp);
  244.     if (SUCCEEDED(hr))
  245.     {
  246.         //Get the ITypeInfo for lcid
  247.         hr=GetTypeInfo(0, lcid, &pTI);
  248.     
  249.         if (SUCCEEDED(hr))
  250.         {
  251.             //Clear exceptions
  252.             SetErrorInfo(0L, NULL);
  253.     
  254.             //This is exactly what DispInvoke does--so skip the overhead.
  255.             hr=pTI->Invoke(pdisp, dispID, wFlags
  256.                 , pDispParams, pVarResult, pExcepInfo, puArgErr);
  257.     
  258.             pTI->Release();
  259.         }
  260.         pdisp->Release();
  261.     }
  262.     return hr;
  263. }
  264. /*
  265.  * CImpIDispatch::Exception
  266.  *
  267.  * Purpose:
  268.  *  Raises an exception for CImpIDispatch::Invoke from within
  269.  *  ITypeInfo::Invoke using the CreateErrorInfo API and the
  270.  *  ICreateErrorInfo interface.
  271.  *
  272.  *  Note that this method doesn't allow for deferred filling
  273.  *  of an EXCEPINFO structure.
  274.  *
  275.  * Parameters:
  276.  *  wException      WORD exception code.
  277.  */
  278. void CImpIDispatch::Exception(WORD wException)
  279. {
  280. }