Exemplo n.º 1
0
int
_CDECL
main(
    int argc,
    char *argv[]
    )
{
    PTREE_NODE Root;
    ULONG i;
    ULONG Seed;

    DbgPrint("Start SplayTest()\n");

    Root = NULL;
    Seed = 0;
    for (i=0; i<2048; i++) {
        Buffer[i].Data = RtlRandom(&Seed);
        Buffer[i].Data = Buffer[i].Data % 512;
        RtlInitializeSplayLinks(&Buffer[i].Links);
        Root  = TreeInsert(Root, &Buffer[i]);
    }

    PrintTree(Root);

    DbgPrint("End SplayTest()\n");

    return TRUE;

}
Exemplo n.º 2
0
VOID
FatInsertName (
    IN PIRP_CONTEXT IrpContext,
    IN PRTL_SPLAY_LINKS *RootNode,
    IN PFILE_NAME_NODE Name
    )

/*++

Routine Description:

    This routine will insert a name in the splay tree pointed to
    by RootNode.

    The name must not already exist in the splay tree.

Arguments:

    RootNode - Supplies a pointer to the table.

    Name - Contains the New name to enter.

Return Value:

    None.

--*/

{
    COMPARISON Comparison;
    PFILE_NAME_NODE Node;

    PAGED_CODE();

    RtlInitializeSplayLinks(&Name->Links);

Restart:

    //
    //  If we are the first entry in the tree, just become the root.
    //

    if (*RootNode == NULL) {

        *RootNode = &Name->Links;

        return;
    }

    Node = CONTAINING_RECORD( *RootNode, FILE_NAME_NODE, Links );

    while (TRUE) {

        //
        //  Compare the prefix in the tree with the prefix we want
        //  to insert.  Note that Oem here doesn't mean anything.
        //

        Comparison = CompareNames(&Node->Name.Oem, &Name->Name.Oem);

        //
        //  We should never find the name in the table already.
        //

        if (Comparison == IsEqual) {

            //
            //  Almost. If the removable media was taken to another machine and
            //  back, and we have something like:
            //
            //  Old: foobar~1  /  foobarbaz
            //  New: foobar~1  /  foobarbazbaz
            //
            //  but a handle was kept open to foobarbaz so we couldn't purge
            //  away the Fcb in the verify path ... opening foobarbazbaz will
            //  try to insert a duplicate shortname. Bang!
            //
            //  Invalidate it and the horse it came in on.  This new one wins.
            //  The old one is gone.  Only if the old one is in normal state
            //  do we really have a problem.
            //
            
            if (Node->Fcb->FcbState == FcbGood) {
                
                FatBugCheck( (ULONG_PTR)*RootNode, (ULONG_PTR)Name, (ULONG_PTR)Node );
            }

            //
            //  Note, once we zap the prefix links we need to restart our walk
            //  of the tree.
            //
            
            FatMarkFcbCondition( IrpContext, Node->Fcb, FcbBad, TRUE );
            FatRemoveNames( IrpContext, Node->Fcb );

            goto Restart;
        }

        //
        //  If the tree prefix is greater than the new prefix then
        //  we go down the left subtree
        //

        if (Comparison == IsGreaterThan) {

            //
            //  We want to go down the left subtree, first check to see
            //  if we have a left subtree
            //

            if (RtlLeftChild(&Node->Links) == NULL) {

                //
                //  there isn't a left child so we insert ourselves as the
                //  new left child
                //

                RtlInsertAsLeftChild(&Node->Links, &Name->Links);

                //
                //  and exit the while loop
                //

                break;

            } else {

                //
                //  there is a left child so simply go down that path, and
                //  go back to the top of the loop
                //

                Node = CONTAINING_RECORD( RtlLeftChild(&Node->Links),
                                          FILE_NAME_NODE,
                                          Links );
            }

        } else {

            //
            //  The tree prefix is either less than or a proper prefix
            //  of the new string.  We treat both cases a less than when
            //  we do insert.  So we want to go down the right subtree,
            //  first check to see if we have a right subtree
            //

            if (RtlRightChild(&Node->Links) == NULL) {

                //
                //  These isn't a right child so we insert ourselves as the
                //  new right child
                //

                RtlInsertAsRightChild(&Node->Links, &Name->Links);

                //
                //  and exit the while loop
                //

                break;

            } else {

                //
                //  there is a right child so simply go down that path, and
                //  go back to the top of the loop
                //

                Node = CONTAINING_RECORD( RtlRightChild(&Node->Links),
                                          FILE_NAME_NODE,
                                          Links );
            }

        }
    }

    return;
}
Exemplo n.º 3
0
BOOLEAN
xixfs_NLInsertNameLinkIgnoreCase (
	IN PXIXFS_IRPCONTEXT IrpContext,
	IN PRTL_SPLAY_LINKS *RootNode,
	IN PXIXFS_LCB NameLink
)
{
    FSRTL_COMPARISON_RESULT Comparison;
    PXIXFS_LCB Node;

    PAGED_CODE();
	DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO),
		("Enter xixfs_NLInsertNameLink \n"));
    //
    //  Check inputs.
    //

    ASSERT_IRPCONTEXT( IrpContext );

    RtlInitializeSplayLinks( &NameLink->IgnoreCaseLinks );

    //
    //  If we are the first entry in the tree, just become the root.
    //

    if (*RootNode == NULL) {

        *RootNode = &NameLink->IgnoreCaseLinks;

        return TRUE;
    }

    Node = CONTAINING_RECORD( *RootNode, XIXFS_LCB, IgnoreCaseLinks );

    while (TRUE) {

        //
        //  Compare the prefix in the tree with the prefix we want
        //  to insert.
        //

        Comparison = xixfs_FCBTLBFullCompareNames( IrpContext, &Node->IgnoreCaseFileName, &NameLink->IgnoreCaseFileName );

        //
        //  If we found the entry, return immediately.
        //

        if (Comparison == EqualTo) { return FALSE; }

        //
        //  If the tree prefix is greater than the new prefix then
        //  we go down the left subtree
        //

        if (Comparison == GreaterThan) {

            //
            //  We want to go down the left subtree, first check to see
            //  if we have a left subtree
            //

            if (RtlLeftChild( &Node->IgnoreCaseLinks ) == NULL) {

                //
                //  there isn't a left child so we insert ourselves as the
                //  new left child
                //

                RtlInsertAsLeftChild( &Node->IgnoreCaseLinks, &NameLink->IgnoreCaseLinks );

                //
                //  and exit the while loop
                //

                break;

            } else {

                //
                //  there is a left child so simply go down that path, and
                //  go back to the top of the loop
                //

                Node = CONTAINING_RECORD( RtlLeftChild( &Node->IgnoreCaseLinks ),
                                          XIXFS_LCB,
                                          IgnoreCaseLinks );
            }

        } else {

            //
            //  The tree prefix is either less than or a proper prefix
            //  of the new string.  We treat both cases as less than when
            //  we do insert.  So we want to go down the right subtree,
            //  first check to see if we have a right subtree
            //

            if (RtlRightChild( &Node->IgnoreCaseLinks ) == NULL) {

                //
                //  These isn't a right child so we insert ourselves as the
                //  new right child
                //

                RtlInsertAsRightChild( &Node->IgnoreCaseLinks, &NameLink->IgnoreCaseLinks );

                //
                //  and exit the while loop
                //

                break;

            } else {

                //
                //  there is a right child so simply go down that path, and
                //  go back to the top of the loop
                //

                Node = CONTAINING_RECORD( RtlRightChild( &Node->IgnoreCaseLinks ),
                                          XIXFS_LCB,
                                          IgnoreCaseLinks );
            }
        }
    }
	
	DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO),
		("Exit xixfs_NLInsertNameLink \n"));
    return TRUE;
}
Exemplo n.º 4
0
VOID
FatInsertName (
    IN PIRP_CONTEXT IrpContext,
    IN PRTL_SPLAY_LINKS *RootNode,
    IN PFILE_NAME_NODE Name
    )

/*++

Routine Description:

    This routine will insert a name in the splay tree pointed to
    by RootNode.

    The name must not already exist in the splay tree.

Arguments:

    RootNode - Supplies a pointer to the table.

    Name - Contains the New name to enter.

Return Value:

    None.

--*/

{
    COMPARISON Comparison;
    PFILE_NAME_NODE Node;

    RtlInitializeSplayLinks(&Name->Links);

    //
    //  If we are the first entry in the tree, just become the root.
    //

    if (*RootNode == NULL) {

        *RootNode = &Name->Links;

        return;
    }

    Node = CONTAINING_RECORD( *RootNode, FILE_NAME_NODE, Links );

    while (TRUE) {

        //
        //  Compare the prefix in the tree with the prefix we want
        //  to insert.  Note that Oem here doesn't mean anything.
        //

        Comparison = CompareNames(&Node->Name.Oem, &Name->Name.Oem);

        //
        //  We should never find the name in the table already.
        //

        if (Comparison == IsEqual) {

            FatBugCheck( (ULONG)*RootNode, (ULONG)Name, (ULONG)Node );
        }

        //
        //  If the tree prefix is greater than the new prefix then
        //  we go down the left subtree
        //

        if (Comparison == IsGreaterThan) {

            //
            //  We want to go down the left subtree, first check to see
            //  if we have a left subtree
            //

            if (RtlLeftChild(&Node->Links) == NULL) {

                //
                //  there isn't a left child so we insert ourselves as the
                //  new left child
                //

                RtlInsertAsLeftChild(&Node->Links, &Name->Links);

                //
                //  and exit the while loop
                //

                break;

            } else {

                //
                //  there is a left child so simply go down that path, and
                //  go back to the top of the loop
                //

                Node = CONTAINING_RECORD( RtlLeftChild(&Node->Links),
                                          FILE_NAME_NODE,
                                          Links );
            }

        } else {

            //
            //  The tree prefix is either less than or a proper prefix
            //  of the new string.  We treat both cases a less than when
            //  we do insert.  So we want to go down the right subtree,
            //  first check to see if we have a right subtree
            //

            if (RtlRightChild(&Node->Links) == NULL) {

                //
                //  These isn't a right child so we insert ourselves as the
                //  new right child
                //

                RtlInsertAsRightChild(&Node->Links, &Name->Links);

                //
                //  and exit the while loop
                //

                break;

            } else {

                //
                //  there is a right child so simply go down that path, and
                //  go back to the top of the loop
                //

                Node = CONTAINING_RECORD( RtlRightChild(&Node->Links),
                                          FILE_NAME_NODE,
                                          Links );
            }

        }
    }

    return;
}
Exemplo n.º 5
0
/*
 * @implemented
 */
PVOID
NTAPI
RtlInsertElementGenericTableFull(IN PRTL_GENERIC_TABLE Table,
                                 IN PVOID Buffer,
                                 IN ULONG BufferSize,
                                 OUT PBOOLEAN NewElement OPTIONAL,
                                 IN PVOID NodeOrParent,
                                 IN TABLE_SEARCH_RESULT SearchResult)
{
    PRTL_SPLAY_LINKS NewNode;

    /* Check if the entry wasn't already found */
    if (SearchResult != TableFoundNode)
    {
        /* We're doing an allocation, sanity check */
        ASSERT(Table->NumberGenericTableElements != (MAXULONG - 1));

        /* Allocate a node */
        NewNode = Table->AllocateRoutine(Table,
                                         BufferSize +
                                         FIELD_OFFSET(TABLE_ENTRY_HEADER,
                                                 UserData));
        if (!NewNode)
        {
            /* No memory or other allocation error, fail */
            if (NewElement) *NewElement = FALSE;
            return NULL;
        }

        /* Initialize the new inserted element */
        RtlInitializeSplayLinks(NewNode);
        InsertTailList(&Table->InsertOrderList,
                       &((PTABLE_ENTRY_HEADER)NewNode)->ListEntry);

        /* Increase element count */
        Table->NumberGenericTableElements++;

        /* Check where we should insert the entry */
        if (SearchResult == TableEmptyTree)
        {
            /* This is the new root node */
            Table->TableRoot = NewNode;
        }
        else if (SearchResult == TableInsertAsLeft)
        {
            /* Insert it left */
            RtlInsertAsLeftChild(NodeOrParent, NewNode);
        }
        else
        {
            /* Right node */
            RtlInsertAsRightChild(NodeOrParent, NewNode);
        }

        /* Copy user buffer */
        RtlCopyMemory(&((PTABLE_ENTRY_HEADER)NewNode)->UserData,
                      Buffer,
                      BufferSize);
    }
    else
    {
        /* Return the node we already found */
        NewNode = NodeOrParent;
    }

    /* Splay the tree */
    Table->TableRoot = RtlSplay(NewNode);

    /* Return status */
    if (NewElement) *NewElement = (SearchResult != TableFoundNode);

    /* Return pointer to user data */
    return &((PTABLE_ENTRY_HEADER)NewNode)->UserData;
}
Exemplo n.º 6
0
BOOLEAN
CdInsertNameLink (
    _In_ PIRP_CONTEXT IrpContext,
    _Inout_ PRTL_SPLAY_LINKS *RootNode,
    _In_ PNAME_LINK NameLink
    )

/*++

Routine Description:

    This routine will insert a name in the splay tree pointed to
    by RootNode.

    The name could already exist in this tree for a case-insensitive tree.
    In that case we simply return FALSE and do nothing.

Arguments:

    RootNode - Supplies a pointer to the table.

    NameLink - Contains the new link to enter.

Return Value:

    BOOLEAN - TRUE if the name is inserted, FALSE otherwise.

--*/

{
    FSRTL_COMPARISON_RESULT Comparison;
    PNAME_LINK Node;

    PAGED_CODE();

    RtlInitializeSplayLinks( &NameLink->Links );

    //
    //  If we are the first entry in the tree, just become the root.
    //

    if (*RootNode == NULL) {

        *RootNode = &NameLink->Links;

        return TRUE;
    }

    Node = CONTAINING_RECORD( *RootNode, NAME_LINK, Links );

    while (TRUE) {

        //
        //  Compare the prefix in the tree with the prefix we want
        //  to insert.
        //

        Comparison = CdFullCompareNames( IrpContext, &Node->FileName, &NameLink->FileName );

        //
        //  If we found the entry, return immediately.
        //

        if (Comparison == EqualTo) { return FALSE; }

        //
        //  If the tree prefix is greater than the new prefix then
        //  we go down the left subtree
        //

        if (Comparison == GreaterThan) {

            //
            //  We want to go down the left subtree, first check to see
            //  if we have a left subtree
            //

            if (RtlLeftChild( &Node->Links ) == NULL) {

                //
                //  there isn't a left child so we insert ourselves as the
                //  new left child
                //

                RtlInsertAsLeftChild( &Node->Links, &NameLink->Links );

                //
                //  and exit the while loop
                //

                break;

            } else {

                //
                //  there is a left child so simply go down that path, and
                //  go back to the top of the loop
                //

                Node = CONTAINING_RECORD( RtlLeftChild( &Node->Links ),
                                          NAME_LINK,
                                          Links );
            }

        } else {

            //
            //  The tree prefix is either less than or a proper prefix
            //  of the new string.  We treat both cases as less than when
            //  we do insert.  So we want to go down the right subtree,
            //  first check to see if we have a right subtree
            //

            if (RtlRightChild( &Node->Links ) == NULL) {

                //
                //  These isn't a right child so we insert ourselves as the
                //  new right child
                //

                RtlInsertAsRightChild( &Node->Links, &NameLink->Links );

                //
                //  and exit the while loop
                //

                break;

            } else {

                //
                //  there is a right child so simply go down that path, and
                //  go back to the top of the loop
                //

                Node = CONTAINING_RECORD( RtlRightChild( &Node->Links ),
                                          NAME_LINK,
                                          Links );
            }
        }
    }

    return TRUE;
}
Exemplo n.º 7
0
PVOID
RtlInsertElementGenericTable (
    IN PRTL_GENERIC_TABLE Table,
    IN PVOID Buffer,
    IN CLONG BufferSize,
    OUT PBOOLEAN NewElement OPTIONAL
    )

/*++

Routine Description:

    The function InsertElementGenericTable will insert a new element
    in a table.  It does this by allocating space for the new element
    (this includes splay links), inserting the element in the table, and
    then returning to the user a pointer to the new element (which is
    the first available space after the splay links).  If an element
    with the same key already exists in the table the return value is a pointer
    to the old element.  The optional output parameter NewElement is used
    to indicate if the element previously existed in the table.  Note: the user
    supplied Buffer is only used for searching the table, upon insertion its
    contents are copied to the newly created element.  This means that
    pointer to the input buffer will not point to the new element.

Arguments:

    Table - Pointer to the table in which to (possibly) insert the
            key buffer.

    Buffer - Passed to the user comparasion routine.  Its contents are
             up to the user but one could imagine that it contains some
             sort of key value.

    BufferSize - The amount of space to allocate when the (possible)
                 insertion is made.  Note that if we actually do
                 not find the node and we do allocate space then we
                 will add the size of the SPLAY_LINKS to this buffer
                 size.  The user should really take care not to depend
                 on anything in the first sizeof(SPLAY_LINKS) bytes
                 of the memory allocated via the memory allocation
                 routine.

    NewElement - Optional Flag.  If present then it will be set to
                 TRUE if the buffer was not "found" in the generic
                 table.

Return Value:

    PVOID - Pointer to the user defined data.

--*/

{

    //
    // Holds a pointer to the node in the table or what would be the
    // parent of the node.
    //
    PRTL_SPLAY_LINKS NodeOrParent;

    //
    // Holds the result of the table lookup.
    //
    SEARCH_RESULT Lookup;

    //
    // Node will point to the splay links of what
    // will be returned to the user.
    //
    PRTL_SPLAY_LINKS NodeToReturn;

    Lookup = FindNodeOrParent(
                 Table,
                 Buffer,
                 &NodeOrParent
                 );

    if (Lookup != FoundNode) {

        //
        // We just check that the table isn't getting
        // too big.
        //

        ASSERT(Table->NumberGenericTableElements != (MAXULONG-1));

        //
        // The node wasn't in the (possibly empty) tree.
        // Call the user allocation routine to get space
        // for the new node.
        //

        NodeToReturn = Table->AllocateRoutine(
                           Table,
                           BufferSize+sizeof(RTL_SPLAY_LINKS)+sizeof(LIST_ENTRY)
                           );

        //
        // If the return is NULL, return NULL from here to indicate that
        // the entry could not be added.
        //

        if (NodeToReturn == NULL) {

            if (ARGUMENT_PRESENT(NewElement)) {

                *NewElement = FALSE;

            }

            return(NULL);

        }

        RtlInitializeSplayLinks(NodeToReturn);
        InitializeListHead((PLIST_ENTRY)((PVOID)(NodeToReturn+1)));

        //
        // Insert the new node at the end of the ordered linked list.
        //

        InsertTailList(
            &Table->InsertOrderList,
            (PLIST_ENTRY)((PVOID)(NodeToReturn+1))
            );

        Table->NumberGenericTableElements++;

        //
        // Insert the new node in the tree.
        //

        if (Lookup == EmptyTree) {

            Table->TableRoot = NodeToReturn;

        } else {

            if (Lookup == InsertAsLeft) {

                RtlInsertAsLeftChild(
                    NodeOrParent,
                    NodeToReturn
                    );

            } else {

                RtlInsertAsRightChild(
                    NodeOrParent,
                    NodeToReturn
                    );

            }

        }

        //
        // Copy the users buffer into the user data area of the table.
        //

        RtlCopyMemory(
            ((PLIST_ENTRY)((PVOID)(NodeToReturn+1)))+1,
            Buffer,
            BufferSize
            );

    } else {

        NodeToReturn = NodeOrParent;

    }

    //
    // Always splay the (possibly) new node.
    //

    Table->TableRoot = RtlSplay(NodeToReturn);

    if (ARGUMENT_PRESENT(NewElement)) {

        *NewElement = ((Lookup == FoundNode)?(FALSE):(TRUE));

    }

    //
    // Insert the element on the ordered list;
    //

    return ((PLIST_ENTRY)((PVOID)(NodeToReturn+1)))+1;
}
Exemplo n.º 8
0
/*
 * @implemented
 */
BOOLEAN
NTAPI
RtlInsertUnicodePrefix(PUNICODE_PREFIX_TABLE PrefixTable,
                       PUNICODE_STRING Prefix,
                       PUNICODE_PREFIX_TABLE_ENTRY PrefixTableEntry)
{
    PUNICODE_PREFIX_TABLE_ENTRY CurrentEntry, PreviousEntry, Entry, NextEntry;
    ULONG NameCount;
    RTL_GENERIC_COMPARE_RESULTS Result;
    PRTL_SPLAY_LINKS SplayLinks;

    DPRINT("RtlInsertUnicodePrefix(): Table %p, Prefix %wZ, "
        "TableEntry %p\n", PrefixTable, Prefix, PrefixTableEntry);

    /* Find out how many names there are */
    NameCount = ComputeUnicodeNameLength(Prefix);

    /* Set up the initial entry data */
    PrefixTableEntry->NameLength = (CSHORT)NameCount;
    PrefixTableEntry->Prefix = Prefix;
    RtlInitializeSplayLinks(&PrefixTableEntry->Links);

    /* Find the right spot where to insert this entry */
    PreviousEntry = (PUNICODE_PREFIX_TABLE_ENTRY)PrefixTable;
    CurrentEntry = PreviousEntry->NextPrefixTree;
    while (CurrentEntry->NameLength > (CSHORT)NameCount)
    {
        /* Not a match, move to the next entry */
        PreviousEntry = CurrentEntry;
        CurrentEntry = CurrentEntry->NextPrefixTree;
    }

    /* Check if we did find a tree by now */
    if (CurrentEntry->NameLength != (CSHORT)NameCount)
    {
        /* We didn't, so insert a new entry in the list */
        PreviousEntry->NextPrefixTree = PrefixTableEntry;
        PrefixTableEntry->NextPrefixTree = CurrentEntry;

        /* This is now a root entry with case match */
        PrefixTableEntry->NodeTypeCode = PFX_NTC_ROOT;
        PrefixTableEntry->CaseMatch = PrefixTableEntry;

        /* Quick return */
        return TRUE;
    }

    /* We found a tree, so start the search loop */
    Entry = CurrentEntry;
    while (TRUE)
    {
        /* Do a case-insensitive comparison to find out the match level */
        Result = CompareUnicodeStrings(Entry->Prefix, Prefix, 0);
        if (Result == GenericEqual)
        {
            /* We have a match, start doing a case-sensitive search */
            NextEntry = Entry;

            /* Search the circular case-match list */
            do
            {
                /* Check if we found a match */
                if (CompareUnicodeStrings(NextEntry->Prefix, Prefix, -1) ==
                    (GenericEqual))
                {
                    /* We must fail the insert: it already exists */
                    return FALSE;
                }

                /* Move to the next entry in the circular list */
                NextEntry = NextEntry->CaseMatch;
            }
            while (NextEntry != Entry);

            /*
             * No match found, so we can safely insert it. Remember that a
             * case insensitive match was found, so this is not a ROOT NTC
             * but a Case Match NTC instead.
             */
            PrefixTableEntry->NodeTypeCode = PFX_NTC_CASE_MATCH;
            PrefixTableEntry->NextPrefixTree = NULL;

            /* Insert it into the circular list */
            PrefixTableEntry->CaseMatch = Entry->CaseMatch;
            Entry->CaseMatch = PrefixTableEntry;
            break;
        }

        /* Check if the result was greater or lesser than */
        if (Result == GenericGreaterThan)
        {
            /* Check out if we have a left child */
            if (RtlLeftChild(&Entry->Links))
            {
                /* We do, enter it and restart the loop */
                SplayLinks = RtlLeftChild(&Entry->Links);
                Entry = CONTAINING_RECORD(SplayLinks,
                                          UNICODE_PREFIX_TABLE_ENTRY,
                                          Links);
            }
            else
            {
                /* We don't, set this entry as a child */
                PrefixTableEntry->NodeTypeCode = PFX_NTC_CHILD;
                PrefixTableEntry->NextPrefixTree = NULL;
                PrefixTableEntry->CaseMatch = PrefixTableEntry;

                /* Insert us into the tree */
                RtlInsertAsLeftChild(&Entry->Links, &PrefixTableEntry->Links);
                break;
            }
        }
        else
        {
            /* Check out if we have a right child */
            if (RtlRightChild(&Entry->Links))
            {
                /* We do, enter it and restart the loop */
                SplayLinks = RtlRightChild(&Entry->Links);
                Entry = CONTAINING_RECORD(SplayLinks,
                                          UNICODE_PREFIX_TABLE_ENTRY,
                                          Links);
            }
            else
            {
                /* We don't, set this entry as a child */
                PrefixTableEntry->NodeTypeCode = PFX_NTC_CHILD;
                PrefixTableEntry->NextPrefixTree = NULL;
                PrefixTableEntry->CaseMatch = PrefixTableEntry;

                /* Insert us into the tree */
                RtlInsertAsRightChild(&Entry->Links, &PrefixTableEntry->Links);
                break;
            }
        }
    }

    /* Get the next tree entry */
    NextEntry = CurrentEntry->NextPrefixTree;

    /* Set what was the current entry to a child entry */
    CurrentEntry->NodeTypeCode = PFX_NTC_CHILD;
    CurrentEntry->NextPrefixTree = NULL;

    /* Splay the tree */
    SplayLinks = RtlSplay(&Entry->Links);

    /* The link points to the root, get it */
    Entry = CONTAINING_RECORD(SplayLinks, UNICODE_PREFIX_TABLE_ENTRY, Links);

    /* Mark the root as a root entry */
    Entry->NodeTypeCode = PFX_NTC_ROOT;

    /* Add it to the tree list */
    PreviousEntry->NextPrefixTree = Entry;
    Entry->NextPrefixTree = NextEntry;

    /* Return success */
    return TRUE;
}
Exemplo n.º 9
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;
}
Exemplo n.º 10
0
VOID
NTAPI
FatInsertName(IN PFAT_IRP_CONTEXT IrpContext,
              IN PRTL_SPLAY_LINKS *RootNode,
              IN PFCB_NAME_LINK Name)
{
    PFCB_NAME_LINK NameLink;
    FSRTL_COMPARISON_RESULT Comparison;

    /* Initialize the splay links */
    RtlInitializeSplayLinks(&Name->Links);

    /* Is this the first entry? */
    if (*RootNode == NULL)
    {
        /* Yes, become root and return */
        *RootNode = &Name->Links;
        return;
    }

    /* Get the name link */
    NameLink = CONTAINING_RECORD(*RootNode, FCB_NAME_LINK, Links);
    while (TRUE)
    {
        /* Compare the prefix */
        if (*(PUCHAR)NameLink->Name.Ansi.Buffer != *(PUCHAR)&Name->Name.Ansi.Buffer)
        {
            if (*(PUCHAR)NameLink->Name.Ansi.Buffer < *(PUCHAR)&Name->Name.Ansi.Buffer)
                Comparison = LessThan;
            else
                Comparison = GreaterThan;
        }
        else
        {
            /* Perform real comparison */
            Comparison = FatiCompareNames(&NameLink->Name.Ansi, &Name->Name.Ansi);
        }

        /* Check the bad case first */
        if (Comparison == EqualTo)
        {
            /* Must not happen */
            ASSERT(FALSE);
        }

        /* Check comparison result */
        if (Comparison == GreaterThan)
        {
            /* Go to the left child */
            if (!RtlLeftChild(&NameLink->Links))
            {
                /* It's absent, insert here and break */
                RtlInsertAsLeftChild(&NameLink->Links, &Name->Links);
                break;
            }
            else
            {
                /* It's present, go inside it */
                NameLink = CONTAINING_RECORD(RtlLeftChild(&NameLink->Links),
                                             FCB_NAME_LINK,
                                             Links);
            }
        }
        else
        {
            /* Go to the right child */
            if (!RtlRightChild(&NameLink->Links))
            {
                /* It's absent, insert here and break */
                RtlInsertAsRightChild(&NameLink->Links, &Name->Links);
                break;
            }
            else
            {
                /* It's present, go inside it */
                NameLink = CONTAINING_RECORD(RtlRightChild(&NameLink->Links),
                                             FCB_NAME_LINK,
                                             Links);
            }
        }
    }
}