Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

199 lines
6.0 KiB

  1. #include "priv.h"
  2. #pragma hdrstop
  3. #include "dspsprt.h"
  4. #define TF_IDISPATCH 0
  5. EXTERN_C HINSTANCE g_hinst;
  6. CImpIDispatch::CImpIDispatch(REFGUID libid, USHORT wVerMajor, USHORT wVerMinor, REFIID riid) :
  7. m_libid(libid), m_wVerMajor(wVerMajor), m_wVerMinor(wVerMinor), m_riid(riid), m_pITINeutral(NULL)
  8. {
  9. ASSERT(NULL == m_pITINeutral);
  10. }
  11. CImpIDispatch::~CImpIDispatch(void)
  12. {
  13. ATOMICRELEASE(m_pITINeutral);
  14. }
  15. STDMETHODIMP CImpIDispatch::GetTypeInfoCount(UINT *pctInfo)
  16. {
  17. *pctInfo = 1;
  18. return S_OK;
  19. }
  20. // helper function for pulling ITypeInfo out of our typelib
  21. STDAPI GetTypeInfoFromLibId(LCID lcid, REFGUID libid, USHORT wVerMajor, USHORT wVerMinor,
  22. REFGUID uuid, ITypeInfo **ppITypeInfo)
  23. {
  24. *ppITypeInfo = NULL; // assume failure
  25. ITypeLib *pITypeLib;
  26. HRESULT hr;
  27. USHORT wResID;
  28. if (!IsEqualGUID(libid, GUID_NULL))
  29. {
  30. // The type libraries are registered under 0 (neutral),
  31. // 7 (German), and 9 (English) with no specific sub-
  32. // language, which would make them 407 or 409 and such.
  33. // If you are sensitive to sub-languages, then use the
  34. // full LCID instead of just the LANGID as done here.
  35. #ifdef DEBUG
  36. hr = E_FAIL; // force load through GetModuleFileName(), to get fusion 1.0 support
  37. #else
  38. hr = LoadRegTypeLib(libid, wVerMajor, wVerMinor, PRIMARYLANGID(lcid), &pITypeLib);
  39. #endif
  40. wResID = 0;
  41. }
  42. else
  43. {
  44. // If libid is GUID_NULL, then get type lib from module and use wVerMajor as
  45. // the resource ID (0 means use first type lib resource).
  46. pITypeLib = NULL;
  47. hr = E_FAIL;
  48. wResID = wVerMajor;
  49. }
  50. // If LoadRegTypeLib fails, try loading directly with LoadTypeLib.
  51. if (FAILED(hr) && g_hinst)
  52. {
  53. WCHAR wszPath[MAX_PATH];
  54. GetModuleFileNameWrapW(g_hinst, wszPath, ARRAYSIZE(wszPath));
  55. // Append resource ID to path, if specified.
  56. if (wResID)
  57. {
  58. WCHAR wszResStr[10];
  59. wnsprintfW(wszResStr, ARRAYSIZE(wszResStr), L"\\%d", wResID);
  60. StrCatBuffW(wszPath, wszResStr, ARRAYSIZE(wszPath));
  61. }
  62. switch (PRIMARYLANGID(lcid))
  63. {
  64. case LANG_NEUTRAL:
  65. case LANG_ENGLISH:
  66. hr = LoadTypeLib(wszPath, &pITypeLib);
  67. break;
  68. }
  69. }
  70. if (SUCCEEDED(hr))
  71. {
  72. // Got the type lib, get type info for the interface we want.
  73. hr = pITypeLib->GetTypeInfoOfGuid(uuid, ppITypeInfo);
  74. pITypeLib->Release();
  75. }
  76. return hr;
  77. }
  78. STDMETHODIMP CImpIDispatch::GetTypeInfo(UINT itInfo, LCID lcid, ITypeInfo **ppITypeInfo)
  79. {
  80. *ppITypeInfo = NULL;
  81. if (0 != itInfo)
  82. return TYPE_E_ELEMENTNOTFOUND;
  83. // docs say we can ignore lcid if we support only one LCID
  84. // we don't have to return DISP_E_UNKNOWNLCID if we're *ignoring* it
  85. ITypeInfo **ppITI = &m_pITINeutral; // our cached typeinfo
  86. // Load a type lib if we don't have the information already.
  87. if (NULL == *ppITI)
  88. {
  89. ITypeInfo *pITIDisp;
  90. HRESULT hr = GetTypeInfoFromLibId(lcid, m_libid, m_wVerMajor, m_wVerMinor, m_riid, &pITIDisp);
  91. if (SUCCEEDED(hr))
  92. {
  93. // All our IDispatch implementations are DUAL. GetTypeInfoOfGuid
  94. // returns the ITypeInfo of the IDispatch-part only. We need to
  95. // find the ITypeInfo for the dual interface-part.
  96. //
  97. HREFTYPE hrefType;
  98. HRESULT hrT = pITIDisp->GetRefTypeOfImplType(0xffffffff, &hrefType);
  99. if (SUCCEEDED(hrT))
  100. {
  101. hrT = pITIDisp->GetRefTypeInfo(hrefType, ppITI);
  102. }
  103. if (FAILED(hrT))
  104. {
  105. // I suspect GetRefTypeOfImplType may fail if someone uses
  106. // CImpIDispatch on a non-dual interface. In this case the
  107. // ITypeInfo we got above is just fine to use.
  108. *ppITI = pITIDisp;
  109. }
  110. else
  111. {
  112. pITIDisp->Release();
  113. }
  114. }
  115. if (FAILED(hr))
  116. return hr;
  117. }
  118. (*ppITI)->AddRef();
  119. *ppITypeInfo = *ppITI;
  120. return S_OK;
  121. }
  122. STDMETHODIMP CImpIDispatch::GetIDsOfNames(REFIID riid, OLECHAR **rgszNames, UINT cNames, LCID lcid, DISPID *rgDispID)
  123. {
  124. if (IID_NULL != riid)
  125. return DISP_E_UNKNOWNINTERFACE;
  126. //Get the right ITypeInfo for lcid.
  127. ITypeInfo *pTI;
  128. HRESULT hr = GetTypeInfo(0, lcid, &pTI);
  129. if (SUCCEEDED(hr))
  130. {
  131. hr = pTI->GetIDsOfNames(rgszNames, cNames, rgDispID);
  132. pTI->Release();
  133. }
  134. #ifdef DEBUG
  135. TCHAR szParam[MAX_PATH] = TEXT("");
  136. if (cNames >= 1)
  137. SHUnicodeToTChar(*rgszNames, szParam, ARRAYSIZE(szParam));
  138. TraceMsg(TF_IDISPATCH, "CImpIDispatch::GetIDsOfNames(%s = %x) called hres(%x)",
  139. szParam, *rgDispID, hr);
  140. #endif
  141. return hr;
  142. }
  143. STDMETHODIMP CImpIDispatch::Invoke(DISPID dispID, REFIID riid,
  144. LCID lcid, unsigned short wFlags, DISPPARAMS *pDispParams,
  145. VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
  146. {
  147. if (IID_NULL != riid)
  148. return DISP_E_UNKNOWNINTERFACE; // riid is supposed to be IID_NULL always
  149. IDispatch *pdisp;
  150. HRESULT hr = QueryInterface(m_riid, (void **)&pdisp);
  151. if (SUCCEEDED(hr))
  152. {
  153. //Get the ITypeInfo for lcid
  154. ITypeInfo *pTI;
  155. hr = GetTypeInfo(0, lcid, &pTI);
  156. if (SUCCEEDED(hr))
  157. {
  158. SetErrorInfo(0, NULL); //Clear exceptions
  159. // This is exactly what DispInvoke does--so skip the overhead.
  160. hr = pTI->Invoke(pdisp, dispID, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
  161. pTI->Release();
  162. }
  163. pdisp->Release();
  164. }
  165. return hr;
  166. }
  167. void CImpIDispatch::Exception(WORD wException)
  168. {
  169. ASSERT(FALSE); // No one should call this yet
  170. }