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.

591 lines
12 KiB

  1. //==========================================================================
  2. //
  3. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. // PURPOSE.
  7. //
  8. // Copyright 1998 - 1999 Microsoft Corporation. All Rights Reserved.
  9. //
  10. //--------------------------------------------------------------------------
  11. #include "precomp.h"
  12. extern HINSTANCE g_hmodThisDll; // Handle to this DLL itself.
  13. //+---------------------------------------------------------------------------
  14. //
  15. // Member: CGenericEnum::CGenericEnum, public
  16. //
  17. // Synopsis: Constructor
  18. //
  19. // Arguments:
  20. //
  21. // Returns:
  22. //
  23. // Modifies:
  24. //
  25. //----------------------------------------------------------------------------
  26. CGenericEnum::CGenericEnum(LPGENERICITEMLIST pGenericItemList,DWORD cOffset)
  27. {
  28. DWORD dwItemIndex;
  29. m_cRef = 1; // give the intial reference
  30. m_pGenericItemList = pGenericItemList;
  31. m_cOffset = cOffset;
  32. AddRef_ItemList(m_pGenericItemList); // increment our hold on shared memory.
  33. // set the current item to point to next record.
  34. m_pNextItem = m_pGenericItemList->pFirstGenericItem;
  35. dwItemIndex = cOffset;
  36. // this is a bug if this happens so assert in final.
  37. if (dwItemIndex > m_pGenericItemList->dwNumItems)
  38. dwItemIndex = 0;
  39. // move the nextItem pointer to the proper position
  40. while(dwItemIndex--)
  41. {
  42. m_pNextItem = m_pNextItem->pNextGenericItem;
  43. ++m_cOffset;
  44. if (NULL == m_pNextItem)
  45. break; // Again, another error.
  46. }
  47. }
  48. //+---------------------------------------------------------------------------
  49. //
  50. // Member: CGenericEnum::~CGenericEnum, public
  51. //
  52. // Synopsis: Destructor.
  53. //
  54. // Arguments:
  55. //
  56. // Returns:
  57. //
  58. // Modifies:
  59. //
  60. //----------------------------------------------------------------------------
  61. CGenericEnum::~CGenericEnum()
  62. {
  63. Release_ItemList(m_pGenericItemList); // decrement our hold on shared memory.
  64. }
  65. //+---------------------------------------------------------------------------
  66. //
  67. // Member: CGenericEnum::QueryInterface, public
  68. //
  69. // Synopsis:
  70. //
  71. // Arguments:
  72. //
  73. // Returns:
  74. //
  75. // Modifies:
  76. //
  77. //----------------------------------------------------------------------------
  78. STDMETHODIMP CGenericEnum::QueryInterface(REFIID riid, LPVOID FAR *ppv)
  79. {
  80. return E_NOINTERFACE;
  81. }
  82. //+---------------------------------------------------------------------------
  83. //
  84. // Member: CGenericEnum::Addref, public
  85. //
  86. // Synopsis:
  87. //
  88. // Arguments:
  89. //
  90. // Returns:
  91. //
  92. // Modifies:
  93. //
  94. //----------------------------------------------------------------------------
  95. STDMETHODIMP_(ULONG) CGenericEnum::AddRef()
  96. {
  97. return ++m_cRef;
  98. }
  99. //+---------------------------------------------------------------------------
  100. //
  101. // Member: CGenericEnum::Release, public
  102. //
  103. // Synopsis:
  104. //
  105. // Arguments:
  106. //
  107. // Returns:
  108. //
  109. // Modifies:
  110. //
  111. //----------------------------------------------------------------------------
  112. STDMETHODIMP_(ULONG) CGenericEnum::Release()
  113. {
  114. if (--m_cRef)
  115. return m_cRef;
  116. DeleteThisObject();
  117. return 0L;
  118. }
  119. //+---------------------------------------------------------------------------
  120. //
  121. // Member: CGenericEnum::Next, public
  122. //
  123. // Synopsis:
  124. //
  125. // Arguments:
  126. //
  127. // Returns:
  128. //
  129. // Modifies:
  130. //
  131. //----------------------------------------------------------------------------
  132. STDMETHODIMP CGenericEnum::Next(ULONG celt, LPGENERICITEM rgelt,ULONG *pceltFetched)
  133. {
  134. HRESULT hr = NOERROR;
  135. ULONG ulFetchCount = celt;
  136. ULONG ulNumFetched = 0;
  137. LPGENERICITEM pGenericItem;
  138. if ( (m_cOffset + celt) > m_pGenericItemList->dwNumItems)
  139. {
  140. ulFetchCount = m_pGenericItemList->dwNumItems - m_cOffset;
  141. hr = S_FALSE;
  142. }
  143. pGenericItem = rgelt;
  144. while (ulFetchCount--)
  145. {
  146. *pGenericItem = *(m_pNextItem->pNextGenericItem);
  147. m_pNextItem = m_pNextItem->pNextGenericItem; // add error checking
  148. ++m_cOffset;
  149. ++ulNumFetched;
  150. ++pGenericItem;
  151. }
  152. if (pceltFetched)
  153. {
  154. *pceltFetched = ulNumFetched;
  155. }
  156. return hr;
  157. }
  158. //+---------------------------------------------------------------------------
  159. //
  160. // Member: CGenericEnum::Skip, public
  161. //
  162. // Synopsis:
  163. //
  164. // Arguments:
  165. //
  166. // Returns:
  167. //
  168. // Modifies:
  169. //
  170. //----------------------------------------------------------------------------
  171. STDMETHODIMP CGenericEnum::Skip(ULONG celt)
  172. {
  173. HRESULT hr;
  174. if ( (m_cOffset + celt) > m_pGenericItemList->dwNumItems)
  175. {
  176. m_cOffset = m_pGenericItemList->dwNumItems;
  177. m_pNextItem = NULL;
  178. hr = S_FALSE;
  179. }
  180. else
  181. {
  182. while (celt--)
  183. {
  184. ++m_cOffset;
  185. m_pNextItem = m_pNextItem->pNextGenericItem;
  186. }
  187. hr = NOERROR;
  188. }
  189. return hr;
  190. }
  191. //+---------------------------------------------------------------------------
  192. //
  193. // Member: CGenericEnum::Reset, public
  194. //
  195. // Synopsis:
  196. //
  197. // Arguments:
  198. //
  199. // Returns:
  200. //
  201. // Modifies:
  202. //
  203. //----------------------------------------------------------------------------
  204. STDMETHODIMP CGenericEnum::Reset()
  205. {
  206. m_pNextItem = m_pGenericItemList->pFirstGenericItem;
  207. return NOERROR;
  208. }
  209. //+---------------------------------------------------------------------------
  210. //
  211. // Member: CGenericEnum::Clone, public
  212. //
  213. // Synopsis:
  214. //
  215. // Arguments:
  216. //
  217. // Returns:
  218. //
  219. // Modifies:
  220. //
  221. //----------------------------------------------------------------------------
  222. STDMETHODIMP CGenericEnum::Clone(CGenericEnum **ppenum)
  223. {
  224. return E_NOTIMPL;
  225. }
  226. // help functions for managing enum list
  227. // helper functions for managing the Generics list.
  228. // properly increments and destroys shared Genericlist in memory.
  229. //+---------------------------------------------------------------------------
  230. //
  231. // Function: AddRef_ItemList, public
  232. //
  233. // Synopsis:
  234. //
  235. // Arguments:
  236. //
  237. // Returns:
  238. //
  239. // Modifies:
  240. //
  241. //----------------------------------------------------------------------------
  242. DWORD AddRef_ItemList(LPGENERICITEMLIST pGenericItemList)
  243. {
  244. return ++pGenericItemList->_cRefs;
  245. }
  246. //+---------------------------------------------------------------------------
  247. //
  248. // Function: Release_ItemList, public
  249. //
  250. // Synopsis:
  251. //
  252. // Arguments:
  253. //
  254. // Returns:
  255. //
  256. // Modifies:
  257. //
  258. //----------------------------------------------------------------------------
  259. DWORD Release_ItemList(LPGENERICITEMLIST pGenericItemList)
  260. {
  261. DWORD cRefs;
  262. // bug, not threadsafe
  263. cRefs = --pGenericItemList->_cRefs;
  264. if (0 == pGenericItemList->_cRefs)
  265. {
  266. LPGENERICITEM pCurItem = pGenericItemList->pFirstGenericItem;
  267. while(pCurItem)
  268. {
  269. LPGENERICITEM pFreeItem = pCurItem;
  270. pCurItem = pCurItem->pNextGenericItem;
  271. FREE(pFreeItem);
  272. }
  273. FREE(pGenericItemList);
  274. }
  275. return cRefs;
  276. }
  277. //+---------------------------------------------------------------------------
  278. //
  279. // Function: CreateItemList, public
  280. //
  281. // Synopsis: create an new list and initialize it to nothing
  282. // and set the refcount to 1.
  283. //
  284. // Arguments:
  285. //
  286. // Returns:
  287. //
  288. // Modifies:
  289. //
  290. //----------------------------------------------------------------------------
  291. LPGENERICITEMLIST CreateItemList()
  292. {
  293. LPGENERICITEMLIST lpGenericList = (LPGENERICITEMLIST) ALLOC(sizeof(GENERICITEMLIST));
  294. if (lpGenericList)
  295. {
  296. memset(lpGenericList,0,sizeof(GENERICITEMLIST));
  297. AddRef_ItemList(lpGenericList);
  298. }
  299. return lpGenericList;
  300. }
  301. //+---------------------------------------------------------------------------
  302. //
  303. // Function: DuplicateList, public
  304. //
  305. // Synopsis: Duplicates the list
  306. //
  307. // Arguments:
  308. //
  309. // Returns:
  310. //
  311. // Modifies:
  312. //
  313. //----------------------------------------------------------------------------
  314. LPGENERICITEMLIST DuplicateItemList(LPGENERICITEMLIST pItemList)
  315. {
  316. LPGENERICITEMLIST lpNewItemList;
  317. LPGENERICITEM pCurItem;
  318. lpNewItemList = CreateItemList();
  319. if (!lpNewItemList)
  320. {
  321. return NULL;
  322. }
  323. pCurItem = pItemList->pFirstGenericItem;
  324. while (pCurItem)
  325. {
  326. LPGENERICITEM pNewItemInList;
  327. Assert(pCurItem->cbSize >= sizeof(GENERICITEM));
  328. pNewItemInList = CreateNewListItem(pCurItem->cbSize);
  329. if (pNewItemInList)
  330. {
  331. memcpy(pNewItemInList,pCurItem,pCurItem->cbSize);
  332. pNewItemInList->pNextGenericItem = NULL;
  333. AddItemToList(lpNewItemList,pNewItemInList);
  334. }
  335. pCurItem = pCurItem->pNextGenericItem;
  336. }
  337. return lpNewItemList;
  338. }
  339. //+---------------------------------------------------------------------------
  340. //
  341. // Function: AddNewItemToList, public
  342. //
  343. // Synopsis: allocates space for a new item and adds it to the list,
  344. // if successfull returns pointer to new item so caller can initialize it.
  345. //
  346. // Arguments:
  347. //
  348. // Returns:
  349. //
  350. // Modifies:
  351. //
  352. //----------------------------------------------------------------------------
  353. LPGENERICITEM AddNewItemToList(LPGENERICITEMLIST lpGenericList,ULONG cbSize)
  354. {
  355. LPGENERICITEM pNewGenericItem;
  356. pNewGenericItem = CreateNewListItem(cbSize);
  357. if (pNewGenericItem)
  358. {
  359. if (!AddItemToList(lpGenericList,pNewGenericItem))
  360. {
  361. FREE(pNewGenericItem);
  362. pNewGenericItem = NULL;
  363. }
  364. }
  365. return pNewGenericItem;
  366. }
  367. //+---------------------------------------------------------------------------
  368. //
  369. // Function: AddItemToList, public
  370. //
  371. // Synopsis:
  372. //
  373. // Arguments:
  374. //
  375. // Returns:
  376. //
  377. // Modifies:
  378. //
  379. //----------------------------------------------------------------------------
  380. BOOL AddItemToList(LPGENERICITEMLIST lpGenericList,LPGENERICITEM pNewGenericItem)
  381. {
  382. LPGENERICITEM pGenericItem;
  383. if (!pNewGenericItem || !lpGenericList)
  384. {
  385. Assert(lpGenericList);
  386. Assert(pNewGenericItem);
  387. return FALSE;
  388. }
  389. if (pNewGenericItem)
  390. {
  391. Assert(pNewGenericItem->cbSize >= sizeof(GENERICITEM));
  392. pGenericItem = lpGenericList->pFirstGenericItem;
  393. if (NULL == pGenericItem)
  394. {
  395. lpGenericList->pFirstGenericItem = pNewGenericItem;
  396. }
  397. else
  398. {
  399. while (pGenericItem->pNextGenericItem)
  400. pGenericItem = pGenericItem->pNextGenericItem;
  401. pGenericItem->pNextGenericItem = pNewGenericItem;
  402. }
  403. ++lpGenericList->dwNumItems;
  404. }
  405. return TRUE;
  406. }
  407. //+---------------------------------------------------------------------------
  408. //
  409. // Function: DeleteItemFromList, public
  410. //
  411. // Synopsis:
  412. //
  413. // Arguments:
  414. //
  415. // Returns:
  416. //
  417. // Modifies:
  418. //
  419. //----------------------------------------------------------------------------
  420. BOOL DeleteItemFromList(LPGENERICITEMLIST lpGenericList,LPGENERICITEM pGenericItem)
  421. {
  422. if (!pGenericItem || !lpGenericList)
  423. {
  424. Assert(lpGenericList);
  425. Assert(pGenericItem);
  426. return FALSE;
  427. }
  428. if (pGenericItem)
  429. {
  430. LPGENERICITEM pCurItem;
  431. GENERICITEM GenericItemTempHead;
  432. Assert(pGenericItem->cbSize >= sizeof(GENERICITEM));
  433. GenericItemTempHead.pNextGenericItem = lpGenericList->pFirstGenericItem;
  434. pCurItem = &GenericItemTempHead;
  435. while(pCurItem->pNextGenericItem)
  436. {
  437. if (pCurItem->pNextGenericItem == pGenericItem)
  438. {
  439. pCurItem->pNextGenericItem = pGenericItem->pNextGenericItem;
  440. FREE(pGenericItem);
  441. // update the head
  442. lpGenericList->pFirstGenericItem = GenericItemTempHead.pNextGenericItem;
  443. // update the number of items in the list
  444. --lpGenericList->dwNumItems;
  445. return TRUE;
  446. }
  447. pCurItem = pCurItem->pNextGenericItem;
  448. }
  449. }
  450. AssertSz(0,"Didn't find item in List");
  451. return FALSE; // didn't find anything.
  452. }
  453. //+---------------------------------------------------------------------------
  454. //
  455. // Function: CreateNewListItem, public
  456. //
  457. // Synopsis:
  458. //
  459. // Arguments:
  460. //
  461. // Returns:
  462. //
  463. // Modifies:
  464. //
  465. //----------------------------------------------------------------------------
  466. LPGENERICITEM CreateNewListItem(ULONG cbSize)
  467. {
  468. LPGENERICITEM pNewGenericItem;
  469. // size must be at least size of the base generic item.
  470. if (cbSize < sizeof(GENERICITEM))
  471. return NULL;
  472. pNewGenericItem = (LPGENERICITEM) ALLOC(cbSize);
  473. // add item to the end of the list so if commit we do
  474. // it in the same order items were added.
  475. if (pNewGenericItem)
  476. {
  477. // initialize to zero, and then add it to the list.
  478. memset(pNewGenericItem,0,cbSize);
  479. pNewGenericItem->cbSize = cbSize;
  480. }
  481. return pNewGenericItem;
  482. }