Source code of Windows XP (NT5)
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.

407 lines
8.7 KiB

  1. /* Copyright 1996 Microsoft */
  2. #include <priv.h>
  3. #include "sccls.h"
  4. #include "aclmulti.h"
  5. //
  6. // CACLMulti -- An AutoComplete List COM object that
  7. // contains other AutoComplete Lists and
  8. // has them do all the work.
  9. //
  10. struct _tagListItem
  11. {
  12. IUnknown *punk;
  13. IEnumString *pes;
  14. IEnumACString *peacs;
  15. IACList *pacl;
  16. };
  17. typedef struct _tagListItem LISTITEM;
  18. #define MULTILIST_GROWTH_CONST 8
  19. /* IUnknown methods */
  20. HRESULT CACLMulti::QueryInterface(REFIID riid, void **ppvObj)
  21. {
  22. if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IEnumString))
  23. {
  24. *ppvObj = SAFECAST(this, IEnumString*);
  25. }
  26. else if (IsEqualIID(riid, IID_IEnumACString))
  27. {
  28. *ppvObj = SAFECAST(this, IEnumACString*);
  29. }
  30. else if (IsEqualIID(riid, IID_IObjMgr))
  31. {
  32. *ppvObj = SAFECAST(this, IObjMgr*);
  33. }
  34. else if (IsEqualIID(riid, IID_IACList))
  35. {
  36. *ppvObj = SAFECAST(this, IACList*);
  37. }
  38. else
  39. {
  40. *ppvObj = NULL;
  41. return E_NOINTERFACE;
  42. }
  43. AddRef();
  44. return S_OK;
  45. }
  46. ULONG CACLMulti::AddRef(void)
  47. {
  48. _cRef++;
  49. return _cRef;
  50. }
  51. ULONG CACLMulti::Release(void)
  52. {
  53. ASSERT(_cRef > 0);
  54. _cRef--;
  55. if (_cRef > 0)
  56. {
  57. return _cRef;
  58. }
  59. delete this;
  60. return 0;
  61. }
  62. /* IEnumString methods */
  63. HRESULT CACLMulti::Next(ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched)
  64. {
  65. HRESULT hr = S_FALSE; // nothing found... stop
  66. *pceltFetched = 0;
  67. if (celt == 0)
  68. {
  69. return S_OK;
  70. }
  71. if (!rgelt)
  72. {
  73. hr = E_FAIL;
  74. }
  75. if (SUCCEEDED(hr) && _hdsa)
  76. {
  77. //
  78. // Keep calling Next() starting with the current list
  79. // until somebody returns something.
  80. //
  81. for( ; _iSubList < DSA_GetItemCount(_hdsa); _iSubList++)
  82. {
  83. LISTITEM li;
  84. if ((DSA_GetItem(_hdsa, _iSubList, &li) != -1) && (li.pes != NULL))
  85. {
  86. hr = li.pes->Next(1, rgelt, pceltFetched);
  87. if (hr == S_OK)
  88. break;
  89. if (FAILED(hr)) // Why is the caller failing?
  90. hr = S_FALSE; // Probably because it failed to conntect to the source (ftp)
  91. }
  92. }
  93. }
  94. ASSERT(SUCCEEDED(hr));
  95. return hr;
  96. }
  97. HRESULT CACLMulti::Skip(ULONG)
  98. {
  99. return E_NOTIMPL;
  100. }
  101. HRESULT CACLMulti::Reset(void)
  102. {
  103. HRESULT hr = S_OK;
  104. TraceMsg(TF_BAND|TF_GENERAL, "ACLMulti::Reset() Beginning");
  105. if (_hdsa)
  106. {
  107. // Call Reset() on each sublist.
  108. for (_iSubList=0; _iSubList < DSA_GetItemCount(_hdsa); _iSubList++)
  109. {
  110. LISTITEM li;
  111. if ((DSA_GetItem(_hdsa, _iSubList, &li) != -1) && (li.pes != NULL))
  112. {
  113. hr = li.pes->Reset();
  114. if (FAILED(hr))
  115. break;
  116. }
  117. }
  118. }
  119. // Reset ourselves to point to the first list.
  120. _iSubList = 0;
  121. return hr;
  122. }
  123. HRESULT CACLMulti::Clone(IEnumString **ppenum)
  124. {
  125. return CACLMulti_Create(ppenum, this);
  126. }
  127. // IEnumAutocomplete methods
  128. HRESULT CACLMulti::NextItem(LPOLESTR pszUrl, ULONG cchMax, ULONG* pulSortIndex)
  129. {
  130. HRESULT hr = S_FALSE; // nothing found... stop
  131. if (!pszUrl)
  132. {
  133. hr = E_FAIL;
  134. }
  135. if (SUCCEEDED(hr) && _hdsa)
  136. {
  137. //
  138. // Keep calling Next() starting with the current list
  139. // until somebody returns something.
  140. //
  141. for( ; _iSubList < DSA_GetItemCount(_hdsa); _iSubList++)
  142. {
  143. LISTITEM li;
  144. if ((DSA_GetItem(_hdsa, _iSubList, &li) != -1) && (li.pes != NULL))
  145. {
  146. // Use the IEnumACString interface if we have it
  147. if (NULL != li.peacs)
  148. {
  149. hr = li.peacs->NextItem(pszUrl, cchMax, pulSortIndex);
  150. }
  151. // Fall back to the old IEnumString interface
  152. else
  153. {
  154. LPWSTR pszNext;
  155. ULONG ulFetched;
  156. hr = li.pes->Next(1, &pszNext, &ulFetched);
  157. if (S_OK == hr)
  158. {
  159. StrCpyN(pszUrl, pszNext, cchMax);
  160. if (pulSortIndex)
  161. {
  162. *pulSortIndex = 0;
  163. }
  164. CoTaskMemFree(pszNext);
  165. }
  166. }
  167. if (hr == S_OK)
  168. break;
  169. if (FAILED(hr)) // Why is the caller failing?
  170. hr = S_FALSE; // Probably because it failed to conntect to the source (ftp)
  171. }
  172. }
  173. }
  174. ASSERT(SUCCEEDED(hr));
  175. return hr;
  176. }
  177. /* IObjMgr methods */
  178. HRESULT CACLMulti::Append(IUnknown *punk)
  179. {
  180. HRESULT hr = E_FAIL;
  181. if (punk)
  182. {
  183. if (!_hdsa)
  184. {
  185. _hdsa = DSA_Create(SIZEOF(LISTITEM), MULTILIST_GROWTH_CONST);
  186. }
  187. if (_hdsa)
  188. {
  189. LISTITEM li = { 0 };
  190. //
  191. // Call QI to get the necessary interfaces,
  192. // and append the interfaces to the internal list.
  193. //
  194. li.punk = punk;
  195. li.punk->AddRef();
  196. li.punk->QueryInterface(IID_IEnumString, (LPVOID *)&li.pes);
  197. li.punk->QueryInterface(IID_IEnumACString, (LPVOID *)&li.peacs);
  198. li.punk->QueryInterface(IID_IACList, (LPVOID *)&li.pacl);
  199. if (DSA_AppendItem(_hdsa, &li) != -1)
  200. {
  201. hr = S_OK;
  202. }
  203. else
  204. {
  205. _FreeListItem(&li, 0);
  206. hr = E_FAIL;
  207. }
  208. }
  209. }
  210. return hr;
  211. }
  212. HRESULT CACLMulti::Remove(IUnknown *punk)
  213. {
  214. HRESULT hr = E_FAIL;
  215. int i;
  216. if (punk && _hdsa)
  217. {
  218. for(i=DPA_GetPtrCount(_hdsa); i>=0; i--)
  219. {
  220. LISTITEM li;
  221. if (DSA_GetItem(_hdsa, i, &li) != -1)
  222. {
  223. if (punk == li.punk)
  224. {
  225. _FreeListItem(&li, 0);
  226. if (DSA_DeleteItem(_hdsa, i))
  227. {
  228. hr = S_OK;
  229. }
  230. break;
  231. }
  232. }
  233. }
  234. }
  235. return hr;
  236. }
  237. /* IACList methods */
  238. HRESULT CACLMulti::Expand(LPCOLESTR pszExpand)
  239. {
  240. HRESULT hr = S_OK;
  241. int i;
  242. if (_hdsa)
  243. {
  244. // Call Expand() on each sublist.
  245. for (i=0; i < DSA_GetItemCount(_hdsa); i++)
  246. {
  247. LISTITEM li;
  248. if ((DSA_GetItem(_hdsa, i, &li) != -1) && (li.pacl != NULL))
  249. {
  250. hr = li.pacl->Expand(pszExpand);
  251. if (hr == S_OK)
  252. break;
  253. }
  254. }
  255. }
  256. if (E_NOTIMPL == hr)
  257. hr = S_OK;
  258. return hr;
  259. }
  260. /* Constructor / Destructor / CreateInstance */
  261. CACLMulti::CACLMulti()
  262. {
  263. DllAddRef();
  264. ASSERT(!_hdsa);
  265. ASSERT(!_iSubList);
  266. _cRef = 1;
  267. }
  268. CACLMulti::~CACLMulti()
  269. {
  270. if (_hdsa)
  271. {
  272. DSA_DestroyCallback(_hdsa, _FreeListItem, 0);
  273. _hdsa = NULL;
  274. }
  275. DllRelease();
  276. }
  277. HRESULT CACLMulti_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi)
  278. {
  279. // aggregation checking is handled in class factory
  280. *ppunk = NULL;
  281. CACLMulti * p = new CACLMulti();
  282. if (p)
  283. {
  284. *ppunk = SAFECAST(p, IEnumString *);
  285. return NOERROR;
  286. }
  287. return E_OUTOFMEMORY;
  288. }
  289. HRESULT CACLMulti_Create(IEnumString **ppenum, CACLMulti * paclMultiToCopy)
  290. {
  291. HRESULT hr = E_OUTOFMEMORY;
  292. *ppenum = NULL;
  293. CACLMulti * p = new CACLMulti();
  294. if (p)
  295. {
  296. if (paclMultiToCopy->_hdsa)
  297. {
  298. // Clone data
  299. int iSize = DSA_GetItemCount(paclMultiToCopy->_hdsa);
  300. int iIndex;
  301. LISTITEM li;
  302. hr = S_OK;
  303. p->_hdsa = DSA_Create(SIZEOF(LISTITEM), MULTILIST_GROWTH_CONST);
  304. // We need to copy the source HDSA
  305. for (iIndex = 0; (iIndex < iSize) && (S_OK == hr); iIndex++)
  306. {
  307. if (DSA_GetItem(paclMultiToCopy->_hdsa, iIndex, &li) != -1)
  308. hr = p->Append(li.punk);
  309. else
  310. hr = E_FAIL;
  311. }
  312. p->_iSubList = paclMultiToCopy->_iSubList;
  313. if (SUCCEEDED(hr))
  314. *ppenum = SAFECAST(p, IEnumString *);
  315. else
  316. p->Release();
  317. }
  318. else
  319. {
  320. p->Release();
  321. }
  322. }
  323. return hr;
  324. }
  325. //
  326. // Frees all the contents of one list item.
  327. //
  328. int CACLMulti::_FreeListItem(LPVOID p, LPVOID d)
  329. {
  330. LISTITEM *pli = (LISTITEM *)p;
  331. SAFERELEASE(pli->pacl);
  332. SAFERELEASE(pli->pes);
  333. SAFERELEASE(pli->peacs);
  334. SAFERELEASE(pli->punk);
  335. return 1;
  336. }