mirror of
https://github.com/reactos/reactos.git
synced 2025-06-19 12:15:19 +00:00
Create a branch for header work.
svn path=/branches/header-work/; revision=45691
This commit is contained in:
parent
14fe274b1c
commit
9ea495ba33
19538 changed files with 0 additions and 1063950 deletions
682
lib/rtl/unicodeprefix.c
Normal file
682
lib/rtl/unicodeprefix.c
Normal file
|
@ -0,0 +1,682 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
* PURPOSE: Unicode Prefix implementation
|
||||
* FILE: lib/rtl/unicodeprefix.c
|
||||
* PROGRAMMER: Alex Ionescu (alex@relsoft.net)
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <rtl.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/*
|
||||
* FIXME: Try to find the official names and add to NDK
|
||||
* Definitions come from fastfat driver.
|
||||
*/
|
||||
typedef USHORT NODE_TYPE_CODE;
|
||||
#define PFX_NTC_TABLE ((NODE_TYPE_CODE)0x0800)
|
||||
#define PFX_NTC_ROOT ((NODE_TYPE_CODE)0x0801)
|
||||
#define PFX_NTC_CHILD ((NODE_TYPE_CODE)0x0802)
|
||||
#define PFX_NTC_CASE_MATCH ((NODE_TYPE_CODE)0x0803)
|
||||
|
||||
/* FUNCTIONS ***************************************************************/
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
ComputeUnicodeNameLength(IN PUNICODE_STRING UnicodeName)
|
||||
{
|
||||
ULONG Chars = UnicodeName->Length / sizeof(WCHAR);
|
||||
ULONG i, NamesFound = 1;
|
||||
|
||||
/* Loop the string */
|
||||
for (i = 0; i < (Chars - 1); i++)
|
||||
{
|
||||
/* Check if we found a backslash, meaning another name */
|
||||
if (UnicodeName->Buffer[i] == '\\') NamesFound++;
|
||||
}
|
||||
|
||||
/* Return the number of names found */
|
||||
return NamesFound;
|
||||
}
|
||||
|
||||
RTL_GENERIC_COMPARE_RESULTS
|
||||
NTAPI
|
||||
CompareUnicodeStrings(IN PUNICODE_STRING Prefix,
|
||||
IN PUNICODE_STRING String,
|
||||
IN ULONG CaseCheckChar)
|
||||
{
|
||||
ULONG StringLength = String->Length / sizeof(WCHAR);
|
||||
ULONG PrefixLength = Prefix->Length / sizeof(WCHAR);
|
||||
ULONG ScanLength = min(StringLength, PrefixLength);
|
||||
ULONG i;
|
||||
WCHAR FoundPrefix, FoundString;
|
||||
PWCHAR p, p1;
|
||||
|
||||
/* Handle case noticed in npfs when Prefix = '\' and name starts with '\' */
|
||||
if ((PrefixLength == 1) &&
|
||||
(Prefix->Buffer[0] == '\\') &&
|
||||
(StringLength > 1) &&
|
||||
(String->Buffer[0] == '\\'))
|
||||
{
|
||||
/* The string is actually a prefix */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Validate the Case Check Character Position */
|
||||
if (CaseCheckChar > ScanLength) CaseCheckChar = ScanLength;
|
||||
|
||||
/* Do the case sensitive comparison first */
|
||||
for (i = 0; i < CaseCheckChar; i++)
|
||||
{
|
||||
/* Compare the two characters */
|
||||
if (Prefix->Buffer[i] != String->Buffer[i]) break;
|
||||
}
|
||||
|
||||
/* Save the characters we found */
|
||||
FoundPrefix = Prefix->Buffer[i];
|
||||
FoundString = String->Buffer[i];
|
||||
|
||||
/* Check if we exausted the search above */
|
||||
if (i == CaseCheckChar)
|
||||
{
|
||||
/* Do a case-insensitive search */
|
||||
p = &Prefix->Buffer[i];
|
||||
p1 = &String->Buffer[i];
|
||||
do
|
||||
{
|
||||
/* Move to the next character */
|
||||
FoundPrefix = *p++;
|
||||
FoundString = *p1++;
|
||||
|
||||
/* Compare it */
|
||||
if (FoundPrefix != FoundString)
|
||||
{
|
||||
/* Upcase the characters */
|
||||
FoundPrefix = RtlUpcaseUnicodeChar(FoundPrefix);
|
||||
FoundString = RtlUpcaseUnicodeChar(FoundString);
|
||||
|
||||
/* Compare them again */
|
||||
if (FoundPrefix != FoundString) break;
|
||||
}
|
||||
|
||||
/* Move to the next char */
|
||||
i++;
|
||||
} while (i < ScanLength);
|
||||
}
|
||||
|
||||
/* Check if we weren't able to find a match in the loops */
|
||||
if (i < ScanLength)
|
||||
{
|
||||
/* If the prefix character found was a backslash, this is a less */
|
||||
if (FoundPrefix == '\\') return GenericLessThan;
|
||||
|
||||
/* If the string character found was a backslack, then this is a more */
|
||||
if (FoundString == '\\') return GenericGreaterThan;
|
||||
|
||||
/* None of those two special cases, do a normal check */
|
||||
if (FoundPrefix < FoundString) return GenericLessThan;
|
||||
|
||||
/* The only choice left is that Prefix > String */
|
||||
return GenericGreaterThan;
|
||||
}
|
||||
|
||||
/* If we got here, a match was found. Check if the prefix is smaller */
|
||||
if (PrefixLength < StringLength)
|
||||
{
|
||||
/* Check if the string is actually a prefix */
|
||||
if (String->Buffer[PrefixLength] == '\\') return -1;
|
||||
|
||||
/* It's not a prefix, and it's shorter, so it's a less */
|
||||
return GenericLessThan;
|
||||
}
|
||||
|
||||
/* Check if the prefix is longer */
|
||||
if (PrefixLength > StringLength) return GenericGreaterThan;
|
||||
|
||||
/* If we got here, then they are 100% equal */
|
||||
return GenericEqual;
|
||||
}
|
||||
|
||||
/*
|
||||
* @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 %b\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;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
RtlInitializeUnicodePrefix(PUNICODE_PREFIX_TABLE PrefixTable)
|
||||
{
|
||||
DPRINT("RtlInitializeUnicodePrefix(): Table %p\n",
|
||||
PrefixTable);
|
||||
|
||||
/* Setup the table */
|
||||
PrefixTable->NameLength = 0;
|
||||
PrefixTable->LastNextEntry = NULL;
|
||||
PrefixTable->NodeTypeCode = PFX_NTC_TABLE;
|
||||
PrefixTable->NextPrefixTree = (PUNICODE_PREFIX_TABLE_ENTRY)PrefixTable;
|
||||
}
|
||||
|
||||
/*
|
||||
* @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;
|
||||
}
|
||||
|
||||
/*
|
||||
* @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 %b\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;
|
||||
}
|
||||
|
||||
/*
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* EOF */
|
Loading…
Add table
Add a link
Reference in a new issue