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.

704 lines
13 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. serialst.cxx
  5. Abstract:
  6. Functions to deal with a serialized list. These are replaced by macros in
  7. the retail version
  8. Contents:
  9. [InitializeSerializedList]
  10. [TerminateSerializedList]
  11. [LockSerializedList]
  12. [UnlockSerializedList]
  13. [InsertAtHeadOfSerializedList]
  14. [InsertAtTailOfSerializedList]
  15. [RemoveFromSerializedList]
  16. [IsSerializedListEmpty]
  17. [HeadOfSerializedList]
  18. [TailOfSerializedList]
  19. [CheckEntryOnSerializedList]
  20. [(CheckEntryOnList)]
  21. SlDequeueHead
  22. SlDequeueTail
  23. IsOnSerializedList
  24. Author:
  25. Richard L Firth (rfirth) 16-Feb-1995
  26. Environment:
  27. Win-32 user level
  28. Revision History:
  29. 16-Feb-1995 rfirth
  30. Created
  31. --*/
  32. #include <wininetp.h>
  33. #if INET_DEBUG
  34. //
  35. // manifests
  36. //
  37. #define SERIALIZED_LIST_SIGNATURE 'tslS'
  38. //
  39. // private prototypes
  40. //
  41. PRIVATE
  42. DEBUG_FUNCTION
  43. BOOL
  44. CheckEntryOnList(
  45. IN PLIST_ENTRY List,
  46. IN PLIST_ENTRY Entry,
  47. IN BOOL ExpectedResult
  48. );
  49. //
  50. // data
  51. //
  52. BOOL fCheckEntryOnList = FALSE;
  53. BOOL ReportCheckEntryOnListErrors = FALSE;
  54. //
  55. // functions
  56. //
  57. DEBUG_FUNCTION
  58. VOID
  59. InitializeSerializedList(
  60. IN LPSERIALIZED_LIST SerializedList
  61. )
  62. /*++
  63. Routine Description:
  64. initializes a serialized list
  65. Arguments:
  66. SerializedList - pointer to SERIALIZED_LIST
  67. Return Value:
  68. None.
  69. --*/
  70. {
  71. INET_ASSERT(SerializedList != NULL);
  72. SerializedList->Signature = SERIALIZED_LIST_SIGNATURE;
  73. SerializedList->LockCount = 0;
  74. INITIALIZE_RESOURCE_INFO(&SerializedList->ResourceInfo);
  75. InitializeListHead(&SerializedList->List);
  76. SerializedList->ElementCount = 0;
  77. InitializeCriticalSection(&SerializedList->Lock);
  78. }
  79. DEBUG_FUNCTION
  80. VOID
  81. TerminateSerializedList(
  82. IN LPSERIALIZED_LIST SerializedList
  83. )
  84. /*++
  85. Routine Description:
  86. Undoes InitializeSerializeList
  87. Arguments:
  88. SerializedList - pointer to serialized list to terminate
  89. Return Value:
  90. None.
  91. --*/
  92. {
  93. INET_ASSERT(SerializedList != NULL);
  94. INET_ASSERT(SerializedList->Signature == SERIALIZED_LIST_SIGNATURE);
  95. INET_ASSERT(SerializedList->ElementCount == 0);
  96. if (SerializedList->ElementCount != 0) {
  97. DEBUG_PRINT(SERIALST,
  98. ERROR,
  99. ("list @ %#x has %d elements, first is %#x\n",
  100. SerializedList,
  101. SerializedList->ElementCount,
  102. SerializedList->List.Flink
  103. ));
  104. } else {
  105. INET_ASSERT(IsListEmpty(&SerializedList->List));
  106. }
  107. DeleteCriticalSection(&SerializedList->Lock);
  108. }
  109. DEBUG_FUNCTION
  110. VOID
  111. LockSerializedList(
  112. IN LPSERIALIZED_LIST SerializedList
  113. )
  114. /*++
  115. Routine Description:
  116. Acquires a serialized list locks
  117. Arguments:
  118. SerializedList - SERIALIZED_LIST to lock
  119. Return Value:
  120. None.
  121. --*/
  122. {
  123. INET_ASSERT(SerializedList->Signature == SERIALIZED_LIST_SIGNATURE);
  124. INET_ASSERT(SerializedList->LockCount >= 0);
  125. EnterCriticalSection(&SerializedList->Lock);
  126. if (SerializedList->LockCount != 0) {
  127. INET_ASSERT(SerializedList->ResourceInfo.Tid == GetCurrentThreadId());
  128. }
  129. ++SerializedList->LockCount;
  130. SerializedList->ResourceInfo.Tid = GetCurrentThreadId();
  131. }
  132. DEBUG_FUNCTION
  133. VOID
  134. UnlockSerializedList(
  135. IN LPSERIALIZED_LIST SerializedList
  136. )
  137. /*++
  138. Routine Description:
  139. Releases a serialized list lock
  140. Arguments:
  141. SerializedList - SERIALIZED_LIST to unlock
  142. Return Value:
  143. None.
  144. --*/
  145. {
  146. INET_ASSERT(SerializedList->Signature == SERIALIZED_LIST_SIGNATURE);
  147. INET_ASSERT(SerializedList->ResourceInfo.Tid == GetCurrentThreadId());
  148. INET_ASSERT(SerializedList->LockCount > 0);
  149. --SerializedList->LockCount;
  150. LeaveCriticalSection(&SerializedList->Lock);
  151. }
  152. DEBUG_FUNCTION
  153. VOID
  154. InsertAtHeadOfSerializedList(
  155. IN LPSERIALIZED_LIST SerializedList,
  156. IN PLIST_ENTRY Entry
  157. )
  158. /*++
  159. Routine Description:
  160. Adds an item to the head of a serialized list
  161. Arguments:
  162. SerializedList - SERIALIZED_LIST to update
  163. Entry - thing to update it with
  164. Return Value:
  165. None.
  166. --*/
  167. {
  168. INET_ASSERT(Entry != &SerializedList->List);
  169. LockSerializedList(SerializedList);
  170. if (fCheckEntryOnList) {
  171. CheckEntryOnList(&SerializedList->List, Entry, FALSE);
  172. }
  173. InsertHeadList(&SerializedList->List, Entry);
  174. ++SerializedList->ElementCount;
  175. INET_ASSERT(SerializedList->ElementCount > 0);
  176. UnlockSerializedList(SerializedList);
  177. }
  178. DEBUG_FUNCTION
  179. VOID
  180. InsertAtTailOfSerializedList(
  181. IN LPSERIALIZED_LIST SerializedList,
  182. IN PLIST_ENTRY Entry
  183. )
  184. /*++
  185. Routine Description:
  186. Adds an item to the head of a serialized list
  187. Arguments:
  188. SerializedList - SERIALIZED_LIST to update
  189. Entry - thing to update it with
  190. Return Value:
  191. None.
  192. --*/
  193. {
  194. INET_ASSERT(Entry != &SerializedList->List);
  195. LockSerializedList(SerializedList);
  196. if (fCheckEntryOnList) {
  197. CheckEntryOnList(&SerializedList->List, Entry, FALSE);
  198. }
  199. InsertTailList(&SerializedList->List, Entry);
  200. ++SerializedList->ElementCount;
  201. INET_ASSERT(SerializedList->ElementCount > 0);
  202. UnlockSerializedList(SerializedList);
  203. }
  204. VOID
  205. DEBUG_FUNCTION
  206. RemoveFromSerializedList(
  207. IN LPSERIALIZED_LIST SerializedList,
  208. IN PLIST_ENTRY Entry
  209. )
  210. /*++
  211. Routine Description:
  212. Removes the entry from a serialized list
  213. Arguments:
  214. SerializedList - SERIALIZED_LIST to remove entry from
  215. Entry - pointer to entry to remove
  216. Return Value:
  217. None.
  218. --*/
  219. {
  220. INET_ASSERT((Entry->Flink != NULL) && (Entry->Blink != NULL));
  221. LockSerializedList(SerializedList);
  222. if (fCheckEntryOnList) {
  223. CheckEntryOnList(&SerializedList->List, Entry, TRUE);
  224. }
  225. INET_ASSERT(SerializedList->ElementCount > 0);
  226. RemoveEntryList(Entry);
  227. --SerializedList->ElementCount;
  228. Entry->Flink = NULL;
  229. Entry->Blink = NULL;
  230. UnlockSerializedList(SerializedList);
  231. }
  232. DEBUG_FUNCTION
  233. BOOL
  234. IsSerializedListEmpty(
  235. IN LPSERIALIZED_LIST SerializedList
  236. )
  237. /*++
  238. Routine Description:
  239. Checks if a serialized list contains any elements
  240. Arguments:
  241. SerializedList - pointer to list to check
  242. Return Value:
  243. BOOL
  244. --*/
  245. {
  246. LockSerializedList(SerializedList);
  247. INET_ASSERT(SerializedList->Signature == SERIALIZED_LIST_SIGNATURE);
  248. BOOL empty;
  249. if (IsListEmpty(&SerializedList->List)) {
  250. INET_ASSERT(SerializedList->ElementCount == 0);
  251. empty = TRUE;
  252. } else {
  253. INET_ASSERT(SerializedList->ElementCount != 0);
  254. empty = FALSE;
  255. }
  256. UnlockSerializedList(SerializedList);
  257. return empty;
  258. }
  259. DEBUG_FUNCTION
  260. PLIST_ENTRY
  261. HeadOfSerializedList(
  262. IN LPSERIALIZED_LIST SerializedList
  263. )
  264. /*++
  265. Routine Description:
  266. Returns the element at the tail of the list, without taking the lock
  267. Arguments:
  268. SerializedList - pointer to SERIALIZED_LIST
  269. Return Value:
  270. PLIST_ENTRY
  271. pointer to element at tail of list
  272. --*/
  273. {
  274. INET_ASSERT(SerializedList->Signature == SERIALIZED_LIST_SIGNATURE);
  275. return SerializedList->List.Flink;
  276. }
  277. DEBUG_FUNCTION
  278. PLIST_ENTRY
  279. TailOfSerializedList(
  280. IN LPSERIALIZED_LIST SerializedList
  281. )
  282. /*++
  283. Routine Description:
  284. Returns the element at the tail of the list, without taking the lock
  285. Arguments:
  286. SerializedList - pointer to SERIALIZED_LIST
  287. Return Value:
  288. PLIST_ENTRY
  289. pointer to element at tail of list
  290. --*/
  291. {
  292. INET_ASSERT(SerializedList->Signature == SERIALIZED_LIST_SIGNATURE);
  293. return SerializedList->List.Blink;
  294. }
  295. DEBUG_FUNCTION
  296. BOOL
  297. CheckEntryOnSerializedList(
  298. IN LPSERIALIZED_LIST SerializedList,
  299. IN PLIST_ENTRY Entry,
  300. IN BOOL ExpectedResult
  301. )
  302. /*++
  303. Routine Description:
  304. Checks an entry exists (or doesn't exist) on a list
  305. Arguments:
  306. SerializedList - pointer to serialized list
  307. Entry - pointer to entry
  308. ExpectedResult - TRUE if expected on list, else FALSE
  309. Return Value:
  310. BOOL
  311. TRUE - expected result
  312. FALSE - unexpected result
  313. --*/
  314. {
  315. INET_ASSERT(SerializedList->Signature == SERIALIZED_LIST_SIGNATURE);
  316. LockSerializedList(SerializedList);
  317. BOOL result;
  318. __try {
  319. result = CheckEntryOnList(&SerializedList->List, Entry, ExpectedResult);
  320. } __except(EXCEPTION_EXECUTE_HANDLER) {
  321. DEBUG_PRINT(SERIALST,
  322. FATAL,
  323. ("List @ %#x (%d elements) is bad\n",
  324. SerializedList,
  325. SerializedList->ElementCount
  326. ));
  327. result = FALSE;
  328. }
  329. ENDEXCEPT
  330. UnlockSerializedList(SerializedList);
  331. return result;
  332. }
  333. PRIVATE
  334. DEBUG_FUNCTION
  335. BOOL
  336. CheckEntryOnList(
  337. IN PLIST_ENTRY List,
  338. IN PLIST_ENTRY Entry,
  339. IN BOOL ExpectedResult
  340. )
  341. {
  342. BOOLEAN found = FALSE;
  343. PLIST_ENTRY p;
  344. if (!IsListEmpty(List)) {
  345. for (p = List->Flink; p != List; p = p->Flink) {
  346. if (p == Entry) {
  347. found = TRUE;
  348. break;
  349. }
  350. }
  351. }
  352. if (found != ExpectedResult) {
  353. if (ReportCheckEntryOnListErrors) {
  354. LPSTR description;
  355. description = found
  356. ? "Entry %#x already on list %#x\n"
  357. : "Entry %#x not found on list %#x\n"
  358. ;
  359. DEBUG_PRINT(SERIALST,
  360. ERROR,
  361. (description,
  362. Entry,
  363. List
  364. ));
  365. DEBUG_BREAK(SERIALST);
  366. }
  367. return FALSE;
  368. }
  369. return TRUE;
  370. }
  371. #endif // INET_DEBUG
  372. //
  373. // functions that are always functions
  374. //
  375. LPVOID
  376. SlDequeueHead(
  377. IN LPSERIALIZED_LIST SerializedList
  378. )
  379. /*++
  380. Routine Description:
  381. Dequeues the element at the head of the queue and returns its address or
  382. NULL if the queue is empty
  383. Arguments:
  384. SerializedList - pointer to SERIALIZED_LIST to dequeue from
  385. Return Value:
  386. LPVOID
  387. --*/
  388. {
  389. LPVOID entry;
  390. if (!IsSerializedListEmpty(SerializedList)) {
  391. LockSerializedList(SerializedList);
  392. if (!IsSerializedListEmpty(SerializedList)) {
  393. entry = (LPVOID)HeadOfSerializedList(SerializedList);
  394. RemoveFromSerializedList(SerializedList, (PLIST_ENTRY)entry);
  395. } else {
  396. entry = NULL;
  397. }
  398. UnlockSerializedList(SerializedList);
  399. } else {
  400. entry = NULL;
  401. }
  402. return entry;
  403. }
  404. LPVOID
  405. SlDequeueTail(
  406. IN LPSERIALIZED_LIST SerializedList
  407. )
  408. /*++
  409. Routine Description:
  410. Dequeues the element at the tail of the queue and returns its address or
  411. NULL if the queue is empty
  412. Arguments:
  413. SerializedList - pointer to SERIALIZED_LIST to dequeue from
  414. Return Value:
  415. LPVOID
  416. --*/
  417. {
  418. LPVOID entry;
  419. if (!IsSerializedListEmpty(SerializedList)) {
  420. LockSerializedList(SerializedList);
  421. if (!IsSerializedListEmpty(SerializedList)) {
  422. entry = (LPVOID)TailOfSerializedList(SerializedList);
  423. RemoveFromSerializedList(SerializedList, (PLIST_ENTRY)entry);
  424. } else {
  425. entry = NULL;
  426. }
  427. UnlockSerializedList(SerializedList);
  428. } else {
  429. entry = NULL;
  430. }
  431. return entry;
  432. }
  433. BOOL
  434. IsOnSerializedList(
  435. IN LPSERIALIZED_LIST SerializedList,
  436. IN PLIST_ENTRY Entry
  437. )
  438. /*++
  439. Routine Description:
  440. Checks if an entry is on a serialized list. Useful to call before
  441. RemoveFromSerializedList() if multiple threads can remove the element
  442. Arguments:
  443. SerializedList - pointer to SERIALIZED_LIST
  444. Entry - pointer to element to check
  445. Return Value:
  446. BOOL
  447. TRUE - Entry is on SerializedList
  448. FALSE - " " not on "
  449. --*/
  450. {
  451. BOOL onList = FALSE;
  452. LPVOID entry;
  453. if (!IsSerializedListEmpty(SerializedList)) {
  454. LockSerializedList(SerializedList);
  455. if (!IsSerializedListEmpty(SerializedList)) {
  456. for (PLIST_ENTRY entry = HeadOfSerializedList(SerializedList);
  457. entry != (PLIST_ENTRY)SlSelf(SerializedList);
  458. entry = entry->Flink) {
  459. if (entry == Entry) {
  460. onList = TRUE;
  461. break;
  462. }
  463. }
  464. }
  465. UnlockSerializedList(SerializedList);
  466. }
  467. return onList;
  468. }