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.

357 lines
8.4 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. dispatch.cpp
  5. Abstract:
  6. This module contains the implementation for the Server
  7. Extension Object Dispatcher service.
  8. Author:
  9. Andy Jacobs (andyj@microsoft.com)
  10. Revision History:
  11. andyj 11/26/96 created
  12. --*/
  13. #include "stdafx.h"
  14. #include "seo.h"
  15. #include "dispatch.h"
  16. class CDictItemNameList {
  17. public:
  18. CDictItemNameList(ISEODictionary *piFrom);
  19. ~CDictItemNameList();
  20. public:
  21. DWORD m_dwCount;
  22. CComVariant *m_aNames;
  23. };
  24. static HRESULT ReallocCComVariant(CComVariant **ppBase,
  25. DWORD dwBaseCnt,
  26. DWORD dwNewBaseCnt) {
  27. CComVariant *pNew = NULL;
  28. if (dwBaseCnt == dwNewBaseCnt) {
  29. return (S_OK);
  30. }
  31. if (!dwNewBaseCnt) {
  32. delete[] *ppBase;
  33. *ppBase = NULL;
  34. return (S_OK);
  35. }
  36. ATLTRY(pNew = new CComVariant[dwNewBaseCnt];)
  37. _ASSERTE(pNew);
  38. if (!pNew) {
  39. return (E_OUTOFMEMORY);
  40. }
  41. for (DWORD dwIdx=0;(dwIdx<dwBaseCnt)&&(dwIdx<dwNewBaseCnt);dwIdx++) {
  42. pNew[dwIdx].Attach(&(*ppBase)[dwIdx]);
  43. }
  44. delete[] *ppBase;
  45. *ppBase = pNew;
  46. return (S_OK);
  47. }
  48. static HRESULT ReallocCComVariant(CComVariant **ppBase,
  49. DWORD dwBaseCnt,
  50. CComVariant *pAdd,
  51. DWORD dwAddCnt) {
  52. HRESULT hrRes;
  53. hrRes = ReallocCComVariant(ppBase,dwBaseCnt,dwBaseCnt+dwAddCnt);
  54. if (!SUCCEEDED(hrRes)) {
  55. return (hrRes);
  56. }
  57. for (DWORD dwIdx=0;dwIdx<dwAddCnt;dwIdx++) {
  58. (*ppBase)[dwIdx+dwBaseCnt].Attach(&pAdd[dwIdx]);
  59. }
  60. return (S_OK);
  61. }
  62. CDictItemNameList::CDictItemNameList(ISEODictionary *piFrom) {
  63. HRESULT hrRes;
  64. m_dwCount = 0;
  65. m_aNames = NULL;
  66. if (piFrom) {
  67. CComPtr<IUnknown> pUnkEnum;
  68. hrRes = piFrom->get__NewEnum(&pUnkEnum);
  69. if (SUCCEEDED(hrRes)) {
  70. CComQIPtr<IEnumVARIANT,&IID_IEnumVARIANT> pevEnum(pUnkEnum);
  71. if (pevEnum) {
  72. while (1) {
  73. CComVariant aNew[20];
  74. DWORD dwCnt;
  75. hrRes = pevEnum->Next(sizeof(aNew)/sizeof(aNew[0]),aNew,&dwCnt);
  76. if (!SUCCEEDED(hrRes)) {
  77. break;
  78. }
  79. if (!dwCnt) {
  80. break;
  81. }
  82. hrRes = ReallocCComVariant(&m_aNames,m_dwCount,aNew,dwCnt);
  83. if (!SUCCEEDED(hrRes)) {
  84. break;
  85. }
  86. for (DWORD dwIdx=0;dwIdx<dwCnt;dwIdx++) {
  87. hrRes = m_aNames[dwIdx+m_dwCount].ChangeType(VT_BSTR);
  88. _ASSERTE(SUCCEEDED(hrRes));
  89. if (!SUCCEEDED(hrRes)) {
  90. // Ack! Ok - just drop this name off the list by moving the last name
  91. // on the list to this position, and fiddling the indexes so that we
  92. // attemp to convert this position again.
  93. if (dwIdx<dwCnt-1) {
  94. m_aNames[dwIdx+m_dwCount].Attach(&m_aNames[dwCnt+m_dwCount-1]);
  95. }
  96. dwIdx--;
  97. dwCnt--;
  98. }
  99. }
  100. m_dwCount += dwCnt;
  101. }
  102. }
  103. }
  104. }
  105. }
  106. CDictItemNameList::~CDictItemNameList() {
  107. delete[] m_aNames;
  108. m_dwCount = 0;
  109. m_aNames = NULL;
  110. }
  111. CSEOBaseDispatcher::CSEOBaseDispatcher() {
  112. m_apbBindings = NULL;
  113. m_dwBindingsCount = 0;
  114. }
  115. CSEOBaseDispatcher::~CSEOBaseDispatcher() {
  116. while (m_dwBindingsCount) {
  117. delete m_apbBindings[--m_dwBindingsCount];
  118. }
  119. delete[] m_apbBindings;
  120. m_apbBindings = NULL;
  121. }
  122. HRESULT STDMETHODCALLTYPE CSEOBaseDispatcher::SetContext(ISEORouter *piRouter, ISEODictionary *pdictBP) {
  123. HRESULT hrRes;
  124. CComPtr<ISEODictionary> pdictBindings;
  125. _ASSERT(!m_dwBindingsCount&&!m_apbBindings);
  126. hrRes = pdictBP->GetInterfaceA(BD_BINDINGS,IID_ISEODictionary,(IUnknown **) &pdictBindings);
  127. if (SUCCEEDED(hrRes)) {
  128. CDictItemNameList dinlBindings(pdictBindings);
  129. if (dinlBindings.m_dwCount) {
  130. m_apbBindings = new CBinding *[dinlBindings.m_dwCount];
  131. if (!m_apbBindings) {
  132. return (E_OUTOFMEMORY);
  133. }
  134. memset(m_apbBindings,0,sizeof(CBinding *)*dinlBindings.m_dwCount);
  135. for (m_dwBindingsCount=0;m_dwBindingsCount<dinlBindings.m_dwCount;m_dwBindingsCount++) {
  136. CComPtr<ISEODictionary> pdictBinding;
  137. pdictBinding.Release();
  138. hrRes = pdictBindings->GetInterfaceW(dinlBindings.m_aNames[m_dwBindingsCount].bstrVal,
  139. IID_ISEODictionary,
  140. (IUnknown **) &pdictBinding);
  141. _ASSERT(SUCCEEDED(hrRes));
  142. if (SUCCEEDED(hrRes)) {
  143. hrRes = AllocBinding(pdictBinding,&m_apbBindings[m_dwBindingsCount]);
  144. _ASSERT(SUCCEEDED(hrRes));
  145. }
  146. }
  147. qsort(m_apbBindings,m_dwBindingsCount,sizeof(m_apbBindings[0]),comp_binding);
  148. }
  149. }
  150. if (SUCCEEDED(hrRes)) {
  151. m_piRouter = piRouter;
  152. m_pdictBP = pdictBP;
  153. }
  154. return (hrRes);
  155. }
  156. static HRESULT GetCLSIDFromBinding(LPCSTR pszCLSID,
  157. LPCSTR pszProgID,
  158. ISEODictionary *piBinding,
  159. CLSID *pclsid) {
  160. HRESULT hrRes;
  161. CComVariant varTmp;
  162. if (!piBinding) {
  163. return (E_POINTER);
  164. }
  165. if (pszCLSID) {
  166. hrRes = piBinding->GetVariantA(pszCLSID,&varTmp);
  167. if (SUCCEEDED(hrRes)) {
  168. hrRes = varTmp.ChangeType(VT_BSTR);
  169. if (SUCCEEDED(hrRes)) {
  170. hrRes = CLSIDFromString(varTmp.bstrVal,pclsid);
  171. if (SUCCEEDED(hrRes)) {
  172. return (hrRes);
  173. }
  174. }
  175. }
  176. varTmp.Clear();
  177. }
  178. if (!pszProgID) {
  179. return (E_FAIL); // tbd - come up with a better error code
  180. }
  181. hrRes = piBinding->GetVariantA(pszProgID,&varTmp);
  182. if (!SUCCEEDED(hrRes)) {
  183. return (hrRes);
  184. }
  185. hrRes = varTmp.ChangeType(VT_BSTR);
  186. if (!SUCCEEDED(hrRes)) {
  187. return (hrRes);
  188. }
  189. hrRes = CLSIDFromProgID(varTmp.bstrVal,pclsid);
  190. return (hrRes);
  191. }
  192. HRESULT CSEOBaseDispatcher::CBinding::Init(ISEODictionary *piBinding) {
  193. HRESULT hrRes;
  194. CComVariant varTmp;
  195. CLSID clsidTmp;
  196. if (!piBinding) {
  197. return (E_POINTER);
  198. }
  199. // Try to get the CLSID of the object - if an error occurs,
  200. // this binding is invalid.
  201. hrRes = GetCLSIDFromBinding(BD_OBJECT,BD_PROGID,piBinding,&m_clsidObject);
  202. if (!SUCCEEDED(hrRes)) {
  203. return (S_FALSE);
  204. }
  205. // From this point on, all errors are silently ignored - we
  206. // use default values if we can't get something from the binding
  207. // database.
  208. hrRes = piBinding->GetVariantA(BD_PRIORITY,&varTmp);
  209. if (SUCCEEDED(hrRes)) {
  210. hrRes = varTmp.ChangeType(VT_I4);
  211. if (SUCCEEDED(hrRes)) {
  212. m_dwPriority = (DWORD) varTmp.lVal;
  213. }
  214. }
  215. if (!SUCCEEDED(hrRes)) {
  216. // If the priority isn't set, default to "last".
  217. m_dwPriority = (DWORD) -1;
  218. }
  219. varTmp.Clear();
  220. m_piBinding = piBinding;
  221. // Try to get an instance of the rule engine.
  222. hrRes = GetCLSIDFromBinding(BD_RULEENGINE,NULL,piBinding,&clsidTmp);
  223. if (SUCCEEDED(hrRes)) {
  224. hrRes = CoCreateInstance(clsidTmp,
  225. NULL,
  226. CLSCTX_ALL,
  227. IID_ISEOBindingRuleEngine,
  228. (LPVOID *) &m_piRuleEngine);
  229. }
  230. // See if the 'exclusive' flag has been set.
  231. m_bExclusive = FALSE;
  232. hrRes = piBinding->GetVariantA(BD_EXCLUSIVE,&varTmp);
  233. if (SUCCEEDED(hrRes)) {
  234. hrRes = varTmp.ChangeType(VT_BOOL);
  235. if (SUCCEEDED(hrRes)) {
  236. if (varTmp.boolVal) {
  237. m_bExclusive = TRUE;
  238. }
  239. } else {
  240. hrRes = varTmp.ChangeType(VT_I4);
  241. if (SUCCEEDED(hrRes)) {
  242. if (varTmp.lVal) {
  243. m_bExclusive = TRUE;
  244. }
  245. }
  246. }
  247. }
  248. varTmp.Clear();
  249. m_bValid = TRUE;
  250. return (S_OK);
  251. }
  252. int CSEOBaseDispatcher::CBinding::Compare(const CBinding& b) const {
  253. if (m_dwPriority == b.m_dwPriority) {
  254. return (0);
  255. } else {
  256. return ((m_dwPriority>b.m_dwPriority)?1:-1);
  257. }
  258. }
  259. HRESULT CSEOBaseDispatcher::AllocBinding(ISEODictionary *pdictBinding, CBinding **ppbBinding) {
  260. HRESULT hrRes;
  261. if (!ppbBinding) {
  262. return (E_POINTER);
  263. }
  264. *ppbBinding = new CBinding;
  265. if (!*ppbBinding) {
  266. return (E_OUTOFMEMORY);
  267. }
  268. hrRes = (*ppbBinding)->Init(pdictBinding);
  269. if (!SUCCEEDED(hrRes)) {
  270. delete *ppbBinding;
  271. *ppbBinding = NULL;
  272. }
  273. return (hrRes);
  274. }
  275. static int _cdecl comp_binding(const void *pv1, const void *pv2) {
  276. const CSEOBaseDispatcher::CBinding **ppb1 = (const CSEOBaseDispatcher::CBinding **) pv1;
  277. const CSEOBaseDispatcher::CBinding **ppb2 = (const CSEOBaseDispatcher::CBinding **) pv2;
  278. return ((*ppb1)->Compare(**ppb2));
  279. }
  280. HRESULT CSEOBaseDispatcher::Dispatch(CEventParams *pEventParams) {
  281. BOOL bObjectCalled = FALSE;
  282. HRESULT hrRes;
  283. for (DWORD dwIdx=0;dwIdx<m_dwBindingsCount;dwIdx++) {
  284. if (!m_apbBindings[dwIdx]->m_bValid) {
  285. continue;
  286. }
  287. if (m_apbBindings[dwIdx]->m_bExclusive && bObjectCalled) {
  288. continue;
  289. }
  290. hrRes = pEventParams->CheckRule(*m_apbBindings[dwIdx]);
  291. if (hrRes == S_OK) {
  292. hrRes = pEventParams->CallObject(*m_apbBindings[dwIdx]);
  293. if ((hrRes == SEO_S_DONEPROCESSING) || m_apbBindings[dwIdx]->m_bExclusive) {
  294. break;
  295. }
  296. }
  297. }
  298. return (S_OK);
  299. }