Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenunicodeprefix.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
1.7.6.1
|