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.

637 lines
13 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Module: clist.cpp
  4. //
  5. // Description:
  6. //
  7. //
  8. //@@BEGIN_MSINTERNAL
  9. // Development Team:
  10. // Mike McLaughlin
  11. //
  12. // History: Date Author Comment
  13. //
  14. // To Do: Date Author Comment
  15. //
  16. //@@END_MSINTERNAL
  17. //
  18. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  19. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  20. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  21. // PURPOSE.
  22. //
  23. // Copyright (c) 1996-1999 Microsoft Corporation. All Rights Reserved.
  24. //
  25. //---------------------------------------------------------------------------
  26. #include "common.h"
  27. //---------------------------------------------------------------------------
  28. // CListSingle Class
  29. //---------------------------------------------------------------------------
  30. ENUMFUNC
  31. CListSingle::EnumerateList(
  32. IN ENUMFUNC (CListSingleItem::*pfn)(
  33. )
  34. )
  35. {
  36. NTSTATUS Status = STATUS_CONTINUE;
  37. PCLIST_SINGLE_ITEM plsi;
  38. Assert(this);
  39. FOR_EACH_CLIST_ITEM_DELETE(this, plsi, CLIST_SINGLE_ITEM) {
  40. Status = (plsi->*pfn)();
  41. if(Status != STATUS_CONTINUE) {
  42. goto exit;
  43. }
  44. } END_EACH_CLIST_ITEM
  45. exit:
  46. return(Status);
  47. }
  48. ENUMFUNC
  49. CListSingle::EnumerateList(
  50. IN ENUMFUNC (CListSingleItem::*pfn)(
  51. PVOID pReference
  52. ),
  53. PVOID pReference
  54. )
  55. {
  56. NTSTATUS Status = STATUS_CONTINUE;
  57. PCLIST_SINGLE_ITEM plsi;
  58. Assert(this);
  59. FOR_EACH_CLIST_ITEM_DELETE(this, plsi, CLIST_SINGLE_ITEM) {
  60. Status = (plsi->*pfn)(pReference);
  61. if(Status != STATUS_CONTINUE) {
  62. goto exit;
  63. }
  64. } END_EACH_CLIST_ITEM
  65. exit:
  66. return(Status);
  67. }
  68. PCLIST_SINGLE_ITEM *
  69. CListSingle::GetListEnd(
  70. )
  71. {
  72. PCLIST_SINGLE_ITEM *pplsi;
  73. for(pplsi = &m_plsiHead;
  74. !IsListEnd(*pplsi);
  75. pplsi = &(*pplsi)->m_plsiNext) {
  76. Assert(*pplsi);
  77. }
  78. return(pplsi);
  79. }
  80. void
  81. CListSingle::ReverseList(
  82. )
  83. {
  84. PCLIST_SINGLE_ITEM plsi = m_plsiHead;
  85. PCLIST_SINGLE_ITEM plsiNext;
  86. PCLIST_SINGLE_ITEM plsiTemp;
  87. if (NULL != plsi) {
  88. plsiNext = plsi->m_plsiNext;
  89. plsi->m_plsiNext = NULL;
  90. while (NULL != plsiNext) {
  91. plsiTemp = plsiNext->m_plsiNext;
  92. plsiNext->m_plsiNext = plsi;
  93. plsi = plsiNext;
  94. plsiNext = plsiTemp;
  95. }
  96. m_plsiHead = plsi;
  97. }
  98. }
  99. //---------------------------------------------------------------------------
  100. // CListSingleItem Class
  101. //---------------------------------------------------------------------------
  102. VOID
  103. CListSingleItem::RemoveList(
  104. IN PCLIST_SINGLE pls
  105. )
  106. {
  107. PCLIST_SINGLE_ITEM *pplsi;
  108. Assert(pls);
  109. Assert(this);
  110. for(pplsi = &pls->m_plsiHead;
  111. !pls->IsListEnd(*pplsi);
  112. pplsi = &(*pplsi)->m_plsiNext) {
  113. Assert(*pplsi);
  114. if(*pplsi == this) {
  115. break;
  116. }
  117. }
  118. *pplsi = m_plsiNext;
  119. }
  120. //---------------------------------------------------------------------------
  121. // CListDouble Class
  122. //---------------------------------------------------------------------------
  123. ULONG
  124. CListDouble::CountList(
  125. )
  126. {
  127. PCLIST_DOUBLE_ITEM pldi;
  128. ULONG c = 0;
  129. Assert(this);
  130. FOR_EACH_CLIST_ITEM(this, pldi) {
  131. Assert(pldi);
  132. c++;
  133. } END_EACH_CLIST_ITEM
  134. return(c);
  135. }
  136. ENUMFUNC
  137. CListDouble::EnumerateList(
  138. IN ENUMFUNC (CListDoubleItem::*pfn)(
  139. )
  140. )
  141. {
  142. NTSTATUS Status = STATUS_CONTINUE;
  143. PCLIST_DOUBLE_ITEM plbi;
  144. Assert(this);
  145. FOR_EACH_CLIST_ITEM_DELETE(this, plbi, CLIST_DOUBLE_ITEM) {
  146. Status = (plbi->*pfn)();
  147. if(Status != STATUS_CONTINUE) {
  148. goto exit;
  149. }
  150. } END_EACH_CLIST_ITEM
  151. exit:
  152. return(Status);
  153. }
  154. ENUMFUNC
  155. CListDouble::EnumerateList(
  156. IN ENUMFUNC (CListDoubleItem::*pfn)(
  157. PVOID pReference
  158. ),
  159. PVOID pReference
  160. )
  161. {
  162. NTSTATUS Status = STATUS_CONTINUE;
  163. PCLIST_DOUBLE_ITEM plbi;
  164. Assert(this);
  165. FOR_EACH_CLIST_ITEM_DELETE(this, plbi, CLIST_DOUBLE_ITEM) {
  166. Status = (plbi->*pfn)(pReference);
  167. if(Status != STATUS_CONTINUE) {
  168. goto exit;
  169. }
  170. } END_EACH_CLIST_ITEM
  171. exit:
  172. return(Status);
  173. }
  174. //---------------------------------------------------------------------------
  175. // CListData Class
  176. //---------------------------------------------------------------------------
  177. VOID
  178. CListData::DestroyList()
  179. {
  180. PCLIST_DATA_DATA pldd;
  181. Assert(this);
  182. FOR_EACH_CLIST_ITEM_DELETE(this, pldd, CLIST_DATA_DATA) {
  183. delete pldd;
  184. } END_EACH_CLIST_ITEM
  185. CListSingle::DestroyList();
  186. }
  187. ULONG
  188. CListData::CountList(
  189. )
  190. {
  191. PCLIST_DATA_DATA pldd;
  192. ULONG c = 0;
  193. Assert(this);
  194. FOR_EACH_CLIST_ITEM(this, pldd) {
  195. Assert(pldd);
  196. c++;
  197. } END_EACH_CLIST_ITEM
  198. return(c);
  199. }
  200. ENUMFUNC
  201. CListData::EnumerateList(
  202. IN ENUMFUNC (CListDataItem::*pfn)(
  203. )
  204. )
  205. {
  206. NTSTATUS Status = STATUS_CONTINUE;
  207. PCLIST_DATA_DATA pldd;
  208. Assert(this);
  209. FOR_EACH_CLIST_ITEM_DELETE(this, pldd, CLIST_DATA_DATA) {
  210. Status = (GetListData(pldd)->*pfn)();
  211. if(Status != STATUS_CONTINUE) {
  212. goto exit;
  213. }
  214. } END_EACH_CLIST_ITEM
  215. exit:
  216. return(Status);
  217. }
  218. ENUMFUNC
  219. CListData::EnumerateList(
  220. IN ENUMFUNC (CListDataItem::*pfn)(
  221. PVOID pReference
  222. ),
  223. PVOID pReference
  224. )
  225. {
  226. NTSTATUS Status = STATUS_CONTINUE;
  227. PCLIST_DATA_DATA pldd;
  228. Assert(this);
  229. FOR_EACH_CLIST_ITEM_DELETE(this, pldd, CLIST_DATA_DATA) {
  230. Status = (GetListData(pldd)->*pfn)(pReference);
  231. if(Status != STATUS_CONTINUE) {
  232. goto exit;
  233. }
  234. } END_EACH_CLIST_ITEM
  235. exit:
  236. return(Status);
  237. }
  238. NTSTATUS
  239. CListData::CreateUniqueList(
  240. OUT PCLIST_DATA pldOut,
  241. IN PVOID (*GetFunction)(
  242. IN PVOID pData
  243. ),
  244. IN BOOL (*CompareFunction)(
  245. IN PVOID pIn,
  246. IN PVOID pOut
  247. )
  248. )
  249. {
  250. NTSTATUS Status = STATUS_SUCCESS;
  251. PCLIST_DATA_DATA plddIn, plddOut;
  252. PVOID pIn, pOut;
  253. BOOL fFoundMatch;
  254. FOR_EACH_CLIST_ITEM(this, plddIn) {
  255. pIn = (*GetFunction)((PVOID)GetListData(plddIn));
  256. if(pIn == NULL) {
  257. continue;
  258. }
  259. AssertAligned(pIn);
  260. fFoundMatch = FALSE;
  261. FOR_EACH_CLIST_ITEM(pldOut, plddOut) {
  262. pOut = (PVOID)pldOut->GetListData(plddOut);
  263. if((*CompareFunction)(pIn, pOut)) {
  264. fFoundMatch = TRUE;
  265. break;
  266. }
  267. } END_EACH_CLIST_ITEM
  268. if(!fFoundMatch) {
  269. Status = pldOut->AddListEnd(pIn);
  270. if(!NT_SUCCESS(Status)) {
  271. Trap();
  272. goto exit;
  273. }
  274. }
  275. } END_EACH_CLIST_ITEM
  276. exit:
  277. if(!NT_SUCCESS(Status)) {
  278. pldOut->DestroyList();
  279. }
  280. return(Status);
  281. }
  282. BOOL
  283. CListData::CheckDupList(
  284. PVOID p
  285. )
  286. {
  287. PCLIST_DATA_DATA pldd;
  288. Assert(this);
  289. FOR_EACH_CLIST_ITEM(this, pldd) {
  290. if(GetListData(pldd) == p) {
  291. return(TRUE);
  292. }
  293. } END_EACH_CLIST_ITEM
  294. return(FALSE);
  295. }
  296. NTSTATUS
  297. CListData::AddList(
  298. PVOID p
  299. )
  300. {
  301. Assert(this);
  302. if(CheckDupList(p)) {
  303. return(STATUS_SUCCESS);
  304. }
  305. return(AddListDup(p));
  306. }
  307. NTSTATUS
  308. CListData::AddListDup(
  309. PVOID p
  310. )
  311. {
  312. Assert(this);
  313. PCLIST_DATA_DATA pldd = new CLIST_DATA_DATA(p);
  314. if(pldd == NULL) {
  315. return(STATUS_INSUFFICIENT_RESOURCES);
  316. }
  317. pldd->AddList(this);
  318. return(STATUS_SUCCESS);
  319. }
  320. NTSTATUS
  321. CListData::AddListEnd(
  322. PVOID p
  323. )
  324. {
  325. ASSERT(!CheckDupList(p));
  326. PCLIST_DATA_DATA pldd = new CLIST_DATA_DATA(p);
  327. if(pldd == NULL) {
  328. return(STATUS_INSUFFICIENT_RESOURCES);
  329. }
  330. *(GetListEnd()) = pldd;
  331. return(STATUS_SUCCESS);
  332. }
  333. NTSTATUS
  334. CListData::AddListOrdered(
  335. PVOID p,
  336. LONG lFieldOffset
  337. )
  338. {
  339. PCLIST_DATA_DATA pldd, *ppldd;
  340. ULONG ulOrder;
  341. ASSERT(!CheckDupList(p));
  342. ulOrder = *((PULONG)(((PCHAR)p) + lFieldOffset));
  343. pldd = new CLIST_DATA_DATA(p);
  344. if(pldd == NULL) {
  345. return(STATUS_INSUFFICIENT_RESOURCES);
  346. }
  347. for(ppldd = (PCLIST_DATA_DATA *)&m_plsiHead;
  348. !IsListEnd(*ppldd);
  349. ppldd = (PCLIST_DATA_DATA *)&(*ppldd)->m_plsiNext) {
  350. Assert(*ppldd);
  351. if(ulOrder < *((PULONG)(((PCHAR)GetListData(*ppldd)) + lFieldOffset))) {
  352. break;
  353. }
  354. }
  355. pldd->m_plsiNext = *ppldd;
  356. *ppldd = pldd;
  357. return(STATUS_SUCCESS);
  358. }
  359. VOID
  360. CListData::RemoveList(
  361. PVOID p
  362. )
  363. {
  364. PCLIST_DATA_DATA pldd;
  365. Assert(this);
  366. FOR_EACH_CLIST_ITEM_DELETE(this, pldd, CLIST_DATA_DATA) {
  367. if(GetListData(pldd) == p) {
  368. pldd->RemoveList(this);
  369. delete pldd;
  370. }
  371. } END_EACH_CLIST_ITEM
  372. }
  373. VOID
  374. CListData::JoinList(
  375. PCLIST_DATA pld
  376. )
  377. {
  378. *GetListEnd() = pld->GetListFirst();
  379. pld->CListSingle::DestroyList();
  380. }
  381. //---------------------------------------------------------------------------
  382. // CListMulti Class
  383. //---------------------------------------------------------------------------
  384. VOID
  385. CListMulti::DestroyList(
  386. )
  387. {
  388. PCLIST_MULTI_DATA plmd;
  389. Assert(this);
  390. FOR_EACH_CLIST_ITEM_DELETE(this, plmd, CLIST_MULTI_DATA) {
  391. delete plmd;
  392. } END_EACH_CLIST_ITEM
  393. CListDouble::DestroyList();
  394. }
  395. ENUMFUNC
  396. CListMulti::EnumerateList(
  397. ENUMFUNC (CListMultiItem::*pfn)(
  398. )
  399. )
  400. {
  401. NTSTATUS Status = STATUS_CONTINUE;
  402. PCLIST_MULTI_DATA plmd;
  403. Assert(this);
  404. FOR_EACH_CLIST_ITEM_DELETE(this, plmd, CLIST_MULTI_DATA) {
  405. Status = (GetListData(plmd)->*pfn)();
  406. if(Status != STATUS_CONTINUE) {
  407. goto exit;
  408. }
  409. } END_EACH_CLIST_ITEM
  410. exit:
  411. return(Status);
  412. }
  413. ENUMFUNC
  414. CListMulti::EnumerateList(
  415. ENUMFUNC (CListMultiItem::*pfn)(
  416. PVOID pReference
  417. ),
  418. PVOID pReference
  419. )
  420. {
  421. NTSTATUS Status = STATUS_CONTINUE;
  422. PCLIST_MULTI_DATA plmd;
  423. Assert(this);
  424. FOR_EACH_CLIST_ITEM_DELETE(this, plmd, CLIST_MULTI_DATA) {
  425. Status = (GetListData(plmd)->*pfn)(pReference);
  426. if(Status != STATUS_CONTINUE) {
  427. goto exit;
  428. }
  429. } END_EACH_CLIST_ITEM
  430. exit:
  431. return(Status);
  432. }
  433. BOOL
  434. CListMulti::CheckDupList(
  435. PVOID p
  436. )
  437. {
  438. PCLIST_MULTI_DATA plmd;
  439. FOR_EACH_CLIST_ITEM(this, plmd) {
  440. if(GetListData(plmd) == p) {
  441. return(TRUE);
  442. }
  443. } END_EACH_CLIST_ITEM
  444. return(FALSE);
  445. }
  446. NTSTATUS
  447. CListMulti::AddList(
  448. PVOID p,
  449. CListMultiItem *plmi
  450. )
  451. {
  452. Assert(this);
  453. Assert(plmi);
  454. if(CheckDupList(p)) {
  455. return(STATUS_SUCCESS);
  456. }
  457. PCLIST_MULTI_DATA plmd = new CLIST_MULTI_DATA(p);
  458. if(plmd == NULL) {
  459. return(STATUS_INSUFFICIENT_RESOURCES);
  460. }
  461. plmd->AddList(this);
  462. plmd->m_ldiItem.AddList(plmi);
  463. return(STATUS_SUCCESS);
  464. }
  465. NTSTATUS
  466. CListMulti::AddListEnd(
  467. PVOID p,
  468. CListMultiItem *plmi
  469. )
  470. {
  471. Assert(this);
  472. Assert(plmi);
  473. if(CheckDupList(p)) {
  474. return(STATUS_SUCCESS);
  475. }
  476. PCLIST_MULTI_DATA plmd = new CLIST_MULTI_DATA(p);
  477. if(plmd == NULL) {
  478. return(STATUS_INSUFFICIENT_RESOURCES);
  479. }
  480. plmd->AddListEnd(this);
  481. plmd->m_ldiItem.AddListEnd(plmi);
  482. return(STATUS_SUCCESS);
  483. }
  484. NTSTATUS
  485. CListMulti::AddListOrdered(
  486. PVOID p,
  487. CListMultiItem *plmi,
  488. LONG lFieldOffset
  489. )
  490. {
  491. PCLIST_MULTI_DATA plmd, plmdNew;
  492. ULONG ulOrder;
  493. ASSERT(!CheckDupList(p));
  494. ulOrder = *((PULONG)(((PCHAR)p) + lFieldOffset));
  495. plmdNew = new CLIST_MULTI_DATA(p);
  496. if(plmdNew == NULL) {
  497. return(STATUS_INSUFFICIENT_RESOURCES);
  498. }
  499. plmdNew->m_ldiItem.AddList(plmi);
  500. FOR_EACH_CLIST_ITEM(this, plmd) {
  501. if(ulOrder < *((PULONG)(((PCHAR)GetListData(plmd)) + lFieldOffset))) {
  502. break;
  503. }
  504. } END_EACH_CLIST_ITEM
  505. InsertTailList(&plmd->m_le, &plmdNew->m_le);
  506. return(STATUS_SUCCESS);
  507. }
  508. VOID
  509. CListMulti::RemoveList(
  510. PVOID p
  511. )
  512. {
  513. PCLIST_MULTI_DATA plmd;
  514. Assert(this);
  515. FOR_EACH_CLIST_ITEM_DELETE(this, plmd, CLIST_MULTI_DATA) {
  516. if(GetListData(plmd) == p) {
  517. delete plmd;
  518. }
  519. } END_EACH_CLIST_ITEM
  520. }
  521. VOID
  522. CListMulti::JoinList(
  523. PCLIST_MULTI plm
  524. )
  525. {
  526. Assert(this);
  527. Assert(plm);
  528. ASSERT(this->m_leHead.Blink->Flink == &this->m_leHead);
  529. ASSERT(plm->m_leHead.Blink->Flink == &plm->m_leHead);
  530. ASSERT(this->m_leHead.Flink->Blink == &this->m_leHead);
  531. ASSERT(plm->m_leHead.Flink->Blink == &plm->m_leHead);
  532. if(!plm->IsLstEmpty()) {
  533. this->m_leHead.Blink->Flink = plm->m_leHead.Flink;
  534. plm->m_leHead.Flink->Blink = this->m_leHead.Blink;
  535. plm->m_leHead.Blink->Flink = &this->m_leHead;
  536. this->m_leHead.Blink = plm->m_leHead.Blink;
  537. InitializeListHead(&plm->m_leHead);
  538. }
  539. }
  540. //---------------------------------------------------------------------------
  541. // CListMultiItem Class
  542. //---------------------------------------------------------------------------
  543. CListMultiItem::~CListMultiItem()
  544. {
  545. PCLIST_MULTI_DATA plmd, plmdNext;
  546. for(plmd = CONTAINING_RECORD(GetListFirst(), CLIST_MULTI_DATA, m_ldiItem);
  547. !IsListEnd(&plmd->m_ldiItem);
  548. plmd = plmdNext) {
  549. Assert(plmd);
  550. plmdNext = CONTAINING_RECORD(
  551. GetListNext(&plmd->m_ldiItem),
  552. CLIST_MULTI_DATA,
  553. m_ldiItem);
  554. delete plmd;
  555. }
  556. }
  557. //---------------------------------------------------------------------------
  558. // end of clist.cpp
  559. //---------------------------------------------------------------------------