]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdePkg/Library/BaseLib/LinkedList.c
MdePkg/DxeRuntimeDebugLibSerialPort: Add new APIs
[mirror_edk2.git] / MdePkg / Library / BaseLib / LinkedList.c
... / ...
CommitLineData
1/** @file\r
2 Linked List Library Functions.\r
3\r
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php.\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "BaseLibInternals.h"\r
16\r
17/**\r
18 If PcdVerifyNodeInList is TRUE, ASSERTs when SecondEntry is or is not part of\r
19 the same doubly-linked list as FirstEntry depending on the value of InList.\r
20 Independent of PcdVerifyNodeInList, ASSERTs when FirstEntry is not part of a\r
21 valid list.\r
22\r
23 If FirstEntry is NULL, then ASSERT().\r
24 If FirstEntry->ForwardLink is NULL, then ASSERT().\r
25 If FirstEntry->BackLink is NULL, then ASSERT().\r
26 If PcdMaximumLinkedListLength is not zero, and List contains more than\r
27 PcdMaximumLinkedListLength nodes, then ASSERT().\r
28 If PcdVerifyNodeInList is TRUE and SecondEntry is NULL, then ASSERT().\r
29\r
30 @param FirstEntry A pointer to a node in a linked list.\r
31 @param SecondEntry A pointer to the node to locate.\r
32 @param InList Defines whether to check if SecondEntry is or is not part\r
33 of the same doubly-linked list as FirstEntry.\r
34\r
35**/\r
36#if !defined (MDEPKG_NDEBUG)\r
37 #define ASSERT_VERIFY_NODE_IN_VALID_LIST(FirstEntry, SecondEntry, InList) \\r
38 do { \\r
39 if (FeaturePcdGet (PcdVerifyNodeInList)) { \\r
40 ASSERT (InList == IsNodeInList ((FirstEntry), (SecondEntry))); \\r
41 } else { \\r
42 ASSERT (InternalBaseLibIsListValid (FirstEntry)); \\r
43 } \\r
44 } while (FALSE)\r
45#else\r
46 #define ASSERT_VERIFY_NODE_IN_VALID_LIST(FirstEntry, SecondEntry, InList)\r
47#endif\r
48\r
49/**\r
50 Worker function that verifies the validity of this list.\r
51\r
52 If List is NULL, then ASSERT().\r
53 If List->ForwardLink is NULL, then ASSERT().\r
54 If List->BackLink is NULL, then ASSERT().\r
55 If PcdMaximumLinkedListLength is not zero, and List contains more than\r
56 PcdMaximumLinkedListLength nodes, then ASSERT().\r
57\r
58 @param List A pointer to a node in a linked list.\r
59\r
60 @retval TRUE if PcdVerifyNodeInList is FALSE\r
61 @retval TRUE if DoMembershipCheck is FALSE\r
62 @retval TRUE if PcdVerifyNodeInList is TRUE and DoMembershipCheck is TRUE\r
63 and Node is a member of List.\r
64 @retval FALSE if PcdVerifyNodeInList is TRUE and DoMembershipCheck is TRUE\r
65 and Node is in not a member of List.\r
66\r
67**/\r
68BOOLEAN\r
69EFIAPI\r
70InternalBaseLibIsListValid (\r
71 IN CONST LIST_ENTRY *List\r
72 )\r
73{\r
74 UINTN Count;\r
75 CONST LIST_ENTRY *Ptr;\r
76\r
77 //\r
78 // Test the validity of List and Node\r
79 //\r
80 ASSERT (List != NULL);\r
81 ASSERT (List->ForwardLink != NULL);\r
82 ASSERT (List->BackLink != NULL);\r
83\r
84 if (PcdGet32 (PcdMaximumLinkedListLength) > 0) {\r
85 Count = 0;\r
86 Ptr = List;\r
87\r
88 //\r
89 // Count the total number of nodes in List.\r
90 // Exit early if the number of nodes in List >= PcdMaximumLinkedListLength\r
91 //\r
92 do {\r
93 Ptr = Ptr->ForwardLink;\r
94 Count++;\r
95 } while ((Ptr != List) && (Count < PcdGet32 (PcdMaximumLinkedListLength)));\r
96\r
97 //\r
98 // return whether linked list is too long\r
99 //\r
100 return (BOOLEAN)(Count < PcdGet32 (PcdMaximumLinkedListLength));\r
101 }\r
102\r
103 return TRUE;\r
104}\r
105\r
106/**\r
107 Checks whether FirstEntry and SecondEntry are part of the same doubly-linked\r
108 list.\r
109\r
110 If FirstEntry is NULL, then ASSERT().\r
111 If FirstEntry->ForwardLink is NULL, then ASSERT().\r
112 If FirstEntry->BackLink is NULL, then ASSERT().\r
113 If SecondEntry is NULL, then ASSERT();\r
114 If PcdMaximumLinkedListLength is not zero, and List contains more than\r
115 PcdMaximumLinkedListLength nodes, then ASSERT().\r
116\r
117 @param FirstEntry A pointer to a node in a linked list.\r
118 @param SecondEntry A pointer to the node to locate.\r
119\r
120 @retval TRUE SecondEntry is in the same doubly-linked list as FirstEntry.\r
121 @retval FALSE SecondEntry isn't in the same doubly-linked list as FirstEntry,\r
122 or FirstEntry is invalid.\r
123\r
124**/\r
125BOOLEAN\r
126EFIAPI\r
127IsNodeInList (\r
128 IN CONST LIST_ENTRY *FirstEntry,\r
129 IN CONST LIST_ENTRY *SecondEntry\r
130 )\r
131{\r
132 UINTN Count;\r
133 CONST LIST_ENTRY *Ptr;\r
134\r
135 //\r
136 // ASSERT List not too long\r
137 //\r
138 ASSERT (InternalBaseLibIsListValid (FirstEntry));\r
139\r
140 ASSERT (SecondEntry != NULL);\r
141\r
142 Count = 0;\r
143 Ptr = FirstEntry;\r
144\r
145 //\r
146 // Check to see if SecondEntry is a member of FirstEntry.\r
147 // Exit early if the number of nodes in List >= PcdMaximumLinkedListLength\r
148 //\r
149 do {\r
150 Ptr = Ptr->ForwardLink;\r
151 if (PcdGet32 (PcdMaximumLinkedListLength) > 0) {\r
152 Count++;\r
153\r
154 //\r
155 // Return if the linked list is too long\r
156 //\r
157 if (Count == PcdGet32 (PcdMaximumLinkedListLength)) {\r
158 return (BOOLEAN)(Ptr == SecondEntry);\r
159 }\r
160 }\r
161\r
162 if (Ptr == SecondEntry) {\r
163 return TRUE;\r
164 }\r
165 } while (Ptr != FirstEntry);\r
166\r
167 return FALSE;\r
168}\r
169\r
170/**\r
171 Initializes the head node of a doubly-linked list, and returns the pointer to\r
172 the head node of the doubly-linked list.\r
173\r
174 Initializes the forward and backward links of a new linked list. After\r
175 initializing a linked list with this function, the other linked list\r
176 functions may be used to add and remove nodes from the linked list. It is up\r
177 to the caller of this function to allocate the memory for ListHead.\r
178\r
179 If ListHead is NULL, then ASSERT().\r
180\r
181 @param ListHead A pointer to the head node of a new doubly-linked list.\r
182\r
183 @return ListHead\r
184\r
185**/\r
186LIST_ENTRY *\r
187EFIAPI\r
188InitializeListHead (\r
189 IN OUT LIST_ENTRY *ListHead\r
190 )\r
191\r
192{\r
193 ASSERT (ListHead != NULL);\r
194\r
195 ListHead->ForwardLink = ListHead;\r
196 ListHead->BackLink = ListHead;\r
197 return ListHead;\r
198}\r
199\r
200/**\r
201 Adds a node to the beginning of a doubly-linked list, and returns the pointer\r
202 to the head node of the doubly-linked list.\r
203\r
204 Adds the node Entry at the beginning of the doubly-linked list denoted by\r
205 ListHead, and returns ListHead.\r
206\r
207 If ListHead is NULL, then ASSERT().\r
208 If Entry is NULL, then ASSERT().\r
209 If ListHead was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or\r
210 InitializeListHead(), then ASSERT().\r
211 If PcdMaximumLinkedListLength is not zero, and prior to insertion the number\r
212 of nodes in ListHead, including the ListHead node, is greater than or\r
213 equal to PcdMaximumLinkedListLength, then ASSERT().\r
214\r
215 @param ListHead A pointer to the head node of a doubly-linked list.\r
216 @param Entry A pointer to a node that is to be inserted at the beginning\r
217 of a doubly-linked list.\r
218\r
219 @return ListHead\r
220\r
221**/\r
222LIST_ENTRY *\r
223EFIAPI\r
224InsertHeadList (\r
225 IN OUT LIST_ENTRY *ListHead,\r
226 IN OUT LIST_ENTRY *Entry\r
227 )\r
228{\r
229 //\r
230 // ASSERT List not too long and Entry is not one of the nodes of List\r
231 //\r
232 ASSERT_VERIFY_NODE_IN_VALID_LIST (ListHead, Entry, FALSE);\r
233\r
234 Entry->ForwardLink = ListHead->ForwardLink;\r
235 Entry->BackLink = ListHead;\r
236 Entry->ForwardLink->BackLink = Entry;\r
237 ListHead->ForwardLink = Entry;\r
238 return ListHead;\r
239}\r
240\r
241/**\r
242 Adds a node to the end of a doubly-linked list, and returns the pointer to\r
243 the head node of the doubly-linked list.\r
244\r
245 Adds the node Entry to the end of the doubly-linked list denoted by ListHead,\r
246 and returns ListHead.\r
247\r
248 If ListHead is NULL, then ASSERT().\r
249 If Entry is NULL, then ASSERT().\r
250 If ListHead was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or\r
251 InitializeListHead(), then ASSERT().\r
252 If PcdMaximumLinkedListLength is not zero, and prior to insertion the number\r
253 of nodes in ListHead, including the ListHead node, is greater than or\r
254 equal to PcdMaximumLinkedListLength, then ASSERT().\r
255\r
256 @param ListHead A pointer to the head node of a doubly-linked list.\r
257 @param Entry A pointer to a node that is to be added at the end of the\r
258 doubly-linked list.\r
259\r
260 @return ListHead\r
261\r
262**/\r
263LIST_ENTRY *\r
264EFIAPI\r
265InsertTailList (\r
266 IN OUT LIST_ENTRY *ListHead,\r
267 IN OUT LIST_ENTRY *Entry\r
268 )\r
269{\r
270 //\r
271 // ASSERT List not too long and Entry is not one of the nodes of List\r
272 //\r
273 ASSERT_VERIFY_NODE_IN_VALID_LIST (ListHead, Entry, FALSE);\r
274\r
275 Entry->ForwardLink = ListHead;\r
276 Entry->BackLink = ListHead->BackLink;\r
277 Entry->BackLink->ForwardLink = Entry;\r
278 ListHead->BackLink = Entry;\r
279 return ListHead;\r
280}\r
281\r
282/**\r
283 Retrieves the first node of a doubly-linked list.\r
284\r
285 Returns the first node of a doubly-linked list. List must have been\r
286 initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead().\r
287 If List is empty, then List is returned.\r
288\r
289 If List is NULL, then ASSERT().\r
290 If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or\r
291 InitializeListHead(), then ASSERT().\r
292 If PcdMaximumLinkedListLength is not zero, and the number of nodes\r
293 in List, including the List node, is greater than or equal to\r
294 PcdMaximumLinkedListLength, then ASSERT().\r
295\r
296 @param List A pointer to the head node of a doubly-linked list.\r
297\r
298 @return The first node of a doubly-linked list.\r
299 @retval List The list is empty.\r
300\r
301**/\r
302LIST_ENTRY *\r
303EFIAPI\r
304GetFirstNode (\r
305 IN CONST LIST_ENTRY *List\r
306 )\r
307{\r
308 //\r
309 // ASSERT List not too long\r
310 //\r
311 ASSERT (InternalBaseLibIsListValid (List));\r
312\r
313 return List->ForwardLink;\r
314}\r
315\r
316/**\r
317 Retrieves the next node of a doubly-linked list.\r
318\r
319 Returns the node of a doubly-linked list that follows Node.\r
320 List must have been initialized with INTIALIZE_LIST_HEAD_VARIABLE()\r
321 or InitializeListHead(). If List is empty, then List is returned.\r
322\r
323 If List is NULL, then ASSERT().\r
324 If Node is NULL, then ASSERT().\r
325 If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or\r
326 InitializeListHead(), then ASSERT().\r
327 If PcdMaximumLinkedListLength is not zero, and List contains more than\r
328 PcdMaximumLinkedListLength nodes, then ASSERT().\r
329 If PcdVerifyNodeInList is TRUE and Node is not a node in List, then ASSERT().\r
330\r
331 @param List A pointer to the head node of a doubly-linked list.\r
332 @param Node A pointer to a node in the doubly-linked list.\r
333\r
334 @return A pointer to the next node if one exists. Otherwise List is returned.\r
335\r
336**/\r
337LIST_ENTRY *\r
338EFIAPI\r
339GetNextNode (\r
340 IN CONST LIST_ENTRY *List,\r
341 IN CONST LIST_ENTRY *Node\r
342 )\r
343{\r
344 //\r
345 // ASSERT List not too long and Node is one of the nodes of List\r
346 //\r
347 ASSERT_VERIFY_NODE_IN_VALID_LIST (List, Node, TRUE);\r
348\r
349 return Node->ForwardLink;\r
350}\r
351\r
352/**\r
353 Retrieves the previous node of a doubly-linked list.\r
354\r
355 Returns the node of a doubly-linked list that precedes Node.\r
356 List must have been initialized with INTIALIZE_LIST_HEAD_VARIABLE()\r
357 or InitializeListHead(). If List is empty, then List is returned.\r
358\r
359 If List is NULL, then ASSERT().\r
360 If Node is NULL, then ASSERT().\r
361 If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or\r
362 InitializeListHead(), then ASSERT().\r
363 If PcdMaximumLinkedListLength is not zero, and List contains more than\r
364 PcdMaximumLinkedListLength nodes, then ASSERT().\r
365 If PcdVerifyNodeInList is TRUE and Node is not a node in List, then ASSERT().\r
366\r
367 @param List A pointer to the head node of a doubly-linked list.\r
368 @param Node A pointer to a node in the doubly-linked list.\r
369\r
370 @return A pointer to the previous node if one exists. Otherwise List is returned.\r
371\r
372**/\r
373LIST_ENTRY *\r
374EFIAPI\r
375GetPreviousNode (\r
376 IN CONST LIST_ENTRY *List,\r
377 IN CONST LIST_ENTRY *Node\r
378 )\r
379{\r
380 //\r
381 // ASSERT List not too long and Node is one of the nodes of List\r
382 //\r
383 ASSERT_VERIFY_NODE_IN_VALID_LIST (List, Node, TRUE);\r
384\r
385 return Node->BackLink;\r
386}\r
387\r
388/**\r
389 Checks to see if a doubly-linked list is empty or not.\r
390\r
391 Checks to see if the doubly-linked list is empty. If the linked list contains\r
392 zero nodes, this function returns TRUE. Otherwise, it returns FALSE.\r
393\r
394 If ListHead is NULL, then ASSERT().\r
395 If ListHead was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or\r
396 InitializeListHead(), then ASSERT().\r
397 If PcdMaximumLinkedListLength is not zero, and the number of nodes\r
398 in List, including the List node, is greater than or equal to\r
399 PcdMaximumLinkedListLength, then ASSERT().\r
400\r
401 @param ListHead A pointer to the head node of a doubly-linked list.\r
402\r
403 @retval TRUE The linked list is empty.\r
404 @retval FALSE The linked list is not empty.\r
405\r
406**/\r
407BOOLEAN\r
408EFIAPI\r
409IsListEmpty (\r
410 IN CONST LIST_ENTRY *ListHead\r
411 )\r
412{\r
413 //\r
414 // ASSERT List not too long\r
415 //\r
416 ASSERT (InternalBaseLibIsListValid (ListHead));\r
417\r
418 return (BOOLEAN)(ListHead->ForwardLink == ListHead);\r
419}\r
420\r
421/**\r
422 Determines if a node in a doubly-linked list is the head node of a the same\r
423 doubly-linked list. This function is typically used to terminate a loop that\r
424 traverses all the nodes in a doubly-linked list starting with the head node.\r
425\r
426 Returns TRUE if Node is equal to List. Returns FALSE if Node is one of the\r
427 nodes in the doubly-linked list specified by List. List must have been\r
428 initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead().\r
429\r
430 If List is NULL, then ASSERT().\r
431 If Node is NULL, then ASSERT().\r
432 If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(),\r
433 then ASSERT().\r
434 If PcdMaximumLinkedListLength is not zero, and the number of nodes\r
435 in List, including the List node, is greater than or equal to\r
436 PcdMaximumLinkedListLength, then ASSERT().\r
437 If PcdVerifyNodeInList is TRUE and Node is not a node in List and Node is not\r
438 equal to List, then ASSERT().\r
439\r
440 @param List A pointer to the head node of a doubly-linked list.\r
441 @param Node A pointer to a node in the doubly-linked list.\r
442\r
443 @retval TRUE Node is the head of the doubly-linked list pointed by List.\r
444 @retval FALSE Node is not the head of the doubly-linked list pointed by List.\r
445\r
446**/\r
447BOOLEAN\r
448EFIAPI\r
449IsNull (\r
450 IN CONST LIST_ENTRY *List,\r
451 IN CONST LIST_ENTRY *Node\r
452 )\r
453{\r
454 //\r
455 // ASSERT List not too long and Node is one of the nodes of List\r
456 //\r
457 ASSERT_VERIFY_NODE_IN_VALID_LIST (List, Node, TRUE);\r
458\r
459 return (BOOLEAN)(Node == List);\r
460}\r
461\r
462/**\r
463 Determines if a node the last node in a doubly-linked list.\r
464\r
465 Returns TRUE if Node is the last node in the doubly-linked list specified by\r
466 List. Otherwise, FALSE is returned. List must have been initialized with\r
467 INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead().\r
468\r
469 If List is NULL, then ASSERT().\r
470 If Node is NULL, then ASSERT().\r
471 If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or\r
472 InitializeListHead(), then ASSERT().\r
473 If PcdMaximumLinkedListLength is not zero, and the number of nodes\r
474 in List, including the List node, is greater than or equal to\r
475 PcdMaximumLinkedListLength, then ASSERT().\r
476 If PcdVerifyNodeInList is TRUE and Node is not a node in List, then ASSERT().\r
477\r
478 @param List A pointer to the head node of a doubly-linked list.\r
479 @param Node A pointer to a node in the doubly-linked list.\r
480\r
481 @retval TRUE Node is the last node in the linked list.\r
482 @retval FALSE Node is not the last node in the linked list.\r
483\r
484**/\r
485BOOLEAN\r
486EFIAPI\r
487IsNodeAtEnd (\r
488 IN CONST LIST_ENTRY *List,\r
489 IN CONST LIST_ENTRY *Node\r
490 )\r
491{\r
492 //\r
493 // ASSERT List not too long and Node is one of the nodes of List\r
494 //\r
495 ASSERT_VERIFY_NODE_IN_VALID_LIST (List, Node, TRUE);\r
496\r
497 return (BOOLEAN)(!IsNull (List, Node) && List->BackLink == Node);\r
498}\r
499\r
500/**\r
501 Swaps the location of two nodes in a doubly-linked list, and returns the\r
502 first node after the swap.\r
503\r
504 If FirstEntry is identical to SecondEntry, then SecondEntry is returned.\r
505 Otherwise, the location of the FirstEntry node is swapped with the location\r
506 of the SecondEntry node in a doubly-linked list. SecondEntry must be in the\r
507 same double linked list as FirstEntry and that double linked list must have\r
508 been initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead().\r
509 SecondEntry is returned after the nodes are swapped.\r
510\r
511 If FirstEntry is NULL, then ASSERT().\r
512 If SecondEntry is NULL, then ASSERT().\r
513 If PcdVerifyNodeInList is TRUE and SecondEntry and FirstEntry are not in the\r
514 same linked list, then ASSERT().\r
515 If PcdMaximumLinkedListLength is not zero, and the number of nodes in the\r
516 linked list containing the FirstEntry and SecondEntry nodes, including\r
517 the FirstEntry and SecondEntry nodes, is greater than or equal to\r
518 PcdMaximumLinkedListLength, then ASSERT().\r
519\r
520 @param FirstEntry A pointer to a node in a linked list.\r
521 @param SecondEntry A pointer to another node in the same linked list.\r
522\r
523 @return SecondEntry.\r
524\r
525**/\r
526LIST_ENTRY *\r
527EFIAPI\r
528SwapListEntries (\r
529 IN OUT LIST_ENTRY *FirstEntry,\r
530 IN OUT LIST_ENTRY *SecondEntry\r
531 )\r
532{\r
533 LIST_ENTRY *Ptr;\r
534\r
535 if (FirstEntry == SecondEntry) {\r
536 return SecondEntry;\r
537 }\r
538\r
539 //\r
540 // ASSERT Entry1 and Entry2 are in the same linked list\r
541 //\r
542 ASSERT_VERIFY_NODE_IN_VALID_LIST (FirstEntry, SecondEntry, TRUE);\r
543\r
544 //\r
545 // Ptr is the node pointed to by FirstEntry->ForwardLink\r
546 //\r
547 Ptr = RemoveEntryList (FirstEntry);\r
548\r
549 //\r
550 // If FirstEntry immediately follows SecondEntry, FirstEntry will be placed\r
551 // immediately in front of SecondEntry\r
552 //\r
553 if (Ptr->BackLink == SecondEntry) {\r
554 return InsertTailList (SecondEntry, FirstEntry);\r
555 }\r
556\r
557 //\r
558 // Ptr == SecondEntry means SecondEntry immediately follows FirstEntry,\r
559 // then there are no further steps necessary\r
560 //\r
561 if (Ptr == InsertHeadList (SecondEntry, FirstEntry)) {\r
562 return Ptr;\r
563 }\r
564\r
565 //\r
566 // Move SecondEntry to the front of Ptr\r
567 //\r
568 RemoveEntryList (SecondEntry);\r
569 InsertTailList (Ptr, SecondEntry);\r
570 return SecondEntry;\r
571}\r
572\r
573/**\r
574 Removes a node from a doubly-linked list, and returns the node that follows\r
575 the removed node.\r
576\r
577 Removes the node Entry from a doubly-linked list. It is up to the caller of\r
578 this function to release the memory used by this node if that is required. On\r
579 exit, the node following Entry in the doubly-linked list is returned. If\r
580 Entry is the only node in the linked list, then the head node of the linked\r
581 list is returned.\r
582\r
583 If Entry is NULL, then ASSERT().\r
584 If Entry is the head node of an empty list, then ASSERT().\r
585 If PcdMaximumLinkedListLength is not zero, and the number of nodes in the\r
586 linked list containing Entry, including the Entry node, is greater than\r
587 or equal to PcdMaximumLinkedListLength, then ASSERT().\r
588\r
589 @param Entry A pointer to a node in a linked list.\r
590\r
591 @return Entry.\r
592\r
593**/\r
594LIST_ENTRY *\r
595EFIAPI\r
596RemoveEntryList (\r
597 IN CONST LIST_ENTRY *Entry\r
598 )\r
599{\r
600 ASSERT (!IsListEmpty (Entry));\r
601\r
602 Entry->ForwardLink->BackLink = Entry->BackLink;\r
603 Entry->BackLink->ForwardLink = Entry->ForwardLink;\r
604 return Entry->ForwardLink;\r
605}\r