/* * @implemented */ PVOID NTAPI RtlEnumerateGenericTableWithoutSplaying(IN PRTL_GENERIC_TABLE Table, IN OUT PVOID *RestartKey) { PRTL_SPLAY_LINKS FoundNode; /* Check if the table is empty */ if (RtlIsGenericTableEmpty(Table)) return NULL; /* Check if we have to restart */ if (!(*RestartKey)) { /* Then find the leftmost element */ FoundNode = Table->TableRoot; do { /* Get the left child */ FoundNode = RtlLeftChild(FoundNode); } while(RtlLeftChild(FoundNode)); /* Splay it */ *RestartKey = FoundNode; } else { /* Otherwise, try using the real successor */ FoundNode = RtlRealSuccessor(*RestartKey); if (FoundNode) *RestartKey = FoundNode; } /* Check if we found the node and return it */ return FoundNode ? &((PTABLE_ENTRY_HEADER)FoundNode)->UserData : NULL; }
TABLE_SEARCH_RESULT NTAPI RtlpFindGenericTableNodeOrParent(IN PRTL_GENERIC_TABLE Table, IN PVOID Buffer, OUT PRTL_SPLAY_LINKS *NodeOrParent) { PRTL_SPLAY_LINKS CurrentNode, ChildNode; RTL_GENERIC_COMPARE_RESULTS Result; /* Quick check to see if the table is empty */ if (RtlIsGenericTableEmpty(Table)) { *NodeOrParent = NULL; return TableEmptyTree; } /* Set the current node */ CurrentNode = Table->TableRoot; /* Start compare loop */ while (TRUE) { /* Do the compare */ Result = Table->CompareRoutine(Table, Buffer, &((PTABLE_ENTRY_HEADER)CurrentNode)-> UserData); if (Result == GenericLessThan) { /* We're less, check if this is the left child */ if ((ChildNode = RtlLeftChild(CurrentNode))) { /* Continue searching from this node */ CurrentNode = ChildNode; } else { /* Otherwise, the element isn't in this tree */ *NodeOrParent = CurrentNode; return TableInsertAsLeft; } } else if (Result == GenericGreaterThan) { /* We're more, check if this is the right child */ if ((ChildNode = RtlRightChild(CurrentNode))) { /* Continue searching from this node */ CurrentNode = ChildNode; } else { /* Otherwise, the element isn't in this tree */ *NodeOrParent = CurrentNode; return TableInsertAsRight; } } else { /* We should've found the node */ ASSERT(Result == GenericEqual); /* Return node found */ *NodeOrParent = CurrentNode; return TableFoundNode; } } }
PVOID RtlEnumerateGenericTable ( IN PRTL_GENERIC_TABLE Table, IN BOOLEAN Restart ) /*++ Routine Description: The function EnumerateGenericTable will return to the caller one-by-one the elements of of a table. The return value is a pointer to the user defined structure associated with the element. The input parameter Restart indicates if the enumeration should start from the beginning or should return the next element. If the are no more new elements to return the return value is NULL. As an example of its use, to enumerate all of the elements in a table the user would write: for (ptr = EnumerateGenericTable(Table,TRUE); ptr != NULL; ptr = EnumerateGenericTable(Table, FALSE)) { : } Arguments: Table - Pointer to the generic table to enumerate. Restart - Flag that if true we should start with the least element in the tree otherwise, return we return a pointer to the user data for the root and make the real successor to the root the new root. Return Value: PVOID - Pointer to the user data. --*/ { if (RtlIsGenericTableEmpty(Table)) { // // Nothing to do if the table is empty. // return NULL; } else { // // Will be used as the "iteration" through the tree. // PRTL_SPLAY_LINKS NodeToReturn; // // If the restart flag is true then go to the least element // in the tree. // if (Restart) { // // We just loop until we find the leftmost child of the root. // for ( NodeToReturn = Table->TableRoot; RtlLeftChild(NodeToReturn); NodeToReturn = RtlLeftChild(NodeToReturn) ) { ; } Table->TableRoot = RtlSplay(NodeToReturn); } else { // // The assumption here is that the root of the // tree is the last node that we returned. We // find the real successor to the root and return // it as next element of the enumeration. The // node that is to be returned is splayed (thereby // making it the root of the tree). Note that we // need to take care when there are no more elements. // NodeToReturn = RtlRealSuccessor(Table->TableRoot); if (NodeToReturn) { Table->TableRoot = RtlSplay(NodeToReturn); } } // // If there actually is a next element in the enumeration // then the pointer to return is right after the list links. // return ((NodeToReturn)? ((PVOID)((PLIST_ENTRY)((PVOID)(NodeToReturn+1))+1)) :((PVOID)(NULL))); } }
PVOID RtlEnumerateGenericTableWithoutSplaying ( IN PRTL_GENERIC_TABLE Table, IN PVOID *RestartKey ) /*++ Routine Description: The function EnumerateGenericTableWithoutSplaying will return to the caller one-by-one the elements of of a table. The return value is a pointer to the user defined structure associated with the element. The input parameter RestartKey indicates if the enumeration should start from the beginning or should return the next element. If the are no more new elements to return the return value is NULL. As an example of its use, to enumerate all of the elements in a table the user would write: *RestartKey = NULL; for (ptr = EnumerateGenericTableWithoutSplaying(Table, &RestartKey); ptr != NULL; ptr = EnumerateGenericTableWithoutSplaying(Table, &RestartKey)) { : } Arguments: Table - Pointer to the generic table to enumerate. RestartKey - Pointer that indicates if we should restart or return the next element. If the contents of RestartKey is NULL, the search will be started from the beginning. Return Value: PVOID - Pointer to the user data. --*/ { if (RtlIsGenericTableEmpty(Table)) { // // Nothing to do if the table is empty. // return NULL; } else { // // Will be used as the "iteration" through the tree. // PRTL_SPLAY_LINKS NodeToReturn; // // If the restart flag is true then go to the least element // in the tree. // if (*RestartKey == NULL) { // // We just loop until we find the leftmost child of the root. // for ( NodeToReturn = Table->TableRoot; RtlLeftChild(NodeToReturn); NodeToReturn = RtlLeftChild(NodeToReturn) ) { ; } *RestartKey = NodeToReturn; } else { // // The caller has passed in the previous entry found // in the table to enable us to continue the search. We call // RtlRealSuccessor to step to the next element in the tree. // NodeToReturn = RtlRealSuccessor(*RestartKey); if (NodeToReturn) { *RestartKey = NodeToReturn; } } // // If there actually is a next element in the enumeration // then the pointer to return is right after the list links. // return ((NodeToReturn)? ((PVOID)((PLIST_ENTRY)((PVOID)(NodeToReturn+1))+1)) :((PVOID)(NULL))); } }
static SEARCH_RESULT FindNodeOrParent( IN PRTL_GENERIC_TABLE Table, IN PVOID Buffer, OUT PRTL_SPLAY_LINKS *NodeOrParent ) /*++ Routine Description: This routine is used by all of the routines of the generic table package to locate the a node in the tree. It will find and return (via the NodeOrParent parameter) the node with the given key, or if that node is not in the tree it will return (via the NodeOrParent parameter) a pointer to the parent. Arguments: Table - The generic table to search for the key. Buffer - Pointer to a buffer holding the key. The table package doesn't examine the key itself. It leaves this up to the user supplied compare routine. NodeOrParent - Will be set to point to the node containing the the key or what should be the parent of the node if it were in the tree. Note that this will *NOT* be set if the search result is EmptyTree. Return Value: SEARCH_RESULT - EmptyTree: The tree was empty. NodeOrParent is *not* altered. FoundNode: A node with the key is in the tree. NodeOrParent points to that node. InsertAsLeft: Node with key was not found. NodeOrParent points to what would be parent. The node would be the left child. InsertAsRight: Node with key was not found. NodeOrParent points to what would be parent. The node would be the right child. --*/ { if (RtlIsGenericTableEmpty(Table)) { return EmptyTree; } else { // // Used as the iteration variable while stepping through // the generic table. // PRTL_SPLAY_LINKS NodeToExamine = Table->TableRoot; // // Just a temporary. Hopefully a good compiler will get // rid of it. // PRTL_SPLAY_LINKS Child; // // Holds the value of the comparasion. // RTL_GENERIC_COMPARE_RESULTS Result; while (TRUE) { // // Compare the buffer with the key in the tree element. // Result = Table->CompareRoutine( Table, Buffer, ((PLIST_ENTRY)((PVOID)(NodeToExamine+1)))+1 ); if (Result == GenericLessThan) { if (Child = RtlLeftChild(NodeToExamine)) { NodeToExamine = Child; } else { // // Node is not in the tree. Set the output // parameter to point to what would be its // parent and return which child it would be. // *NodeOrParent = NodeToExamine; return InsertAsLeft; } } else if (Result == GenericGreaterThan) { if (Child = RtlRightChild(NodeToExamine)) { NodeToExamine = Child; } else { // // Node is not in the tree. Set the output // parameter to point to what would be its // parent and return which child it would be. // *NodeOrParent = NodeToExamine; return InsertAsRight; } } else { // // Node is in the tree (or it better be because of the // assert). Set the output parameter to point to // the node and tell the caller that we found the node. // ASSERT(Result == GenericEqual); *NodeOrParent = NodeToExamine; return FoundNode; } } } }