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.

811 lines
20 KiB

  1. /////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1998 Active Voice Corporation. All Rights Reserved.
  4. //
  5. // Active Agent(r) and Unified Communications(tm) are trademarks of Active Voice Corporation.
  6. //
  7. // Other brand and product names used herein are trademarks of their respective owners.
  8. //
  9. // The entire program and user interface including the structure, sequence, selection,
  10. // and arrangement of the dialog, the exclusively "yes" and "no" choices represented
  11. // by "1" and "2," and each dialog message are protected by copyrights registered in
  12. // the United States and by international treaties.
  13. //
  14. // Protected by one or more of the following United States patents: 5,070,526, 5,488,650,
  15. // 5,434,906, 5,581,604, 5,533,102, 5,568,540, 5,625,676, 5,651,054.
  16. //
  17. // Active Voice Corporation
  18. // Seattle, Washington
  19. // USA
  20. //
  21. /////////////////////////////////////////////////////////////////////////////////////////
  22. ////
  23. // list.c - linked list functions
  24. ////
  25. #include "winlocal.h"
  26. #include "list.h"
  27. #include "mem.h"
  28. #include "trace.h"
  29. ////
  30. // private definitions
  31. ////
  32. // list node
  33. //
  34. typedef struct LISTNODE
  35. {
  36. struct LISTNODE FAR *lpNodePrev;
  37. struct LISTNODE FAR *lpNodeNext;
  38. LISTELEM elem;
  39. } LISTNODE, FAR *LPLISTNODE;
  40. // list
  41. //
  42. typedef struct LIST
  43. {
  44. DWORD dwVersion;
  45. HINSTANCE hInst;
  46. HTASK hTask;
  47. LPLISTNODE lpNodeHead;
  48. LPLISTNODE lpNodeTail;
  49. long cNodes;
  50. } LIST, FAR *LPLIST;
  51. // helper functions
  52. //
  53. static LPLIST ListGetPtr(HLIST hList);
  54. static HLIST ListGetHandle(LPLIST lpList);
  55. static LPLISTNODE ListNodeGetPtr(HLISTNODE hNode);
  56. static HLISTNODE ListNodeGetHandle(LPLISTNODE lpNode);
  57. static LPLISTNODE ListNodeCreate(LPLIST lpList, LPLISTNODE lpNodePrev, LPLISTNODE lpNodeNext, LISTELEM elem);
  58. static int ListNodeDestroy(LPLIST lpList, LPLISTNODE lpNode);
  59. ////
  60. // public functions
  61. ////
  62. ////
  63. // list constructor and destructor functions
  64. ////
  65. // ListCreate - list constructor
  66. // <dwVersion> (i) must be LIST_VERSION
  67. // <hInst> (i) instance handle of calling module
  68. // return new list handle (NULL if error)
  69. //
  70. HLIST DLLEXPORT WINAPI ListCreate(DWORD dwVersion, HINSTANCE hInst)
  71. {
  72. BOOL fSuccess = TRUE;
  73. LPLIST lpList = NULL;
  74. if (dwVersion != LIST_VERSION)
  75. fSuccess = TraceFALSE(NULL);
  76. else if (hInst == NULL)
  77. fSuccess = TraceFALSE(NULL);
  78. else if ((lpList = (LPLIST) MemAlloc(NULL, sizeof(LIST), 0)) == NULL)
  79. fSuccess = TraceFALSE(NULL);
  80. else
  81. {
  82. // initially the list is empty
  83. //
  84. lpList->dwVersion = dwVersion;
  85. lpList->hInst = hInst;
  86. lpList->hTask = GetCurrentTask();
  87. lpList->lpNodeHead = NULL;
  88. lpList->lpNodeTail = NULL;
  89. lpList->cNodes = 0;
  90. }
  91. return fSuccess ? ListGetHandle(lpList) : NULL;
  92. }
  93. // ListDestroy - list destructor
  94. // <hList> (i) handle returned from ListCreate
  95. // return 0 if success
  96. // NOTE: any nodes within list are destroyed also
  97. //
  98. int DLLEXPORT WINAPI ListDestroy(HLIST hList)
  99. {
  100. BOOL fSuccess = TRUE;
  101. LPLIST lpList;
  102. if ((lpList = ListGetPtr(hList)) == NULL)
  103. fSuccess = TraceFALSE(NULL);
  104. // make sure the list is emptied
  105. //
  106. else if (ListRemoveAll(hList) != 0)
  107. fSuccess = TraceFALSE(NULL);
  108. else if ((lpList = MemFree(NULL, lpList)) != NULL)
  109. fSuccess = TraceFALSE(NULL);
  110. return fSuccess ? 0 : -1;
  111. }
  112. ////
  113. // list status functions
  114. ////
  115. // ListGetCount - return count of nodes in list
  116. // <hList> (i) handle returned from ListCreate
  117. // return node count (-1 if error)
  118. //
  119. long DLLEXPORT WINAPI ListGetCount(HLIST hList)
  120. {
  121. BOOL fSuccess = TRUE;
  122. LPLIST lpList;
  123. if ((lpList = ListGetPtr(hList)) == NULL)
  124. fSuccess = TraceFALSE(NULL);
  125. return fSuccess ? lpList->cNodes : -1;
  126. }
  127. // ListIsEmpty - return TRUE if list has no nodes
  128. // <hList> (i) handle returned from ListCreate
  129. // return TRUE or FALSE
  130. //
  131. BOOL DLLEXPORT WINAPI ListIsEmpty(HLIST hList)
  132. {
  133. return (BOOL) (ListGetCount(hList) <= 0);
  134. }
  135. ////
  136. // list iteration functions
  137. ////
  138. // ListGetHeadNode - get list head node
  139. // <hList> (i) handle returned from ListCreate
  140. // return list head node (NULL if error or empty)
  141. //
  142. HLISTNODE DLLEXPORT WINAPI ListGetHeadNode(HLIST hList)
  143. {
  144. BOOL fSuccess = TRUE;
  145. LPLIST lpList;
  146. if ((lpList = ListGetPtr(hList)) == NULL)
  147. fSuccess = TraceFALSE(NULL);
  148. else if (lpList->lpNodeHead == NULL)
  149. fSuccess = FALSE; // empty list, which is not an error
  150. return fSuccess ? ListNodeGetHandle(lpList->lpNodeHead) : NULL;
  151. }
  152. // ListGetTailNode - get list tail node
  153. // <hList> (i) handle returned from ListCreate
  154. // return list tail node (NULL if error or empty)
  155. //
  156. HLISTNODE DLLEXPORT WINAPI ListGetTailNode(HLIST hList)
  157. {
  158. BOOL fSuccess = TRUE;
  159. LPLIST lpList;
  160. if ((lpList = ListGetPtr(hList)) == NULL)
  161. fSuccess = TraceFALSE(NULL);
  162. else if (lpList->lpNodeTail == NULL)
  163. fSuccess = FALSE; // empty list, which is not an error
  164. return fSuccess ? ListNodeGetHandle(lpList->lpNodeTail) : NULL;
  165. }
  166. // ListGetNextNode - get node which follows specified node
  167. // <hList> (i) handle returned from ListCreate
  168. // <hNode> (i) node handle
  169. // return node which follows specified node (NULL if error or none)
  170. //
  171. HLISTNODE DLLEXPORT WINAPI ListGetNextNode(HLIST hList, HLISTNODE hNode)
  172. {
  173. BOOL fSuccess = TRUE;
  174. LPLIST lpList;
  175. LPLISTNODE lpNode;
  176. if ((lpList = ListGetPtr(hList)) == NULL)
  177. fSuccess = TraceFALSE(NULL);
  178. else if ((lpNode = ListNodeGetPtr(hNode)) == NULL)
  179. fSuccess = TraceFALSE(NULL);
  180. else if (lpNode->lpNodeNext == NULL)
  181. fSuccess = FALSE; // no more nodes, which is not an error
  182. return fSuccess ? ListNodeGetHandle(lpNode->lpNodeNext) : NULL;
  183. }
  184. // ListGetPrevNode - get node which precedes specified node
  185. // <hList> (i) handle returned from ListCreate
  186. // <hNode> (i) node handle
  187. // return node which precedes specified node (NULL if error or none)
  188. //
  189. HLISTNODE DLLEXPORT WINAPI ListGetPrevNode(HLIST hList, HLISTNODE hNode)
  190. {
  191. BOOL fSuccess = TRUE;
  192. LPLIST lpList;
  193. LPLISTNODE lpNode;
  194. if ((lpList = ListGetPtr(hList)) == NULL)
  195. fSuccess = TraceFALSE(NULL);
  196. else if ((lpNode = ListNodeGetPtr(hNode)) == NULL)
  197. fSuccess = TraceFALSE(NULL);
  198. else if (lpNode->lpNodePrev == NULL)
  199. fSuccess = FALSE; // no more nodes, which is not an error
  200. return fSuccess ? ListNodeGetHandle(lpNode->lpNodePrev) : NULL;
  201. }
  202. ////
  203. // list element insertion functions
  204. ////
  205. // ListAddHead - add new node with data <elem> to head of list,
  206. // <hList> (i) handle returned from ListCreate
  207. // <elem> (i) new data element
  208. // returns new node handle (NULL if error)
  209. //
  210. HLISTNODE DLLEXPORT WINAPI ListAddHead(HLIST hList, LISTELEM elem)
  211. {
  212. BOOL fSuccess = TRUE;
  213. LPLIST lpList;
  214. LPLISTNODE lpNodeNew;
  215. if ((lpList = ListGetPtr(hList)) == NULL)
  216. fSuccess = TraceFALSE(NULL);
  217. else if ((lpNodeNew = ListNodeCreate(lpList,
  218. NULL, lpList->lpNodeHead, elem)) == NULL)
  219. fSuccess = TraceFALSE(NULL);
  220. else
  221. {
  222. if (lpList->lpNodeHead != NULL)
  223. lpList->lpNodeHead->lpNodePrev = lpNodeNew;
  224. else
  225. lpList->lpNodeTail = lpNodeNew;
  226. lpList->lpNodeHead = lpNodeNew;
  227. }
  228. return fSuccess ? ListNodeGetHandle(lpNodeNew) : NULL;
  229. }
  230. // ListAddTail - add new node with data <elem> to tail of list,
  231. // <hList> (i) handle returned from ListCreate
  232. // <elem> (i) new data element
  233. // returns new node handle (NULL if error)
  234. //
  235. HLISTNODE DLLEXPORT WINAPI ListAddTail(HLIST hList, LISTELEM elem)
  236. {
  237. BOOL fSuccess = TRUE;
  238. LPLIST lpList;
  239. LPLISTNODE lpNodeNew;
  240. if ((lpList = ListGetPtr(hList)) == NULL)
  241. fSuccess = TraceFALSE(NULL);
  242. else if ((lpNodeNew = ListNodeCreate(lpList,
  243. lpList->lpNodeTail, NULL, elem)) == NULL)
  244. fSuccess = TraceFALSE(NULL);
  245. else
  246. {
  247. if (lpList->lpNodeTail != NULL)
  248. lpList->lpNodeTail->lpNodeNext = lpNodeNew;
  249. else
  250. lpList->lpNodeHead = lpNodeNew;
  251. lpList->lpNodeTail = lpNodeNew;
  252. }
  253. return fSuccess ? ListNodeGetHandle(lpNodeNew) : NULL;
  254. }
  255. // ListInsertBefore - insert new node with data <elem> before specified node
  256. // <hList> (i) handle returned from ListCreate
  257. // <hNode> (i) node handle
  258. // <elem> (i) new data element
  259. // return handle to new node (NULL if error)
  260. //
  261. HLISTNODE DLLEXPORT WINAPI ListInsertBefore(HLIST hList, HLISTNODE hNode, LISTELEM elem)
  262. {
  263. BOOL fSuccess = TRUE;
  264. LPLIST lpList;
  265. LPLISTNODE lpNodeOld;
  266. LPLISTNODE lpNodeNew;
  267. if ((lpList = ListGetPtr(hList)) == NULL)
  268. fSuccess = TraceFALSE(NULL);
  269. // special case to insert at head of list
  270. //
  271. else if (hNode == NULL)
  272. return ListAddHead(hList, elem);
  273. else if ((lpNodeOld = ListNodeGetPtr(hNode)) == NULL)
  274. fSuccess = TraceFALSE(NULL);
  275. else if ((lpNodeNew = ListNodeCreate(lpList,
  276. lpNodeOld->lpNodePrev, lpNodeOld, elem)) == NULL)
  277. fSuccess = TraceFALSE(NULL);
  278. else
  279. {
  280. if (lpNodeOld->lpNodePrev != NULL)
  281. lpNodeOld->lpNodePrev->lpNodeNext = lpNodeNew;
  282. else
  283. lpList->lpNodeHead = lpNodeNew;
  284. lpNodeOld->lpNodePrev = lpNodeNew;
  285. }
  286. return fSuccess ? ListNodeGetHandle(lpNodeNew) : NULL;
  287. }
  288. // ListInsertAfter - insert new node with data <elem> after specified node
  289. // <hList> (i) handle returned from ListCreate
  290. // <hNode> (i) node handle
  291. // <elem> (i) new data element
  292. // return handle to new node (NULL if error)
  293. //
  294. HLISTNODE DLLEXPORT WINAPI ListInsertAfter(HLIST hList, HLISTNODE hNode, LISTELEM elem)
  295. {
  296. BOOL fSuccess = TRUE;
  297. LPLIST lpList;
  298. LPLISTNODE lpNodeOld;
  299. LPLISTNODE lpNodeNew;
  300. if ((lpList = ListGetPtr(hList)) == NULL)
  301. fSuccess = TraceFALSE(NULL);
  302. // special case to insert at tail of list
  303. //
  304. else if (hNode == NULL)
  305. return ListAddTail(hList, elem);
  306. else if ((lpNodeOld = ListNodeGetPtr(hNode)) == NULL)
  307. fSuccess = TraceFALSE(NULL);
  308. else if ((lpNodeNew = ListNodeCreate(lpList,
  309. lpNodeOld, lpNodeOld->lpNodeNext, elem)) == NULL)
  310. fSuccess = TraceFALSE(NULL);
  311. else
  312. {
  313. if (lpNodeOld->lpNodeNext != NULL)
  314. lpNodeOld->lpNodeNext->lpNodePrev = lpNodeNew;
  315. else
  316. lpList->lpNodeTail = lpNodeNew;
  317. lpNodeOld->lpNodeNext = lpNodeNew;
  318. }
  319. return fSuccess ? ListNodeGetHandle(lpNodeNew) : NULL;
  320. }
  321. ////
  322. // list element removal functions
  323. ////
  324. // ListRemoveHead - remove node from head of list,
  325. // <hList> (i) handle returned from ListCreate
  326. // returns removed data element
  327. //
  328. LISTELEM DLLEXPORT WINAPI ListRemoveHead(HLIST hList)
  329. {
  330. BOOL fSuccess = TRUE;
  331. LPLIST lpList;
  332. LPLISTNODE lpNodeOld;
  333. LISTELEM elemOld;
  334. if ((lpList = ListGetPtr(hList)) == NULL)
  335. fSuccess = TraceFALSE(NULL);
  336. // error if list is empty
  337. //
  338. else if (lpList->lpNodeHead == NULL)
  339. fSuccess = TraceFALSE(NULL);
  340. else
  341. {
  342. // save the node to be removed
  343. //
  344. lpNodeOld = lpList->lpNodeHead;
  345. elemOld = lpNodeOld->elem;
  346. // point to new head node and tail node, if any
  347. //
  348. lpList->lpNodeHead = lpNodeOld->lpNodeNext;
  349. if (lpList->lpNodeHead != NULL)
  350. lpList->lpNodeHead->lpNodePrev = NULL;
  351. else
  352. lpList->lpNodeTail = NULL;
  353. if (ListNodeDestroy(lpList, lpNodeOld) != 0)
  354. fSuccess = TraceFALSE(NULL);
  355. }
  356. return fSuccess ? elemOld : (LISTELEM) NULL;
  357. }
  358. // ListRemoveTail - remove node from tail of list,
  359. // <hList> (i) handle returned from ListCreate
  360. // returns removed data element
  361. //
  362. LISTELEM DLLEXPORT WINAPI ListRemoveTail(HLIST hList)
  363. {
  364. BOOL fSuccess = TRUE;
  365. LPLIST lpList;
  366. LPLISTNODE lpNodeOld;
  367. LISTELEM elemOld;
  368. if ((lpList = ListGetPtr(hList)) == NULL)
  369. fSuccess = TraceFALSE(NULL);
  370. // error if list is empty
  371. //
  372. else if (lpList->lpNodeTail == NULL)
  373. fSuccess = TraceFALSE(NULL);
  374. else
  375. {
  376. // save the node to be removed
  377. //
  378. lpNodeOld = lpList->lpNodeTail;
  379. elemOld = lpNodeOld->elem;
  380. // point to new tail node and head node, if any
  381. //
  382. lpList->lpNodeTail = lpNodeOld->lpNodePrev;
  383. if (lpList->lpNodeTail != NULL)
  384. lpList->lpNodeTail->lpNodeNext = NULL;
  385. else
  386. lpList->lpNodeHead = NULL;
  387. if (ListNodeDestroy(lpList, lpNodeOld) != 0)
  388. fSuccess = TraceFALSE(NULL);
  389. }
  390. return fSuccess ? elemOld : (LISTELEM) NULL;
  391. }
  392. // ListRemoveAt - remove specified node from list,
  393. // <hList> (i) handle returned from ListCreate
  394. // <hNode> (i) node handle
  395. // returns removed data element
  396. //
  397. LISTELEM DLLEXPORT WINAPI ListRemoveAt(HLIST hList, HLISTNODE hNode)
  398. {
  399. BOOL fSuccess = TRUE;
  400. LPLIST lpList;
  401. LPLISTNODE lpNodeOld;
  402. LISTELEM elemOld;
  403. if ((lpList = ListGetPtr(hList)) == NULL)
  404. fSuccess = TraceFALSE(NULL);
  405. else if ((lpNodeOld = ListNodeGetPtr(hNode)) == NULL)
  406. fSuccess = TraceFALSE(NULL);
  407. else
  408. {
  409. // save the data to be removed
  410. //
  411. elemOld = lpNodeOld->elem;
  412. if (lpNodeOld == lpList->lpNodeHead)
  413. lpList->lpNodeHead = lpNodeOld->lpNodeNext;
  414. else
  415. lpNodeOld->lpNodePrev->lpNodeNext = lpNodeOld->lpNodeNext;
  416. if (lpNodeOld == lpList->lpNodeTail)
  417. lpList->lpNodeTail = lpNodeOld->lpNodePrev;
  418. else
  419. lpNodeOld->lpNodeNext->lpNodePrev = lpNodeOld->lpNodePrev;
  420. if (ListNodeDestroy(lpList, lpNodeOld) != 0)
  421. fSuccess = TraceFALSE(NULL);
  422. }
  423. return fSuccess ? elemOld : (LISTELEM) NULL;
  424. }
  425. // ListRemoveAll - remove all nodes from list
  426. // <hList> (i) handle returned from ListCreate
  427. // return 0 if success
  428. //
  429. int DLLEXPORT WINAPI ListRemoveAll(HLIST hList)
  430. {
  431. BOOL fSuccess = TRUE;
  432. while (fSuccess && !ListIsEmpty(hList))
  433. ListRemoveHead(hList);
  434. return fSuccess ? 0 : -1;
  435. }
  436. ////
  437. // list element get/set value functions
  438. ////
  439. // ListGetHead - return data element from head node
  440. // <hList> (i) handle returned from ListCreate
  441. // return data element
  442. //
  443. LISTELEM DLLEXPORT WINAPI ListGetHead(HLIST hList)
  444. {
  445. return ListGetAt(hList, ListGetHeadNode(hList));
  446. }
  447. // ListGetTail - return data element from tail node
  448. // <hList> (i) handle returned from ListCreate
  449. // return data element
  450. //
  451. LISTELEM DLLEXPORT WINAPI ListGetTail(HLIST hList)
  452. {
  453. return ListGetAt(hList, ListGetTailNode(hList));
  454. }
  455. // ListGetAt - return data element from specified node
  456. // <hList> (i) handle returned from ListCreate
  457. // <hNode> (i) node handle
  458. // return data element
  459. //
  460. LISTELEM DLLEXPORT WINAPI ListGetAt(HLIST hList, HLISTNODE hNode)
  461. {
  462. BOOL fSuccess = TRUE;
  463. LPLIST lpList;
  464. LPLISTNODE lpNode;
  465. if ((lpList = ListGetPtr(hList)) == NULL)
  466. fSuccess = TraceFALSE(NULL);
  467. else if ((lpNode = ListNodeGetPtr(hNode)) == NULL)
  468. fSuccess = TraceFALSE(NULL);
  469. return fSuccess ? lpNode->elem : (LISTELEM) NULL;
  470. }
  471. // ListSetAt - set data element in specified node
  472. // <hList> (i) handle returned from ListCreate
  473. // <hNode> (i) node handle
  474. // <elem> (i) data element
  475. // return 0 if success
  476. //
  477. int DLLEXPORT WINAPI ListSetAt(HLIST hList, HLISTNODE hNode, LISTELEM elem)
  478. {
  479. BOOL fSuccess = TRUE;
  480. LPLIST lpList;
  481. LPLISTNODE lpNode;
  482. if ((lpList = ListGetPtr(hList)) == NULL)
  483. fSuccess = TraceFALSE(NULL);
  484. else if ((lpNode = ListNodeGetPtr(hNode)) == NULL)
  485. fSuccess = TraceFALSE(NULL);
  486. else
  487. lpNode->elem = elem;
  488. return fSuccess ? 0 : -1;
  489. }
  490. // ListFind - search list for node with matching element
  491. // <hList> (i) handle returned from ListCreate
  492. // <elem> (i) data element to match
  493. // <hNodeAfter> (i) node handle to begin search after
  494. // NULL start search at head node
  495. // return matching node (NULL if error or none)
  496. //
  497. HLISTNODE DLLEXPORT WINAPI ListFind(HLIST hList, LISTELEM elem, HLISTNODE hNodeAfter)
  498. {
  499. BOOL fSuccess = TRUE;
  500. LPLIST lpList;
  501. LPLISTNODE lpNode;
  502. if ((lpList = ListGetPtr(hList)) == NULL)
  503. fSuccess = TraceFALSE(NULL);
  504. // if not otherwise specified, start search at head node
  505. //
  506. else if (hNodeAfter == NULL)
  507. lpNode = lpList->lpNodeHead;
  508. else if ((lpNode = ListNodeGetPtr(hNodeAfter)) == NULL)
  509. fSuccess = TraceFALSE(NULL);
  510. // otherwise, start search at after specified node
  511. //
  512. else
  513. lpNode = lpNode->lpNodeNext;
  514. if (fSuccess)
  515. {
  516. while (lpNode != NULL)
  517. {
  518. if (lpNode->elem == elem)
  519. return ListNodeGetHandle(lpNode);
  520. lpNode = lpNode->lpNodeNext;
  521. }
  522. }
  523. return NULL;
  524. }
  525. // ListFindIndex - search list for nth node in list
  526. // <hList> (i) handle returned from ListCreate
  527. // <nIndex> (i) zero based index into list
  528. // return handle to node (NULL if error)
  529. //
  530. HLISTNODE DLLEXPORT WINAPI ListFindIndex(HLIST hList, long nIndex)
  531. {
  532. BOOL fSuccess = TRUE;
  533. LPLIST lpList;
  534. LPLISTNODE lpNode;
  535. if ((lpList = ListGetPtr(hList)) == NULL)
  536. fSuccess = TraceFALSE(NULL);
  537. // error if index out of range
  538. //
  539. else if (nIndex < 0 || nIndex >= lpList->cNodes)
  540. fSuccess = TraceFALSE(NULL);
  541. else for (lpNode = lpList->lpNodeHead;
  542. lpNode != NULL; lpNode = lpNode->lpNodeNext)
  543. {
  544. if (nIndex-- == 0)
  545. return ListNodeGetHandle(lpNode);
  546. }
  547. return NULL;
  548. }
  549. ////
  550. // private functions
  551. ////
  552. // ListGetPtr - verify that list handle is valid,
  553. // <hList> (i) handle returned from ListCreate
  554. // return corresponding list pointer (NULL if error)
  555. //
  556. static LPLIST ListGetPtr(HLIST hList)
  557. {
  558. BOOL fSuccess = TRUE;
  559. LPLIST lpList;
  560. if ((lpList = (LPLIST) hList) == NULL)
  561. fSuccess = TraceFALSE(NULL);
  562. else if (IsBadWritePtr(lpList, sizeof(LIST)))
  563. fSuccess = TraceFALSE(NULL);
  564. #ifdef CHECKTASK
  565. // make sure current task owns the list handle
  566. //
  567. else if (lpList->hTask != GetCurrentTask())
  568. fSuccess = TraceFALSE(NULL);
  569. #endif
  570. return fSuccess ? lpList : NULL;
  571. }
  572. // ListGetHandle - verify that list pointer is valid,
  573. // <lpList> (i) pointer to LIST struct
  574. // return corresponding list handle (NULL if error)
  575. //
  576. static HLIST ListGetHandle(LPLIST lpList)
  577. {
  578. BOOL fSuccess = TRUE;
  579. HLIST hList;
  580. if ((hList = (HLIST) lpList) == NULL)
  581. fSuccess = TraceFALSE(NULL);
  582. return fSuccess ? hList : NULL;
  583. }
  584. // ListNodeGetPtr - verify that list node handle is valid,
  585. // <hNode> (i) node handle
  586. // return corresponding list node pointer (NULL if error)
  587. //
  588. static LPLISTNODE ListNodeGetPtr(HLISTNODE hNode)
  589. {
  590. BOOL fSuccess = TRUE;
  591. LPLISTNODE lpNode;
  592. if ((lpNode = (LPLISTNODE) hNode) == NULL)
  593. fSuccess = TraceFALSE(NULL);
  594. else if (IsBadWritePtr(lpNode, sizeof(LISTNODE)))
  595. fSuccess = TraceFALSE(NULL);
  596. return fSuccess ? lpNode : NULL;
  597. }
  598. // ListNodeGetHandle - verify that list node pointer is valid,
  599. // <lpNode> (i) pointer to LISTNODE struct
  600. // return corresponding list node handle (NULL if error)
  601. //
  602. static HLISTNODE ListNodeGetHandle(LPLISTNODE lpNode)
  603. {
  604. BOOL fSuccess = TRUE;
  605. HLISTNODE hNode;
  606. if ((hNode = (HLISTNODE) lpNode) == NULL)
  607. fSuccess = TraceFALSE(NULL);
  608. return fSuccess ? hNode : NULL;
  609. }
  610. // ListNodeCreate - list node constructor
  611. // <lpList> (i) pointer to LIST struct
  612. // <lpNodePrev> (i) pointer to prior LISTNODE struct
  613. // <lpNodeNext> (i) pointer to next LISTNODE struct
  614. // <elem> (i) new data element
  615. // return new list node handle (NULL if error)
  616. // NOTE: list node count is incremented here
  617. //
  618. static LPLISTNODE ListNodeCreate(LPLIST lpList, LPLISTNODE lpNodePrev, LPLISTNODE lpNodeNext, LISTELEM elem)
  619. {
  620. BOOL fSuccess = TRUE;
  621. LPLISTNODE lpNode;
  622. if (lpList == NULL)
  623. fSuccess = TraceFALSE(NULL);
  624. // check for overflow
  625. //
  626. else if (++lpList->cNodes <= 0)
  627. fSuccess = TraceFALSE(NULL);
  628. else if ((lpNode = (LPLISTNODE) MemAlloc(NULL, sizeof(LISTNODE), 0)) == NULL)
  629. fSuccess = TraceFALSE(NULL);
  630. else
  631. {
  632. // initialize using supplied values
  633. //
  634. lpNode->lpNodePrev = lpNodePrev;
  635. lpNode->lpNodeNext = lpNodeNext;
  636. lpNode->elem = elem;
  637. }
  638. return fSuccess ? lpNode : NULL;
  639. }
  640. // ListNodeDestroy - list node destructor
  641. // <lpList> (i) pointer to LIST struct
  642. // <lpNode> (i) pointer to LISTNODE struct to destroy
  643. // return 0 if success
  644. // NOTE: list node count is decremented here
  645. //
  646. static int ListNodeDestroy(LPLIST lpList, LPLISTNODE lpNode)
  647. {
  648. BOOL fSuccess = TRUE;
  649. if (lpList == NULL)
  650. fSuccess = TraceFALSE(NULL);
  651. else if (lpNode == NULL)
  652. fSuccess = TraceFALSE(NULL);
  653. // check for underflow
  654. //
  655. else if (--lpList->cNodes < 0)
  656. fSuccess = TraceFALSE(NULL);
  657. else if ((lpNode = MemFree(NULL, lpNode)) != NULL)
  658. fSuccess = TraceFALSE(NULL);
  659. return fSuccess ? 0 : -1;
  660. }