Exemplo n.º 1
0
/*
* @implemented
*/
PRTL_SPLAY_LINKS
NTAPI
RtlRealSuccessor(PRTL_SPLAY_LINKS Links)
{
    PRTL_SPLAY_LINKS Child;

    /* Get the right child */
    Child = RtlRightChild(Links);
    if (Child)
    {
        /* Get left-most child */
        while (RtlLeftChild(Child)) Child = RtlLeftChild(Child);
        return Child;
    }

    /* We don't have a right child, keep looping until we find our parent */
    Child = Links;
    while (RtlIsRightChild(Child)) Child = RtlParent(Child);

    /* The parent should be a left child, return the real successor */
    if (RtlIsLeftChild(Child)) return RtlParent(Child);

    /* The parent isn't a right child, so no real successor for us */
    return NULL;
}
Exemplo n.º 2
0
PRTL_SPLAY_LINKS
RtlRealPredecessor (
    IN PRTL_SPLAY_LINKS Links
    )

/*++

Routine Description:

    The RealPredecessor function takes as input a pointer to a splay link
    in a tree and returns a pointer to the predecessor of the input node
    within the entire tree.  If there is not a predecessor, the return value
    is NULL.

Arguments:

    Links - Supplies a pointer to a splay link in a tree.

Return Value:

    PRTL_SPLAY_LINKS - returns a pointer to the predecessor in the entire tree

--*/

{
    PRTL_SPLAY_LINKS Ptr;

    /*
      first check to see if there is a left subtree to the input link
      if there is then the real predecessor is the right most node in
      the left subtree.  That is find and return P in the following diagram

                  Links
                   /
                  .
                   .
                    .
                     P
                    /
    */

    if ((Ptr = RtlLeftChild(Links)) != NULL) {

        while (RtlRightChild(Ptr) != NULL) {
            Ptr = RtlRightChild(Ptr);
        }

        return Ptr;

    }

    /*
      we do not have a left child so check to see if have a parent and if
      so find the first ancestor that we are a right descendent of. That
      is find and return P in the following diagram

                       P
                        \
                         .
                        .
                       .
                    Links
    */

    Ptr = Links;
    while (RtlIsLeftChild(Ptr)) {
        Ptr = RtlParent(Ptr);
    }

    if (RtlIsRightChild(Ptr)) {
        return RtlParent(Ptr);
    }

    //
    //  otherwise we are do not have a real predecessor so we simply return
    //  NULL
    //

    return NULL;

}
Exemplo n.º 3
0
PRTL_SPLAY_LINKS
RtlSplay (
    IN PRTL_SPLAY_LINKS Links
    )

/*++

Routine Description:

    The Splay function takes as input a pointer to a splay link in a tree
    and splays the tree.  Its function return value is a pointer to the
    root of the splayed tree.

Arguments:

    Links - Supplies a pointer to a splay link in a tree.

Return Value:

    PRTL_SPLAY_LINKS - returns a pointer to the root of the splayed tree.

--*/

{
    PRTL_SPLAY_LINKS L;
    PRTL_SPLAY_LINKS P;
    PRTL_SPLAY_LINKS G;

    //
    //  while links is not the root we need to keep rotating it toward
    //  the root
    //

    L = Links;

    while (!RtlIsRoot(L)) {

        P = RtlParent(L);
        G = RtlParent(P);

        if (RtlIsLeftChild(L)) {

            if (RtlIsRoot(P)) {

                /*
                  we have the following case

                          P           L
                         / \         / \
                        L   c  ==>  a   P
                       / \             / \
                      a   b           b   c
                */

                //
                //  Connect P & b
                //

                P->LeftChild = L->RightChild;
                if (P->LeftChild != NULL) {P->LeftChild->Parent = P;}

                //
                //  Connect L & P
                //

                L->RightChild = P;
                P->Parent = L;

                //
                //  Make L the root
                //

                L->Parent = L;

            } else if (RtlIsLeftChild(P)) {

                /*
                  we have the following case

                          |           |
                          G           L
                         / \         / \
                        P   d  ==>  a   P
                       / \             / \
                      L   c           b   G
                     / \                 / \
                    a   b               c   d
                */

                //
                //  Connect P & b
                //

                P->LeftChild = L->RightChild;
                if (P->LeftChild != NULL) {P->LeftChild->Parent = P;}

                //
                //  Connect G & c
                //

                G->LeftChild = P->RightChild;
                if (G->LeftChild != NULL) {G->LeftChild->Parent = G;}

                //
                //  Connect L & Great GrandParent
                //

                if (RtlIsRoot(G)) {
                    L->Parent = L;
                } else {
                    L->Parent = G->Parent;
                    *(ParentsChildPointerAddress(G)) = L;
                }

                //
                //  Connect L & P
                //

                L->RightChild = P;
                P->Parent = L;

                //
                //  Connect P & G
                //

                P->RightChild = G;
                G->Parent = P;

            } else { // RtlIsRightChild(Parent)

                /*
                  we have the following case

                        |                |
                        G                L
                       / \             /   \
                      a   P           G     P
                         / \         / \   / \
                        L   d  ==>  a   b c   d
                       / \
                      b   c
                */

                //
                //  Connect G & b
                //

                G->RightChild = L->LeftChild;
                if (G->RightChild != NULL) {G->RightChild->Parent = G;}

                //
                //  Connect P & c
                //

                P->LeftChild = L->RightChild;
                if (P->LeftChild != NULL) {P->LeftChild->Parent = P;}

                //
                //  Connect L & Great GrandParent
                //

                if (RtlIsRoot(G)) {
                    L->Parent = L;
                } else {
                    L->Parent = G->Parent;
                    *(ParentsChildPointerAddress(G)) = L;
                }

                //
                //  Connect L & G
                //

                L->LeftChild = G;
                G->Parent = L;

                //
                //  Connect L & P
                //

                L->RightChild = P;
                P->Parent = L;

            }

        } else { // RtlIsRightChild(L)

            if (RtlIsRoot(P)) {

                /*
                  we have the following case

                        P               L
                       / \             / \
                      a   L           P   c
                         / \         / \
                        b   c  ==>  a   b
                */

                //
                //  Connect P & b
                //

                P->RightChild = L->LeftChild;
                if (P->RightChild != NULL) {P->RightChild->Parent = P;}

                //
                //  Connect P & L
                //

                L->LeftChild = P;
                P->Parent = L;

                //
                //  Make L the root
                //

                L->Parent = L;

            } else if (RtlIsRightChild(P)) {

                /*
                  we have the following case

                      |                   |
                      G                   L
                     / \                 / \
                    a   P               P   d
                       / \             / \
                      b   L           G   c
                         / \         / \
                        c   d  ==>  a   b
                */

                //
                //  Connect G & b
                //

                G->RightChild = P->LeftChild;
                if (G->RightChild != NULL) {G->RightChild->Parent = G;}

                //
                //  Connect P & c
                //

                P->RightChild = L->LeftChild;
                if (P->RightChild != NULL) {P->RightChild->Parent = P;}

                //
                //  Connect L & Great GrandParent
                //

                if (RtlIsRoot(G)) {
                    L->Parent = L;
                } else {
                    L->Parent = G->Parent;
                    *(ParentsChildPointerAddress(G)) = L;
                }

                //
                //  Connect L & P
                //

                L->LeftChild = P;
                P->Parent = L;

                //
                //  Connect P & G
                //

                P->LeftChild = G;
                G->Parent = P;

            } else { // RtlIsLeftChild(P)

                /*
                  we have the following case

                          |              |
                          G              L
                         / \           /   \
                        P   d         P     G
                       / \           / \   / \
                      a   L    ==>  a   b c   d
                         / \
                        b   c
                */

                //
                //  Connect P & b
                //

                P->RightChild = L->LeftChild;
                if (P->RightChild != NULL) {P->RightChild->Parent = P;}

                //
                //  Connect G & c
                //

                G->LeftChild = L->RightChild;
                if (G->LeftChild != NULL) {G->LeftChild->Parent = G;}

                //
                //  Connect L & Great GrandParent
                //

                if (RtlIsRoot(G)) {
                    L->Parent = L;
                } else {
                    L->Parent = G->Parent;
                    *(ParentsChildPointerAddress(G)) = L;
                }

                //
                //  Connect L & P
                //

                L->LeftChild = P;
                P->Parent = L;

                //
                //  Connect L & G
                //

                L->RightChild = G;
                G->Parent = L;

            }
        }
    }

    return L;
}
Exemplo n.º 4
0
FORCEINLINE
VOID
RtlpDeleteAvlTreeNode(IN PRTL_AVL_TABLE Table,
                      IN PRTL_BALANCED_LINKS Node)
{
    PRTL_BALANCED_LINKS DeleteNode = NULL, ParentNode;
    PRTL_BALANCED_LINKS *Node1, *Node2;
    CHAR Balance;

    /* Take one of the children if possible */
    if (!(RtlLeftChildAvl(Node)) || !(RtlRightChildAvl(Node))) DeleteNode = Node;

    /* Otherwise, check if one side is longer */
    if (!(DeleteNode) && (RtlBalance(Node) >= RtlBalancedAvlTree))
    {
        /* Pick the successor which will be the longest side in this case */
        DeleteNode = RtlRightChildAvl(Node);
        while (RtlLeftChildAvl(DeleteNode)) DeleteNode = RtlLeftChildAvl(DeleteNode);
    }
    else if (!DeleteNode)
    {
        /* Pick the predecessor which will be the longest side in this case */
        DeleteNode = RtlLeftChildAvl(Node);
        while (RtlRightChildAvl(DeleteNode)) DeleteNode = RtlRightChildAvl(DeleteNode);
    }

    /* Get the parent node */
    ParentNode = RtlParentAvl(DeleteNode);
    DPRINT("Parent: %p\n", ParentNode);

    /* Pick which now to use based on whether or not we have a left child */
    Node1 = RtlLeftChildAvl(DeleteNode) ? &DeleteNode->LeftChild : &DeleteNode->RightChild;
    DPRINT("Node 1: %p %p\n", Node1, *Node1);

    /* Pick which node to swap based on if we're already a left child or not */
    Node2 = RtlIsLeftChildAvl(DeleteNode) ? &ParentNode->LeftChild : &ParentNode->RightChild;
    DPRINT("Node 2: %p %p\n", Node2, *Node2);

    /* Pick the correct balance depending on which side will get heavier */
    Balance = RtlIsLeftChildAvl(DeleteNode) ? RtlLeftHeavyAvlTree : RtlRightHeavyAvlTree;
    DPRINT("Balance: %lx\n", Balance);

    /* Swap the children nodes, making one side heavier */
    *Node2 = *Node1;

    /* If the node has a child now, update its parent */
    if (*Node1) RtlSetParent(*Node1, ParentNode);

    /* Assume balanced root for loop optimization */
    RtlSetBalance(&Table->BalancedRoot, RtlBalancedAvlTree);

    /* Loop up the tree by parents */
    while (TRUE)
    {
        /* Check if the tree's balance increased */
        if (RtlBalance(ParentNode) == Balance)
        {
            /* Now the tree is balanced */
            RtlSetBalance(ParentNode, RtlBalancedAvlTree);
        }
        else if (RtlBalance(ParentNode) == RtlBalancedAvlTree)
        {
            /* The tree has now become less balanced, since it was balanced */
            RtlSetBalance(ParentNode, -Balance);

            /* Deal with the loop optimization to detect loss of a tree level */
            if (RtlBalance(&Table->BalancedRoot) != RtlBalancedAvlTree) Table->DepthOfTree--;
            break;
        }
        else
        {
            /* The tree has become unbalanced, so a rebalance is needed */
            if (RtlpRebalanceAvlTreeNode(ParentNode)) break;

            /* Get the new parent after the balance */
            ParentNode = RtlParentAvl(ParentNode);
        }

        /* Choose which balance factor to use based on which side we're on */
        Balance = RtlIsRightChild(ParentNode) ?
                  RtlRightHeavyAvlTree : RtlLeftHeavyAvlTree;

        /* Iterate up the tree */
        ParentNode = RtlParentAvl(ParentNode);
    }

    /* Check if this isn't the node we ended up deleting directly */
    if (Node == DeleteNode) return;

    /* Copy the deleted node itself */
    RtlpCopyAvlNodeData(DeleteNode, Node);

    /* Pick the right node to unlink */
    Node1 = RtlIsLeftChildAvl(Node) ?
            &(RtlParentAvl(DeleteNode))->LeftChild : &(RtlParentAvl(DeleteNode))->RightChild;
    *Node1 = DeleteNode;

    /* Reparent as appropriate */
    if (RtlLeftChildAvl(DeleteNode)) RtlSetParent(RtlLeftChildAvl(DeleteNode), DeleteNode);
    if (RtlRightChildAvl(DeleteNode)) RtlSetParent(RtlRightChildAvl(DeleteNode), DeleteNode);
}
Exemplo n.º 5
0
VOID
DumpTunnel (
    PTUNNEL Tunnel
    )
{
    PRTL_SPLAY_LINKS SplayLinks, Ptr;
    PTUNNEL_NODE Node;
    PLIST_ENTRY Link;
    ULONG Indent = 1, i;
    ULONG EntryCount = 0;
    BOOLEAN CountOff = FALSE;

    DbgPrint("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");

    DbgPrint("NumEntries = %d\n", Tunnel->NumEntries);
    DbgPrint("****** Cache Tree\n");

    SplayLinks = Tunnel->Cache;

    if (SplayLinks == NULL) {

        goto end;
    }

    while (RtlLeftChild(SplayLinks) != NULL) {

        SplayLinks = RtlLeftChild(SplayLinks);
        Indent++;
    }

    while (SplayLinks) {

        Node = CONTAINING_RECORD( SplayLinks, TUNNEL_NODE, CacheLinks );

        EntryCount++;

        DumpNode(Node, Indent);

        Ptr = SplayLinks;

        /*
          first check to see if there is a right subtree to the input link
          if there is then the real successor is the left most node in
          the right subtree.  That is find and return P in the following diagram

                      Links
                         \
                          .
                         .
                        .
                       /
                      P
                       \
        */

        if ((Ptr = RtlRightChild(SplayLinks)) != NULL) {

            Indent++;
            while (RtlLeftChild(Ptr) != NULL) {

                Indent++;
                Ptr = RtlLeftChild(Ptr);
            }

            SplayLinks = Ptr;

        } else {
            /*
              we do not have a right child so check to see if have a parent and if
              so find the first ancestor that we are a left decendent of. That
              is find and return P in the following diagram

                               P
                              /
                             .
                              .
                               .
                              Links
            */

            Ptr = SplayLinks;
            while (RtlIsRightChild(Ptr)) {

                Indent--;
                Ptr = RtlParent(Ptr);
            }

            if (!RtlIsLeftChild(Ptr)) {

                //
                //  we do not have a real successor so we simply return
                //  NULL
                //
                SplayLinks = NULL;

            } else {

                Indent--;
                SplayLinks = RtlParent(Ptr);
            }
        }
    }

    end:

    if (CountOff = (EntryCount != Tunnel->NumEntries)) {

        DbgPrint("!!!!!!!!!! Splay Tree Count Mismatch (%d != %d)\n", EntryCount, Tunnel->NumEntries);
    }

    EntryCount = 0;

    DbgPrint("****** Timer Queue\n");

    for (Link = Tunnel->TimerQueue.Flink;
         Link != &Tunnel->TimerQueue;
         Link = Link->Flink) {

        Node = CONTAINING_RECORD( Link, TUNNEL_NODE, ListLinks );

        EntryCount++;

        DumpNode(Node, 1);
    }

    if (CountOff |= (EntryCount != Tunnel->NumEntries)) {

        DbgPrint("!!!!!!!!!! Timer Queue Count Mismatch (%d != %d)\n", EntryCount, Tunnel->NumEntries);
    }

    ASSERT(!CountOff);

    DbgPrint("------------------------------------------------------------------\n");
}
Exemplo n.º 6
0
/*
* @implemented
*/
PRTL_SPLAY_LINKS
NTAPI
RtlSplay(PRTL_SPLAY_LINKS Links)
{
    /*
     * Implementation Notes (http://en.wikipedia.org/wiki/Splay_tree):
     *
     * To do a splay, we carry out a sequence of rotations,
     * each of which moves the target node N closer to the root.
     *
     * Each particular step depends on only two factors:
     *  - Whether N is the left or right child of its parent node, P,
     *  - Whether P is the left or right child of its parent, G (for grandparent node).
     *
     * Thus, there are four cases:
     *  - Case 1: N is the left child of P and P is the left child of G.
     *            In this case we perform a double right rotation, so that
     *            P becomes N's right child, and G becomes P's right child.
     *
     *  - Case 2: N is the right child of P and P is the right child of G.
     *            In this case we perform a double left rotation, so that
     *            P becomes N's left child, and G becomes P's left child.
     *
     *  - Case 3: N is the left child of P and P is the right child of G.
     *            In this case we perform a rotation so that
     *            G becomes N's left child, and P becomes N's right child.
     *
     *  - Case 4: N is the right child of P and P is the left child of G.
     *            In this case we perform a rotation so that
     *            P becomes N's left child, and G becomes N's right child.
     *
     * Finally, if N doesn't have a grandparent node, we simply perform a
     * left or right rotation to move it to the root.
     *
     * By performing a splay on the node of interest after every operation,
     * we keep recently accessed nodes near the root and keep the tree
     * roughly balanced, so that we achieve the desired amortized time bounds.
     */
    PRTL_SPLAY_LINKS N, P, G;

    /* N is the item we'll be playing with */
    N = Links;

    /* Let the algorithm run until N becomes the root entry */
    while (!RtlIsRoot(N))
    {
        /* Now get the parent and grand-parent */
        P = RtlParent(N);
        G = RtlParent(P);

        /* Case 1 & 3: N is left child of P */
        if (RtlIsLeftChild(N))
        {
            /* Case 1: P is the left child of G */
            if (RtlIsLeftChild(P))
            {
                /*
                 * N's right-child becomes P's left child and
                 * P's right-child becomes G's left child.
                 */
                RtlLeftChild(P) = RtlRightChild(N);
                RtlLeftChild(G) = RtlRightChild(P);

                /*
                 * If they exist, update their parent pointers too,
                 * since they've changed trees.
                 */
                if (RtlLeftChild(P)) RtlParent(RtlLeftChild(P)) = P;
                if (RtlLeftChild(G)) RtlParent(RtlLeftChild(G)) = G;

                /*
                 * Now we'll shove N all the way to the top.
                 * Check if G is the root first.
                 */
                if (RtlIsRoot(G))
                {
                    /* G doesn't have a parent, so N will become the root! */
                    RtlParent(N) = N;
                }
                else
                {
                    /* G has a parent, so inherit it since we take G's place */
                    RtlParent(N) = RtlParent(G);

                    /*
                     * Now find out who was referencing G and have it reference
                     * N instead, since we're taking G's place.
                     */
                    if (RtlIsLeftChild(G))
                    {
                        /*
                         * G was a left child, so change its parent's left
                         * child link to point to N now.
                         */
                        RtlLeftChild(RtlParent(G)) = N;
                    }
                    else
                    {
                        /*
                         * G was a right child, so change its parent's right
                         * child link to point to N now.
                         */
                        RtlRightChild(RtlParent(G)) = N;
                    }
                }

                /* Now N is on top, so P has become its child. */
                RtlRightChild(N) = P;
                RtlParent(P) = N;

                /* N is on top, P is its child, so G is grandchild. */
                RtlRightChild(P) = G;
                RtlParent(G) = P;
            }
            /* Case 3: P is the right child of G */
            else if (RtlIsRightChild(P))
            {
                /*
                 * N's left-child becomes G's right child and
                 * N's right-child becomes P's left child.
                 */
                RtlRightChild(G) = RtlLeftChild(N);
                RtlLeftChild(P) = RtlRightChild(N);

                /*
                 * If they exist, update their parent pointers too,
                 * since they've changed trees.
                 */
                if (RtlRightChild(G)) RtlParent(RtlRightChild(G)) = G;
                if (RtlLeftChild(P)) RtlParent(RtlLeftChild(P)) = P;

                /*
                 * Now we'll shove N all the way to the top.
                 * Check if G is the root first.
                 */
                if (RtlIsRoot(G))
                {
                    /* G doesn't have a parent, so N will become the root! */
                    RtlParent(N) = N;
                }
                else
                {
                    /* G has a parent, so inherit it since we take G's place */
                    RtlParent(N) = RtlParent(G);

                    /*
                     * Now find out who was referencing G and have it reference
                     * N instead, since we're taking G's place.
                     */
                    if (RtlIsLeftChild(G))
                    {
                        /*
                         * G was a left child, so change its parent's left
                         * child link to point to N now.
                         */
                        RtlLeftChild(RtlParent(G)) = N;
                    }
                    else
                    {
                        /*
                         * G was a right child, so change its parent's right
                         * child link to point to N now.
                         */
                        RtlRightChild(RtlParent(G)) = N;
                    }
                }

                /* Now N is on top, so G has become its left child. */
                RtlLeftChild(N) = G;
                RtlParent(G) = N;

                /* N is on top, G is its left child, so P is right child. */
                RtlRightChild(N) = P;
                RtlParent(P) = N;
            }
            /* "Finally" case: N doesn't have a grandparent => P is root */
            else
            {
                /* P's left-child becomes N's right child */
                RtlLeftChild(P) = RtlRightChild(N);

                /* If it exists, update its parent pointer too */
                if (RtlLeftChild(P)) RtlParent(RtlLeftChild(P)) = P;

                /* Now make N the root, no need to worry about references */
                N->Parent = N;

                /* And make P its right child */
                N->RightChild = P;
                P->Parent = N;
            }
        }
        /* Case 2 & 4: N is right child of P */
        else
        {
            /* Case 2: P is the right child of G */
            if (RtlIsRightChild(P))
            {
                /*
                 * P's left-child becomes G's right child and
                 * N's left-child becomes P's right child.
                 */
                RtlRightChild(G) = RtlLeftChild(P);
                RtlRightChild(P) = RtlLeftChild(N);

                /*
                 * If they exist, update their parent pointers too,
                 * since they've changed trees.
                 */
                if (RtlRightChild(G)) RtlParent(RtlRightChild(G)) = G;
                if (RtlRightChild(P)) RtlParent(RtlRightChild(P)) = P;

                /*
                 * Now we'll shove N all the way to the top.
                 * Check if G is the root first.
                 */
                if (RtlIsRoot(G))
                {
                    /* G doesn't have a parent, so N will become the root! */
                    RtlParent(N) = N;
                }
                else
                {
                    /* G has a parent, so inherit it since we take G's place */
                    RtlParent(N) = RtlParent(G);

                    /*
                     * Now find out who was referencing G and have it reference
                     * N instead, since we're taking G's place.
                     */
                    if (RtlIsLeftChild(G))
                    {
                        /*
                         * G was a left child, so change its parent's left
                         * child link to point to N now.
                         */
                        RtlLeftChild(RtlParent(G)) = N;
                    }
                    else
                    {
                        /*
                         * G was a right child, so change its parent's right
                         * child link to point to N now.
                         */
                        RtlRightChild(RtlParent(G)) = N;
                    }
                }

                /* Now N is on top, so P has become its child. */
                RtlLeftChild(N) = P;
                RtlParent(P) = N;

                /* N is on top, P is its child, so G is grandchild. */
                RtlLeftChild(P) = G;
                RtlParent(G) = P;
            }
            /* Case 4: P is the left child of G */
            else if (RtlIsLeftChild(P))
            {
                /*
                 * N's left-child becomes G's right child and
                 * N's right-child becomes P's left child.
                 */
                RtlRightChild(P) = RtlLeftChild(N);
                RtlLeftChild(G) = RtlRightChild(N);

                /*
                 * If they exist, update their parent pointers too,
                 * since they've changed trees.
                 */
                if (RtlRightChild(P)) RtlParent(RtlRightChild(P)) = P;
                if (RtlLeftChild(G)) RtlParent(RtlLeftChild(G)) = G;

                /*
                 * Now we'll shove N all the way to the top.
                 * Check if G is the root first.
                 */
                if (RtlIsRoot(G))
                {
                    /* G doesn't have a parent, so N will become the root! */
                    RtlParent(N) = N;
                }
                else
                {
                    /* G has a parent, so inherit it since we take G's place */
                    RtlParent(N) = RtlParent(G);

                    /*
                     * Now find out who was referencing G and have it reference
                     * N instead, since we're taking G's place.
                     */
                    if (RtlIsLeftChild(G))
                    {
                        /*
                         * G was a left child, so change its parent's left
                         * child link to point to N now.
                         */
                        RtlLeftChild(RtlParent(G)) = N;
                    }
                    else
                    {
                        /*
                         * G was a right child, so change its parent's right
                         * child link to point to N now.
                         */
                        RtlRightChild(RtlParent(G)) = N;
                    }
                }

                /* Now N is on top, so P has become its left child. */
                RtlLeftChild(N) = P;
                RtlParent(G) = N;

                /* N is on top, P is its left child, so G is right child. */
                RtlRightChild(N) = G;
                RtlParent(P) = N;
            }
            /* "Finally" case: N doesn't have a grandparent => P is root */
            else
            {
                /* P's right-child becomes N's left child */
                RtlRightChild(P) = RtlLeftChild(N);

                /* If it exists, update its parent pointer too */
                if (RtlRightChild(P)) RtlParent(RtlRightChild(P)) = P;

                /* Now make N the root, no need to worry about references */
                N->Parent = N;

                /* And make P its left child */
                N->LeftChild = P;
                P->Parent = N;
            }
        }
    }

    /* Return the root entry */
    ASSERT(RtlIsRoot(N));
    return N;
}