示例#1
0
文件: splay.c 项目: BaoYu0721/WRK-1.2
VOID
SwapSplayLinks (
    IN PRTL_SPLAY_LINKS Link1,
    IN PRTL_SPLAY_LINKS Link2
    )

{
    PRTL_SPLAY_LINKS *Parent1ChildPtr;
    PRTL_SPLAY_LINKS *Parent2ChildPtr;

    /*
      We have the following situation


             Parent1            Parent2
                |                  |
                |                  |
              Link1              Link2
               / \                / \
              /   \              /   \
            LC1   RC1          LC2   RC2

      where one of the links can possibly be the root and one of the links
      can possibly be a direct child of the other.  Without loss of
      generality we'll make link2 be the possible and root and link1 be
      the possible child.
    */

    if ((RtlIsRoot(Link1)) || (RtlParent(Link2) == Link1)) {
        SwapPointers(Link1, Link2);
    }

    //
    //  The four cases we need to handle are
    //
    //  1. Link1 is not a child of link2 and link2 is not the root
    //  2. Link1 is not a child of link2 and link2 is     the root
    //  3. Link1 is     a child of link2 and link2 is not the root
    //  4. Link1 is     a child of link2 and link2 is     the root
    //
    //
    //  Each case will be handled separately
    //

    if (RtlParent(Link1) != Link2) {

        if (!RtlIsRoot(Link2)) {

            //
            //  Case 1 the initial steps are:
            //
            //  1. get both parent child pointers
            //  2. swap the parent child pointers
            //  3. swap the parent pointers
            //

            Parent1ChildPtr = ParentsChildPointerAddress(Link1);
            Parent2ChildPtr = ParentsChildPointerAddress(Link2);

            SwapPointers(*Parent1ChildPtr, *Parent2ChildPtr);

            SwapPointers(Link1->Parent, Link2->Parent);

        } else {

            //
            //  Case 2 the initial steps are:
            //
            //  1. Set link1's parent child pointer to link2
            //  2. Set parent pointer of link2 to link1's parent
            //  3. Set parent pointer of link1 to be itself
            //

            Parent1ChildPtr = ParentsChildPointerAddress(Link1);
            *Parent1ChildPtr = Link2;

            Link2->Parent = Link1->Parent;

            Link1->Parent = Link1;

        }

        //
        //  Case 1 and 2 common steps are:
        //
        //  1. swap the child pointers
        //

        SwapPointers(Link1->LeftChild, Link2->LeftChild);
        SwapPointers(Link1->RightChild, Link2->RightChild);

    } else { // RtlParent(Link1) == Link2

        if (!RtlIsRoot(Link2)) {

            //
            //  Case 3 the initial steps are:
            //
            //  1. Set Link2's parent child pointer to link1
            //  2. Set Link1's parent pointer to parent of link2
            //

            Parent2ChildPtr = ParentsChildPointerAddress(Link2);
            *Parent2ChildPtr = Link1;

            Link1->Parent = Link2->Parent;

        } else {

            //
            //  Case 4 the initial steps are:
            //
            //  1. Set Link1's parent pointer to be link1
            //

            Link1->Parent = Link1;

        }

        //
        //  Case 3 and 4 common steps are:
        //
        //  1. Swap the child pointers
        //  2. if link1 was a left child (i.e., RtlLeftChild(Link1) == Link1)
        //     then set left child of link1 to link2
        //     else set right child of link1 to link2
        //

        SwapPointers(Link1->LeftChild, Link2->LeftChild);
        SwapPointers(Link1->RightChild, Link2->RightChild);

        if (Link1->LeftChild == Link1) {
            Link1->LeftChild = Link2;
        } else {
            Link1->RightChild = Link2;
        }

    }

    //
    //  Case 1, 2, 3, 4 common (and final) steps are:
    //
    //  1. Fix the parent pointers of the left and right children
    //

    if (Link1->LeftChild  != NULL) {Link1->LeftChild->Parent  = Link1;}
    if (Link1->RightChild != NULL) {Link1->RightChild->Parent = Link1;}
    if (Link2->LeftChild  != NULL) {Link2->LeftChild->Parent  = Link2;}
    if (Link2->RightChild != NULL) {Link2->RightChild->Parent = Link2;}
}
示例#2
0
文件: splay.c 项目: BaoYu0721/WRK-1.2
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;
}
示例#3
0
文件: splay.c 项目: BaoYu0721/WRK-1.2
VOID
RtlDeleteNoSplay (
    IN PRTL_SPLAY_LINKS Links,
    IN OUT PRTL_SPLAY_LINKS *Root
    )

/*++

Routine Description:

    The Delete function takes as input a pointer to a splay link in a tree,
    a pointer to the callers pointer to the tree and deletes that node from
    the tree.  The caller's pointer is updated upon return.  If the tree is
    now empty, the value is NULL.

    Unfortunately, the original RtlDelete() always splays and this is not
    always a desireable side-effect.

Arguments:

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

    Root - Pointer to the callers pointer to the root 

Return Value:

    None

--*/

{
    PRTL_SPLAY_LINKS Predecessor;
    PRTL_SPLAY_LINKS Parent;
    PRTL_SPLAY_LINKS Child;

    PRTL_SPLAY_LINKS *ParentChildPtr;

    //
    //  First check to see if Links as two children.  If it does then swap
    //  Links with its subtree predecessor.  Now we are guaranteed that Links
    //  has at most one child.
    //

    if ((RtlLeftChild(Links) != NULL) && (RtlRightChild(Links) != NULL)) {

        //
        //  get the predecessor, and swap their position in the tree
        //

        Predecessor = RtlSubtreePredecessor(Links);

        if (RtlIsRoot(Links)) {

            //
            //  If we're switching with the root of the tree, fix the
            //  caller's root pointer
            //

            *Root = Predecessor;
        }

        SwapSplayLinks(Predecessor, Links);

    }

    //
    //  If Links has no children then delete links by checking if it is
    //  already the root or has a parent.  If it is the root then the
    //  tree is now empty, otherwise it set the appropriate parent's child
    //  pointer (i.e., the one to links) to NULL.
    //

    if ((RtlLeftChild(Links) == NULL) && (RtlRightChild(Links) == NULL)) {

        //
        //  Links has no children, if it is the root then set root to NULL
        //

        if (RtlIsRoot(Links)) {

            *Root = NULL;

            return;
        }

        //
        //  Links as not children and is not the root, so to the parent's
        //  child pointer to NULL.
        //

        ParentChildPtr = ParentsChildPointerAddress(Links);
        *ParentChildPtr = NULL;

        return;
    }

    //
    //  otherwise Links has one child.  If it is the root then make the child
    //  the new root, otherwise link together the child and parent. But first
    //  remember who our child is.
    //

    if (RtlLeftChild(Links) != NULL) {
        Child = RtlLeftChild(Links);
    } else {
        Child = RtlRightChild(Links);
    }

    //
    //  If links is the root then we make the child the root and return the
    //  child.
    //

    if (RtlIsRoot(Links)) {
        Child->Parent = Child;

        *Root = Child;

        return;
    }

    //
    //  Links is not the root, so set link's parent child pointer to be
    //  the child and the set child's parent to be link's parent.
    //

    ParentChildPtr = ParentsChildPointerAddress(Links);
    *ParentChildPtr = Child;
    Child->Parent = Links->Parent;

    return;
}
示例#4
0
/*
 * @implemented
 */
VOID
NTAPI
RtlRemoveUnicodePrefix(PUNICODE_PREFIX_TABLE PrefixTable,
                       PUNICODE_PREFIX_TABLE_ENTRY PrefixTableEntry)
{
    PUNICODE_PREFIX_TABLE_ENTRY Entry, RefEntry, NewEntry;
    PRTL_SPLAY_LINKS SplayLinks;

    DPRINT("RtlRemoveUnicodePrefix(): Table %p, TableEntry %p\n",
        PrefixTable, PrefixTableEntry);

    /* Erase the last entry */
    PrefixTable->LastNextEntry = NULL;

    /* Check if this was a Case Match Entry */
    if (PrefixTableEntry->NodeTypeCode == PFX_NTC_CASE_MATCH)
    {
        /* Get the case match entry */
        Entry = PrefixTableEntry->CaseMatch;

        /* Now loop until we find one referencing what the caller sent */
        while (Entry->CaseMatch != PrefixTableEntry) Entry = Entry->CaseMatch;

        /* We found the entry that was sent, link them to delete this entry */
        Entry->CaseMatch = PrefixTableEntry->CaseMatch;
    }
    else if ((PrefixTableEntry->NodeTypeCode == PFX_NTC_ROOT) ||
            (PrefixTableEntry->NodeTypeCode == PFX_NTC_CHILD))
    {
        /* Check if this entry is a case match */
        if (PrefixTableEntry->CaseMatch != PrefixTableEntry)
        {
            /* Get the case match entry */
            Entry = PrefixTableEntry->CaseMatch;

            /* Now loop until we find one referencing what the caller sent */
            while (Entry->CaseMatch != PrefixTableEntry) Entry = Entry->CaseMatch;

            /* We found the entry that was sent, link them to delete this entry */
            Entry->CaseMatch = PrefixTableEntry->CaseMatch;

            /* Copy the data */
            Entry->NodeTypeCode = PrefixTableEntry->NodeTypeCode;
            Entry->NextPrefixTree = PrefixTableEntry->NextPrefixTree;
            Entry->Links = PrefixTableEntry->Links;

            /* Now check if we are a root entry */
            if (RtlIsRoot(&PrefixTableEntry->Links))
            {
                /* We are, so make this entry root as well */
                Entry->Links.Parent = &Entry->Links;

                /* Find the entry referencing us */
                RefEntry = Entry->NextPrefixTree;
                while (RefEntry->NextPrefixTree != Entry)
                {
                    /* Not this one, move to the next entry */
                    RefEntry = RefEntry->NextPrefixTree;
                }

                /* Link them to us now */
                RefEntry->NextPrefixTree = Entry;
            }
            else if (RtlIsLeftChild(&PrefixTableEntry->Links))
            {
                /* We were the left child, so make us as well */
                RtlParent(&PrefixTableEntry->Links)->LeftChild = &Entry->Links;
            }
            else
            {
                /* We were the right child, so make us as well */
                RtlParent(&PrefixTableEntry->Links)->RightChild = &Entry->Links;
            }

            /* Check if we have a left child */
            if (RtlLeftChild(&Entry->Links))
            {
                /* Update its parent link */
                RtlLeftChild(&Entry->Links)->Parent = &Entry->Links;
            }
            /* Check if we have a right child */
            if (RtlRightChild(&Entry->Links))
            {
                /* Update its parent link */
                RtlRightChild(&Entry->Links)->Parent = &Entry->Links;
            }
        }
        else
        {
            /* It's not a case match, so we'll delete the actual entry */
            SplayLinks = &PrefixTableEntry->Links;

            /* Find the root entry */
            while (!RtlIsRoot(SplayLinks)) SplayLinks = RtlParent(SplayLinks);
            Entry = CONTAINING_RECORD(SplayLinks,
                                      UNICODE_PREFIX_TABLE_ENTRY,
                                      Links);

            /* Delete the entry and check if the whole tree is gone */
            SplayLinks = RtlDelete(&PrefixTableEntry->Links);
            if (!SplayLinks)
            {
                /* The tree is also gone now, find the entry referencing us */
                RefEntry = Entry->NextPrefixTree;
                while (RefEntry->NextPrefixTree != Entry)
                {
                    /* Not this one, move to the next entry */
                    RefEntry = RefEntry->NextPrefixTree;
                }

                /* Link them so this entry stops being referenced */
                RefEntry->NextPrefixTree = Entry->NextPrefixTree;
            }
            else if (&Entry->Links != SplayLinks)
            {
                /* The tree is still here, but we got moved to a new one */
                NewEntry = CONTAINING_RECORD(SplayLinks,
                                             UNICODE_PREFIX_TABLE_ENTRY,
                                             Links);

                /* Find the entry referencing us */
                RefEntry = Entry->NextPrefixTree;
                while (RefEntry->NextPrefixTree != Entry)
                {
                    /* Not this one, move to the next entry */
                    RefEntry = RefEntry->NextPrefixTree;
                }

                /* Since we got moved, make us the new root entry */
                NewEntry->NodeTypeCode = PFX_NTC_ROOT;

                /* Link us with the entry referencing the old root */
                RefEntry->NextPrefixTree = NewEntry;

                /* And link us with the old tree */
                NewEntry->NextPrefixTree = Entry->NextPrefixTree;

                /* Set the old tree as a child */
                Entry->NodeTypeCode = PFX_NTC_CHILD;
                Entry->NextPrefixTree = NULL;
            }
        }
    }
}
示例#5
0
文件: splay.c 项目: BaoYu0721/WRK-1.2
PRTL_SPLAY_LINKS
RtlDelete (
    IN PRTL_SPLAY_LINKS Links
    )

/*++

Routine Description:

    The Delete function takes as input a pointer to a splay link in a tree
    and deletes that node from the tree.  Its function return value is a
    pointer to the root of the tree.  If the tree is now empty, 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 root of the tree.

--*/

{
    PRTL_SPLAY_LINKS Predecessor;
    PRTL_SPLAY_LINKS Parent;
    PRTL_SPLAY_LINKS Child;

    PRTL_SPLAY_LINKS *ParentChildPtr;

    //
    //  First check to see if Links as two children.  If it does then swap
    //  Links with its subtree predecessor.  Now we are guaranteed that Links
    //  has at most one child.
    //

    if ((RtlLeftChild(Links) != NULL) && (RtlRightChild(Links) != NULL)) {

        //
        //  get the predecessor, and swap their position in the tree
        //

        Predecessor = RtlSubtreePredecessor(Links);
        SwapSplayLinks(Predecessor, Links);

    }

    //
    //  If Links has no children then delete links by checking if it is
    //  already the root or has a parent.  If it is the root then the
    //  tree is now empty, otherwise it set the appropriate parent's child
    //  pointer (i.e., the one to links) to NULL, and splay the parent.
    //

    if ((RtlLeftChild(Links) == NULL) && (RtlRightChild(Links) == NULL)) {

        //
        //  Links has no children, if it is the root then return NULL
        //

        if (RtlIsRoot(Links)) {

            return NULL;
        }

        //
        //  Links as not children and is not the root, so to the parent's
        //  child pointer to NULL and splay the parent.
        //

        Parent = RtlParent(Links);

        ParentChildPtr = ParentsChildPointerAddress(Links);
        *ParentChildPtr = NULL;

        return RtlSplay(Parent);

    }

    //
    //  otherwise Links has one child.  If it is the root then make the child
    //  the new root, otherwise link together the child and parent, and splay
    //  the parent.  But first remember who our child is.
    //

    if (RtlLeftChild(Links) != NULL) {
        Child = RtlLeftChild(Links);
    } else {
        Child = RtlRightChild(Links);
    }

    //
    //  If links is the root then we make the child the root and return the
    //  child.
    //

    if (RtlIsRoot(Links)) {
        Child->Parent = Child;
        return Child;
    }

    //
    //  Links is not the root, so set link's parent child pointer to be
    //  the child and the set child's parent to be link's parent, and splay
    //  the parent.
    //

    ParentChildPtr = ParentsChildPointerAddress(Links);
    *ParentChildPtr = Child;
    Child->Parent = Links->Parent;

    return RtlSplay(RtlParent(Child));

}
示例#6
0
/*
* @implemented
*/
PUNICODE_PREFIX_TABLE_ENTRY
NTAPI
RtlNextUnicodePrefix(PUNICODE_PREFIX_TABLE PrefixTable,
                     BOOLEAN Restart)
{
    PRTL_SPLAY_LINKS SplayLinks;
    PUNICODE_PREFIX_TABLE_ENTRY Entry, CaseMatchEntry = NULL;

    DPRINT("RtlNextUnicodePrefix(): Table %p Restart %u\n",
        PrefixTable, Restart);

    /* We might need this entry 2/3rd of the time, so cache it now */
    if (PrefixTable->LastNextEntry)
        CaseMatchEntry = PrefixTable->LastNextEntry->CaseMatch;

    /* Check if this is a restart or if we don't have a last entry */
    if ((Restart) || !(PrefixTable->LastNextEntry))
    {
        /* Get the next entry and validate it */
        Entry = PrefixTable->NextPrefixTree;
        if (Entry->NodeTypeCode == PFX_NTC_TABLE) return NULL;

        /* Now get the Splay Tree Links */
        SplayLinks = &Entry->Links;

        /* Loop until we get the first node in the tree */
        while (RtlLeftChild(SplayLinks)) SplayLinks = RtlLeftChild(SplayLinks);

        /* Get the entry from it */
        Entry = CONTAINING_RECORD(SplayLinks,
                                  UNICODE_PREFIX_TABLE_ENTRY,
                                  Links);
    }
    else if (CaseMatchEntry->NodeTypeCode == PFX_NTC_CASE_MATCH)
    {
        /* If the last entry was a Case Match, then return it */
        Entry = CaseMatchEntry;
    }
    else
    {
        /* Find the successor */
        SplayLinks = RtlRealSuccessor(&CaseMatchEntry->Links);
        if (!SplayLinks)
        {
            /* Didn't find one, we'll have to search the tree */
            SplayLinks = &PrefixTable->LastNextEntry->Links;

            /* Get the topmost node (root) */
            while (!RtlIsRoot(SplayLinks)) SplayLinks = RtlParent(SplayLinks);
            Entry = CONTAINING_RECORD(SplayLinks,
                                      UNICODE_PREFIX_TABLE_ENTRY,
                                      Links);

            /* Get its tree and make sure somethign is in it */
            Entry = Entry->NextPrefixTree;
            if (Entry->NameLength <= 0) return NULL;

            /* Select these new links and find the first node */
            while (RtlLeftChild(SplayLinks)) SplayLinks = RtlLeftChild(SplayLinks);
        }

        /* Get the entry from it */
        Entry = CONTAINING_RECORD(SplayLinks,
                                  UNICODE_PREFIX_TABLE_ENTRY,
                                  Links);
    }

    /* Save this entry as the last one returned, and return it */
    PrefixTable->LastNextEntry = Entry;
    return Entry;
}
示例#7
0
VOID
FsRtlAddToTunnelCache (
    IN PTUNNEL Cache,
    IN ULONGLONG DirKey,
    IN PUNICODE_STRING ShortName,
    IN PUNICODE_STRING LongName,
    IN BOOLEAN KeyByShortName,
    IN ULONG DataLength,
    IN PVOID Data
    )
/*++

Routine Description:

    Adds an entry to the tunnel cache keyed by

        DirectoryKey ## (KeyByShortName ? ShortName : LongName)

    ShortName, LongName, and Data are copied and stored in the tunnel. As a side
    effect, if there are too many entries in the tunnel cache, this routine will
    initiate expiration in the tunnel cache.

Arguments:

    Cache - a tunnel cache initialized by FsRtlInitializeTunnelCache()

    DirKey - the key value of the directory the name appeared in

    ShortName - (optional if !KeyByShortName) the 8.3 name of the file

    LongName - (optional if KeyByShortName) the long name of the file

    KeyByShortName - specifies which name is keyed in the tunnel cache

    DataLength - specifies the length of the opaque data segment (file
    system specific) which contains the tunnelling information for this
    file

    Data - pointer to the opaque tunneling data segment

Return Value:

    None

--*/
{
    LONG Compare;
    ULONG NodeSize;
    PUNICODE_STRING NameKey;
    PRTL_SPLAY_LINKS *Links;
    LIST_ENTRY FreePoolList;

    PTUNNEL_NODE Node = NULL;
    PTUNNEL_NODE NewNode = NULL;
    BOOLEAN FreeOldNode = FALSE;
    BOOLEAN AllocatedFromPool = FALSE;

    PAGED_CODE();

    //
    //  If MaxEntries is 0 then tunneling is disabled.
    //

    if (TunnelMaxEntries == 0) return;

    InitializeListHead(&FreePoolList);

    //
    //  Grab a new node for this data
    //

    NodeSize = sizeof(TUNNEL_NODE) + ShortName->Length + LongName->Length + DataLength;

    if (LOOKASIDE_NODE_SIZE >= NodeSize) {

        NewNode = ExAllocateFromPagedLookasideList(&TunnelLookasideList);
    }

    if (NewNode == NULL) {

        //
        //  Data doesn't fit in lookaside nodes
        //

        NewNode = ExAllocatePoolWithTag(PagedPool, NodeSize, 'PnuT');

        if (NewNode == NULL) {

            //
            //  Give up tunneling this entry
            //

            return;
        }

        AllocatedFromPool = TRUE;
    }

    //
    //  Traverse the cache to find our insertion point
    //

    NameKey = (KeyByShortName ? ShortName : LongName);

    ExAcquireFastMutex(&Cache->Mutex);

    Links = &Cache->Cache;

    while (*Links) {

        Node = CONTAINING_RECORD(*Links, TUNNEL_NODE, CacheLinks);

        Compare = FsRtlCompareNodeAndKey(Node, DirKey, NameKey);

        if (Compare > 0) {

            Links = &RtlLeftChild(&Node->CacheLinks);

        } else {

            if (Compare < 0) {

                Links = &RtlRightChild(&Node->CacheLinks);

            } else {

                break;
            }
        }
    }

    //
    //  Thread new data into the splay tree
    //

    RtlInitializeSplayLinks(&NewNode->CacheLinks);

    if (Node) {

        //
        //  Not inserting first node in tree
        //

        if (*Links) {

            //
            //  Entry exists in the cache, so replace by swapping all splay links
            //

            RtlRightChild(&NewNode->CacheLinks) = RtlRightChild(*Links);
            RtlLeftChild(&NewNode->CacheLinks) = RtlLeftChild(*Links);

            if (RtlRightChild(*Links)) RtlParent(RtlRightChild(*Links)) = &NewNode->CacheLinks;
            if (RtlLeftChild(*Links)) RtlParent(RtlLeftChild(*Links)) = &NewNode->CacheLinks;

            if (!RtlIsRoot(*Links)) {

                //
                //  Change over the parent links. Note that we've messed with *Links now
                //  since it is pointing at the parent member.
                //

                RtlParent(&NewNode->CacheLinks) = RtlParent(*Links);

                if (RtlIsLeftChild(*Links)) {

                    RtlLeftChild(RtlParent(*Links)) = &NewNode->CacheLinks;

                } else {

                    RtlRightChild(RtlParent(*Links)) = &NewNode->CacheLinks;
                }

            } else {

                //
                //  Set root of the cache
                //

                Cache->Cache = &NewNode->CacheLinks;
            }

            //
            //  Free old node
            //

            RemoveEntryList(&Node->ListLinks);

            FsRtlFreeTunnelNode(Node, &FreePoolList);

            Cache->NumEntries--;

        } else {

            //
            //  Simple insertion as a leaf
            //

            NewNode->CacheLinks.Parent = &Node->CacheLinks;
            *Links = &NewNode->CacheLinks;
        }

    } else {

        Cache->Cache = &NewNode->CacheLinks;
    }

    //
    //  Thread onto the timer list
    //

    FsRtlQueryNormalizedSystemTime(&NewNode->CreateTime);
    InsertTailList(&Cache->TimerQueue, &NewNode->ListLinks);

    Cache->NumEntries++;

    //
    //  Stash tunneling information
    //

    NewNode->DirKey = DirKey;

    if (KeyByShortName) {

        NewNode->Flags = TUNNEL_FLAG_KEY_SHORT;

    } else {

        NewNode->Flags = 0;
    }

    //
    //  Initialize the internal UNICODE_STRINGS to point at the buffer segments. For various
    //  reasons (UNICODE APIs are incomplete, we're avoiding calling any allocate routine more
    //  than once, UNICODE strings are not guaranteed to be null terminated) we have to do a lot
    //  of this by hand.
    //
    //  The data is layed out like this in the allocated block:
    //
    //  -----------------------------------------------------------------------------------
    //  | TUNNEL_NODE | Node->ShortName.Buffer | Node->LongName.Buffer | Node->TunnelData |
    //  -----------------------------------------------------------------------------------
    //

    NewNode->ShortName.Buffer = (PWCHAR)((PCHAR)NewNode + sizeof(TUNNEL_NODE));
    NewNode->LongName.Buffer = (PWCHAR)((PCHAR)NewNode + sizeof(TUNNEL_NODE) + ShortName->Length);

    NewNode->ShortName.Length = NewNode->ShortName.MaximumLength = ShortName->Length;
    NewNode->LongName.Length = NewNode->LongName.MaximumLength = LongName->Length;

    if (ShortName->Length) {

        RtlCopyMemory(NewNode->ShortName.Buffer, ShortName->Buffer, ShortName->Length);
    }

    if (LongName->Length) {

        RtlCopyMemory(NewNode->LongName.Buffer, LongName->Buffer, LongName->Length);
    }

    NewNode->TunnelData = (PVOID)((PCHAR)NewNode + sizeof(TUNNEL_NODE) + ShortName->Length + LongName->Length);

    NewNode->TunnelDataLength = DataLength;

    RtlCopyMemory(NewNode->TunnelData, Data, DataLength);

    if (AllocatedFromPool) {

        SetFlag(NewNode->Flags, TUNNEL_FLAG_NON_LOOKASIDE);
    }

#if defined(TUNNELTEST) || defined (KEYVIEW)
    DbgPrint("FsRtlAddToTunnelCache:\n");
    DumpNode(NewNode, 1);
#ifndef KEYVIEW
    DumpTunnel(Cache);
#endif
#endif // TUNNELTEST

    //
    //  Clean out the cache, release, and then drop any pool memory we need to
    //

    FsRtlPruneTunnelCache(Cache, &FreePoolList);

    ExReleaseFastMutex(&Cache->Mutex);

    FsRtlEmptyFreePoolList(&FreePoolList);

    return;
}
示例#8
0
文件: splaytree.c 项目: killvxk/NT_OS
static
VOID
SwapSplayLinks(PRTL_SPLAY_LINKS LinkA,
               PRTL_SPLAY_LINKS LinkB)
{
    if (RtlParent(LinkA) == LinkB || RtlIsRoot(LinkB)) {
        PRTL_SPLAY_LINKS Tmp = LinkA;
        LinkA = LinkB;
        LinkB = Tmp;
    }

    {
        RTL_SPLAY_LINKS Ta = *LinkA, Tb = *LinkB;
        BOOLEAN RootA = RtlIsRoot(LinkA), 
            LeftA = RtlIsLeftChild(LinkA), 
            LeftB = RtlIsLeftChild(LinkB);
        *LinkB = Ta; *LinkA = Tb;

        // A was parent of B is a special case: A->Parent is now B
        if (RtlParent(&Tb) == LinkA) {
            if (!RootA) {
                if (LeftA) {
                    RtlInsertAsLeftChild(RtlParent(&Ta), LinkB);
                } else {
                    RtlInsertAsRightChild(RtlParent(&Ta), LinkB);
                }
            }
            if (LeftB) {
                RtlInsertAsLeftChild(LinkB, LinkA);
            } else {
                RtlInsertAsRightChild(LinkB, LinkA);
            }
        }

        FixupChildLinks(LinkA, FALSE, LeftB);
        FixupChildLinks(LinkB, RootA, LeftA);

        // A was root is a special case: B->Parent is now B
        if (RootA)
            RtlParent(LinkB) = LinkB;

#ifdef VERIFY_SWAP_SPLAY_LINKS
        // Verify the distinct cases of node swap
        if (RootA) {
            if (RtlParent(&Tb) == LinkA) {
                // LinkA = D, LinkB = B
                // D B   S   S.L S.R S   Q   Q.R
                ASSERT(RtlParent(LinkA) == LinkB);
                ASSERT(RtlLeftChild(LinkA) == RtlLeftChild(&Tb));
                ASSERT(RtlRightChild(LinkA) == RtlRightChild(&Tb));
                ASSERT(RtlParent(LinkB) == LinkB);
                ASSERT(RtlLeftChild(LinkB) == (LeftB ? LinkA : RtlLeftChild(&Ta)));
                ASSERT(RtlRightChild(LinkB) == (LeftB ? RtlRightChild(&Ta) : LinkA));
            } else {
                // LinkA = D, LinkB = A
                // D A   S.P S.L S.R S   Q.L Q.R
                ASSERT(RtlParent(LinkA) == RtlParent(&Tb));
                ASSERT(RtlLeftChild(LinkA) == RtlLeftChild(&Tb));
                ASSERT(RtlRightChild(LinkA) == RtlRightChild(&Tb));
                ASSERT(RtlParent(LinkB) == LinkB);
                ASSERT(RtlLeftChild(LinkB) == RtlLeftChild(&Ta));
                ASSERT(RtlRightChild(LinkB) == RtlRightChild(&Ta));
            }
        } else {
            if (RtlParent(&Tb) == LinkA) {
                // LinkA = B, LinkB = A
                // B A   S   S.L S.R Q.P Q   Q.R
                ASSERT(RtlParent(LinkA) == LinkB);
                ASSERT(RtlLeftChild(LinkA) == RtlLeftChild(&Tb));
                ASSERT(RtlRightChild(LinkA) == RtlRightChild(&Tb));
                ASSERT(RtlParent(LinkB) == RtlParent(&Ta));
                ASSERT(RtlLeftChild(LinkB) == (LeftB ? LinkA : RtlLeftChild(&Ta)));
                ASSERT(RtlRightChild(LinkB) == (LeftB ? RtlRightChild(&Ta) : LinkA));            
            } else {
                // LinkA = A, LinkB = C
                // A C   S.P S.L S.R Q.P Q.L Q.R
                ASSERT(!memcmp(LinkA, &Tb, sizeof(Tb)));
                ASSERT(!memcmp(LinkB, &Ta, sizeof(Ta)));
            }
        }
#endif
    }
}
示例#9
0
文件: splaytree.c 项目: killvxk/NT_OS
/*
* @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;
}
示例#10
0
文件: splaytree.c 项目: killvxk/NT_OS
/*
 * @implemented
 */
PRTL_SPLAY_LINKS
NTAPI
RtlDelete(PRTL_SPLAY_LINKS Links)
{
    PRTL_SPLAY_LINKS N, P, C, SP;
    N = Links;

    /* Check if we have two children */
    if ((RtlLeftChild(N)) && (RtlRightChild(N)))
    {
        /* Get the predecessor */
        SP = RtlSubtreePredecessor(N);

        /* Swap it with N, this will guarantee that N will have only a child */
        SwapSplayLinks(SP, N);
    }

    /* Check if we have no children */
    if (!(RtlLeftChild(N)) && !(RtlRightChild(N)))
    {
        /* If we are also the root, then the tree is gone */
        if (RtlIsRoot(N)) return NULL;

        /* Get our parent */
        P = RtlParent(N);

        /* Find out who is referencing us and delete the reference */
        if (RtlIsLeftChild(N))
        {
            /* N was a left child, so erase its parent's left child link */
            RtlLeftChild(RtlParent(N)) = NULL;
        }
        else
        {
            /* N was a right child, so erase its parent's right child link */
            RtlRightChild(RtlParent(N)) = NULL;
        }

        /* And finally splay the parent */
        return RtlSplay(P);
    }

    /* If we got here, we have a child (not two: we swapped above!) */
    if (RtlLeftChild(N))
    {
        /* We have a left child, so get it */
        C = RtlLeftChild(N);
    }
    else
    {
        /* We have a right child, get him instead */
        C = RtlRightChild(N);
    }

    /* Check if we are the root entry */
    if (RtlIsRoot(N))
    {
        /* Our child is now root, return him */
        C->Parent = C;
        return C;
    }

    /* Find out who is referencing us and link to our child instead */
    if (RtlIsLeftChild(N))
    {
        /* N was a left child, so set its parent's left child as our child */
        RtlLeftChild(RtlParent(N)) = C;
    }
    else
    {
        /* N was a right child, so set its parent's right child as our child */
        RtlRightChild(RtlParent(N)) = C;
    }

    /* Finally, inherit our parent and splay the parent */
    C->Parent = N->Parent;
    return RtlSplay(RtlParent(C));
}