ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

unicodeprefix.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:         See COPYING in the top level directory
00003  * PROJECT:           ReactOS system libraries
00004  * PURPOSE:           Unicode Prefix implementation
00005  * FILE:              lib/rtl/unicodeprefix.c
00006  * PROGRAMMER:        Alex Ionescu (alex@relsoft.net)
00007  */
00008 
00009 /* INCLUDES *****************************************************************/
00010 
00011 #include <rtl.h>
00012 
00013 #define NDEBUG
00014 #include <debug.h>
00015 
00016 /*
00017  * FIXME: Try to find the official names and add to NDK
00018  * Definitions come from fastfat driver.
00019  */
00020 typedef USHORT NODE_TYPE_CODE;
00021 #define PFX_NTC_TABLE       ((NODE_TYPE_CODE)0x0800)
00022 #define PFX_NTC_ROOT        ((NODE_TYPE_CODE)0x0801)
00023 #define PFX_NTC_CHILD       ((NODE_TYPE_CODE)0x0802)
00024 #define PFX_NTC_CASE_MATCH  ((NODE_TYPE_CODE)0x0803)
00025 
00026 /* FUNCTIONS ***************************************************************/
00027 
00028 ULONG
00029 NTAPI
00030 ComputeUnicodeNameLength(IN PUNICODE_STRING UnicodeName)
00031 {
00032     ULONG Chars = UnicodeName->Length / sizeof(WCHAR);
00033     ULONG i, NamesFound = 1;
00034 
00035     /* Loop the string */
00036     for (i = 0; i < (Chars - 1); i++)
00037     {
00038         /* Check if we found a backslash, meaning another name */
00039         if (UnicodeName->Buffer[i] == '\\') NamesFound++;
00040     }
00041 
00042     /* Return the number of names found */
00043     return NamesFound;
00044 }
00045 
00046 RTL_GENERIC_COMPARE_RESULTS
00047 NTAPI
00048 CompareUnicodeStrings(IN PUNICODE_STRING Prefix,
00049                       IN PUNICODE_STRING String,
00050                       IN ULONG CaseCheckChar)
00051 {
00052     ULONG StringLength = String->Length / sizeof(WCHAR);
00053     ULONG PrefixLength = Prefix->Length / sizeof(WCHAR);
00054     ULONG ScanLength = min(StringLength, PrefixLength);
00055     ULONG i;
00056     WCHAR FoundPrefix, FoundString;
00057     PWCHAR p, p1;
00058 
00059     /* Handle case noticed in npfs when Prefix = '\' and name starts with '\' */
00060     if ((PrefixLength == 1) &&
00061         (Prefix->Buffer[0] == '\\') &&
00062         (StringLength > 1) &&
00063         (String->Buffer[0] == '\\'))
00064     {
00065         /* The string is actually a prefix */
00066         return -1;
00067     }
00068 
00069     /* Validate the Case Check Character Position */
00070     if (CaseCheckChar > ScanLength) CaseCheckChar = ScanLength;
00071 
00072     /* Do the case sensitive comparison first */
00073     for (i = 0; i < CaseCheckChar; i++)
00074     {
00075         /* Compare the two characters */
00076         if (Prefix->Buffer[i] != String->Buffer[i]) break;
00077     }
00078 
00079     /* Save the characters we found */
00080     FoundPrefix = Prefix->Buffer[i];
00081     FoundString = String->Buffer[i];
00082 
00083     /* Check if we exausted the search above */
00084     if (i == CaseCheckChar)
00085     {
00086         /* Do a case-insensitive search */
00087         p = &Prefix->Buffer[i];
00088         p1 = &String->Buffer[i];
00089         do
00090         {
00091             /* Move to the next character */
00092             FoundPrefix = *p++;
00093             FoundString = *p1++;
00094 
00095             /* Compare it */
00096             if (FoundPrefix != FoundString)
00097             {
00098                 /* Upcase the characters */
00099                 FoundPrefix = RtlUpcaseUnicodeChar(FoundPrefix);
00100                 FoundString = RtlUpcaseUnicodeChar(FoundString);
00101 
00102                 /* Compare them again */
00103                 if (FoundPrefix != FoundString) break;
00104             }
00105 
00106             /* Move to the next char */
00107             i++;
00108         } while (i < ScanLength);
00109     }
00110 
00111     /* Check if we weren't able to find a match in the loops */
00112     if (i < ScanLength)
00113     {
00114         /* If the prefix character found was a backslash, this is a less */
00115         if (FoundPrefix == '\\') return GenericLessThan;
00116 
00117         /* If the string character found was a backslack, then this is a more */
00118         if (FoundString == '\\') return GenericGreaterThan;
00119 
00120         /* None of those two special cases, do a normal check */
00121         if (FoundPrefix < FoundString) return GenericLessThan;
00122 
00123         /* The only choice left is that Prefix > String */
00124         return GenericGreaterThan;
00125     }
00126 
00127     /* If we got here, a match was found. Check if the prefix is smaller */
00128     if (PrefixLength < StringLength)
00129     {
00130         /* Check if the string is actually a prefix */
00131         if (String->Buffer[PrefixLength] == '\\') return -1;
00132 
00133         /* It's not a prefix, and it's shorter, so it's a less */
00134         return GenericLessThan;
00135     }
00136 
00137     /* Check if the prefix is longer */
00138     if (PrefixLength > StringLength) return GenericGreaterThan;
00139 
00140     /* If we got here, then they are 100% equal */
00141     return GenericEqual;
00142 }
00143 
00144 /*
00145  * @implemented
00146  */
00147 PUNICODE_PREFIX_TABLE_ENTRY
00148 NTAPI
00149 RtlFindUnicodePrefix(PUNICODE_PREFIX_TABLE PrefixTable,
00150                      PUNICODE_STRING FullName,
00151                      ULONG CaseInsensitiveIndex)
00152 {
00153     ULONG NameCount;
00154     PUNICODE_PREFIX_TABLE_ENTRY CurrentEntry, PreviousEntry, Entry, NextEntry;
00155     PRTL_SPLAY_LINKS SplayLinks;
00156     RTL_GENERIC_COMPARE_RESULTS Result;
00157 
00158     DPRINT("RtlFindUnicodePrefix(): Table %p, FullName %wZ, "
00159         "CaseInsensitive %b\n", PrefixTable, FullName, CaseInsensitiveIndex);
00160 
00161     /* Find out how many names there are */
00162     NameCount = ComputeUnicodeNameLength(FullName);
00163 
00164     /* Find the right spot where to start looking for this entry */
00165     PreviousEntry = (PUNICODE_PREFIX_TABLE_ENTRY)PrefixTable;
00166     CurrentEntry = PreviousEntry->NextPrefixTree;
00167     while (CurrentEntry->NameLength > (CSHORT)NameCount)
00168     {
00169         /* Not a match, move to the next entry */
00170         PreviousEntry = CurrentEntry;
00171         CurrentEntry = CurrentEntry->NextPrefixTree;
00172     }
00173 
00174     /* Loop every entry which has valid entries */
00175     while (CurrentEntry->NameLength)
00176     {
00177         /* Get the splay links and loop */
00178         SplayLinks = &CurrentEntry->Links;
00179         while (SplayLinks)
00180         {
00181             /* Get the entry */
00182             Entry = CONTAINING_RECORD(SplayLinks,
00183                                       UNICODE_PREFIX_TABLE_ENTRY,
00184                                       Links);
00185 
00186             /* Do the comparison */
00187             Result = CompareUnicodeStrings(Entry->Prefix, FullName, 0);
00188             if (Result == GenericGreaterThan)
00189             {
00190                 /* Prefix is greater, so restart on the left child */
00191                 SplayLinks = RtlLeftChild(SplayLinks);
00192                 continue;
00193             }
00194             else if (Result == GenericLessThan)
00195             {
00196                 /* Prefix is smaller, so restart on the right child */
00197                 SplayLinks = RtlRightChild(SplayLinks);
00198                 continue;
00199             }
00200 
00201             /*
00202              * We have a match, check if this was a case-sensitive search
00203              * NOTE: An index of 0 means case-insensitive(ie, we'll be case
00204              * insensitive since index 0, ie, all the time)
00205              */
00206             if (!CaseInsensitiveIndex)
00207             {
00208                 /*
00209                  * Check if this entry was a child. We need to return the root,
00210                  * so if this entry was a child, we'll splay the tree and get
00211                  * the root, and set the current entry as a child.
00212                  */
00213                 if (Entry->NodeTypeCode == PFX_NTC_CHILD)
00214                 {
00215                     /* Get the next entry */
00216                     NextEntry = CurrentEntry->NextPrefixTree;
00217 
00218                     /* Make the current entry become a child */
00219                     CurrentEntry->NodeTypeCode = PFX_NTC_CHILD;
00220                     CurrentEntry->NextPrefixTree = NULL;
00221 
00222                     /* Splay the tree */
00223                     SplayLinks = RtlSplay(&Entry->Links);
00224 
00225                     /* Get the new root entry */
00226                     Entry = CONTAINING_RECORD(SplayLinks,
00227                                               UNICODE_PREFIX_TABLE_ENTRY,
00228                                               Links);
00229 
00230                     /* Set it as a root entry */
00231                     Entry->NodeTypeCode = PFX_NTC_ROOT;
00232 
00233                     /* Add it to the root entries list */
00234                     PreviousEntry->NextPrefixTree = Entry;
00235                     Entry->NextPrefixTree = NextEntry;
00236                 }
00237 
00238                 /* Return the entry */
00239                 return Entry;
00240             }
00241 
00242             /* We'll do a case-sensitive search if we've reached this point */
00243             NextEntry = Entry;
00244             do
00245             {
00246                 /* Do the case-sensitive search */
00247                 Result = CompareUnicodeStrings(NextEntry->Prefix,
00248                                                FullName,
00249                                                CaseInsensitiveIndex);
00250                 if ((Result != GenericLessThan) &&
00251                     (Result != GenericGreaterThan))
00252                 {
00253                     /* This is a positive match, return it */
00254                     return NextEntry;
00255                 }
00256 
00257                 /* No match yet, continue looping the circular list */
00258                 NextEntry = NextEntry->CaseMatch;
00259             } while (NextEntry != Entry);
00260 
00261             /*
00262              * If we got here, then we found a non-case-sensitive match, but
00263              * we need to find a case-sensitive match, so we'll just keep
00264              * searching the next tree (NOTE: we need to break out for this).
00265              */
00266             break;
00267         }
00268 
00269         /* Splay links exhausted, move to next entry */
00270         PreviousEntry = CurrentEntry;
00271         CurrentEntry = CurrentEntry->NextPrefixTree;
00272     }
00273 
00274     /* If we got here, nothing was found */
00275     return NULL;
00276 }
00277 
00278 /*
00279  * @implemented
00280  */
00281 VOID
00282 NTAPI
00283 RtlInitializeUnicodePrefix(PUNICODE_PREFIX_TABLE PrefixTable)
00284 {
00285     DPRINT("RtlInitializeUnicodePrefix(): Table %p\n",
00286         PrefixTable);
00287 
00288     /* Setup the table */
00289     PrefixTable->NameLength = 0;
00290     PrefixTable->LastNextEntry = NULL;
00291     PrefixTable->NodeTypeCode = PFX_NTC_TABLE;
00292     PrefixTable->NextPrefixTree = (PUNICODE_PREFIX_TABLE_ENTRY)PrefixTable;
00293 }
00294 
00295 /*
00296  * @implemented
00297  */
00298 BOOLEAN
00299 NTAPI
00300 RtlInsertUnicodePrefix(PUNICODE_PREFIX_TABLE PrefixTable,
00301                        PUNICODE_STRING Prefix,
00302                        PUNICODE_PREFIX_TABLE_ENTRY PrefixTableEntry)
00303 {
00304     PUNICODE_PREFIX_TABLE_ENTRY CurrentEntry, PreviousEntry, Entry, NextEntry;
00305     ULONG NameCount;
00306     RTL_GENERIC_COMPARE_RESULTS Result;
00307     PRTL_SPLAY_LINKS SplayLinks;
00308 
00309     DPRINT("RtlInsertUnicodePrefix(): Table %p, Prefix %wZ, "
00310         "TableEntry %p\n", PrefixTable, Prefix, PrefixTableEntry);
00311 
00312     /* Find out how many names there are */
00313     NameCount = ComputeUnicodeNameLength(Prefix);
00314 
00315     /* Set up the initial entry data */
00316     PrefixTableEntry->NameLength = (CSHORT)NameCount;
00317     PrefixTableEntry->Prefix = Prefix;
00318     RtlInitializeSplayLinks(&PrefixTableEntry->Links);
00319 
00320     /* Find the right spot where to insert this entry */
00321     PreviousEntry = (PUNICODE_PREFIX_TABLE_ENTRY)PrefixTable;
00322     CurrentEntry = PreviousEntry->NextPrefixTree;
00323     while (CurrentEntry->NameLength > (CSHORT)NameCount)
00324     {
00325         /* Not a match, move to the next entry */
00326         PreviousEntry = CurrentEntry;
00327         CurrentEntry = CurrentEntry->NextPrefixTree;
00328     }
00329 
00330     /* Check if we did find a tree by now */
00331     if (CurrentEntry->NameLength != (CSHORT)NameCount)
00332     {
00333         /* We didn't, so insert a new entry in the list */
00334         PreviousEntry->NextPrefixTree = PrefixTableEntry;
00335         PrefixTableEntry->NextPrefixTree = CurrentEntry;
00336 
00337         /* This is now a root entry with case match */
00338         PrefixTableEntry->NodeTypeCode = PFX_NTC_ROOT;
00339         PrefixTableEntry->CaseMatch = PrefixTableEntry;
00340 
00341         /* Quick return */
00342         return TRUE;
00343     }
00344 
00345     /* We found a tree, so start the search loop */
00346     Entry = CurrentEntry;
00347     while (TRUE)
00348     {
00349         /* Do a case-insensitive comparison to find out the match level */
00350         Result = CompareUnicodeStrings(Entry->Prefix, Prefix, 0);
00351         if (Result == GenericEqual)
00352         {
00353             /* We have a match, start doing a case-sensitive search */
00354             NextEntry = Entry;
00355 
00356             /* Search the circular case-match list */
00357             do
00358             {
00359                 /* Check if we found a match */
00360                 if (CompareUnicodeStrings(NextEntry->Prefix, Prefix, -1) ==
00361                     (GenericEqual))
00362                 {
00363                     /* We must fail the insert: it already exists */
00364                     return FALSE;
00365                 }
00366 
00367                 /* Move to the next entry in the circular list */
00368                 NextEntry = NextEntry->CaseMatch;
00369             }
00370             while (NextEntry != Entry);
00371 
00372             /*
00373              * No match found, so we can safely insert it. Remember that a
00374              * case insensitive match was found, so this is not a ROOT NTC
00375              * but a Case Match NTC instead.
00376              */
00377             PrefixTableEntry->NodeTypeCode = PFX_NTC_CASE_MATCH;
00378             PrefixTableEntry->NextPrefixTree = NULL;
00379 
00380             /* Insert it into the circular list */
00381             PrefixTableEntry->CaseMatch = Entry->CaseMatch;
00382             Entry->CaseMatch = PrefixTableEntry;
00383             break;
00384         }
00385 
00386         /* Check if the result was greater or lesser than */
00387         if (Result == GenericGreaterThan)
00388         {
00389             /* Check out if we have a left child */
00390             if (RtlLeftChild(&Entry->Links))
00391             {
00392                 /* We do, enter it and restart the loop */
00393                 SplayLinks = RtlLeftChild(&Entry->Links);
00394                 Entry = CONTAINING_RECORD(SplayLinks,
00395                                           UNICODE_PREFIX_TABLE_ENTRY,
00396                                           Links);
00397             }
00398             else
00399             {
00400                 /* We don't, set this entry as a child */
00401                 PrefixTableEntry->NodeTypeCode = PFX_NTC_CHILD;
00402                 PrefixTableEntry->NextPrefixTree = NULL;
00403                 PrefixTableEntry->CaseMatch = PrefixTableEntry;
00404 
00405                 /* Insert us into the tree */
00406                 RtlInsertAsLeftChild(&Entry->Links, &PrefixTableEntry->Links);
00407                 break;
00408             }
00409         }
00410         else
00411         {
00412             /* Check out if we have a right child */
00413             if (RtlRightChild(&Entry->Links))
00414             {
00415                 /* We do, enter it and restart the loop */
00416                 SplayLinks = RtlRightChild(&Entry->Links);
00417                 Entry = CONTAINING_RECORD(SplayLinks,
00418                                           UNICODE_PREFIX_TABLE_ENTRY,
00419                                           Links);
00420             }
00421             else
00422             {
00423                 /* We don't, set this entry as a child */
00424                 PrefixTableEntry->NodeTypeCode = PFX_NTC_CHILD;
00425                 PrefixTableEntry->NextPrefixTree = NULL;
00426                 PrefixTableEntry->CaseMatch = PrefixTableEntry;
00427 
00428                 /* Insert us into the tree */
00429                 RtlInsertAsRightChild(&Entry->Links, &PrefixTableEntry->Links);
00430                 break;
00431             }
00432         }
00433     }
00434 
00435     /* Get the next tree entry */
00436     NextEntry = CurrentEntry->NextPrefixTree;
00437 
00438     /* Set what was the current entry to a child entry */
00439     CurrentEntry->NodeTypeCode = PFX_NTC_CHILD;
00440     CurrentEntry->NextPrefixTree = NULL;
00441 
00442     /* Splay the tree */
00443     SplayLinks = RtlSplay(&Entry->Links);
00444 
00445     /* The link points to the root, get it */
00446     Entry = CONTAINING_RECORD(SplayLinks, UNICODE_PREFIX_TABLE_ENTRY, Links);
00447 
00448     /* Mark the root as a root entry */
00449     Entry->NodeTypeCode = PFX_NTC_ROOT;
00450 
00451     /* Add it to the tree list */
00452     PreviousEntry->NextPrefixTree = Entry;
00453     Entry->NextPrefixTree = NextEntry;
00454 
00455     /* Return success */
00456     return TRUE;
00457 }
00458 
00459 /*
00460 * @implemented
00461 */
00462 PUNICODE_PREFIX_TABLE_ENTRY
00463 NTAPI
00464 RtlNextUnicodePrefix(PUNICODE_PREFIX_TABLE PrefixTable,
00465                      BOOLEAN Restart)
00466 {
00467     PRTL_SPLAY_LINKS SplayLinks;
00468     PUNICODE_PREFIX_TABLE_ENTRY Entry, CaseMatchEntry = NULL;
00469 
00470     DPRINT("RtlNextUnicodePrefix(): Table %p Restart %b\n",
00471         PrefixTable, Restart);
00472 
00473     /* We might need this entry 2/3rd of the time, so cache it now */
00474     if (PrefixTable->LastNextEntry)
00475         CaseMatchEntry = PrefixTable->LastNextEntry->CaseMatch;
00476 
00477     /* Check if this is a restart or if we don't have a last entry */
00478     if ((Restart) || !(PrefixTable->LastNextEntry))
00479     {
00480         /* Get the next entry and validate it */
00481         Entry = PrefixTable->NextPrefixTree;
00482         if (Entry->NodeTypeCode == PFX_NTC_TABLE) return NULL;
00483 
00484         /* Now get the Splay Tree Links */
00485         SplayLinks = &Entry->Links;
00486 
00487         /* Loop until we get the first node in the tree */
00488         while (RtlLeftChild(SplayLinks)) SplayLinks = RtlLeftChild(SplayLinks);
00489 
00490         /* Get the entry from it */
00491         Entry = CONTAINING_RECORD(SplayLinks,
00492                                   UNICODE_PREFIX_TABLE_ENTRY,
00493                                   Links);
00494     }
00495     else if (CaseMatchEntry->NodeTypeCode == PFX_NTC_CASE_MATCH)
00496     {
00497         /* If the last entry was a Case Match, then return it */
00498         Entry = CaseMatchEntry;
00499     }
00500     else
00501     {
00502         /* Find the successor */
00503         SplayLinks = RtlRealSuccessor(&CaseMatchEntry->Links);
00504         if (!SplayLinks)
00505         {
00506             /* Didn't find one, we'll have to search the tree */
00507             SplayLinks = &PrefixTable->LastNextEntry->Links;
00508 
00509             /* Get the topmost node (root) */
00510             while (!RtlIsRoot(SplayLinks)) SplayLinks = RtlParent(SplayLinks);
00511             Entry = CONTAINING_RECORD(SplayLinks,
00512                                       UNICODE_PREFIX_TABLE_ENTRY,
00513                                       Links);
00514 
00515             /* Get its tree and make sure somethign is in it */
00516             Entry = Entry->NextPrefixTree;
00517             if (Entry->NameLength <= 0) return NULL;
00518 
00519             /* Select these new links and find the first node */
00520             while (RtlLeftChild(SplayLinks)) SplayLinks = RtlLeftChild(SplayLinks);
00521         }
00522 
00523         /* Get the entry from it */
00524         Entry = CONTAINING_RECORD(SplayLinks,
00525                                   UNICODE_PREFIX_TABLE_ENTRY,
00526                                   Links);
00527     }
00528 
00529     /* Save this entry as the last one returned, and return it */
00530     PrefixTable->LastNextEntry = Entry;
00531     return Entry;
00532 }
00533 
00534 /*
00535  * @implemented
00536  */
00537 VOID
00538 NTAPI
00539 RtlRemoveUnicodePrefix(PUNICODE_PREFIX_TABLE PrefixTable,
00540                        PUNICODE_PREFIX_TABLE_ENTRY PrefixTableEntry)
00541 {
00542     PUNICODE_PREFIX_TABLE_ENTRY Entry, RefEntry, NewEntry;
00543     PRTL_SPLAY_LINKS SplayLinks;
00544 
00545     DPRINT("RtlRemoveUnicodePrefix(): Table %p, TableEntry %p\n",
00546         PrefixTable, PrefixTableEntry);
00547 
00548     /* Erase the last entry */
00549     PrefixTable->LastNextEntry = NULL;
00550 
00551     /* Check if this was a Case Match Entry */
00552     if (PrefixTableEntry->NodeTypeCode == PFX_NTC_CASE_MATCH)
00553     {
00554         /* Get the case match entry */
00555         Entry = PrefixTableEntry->CaseMatch;
00556 
00557         /* Now loop until we find one referencing what the caller sent */
00558         while (Entry->CaseMatch != PrefixTableEntry) Entry = Entry->CaseMatch;
00559 
00560         /* We found the entry that was sent, link them to delete this entry */
00561         Entry->CaseMatch = PrefixTableEntry->CaseMatch;
00562     }
00563     else if ((PrefixTableEntry->NodeTypeCode == PFX_NTC_ROOT) ||
00564             (PrefixTableEntry->NodeTypeCode == PFX_NTC_CHILD))
00565     {
00566         /* Check if this entry is a case match */
00567         if (PrefixTableEntry->CaseMatch != PrefixTableEntry)
00568         {
00569             /* Get the case match entry */
00570             Entry = PrefixTableEntry->CaseMatch;
00571 
00572             /* Now loop until we find one referencing what the caller sent */
00573             while (Entry->CaseMatch != PrefixTableEntry) Entry = Entry->CaseMatch;
00574 
00575             /* We found the entry that was sent, link them to delete this entry */
00576             Entry->CaseMatch = PrefixTableEntry->CaseMatch;
00577 
00578             /* Copy the data */
00579             Entry->NodeTypeCode = PrefixTableEntry->NodeTypeCode;
00580             Entry->NextPrefixTree = PrefixTableEntry->NextPrefixTree;
00581             Entry->Links = PrefixTableEntry->Links;
00582 
00583             /* Now check if we are a root entry */
00584             if (RtlIsRoot(&PrefixTableEntry->Links))
00585             {
00586                 /* We are, so make this entry root as well */
00587                 Entry->Links.Parent = &Entry->Links;
00588 
00589                 /* Find the entry referencing us */
00590                 RefEntry = Entry->NextPrefixTree;
00591                 while (RefEntry->NextPrefixTree != Entry)
00592                 {
00593                     /* Not this one, move to the next entry */
00594                     RefEntry = RefEntry->NextPrefixTree;
00595                 }
00596 
00597                 /* Link them to us now */
00598                 RefEntry->NextPrefixTree = Entry;
00599             }
00600             else if (RtlIsLeftChild(&PrefixTableEntry->Links))
00601             {
00602                 /* We were the left child, so make us as well */
00603                 RtlParent(&PrefixTableEntry->Links)->LeftChild = &Entry->Links;
00604             }
00605             else
00606             {
00607                 /* We were the right child, so make us as well */
00608                 RtlParent(&PrefixTableEntry->Links)->RightChild = &Entry->Links;
00609             }
00610 
00611             /* Check if we have a left child */
00612             if (RtlLeftChild(&Entry->Links))
00613             {
00614                 /* Update its parent link */
00615                 RtlLeftChild(&Entry->Links)->Parent = &Entry->Links;
00616             }
00617             /* Check if we have a right child */
00618             if (RtlRightChild(&Entry->Links))
00619             {
00620                 /* Update its parent link */
00621                 RtlRightChild(&Entry->Links)->Parent = &Entry->Links;
00622             }
00623         }
00624         else
00625         {
00626             /* It's not a case match, so we'll delete the actual entry */
00627             SplayLinks = &PrefixTableEntry->Links;
00628 
00629             /* Find the root entry */
00630             while (!RtlIsRoot(SplayLinks)) SplayLinks = RtlParent(SplayLinks);
00631             Entry = CONTAINING_RECORD(SplayLinks,
00632                                       UNICODE_PREFIX_TABLE_ENTRY,
00633                                       Links);
00634 
00635             /* Delete the entry and check if the whole tree is gone */
00636             SplayLinks = RtlDelete(&PrefixTableEntry->Links);
00637             if (!SplayLinks)
00638             {
00639                 /* The tree is also gone now, find the entry referencing us */
00640                 RefEntry = Entry->NextPrefixTree;
00641                 while (RefEntry->NextPrefixTree != Entry)
00642                 {
00643                     /* Not this one, move to the next entry */
00644                     RefEntry = RefEntry->NextPrefixTree;
00645                 }
00646 
00647                 /* Link them so this entry stops being referenced */
00648                 RefEntry->NextPrefixTree = Entry->NextPrefixTree;
00649             }
00650             else if (&Entry->Links != SplayLinks)
00651             {
00652                 /* The tree is still here, but we got moved to a new one */
00653                 NewEntry = CONTAINING_RECORD(SplayLinks,
00654                                              UNICODE_PREFIX_TABLE_ENTRY,
00655                                              Links);
00656 
00657                 /* Find the entry referencing us */
00658                 RefEntry = Entry->NextPrefixTree;
00659                 while (RefEntry->NextPrefixTree != Entry)
00660                 {
00661                     /* Not this one, move to the next entry */
00662                     RefEntry = RefEntry->NextPrefixTree;
00663                 }
00664 
00665                 /* Since we got moved, make us the new root entry */
00666                 NewEntry->NodeTypeCode = PFX_NTC_ROOT;
00667 
00668                 /* Link us with the entry referencing the old root */
00669                 RefEntry->NextPrefixTree = NewEntry;
00670 
00671                 /* And link us with the old tree */
00672                 NewEntry->NextPrefixTree = Entry->NextPrefixTree;
00673 
00674                 /* Set the old tree as a child */
00675                 Entry->NodeTypeCode = PFX_NTC_CHILD;
00676                 Entry->NextPrefixTree = NULL;
00677             }
00678         }
00679     }
00680 }
00681 
00682 /* EOF */

Generated on Sat May 26 2012 04:35:24 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.