/*
 * @implemented
 */
PVOID
NTAPI
RtlEnumerateGenericTable(IN PRTL_GENERIC_TABLE Table,
                         IN BOOLEAN Restart)
{
    PRTL_SPLAY_LINKS FoundNode;

    /* Check if the table is empty */
    if (RtlIsGenericTableEmpty(Table)) return NULL;

    /* Check if we have to restart */
    if (Restart)
    {
        /* Then find the leftmost element */
        FoundNode = Table->TableRoot;
        do
        {
            /* Get the left child */
            FoundNode = RtlLeftChild(FoundNode);
        } while(RtlLeftChild(FoundNode));

        /* Splay it */
        Table->TableRoot = RtlSplay(FoundNode);
    }
    else
    {
        /* Otherwise, try using the real successor */
        FoundNode = RtlRealSuccessor(Table->TableRoot);
        if (FoundNode) Table->TableRoot = RtlSplay(FoundNode);
    }

    /* Check if we found the node and return it */
    return FoundNode ? &((PTABLE_ENTRY_HEADER)FoundNode)->UserData : NULL;
}
Beispiel #2
0
PFCB
NTAPI
FatFindFcb(PFAT_IRP_CONTEXT IrpContext,
           PRTL_SPLAY_LINKS *RootNode,
           PSTRING AnsiName,
           PBOOLEAN IsDosName)
{
    PFCB_NAME_LINK Node;
    FSRTL_COMPARISON_RESULT Comparison;
    PRTL_SPLAY_LINKS Links;

    Links = *RootNode;

    while (Links)
    {
        Node = CONTAINING_RECORD(Links, FCB_NAME_LINK, Links);

        /* Compare the prefix */
        if (*(PUCHAR)Node->Name.Ansi.Buffer != *(PUCHAR)AnsiName->Buffer)
        {
            if (*(PUCHAR)Node->Name.Ansi.Buffer < *(PUCHAR)AnsiName->Buffer)
                Comparison = LessThan;
            else
                Comparison = GreaterThan;
        }
        else
        {
            /* Perform real comparison */
            Comparison = FatiCompareNames(&Node->Name.Ansi, AnsiName);
        }

        /* Do they match? */
        if (Comparison == GreaterThan)
        {
            /* No, it's greater, go to the left child */
            Links = RtlLeftChild(Links);
        }
        else if (Comparison == LessThan)
        {
            /* No, it's lesser, go to the right child */
            Links = RtlRightChild(Links);
        }
        else
        {
            /* Exact match, balance the tree */
            *RootNode = RtlSplay(Links);

            /* Save type of the name, if needed */
            if (IsDosName)
                *IsDosName = Node->IsDosName;

            /* Return the found fcb */
            return Node->Fcb;
        }
    }

    /* Nothing found */
    return NULL;
}
/*
 * @implemented
 */
PVOID
NTAPI
RtlLookupElementGenericTableFull(IN PRTL_GENERIC_TABLE Table,
                                 IN PVOID Buffer,
                                 OUT PVOID *NodeOrParent,
                                 OUT TABLE_SEARCH_RESULT *SearchResult)
{
    /* Do the initial lookup */
    *SearchResult = RtlpFindGenericTableNodeOrParent(Table,
                    Buffer,
                    (PRTL_SPLAY_LINKS *)
                    NodeOrParent);

    /* Check if we found anything */
    if ((*SearchResult == TableEmptyTree) || (*SearchResult != TableFoundNode))
    {
        /* Nothing found */
        return NULL;
    }

    /* Otherwise, splay the tree and return this entry */
    Table->TableRoot = RtlSplay(*NodeOrParent);
    return &((PTABLE_ENTRY_HEADER)*NodeOrParent)->UserData;
}
Beispiel #4
0
PFCB
FatFindFcb (
    IN PIRP_CONTEXT IrpContext,
    IN OUT PRTL_SPLAY_LINKS *RootNode,
    IN PSTRING Name,
    OUT PBOOLEAN FileNameDos OPTIONAL
    )

/*++

Routine Description:

    This routine searches either the Oem or Unicode splay tree looking
    for an Fcb with the specified name.  In the case the Fcb is found,
    rebalance the tree.

Arguments:

    RootNode - Supplies the parent to search.

    Name - If present, search the Oem tree.

    UnicodeName - If present, search the Unicode tree.

Return Value:

    PFCB - The Fcb, or NULL if none was found.

--*/

{
    COMPARISON Comparison;
    PFILE_NAME_NODE Node;
    PRTL_SPLAY_LINKS Links;

    PAGED_CODE();

    Links = *RootNode;

    while (Links != NULL) {

        Node = CONTAINING_RECORD(Links, FILE_NAME_NODE, Links);

        //
        //  Compare the prefix in the tree with the full name
        //

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

        //
        //  See if they don't match
        //

        if (Comparison == IsGreaterThan) {

            //
            //  The prefix is greater than the full name
            //  so we go down the left child
            //

            Links = RtlLeftChild(Links);

            //
            //  And continue searching down this tree
            //

        } else if (Comparison == IsLessThan) {

            //
            //  The prefix is less than the full name
            //  so we go down the right child
            //

            Links = RtlRightChild(Links);

            //
            //  And continue searching down this tree
            //

        } else {

            //
            //  We found it.
            //
            //  Splay the tree and save the new root.
            //

            *RootNode = RtlSplay(Links);

            //
            //  Tell the caller what kind of name we hit
            //

            if (FileNameDos) {

                *FileNameDos = Node->FileNameDos;
            }

            return Node->Fcb;
        }
    }

    //
    //  We didn't find the Fcb.
    //

    return NULL;
}
Beispiel #5
0
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));

}
PXIXFS_LCB
xixfs_NLFindNameLinkIgnoreCase (
    IN PXIXFS_IRPCONTEXT IrpContext,
    IN PRTL_SPLAY_LINKS *RootNode,
    IN PUNICODE_STRING Name
    )
{
	FSRTL_COMPARISON_RESULT Comparison;
	PXIXFS_LCB Node;
	PRTL_SPLAY_LINKS Links;

	PAGED_CODE();
	DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO),
		("Enter xixfs_NLFindNameLink \n"));

	Links = *RootNode;

	while (Links != NULL) {

		Node = CONTAINING_RECORD( Links, XIXFS_LCB, IgnoreCaseLinks );

		//
		//  Compare the prefix in the tree with the full name
		//

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

		//
		//  See if they don't match
		//

		if (Comparison == GreaterThan) {

			//
			//  The prefix is greater than the full name
			//  so we go down the left child
			//

			Links = RtlLeftChild( Links );

			//
			//  And continue searching down this tree
			//

		} else if (Comparison == LessThan) {

			//
			//  The prefix is less than the full name
			//  so we go down the right child
			//

			Links = RtlRightChild( Links );

			//
			//  And continue searching down this tree
			//

		} else {

			//
			//  We found it.
			//
			//  Splay the tree and save the new root.
			//

			*RootNode = RtlSplay( Links );

			return Node;
		}
	}

	//
	//  We didn't find the Link.
	//
	DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_DIRINFO|DEBUG_TARGET_FCB|DEBUG_TARGET_FILEINFO),
		("Exit xixfs_NLFindNameLink \n"));
	return NULL;
}
/*
 * @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;
}
Beispiel #8
0
PTREE_NODE
TreeInsert (
    IN PTREE_NODE Root,
    IN PTREE_NODE Node
    )

{
    PRTL_SPLAY_LINKS Temp;

    if (Root == NULL) {

        //DbgPrint("Add as root %u\n", Node->Data);
        return Node;

    }

    while (TRUE) {

        if (Root->Data == Node->Data) {

            //DbgPrint("Delete %u\n", Node->Data);

            Temp = RtlDelete(&Root->Links);
            if (Temp == NULL) {
                return NULL;
            } else {
                return CONTAINING_RECORD(Temp, TREE_NODE, Links);
            }

        }

        if (Root->Data < Node->Data) {

            //
            //  Go right
            //

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

                //DbgPrint("Add as right child %u\n", Node->Data);
                RtlInsertAsRightChild(&Root->Links, &Node->Links);
                return CONTAINING_RECORD(RtlSplay(&Node->Links), TREE_NODE, Links);

            } else {

                Root = CONTAINING_RECORD(RtlRightChild(&Root->Links), TREE_NODE, Links);

            }

        } else {

            //
            //  Go Left
            //

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

                //DbgPrint("Add as left child %u\n", Node->Data);
                RtlInsertAsLeftChild(&Root->Links, &Node->Links);
                return CONTAINING_RECORD(RtlSplay(&Node->Links), TREE_NODE, Links);

            } else {

                Root = CONTAINING_RECORD(RtlLeftChild(&Root->Links), TREE_NODE, Links);

            }

        }
    }
}
PNAME_LINK
CdFindNameLink (
    _In_ PIRP_CONTEXT IrpContext,
    _In_ PRTL_SPLAY_LINKS *RootNode,
    _In_ PUNICODE_STRING Name
    )

/*++

Routine Description:

    This routine searches through a splay link tree looking for a match for the
    input name.  If we find the corresponding name we will rebalance the
    tree.

Arguments:

    RootNode - Supplies the parent to search.

    Name - This is the name to search for.  Note if we are doing a case
        insensitive search the name would have been upcased already.

Return Value:

    PNAME_LINK - The name link found or NULL if there is no match.

--*/

{
    FSRTL_COMPARISON_RESULT Comparison;
    PNAME_LINK Node;
    PRTL_SPLAY_LINKS Links;

    PAGED_CODE();

    Links = *RootNode;

    while (Links != NULL) {

        Node = CONTAINING_RECORD( Links, NAME_LINK, Links );

        //
        //  Compare the prefix in the tree with the full name
        //

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

        //
        //  See if they don't match
        //

        if (Comparison == GreaterThan) {

            //
            //  The prefix is greater than the full name
            //  so we go down the left child
            //

            Links = RtlLeftChild( Links );

            //
            //  And continue searching down this tree
            //

        } else if (Comparison == LessThan) {

            //
            //  The prefix is less than the full name
            //  so we go down the right child
            //

            Links = RtlRightChild( Links );

            //
            //  And continue searching down this tree
            //

        } else {

            //
            //  We found it.
            //
            //  Splay the tree and save the new root.
            //

            *RootNode = RtlSplay( Links );

            return Node;
        }
    }

    //
    //  We didn't find the Link.
    //

    return NULL;
}
Beispiel #10
0
PVOID
RtlEnumerateGenericTable (
    IN PRTL_GENERIC_TABLE Table,
    IN BOOLEAN Restart
    )

/*++

Routine Description:

    The function EnumerateGenericTable will return to the caller one-by-one
    the elements of of a table.  The return value is a pointer to the user
    defined structure associated with the element.  The input parameter
    Restart indicates if the enumeration should start from the beginning
    or should return the next element.  If the are no more new elements to
    return the return value is NULL.  As an example of its use, to enumerate
    all of the elements in a table the user would write:

        for (ptr = EnumerateGenericTable(Table,TRUE);
             ptr != NULL;
             ptr = EnumerateGenericTable(Table, FALSE)) {
                :
        }

Arguments:

    Table - Pointer to the generic table to enumerate.

    Restart - Flag that if true we should start with the least
              element in the tree otherwise, return we return
              a pointer to the user data for the root and make
              the real successor to the root the new root.

Return Value:

    PVOID - Pointer to the user data.

--*/

{

    if (RtlIsGenericTableEmpty(Table)) {

        //
        // Nothing to do if the table is empty.
        //

        return NULL;

    } else {

        //
        // Will be used as the "iteration" through the tree.
        //
        PRTL_SPLAY_LINKS NodeToReturn;

        //
        // If the restart flag is true then go to the least element
        // in the tree.
        //

        if (Restart) {

            //
            // We just loop until we find the leftmost child of the root.
            //

            for (
                NodeToReturn = Table->TableRoot;
                RtlLeftChild(NodeToReturn);
                NodeToReturn = RtlLeftChild(NodeToReturn)
                ) {
                ;
            }

            Table->TableRoot = RtlSplay(NodeToReturn);

        } else {

            //
            // The assumption here is that the root of the
            // tree is the last node that we returned.  We
            // find the real successor to the root and return
            // it as next element of the enumeration.  The
            // node that is to be returned is splayed (thereby
            // making it the root of the tree).  Note that we
            // need to take care when there are no more elements.
            //

            NodeToReturn = RtlRealSuccessor(Table->TableRoot);

            if (NodeToReturn) {

                Table->TableRoot = RtlSplay(NodeToReturn);

            }

        }

        //
        // If there actually is a next element in the enumeration
        // then the pointer to return is right after the list links.
        //

        return ((NodeToReturn)?
                   ((PVOID)((PLIST_ENTRY)((PVOID)(NodeToReturn+1))+1))
                  :((PVOID)(NULL)));

    }

}
Beispiel #11
0
PVOID
RtlLookupElementGenericTable (
    IN PRTL_GENERIC_TABLE Table,
    IN PVOID Buffer
    )

/*++

Routine Description:

    The function LookupElementGenericTable will find an element in a generic
    table.  If the element is located the return value is a pointer to
    the user defined structure associated with the element, otherwise if
    the element is not located the return value is NULL.  The user supplied
    input buffer is only used as a key in locating the element in the table.

Arguments:

    Table - Pointer to the users Generic table to search for the key.

    Buffer - Used for the comparasion.

Return Value:

    PVOID - returns a pointer to the user 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;

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

    if ((Lookup == EmptyTree) || (Lookup != FoundNode)) {

        return NULL;

    } else {

        //
        // Splay the tree with this node.
        //

        Table->TableRoot = RtlSplay(NodeOrParent);

        //
        // Return a pointer to the user data.
        //

        return ((PLIST_ENTRY)((PVOID)(NodeOrParent+1)))+1;

    }

}
Beispiel #12
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;
}
Beispiel #13
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;
}
Beispiel #14
0
/*
 * @implemented
 */
PUNICODE_PREFIX_TABLE_ENTRY
NTAPI
RtlFindUnicodePrefix(PUNICODE_PREFIX_TABLE PrefixTable,
                     PUNICODE_STRING FullName,
                     ULONG CaseInsensitiveIndex)
{
    ULONG NameCount;
    PUNICODE_PREFIX_TABLE_ENTRY CurrentEntry, PreviousEntry, Entry, NextEntry;
    PRTL_SPLAY_LINKS SplayLinks;
    RTL_GENERIC_COMPARE_RESULTS Result;

    DPRINT("RtlFindUnicodePrefix(): Table %p, FullName %wZ, "
        "CaseInsensitive %lu\n", PrefixTable, FullName, CaseInsensitiveIndex);

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

    /* Find the right spot where to start looking for 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;
    }

    /* Loop every entry which has valid entries */
    while (CurrentEntry->NameLength)
    {
        /* Get the splay links and loop */
        SplayLinks = &CurrentEntry->Links;
        while (SplayLinks)
        {
            /* Get the entry */
            Entry = CONTAINING_RECORD(SplayLinks,
                                      UNICODE_PREFIX_TABLE_ENTRY,
                                      Links);

            /* Do the comparison */
            Result = CompareUnicodeStrings(Entry->Prefix, FullName, 0);
            if (Result == GenericGreaterThan)
            {
                /* Prefix is greater, so restart on the left child */
                SplayLinks = RtlLeftChild(SplayLinks);
                continue;
            }
            else if (Result == GenericLessThan)
            {
                /* Prefix is smaller, so restart on the right child */
                SplayLinks = RtlRightChild(SplayLinks);
                continue;
            }

            /*
             * We have a match, check if this was a case-sensitive search
             * NOTE: An index of 0 means case-insensitive(ie, we'll be case
             * insensitive since index 0, ie, all the time)
             */
            if (!CaseInsensitiveIndex)
            {
                /*
                 * Check if this entry was a child. We need to return the root,
                 * so if this entry was a child, we'll splay the tree and get
                 * the root, and set the current entry as a child.
                 */
                if (Entry->NodeTypeCode == PFX_NTC_CHILD)
                {
                    /* Get the next entry */
                    NextEntry = CurrentEntry->NextPrefixTree;

                    /* Make the current entry become a child */
                    CurrentEntry->NodeTypeCode = PFX_NTC_CHILD;
                    CurrentEntry->NextPrefixTree = NULL;

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

                    /* Get the new root entry */
                    Entry = CONTAINING_RECORD(SplayLinks,
                                              UNICODE_PREFIX_TABLE_ENTRY,
                                              Links);

                    /* Set it as a root entry */
                    Entry->NodeTypeCode = PFX_NTC_ROOT;

                    /* Add it to the root entries list */
                    PreviousEntry->NextPrefixTree = Entry;
                    Entry->NextPrefixTree = NextEntry;
                }

                /* Return the entry */
                return Entry;
            }

            /* We'll do a case-sensitive search if we've reached this point */
            NextEntry = Entry;
            do
            {
                /* Do the case-sensitive search */
                Result = CompareUnicodeStrings(NextEntry->Prefix,
                                               FullName,
                                               CaseInsensitiveIndex);
                if ((Result != GenericLessThan) &&
                    (Result != GenericGreaterThan))
                {
                    /* This is a positive match, return it */
                    return NextEntry;
                }

                /* No match yet, continue looping the circular list */
                NextEntry = NextEntry->CaseMatch;
            } while (NextEntry != Entry);

            /*
             * If we got here, then we found a non-case-sensitive match, but
             * we need to find a case-sensitive match, so we'll just keep
             * searching the next tree (NOTE: we need to break out for this).
             */
            break;
        }

        /* Splay links exhausted, move to next entry */
        PreviousEntry = CurrentEntry;
        CurrentEntry = CurrentEntry->NextPrefixTree;
    }

    /* If we got here, nothing was found */
    return NULL;
}
Beispiel #15
0
/*
 * @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));
}