b9fe0d88771b7fb9cc5f45b5497cd6fd7c0ff4aa
[reactos.git] / reactos / drivers / filesystems / fastfat_new / fcb.c
1 /*
2 * PROJECT: ReactOS FAT file system driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/filesystems/fastfat/fcb.c
5 * PURPOSE: FCB manipulation routines.
6 * PROGRAMMERS: Aleksey Bragin <aleksey@reactos.org>
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #define NDEBUG
12 #include "fastfat.h"
13
14 #define TAG_FILENAME 'fBnF'
15
16 /* FUNCTIONS ****************************************************************/
17
18 FSRTL_COMPARISON_RESULT
19 NTAPI
20 FatiCompareNames(PSTRING NameA,
21 PSTRING NameB)
22 {
23 ULONG MinimumLen, i;
24
25 /* Calc the minimum length */
26 MinimumLen = NameA->Length < NameB->Length ? NameA->Length :
27 NameB->Length;
28
29 /* Actually compare them */
30 i = (ULONG)RtlCompareMemory( NameA->Buffer, NameB->Buffer, MinimumLen );
31
32 if (i < MinimumLen)
33 {
34 /* Compare prefixes */
35 if (NameA->Buffer[i] < NameB->Buffer[i])
36 return LessThan;
37 else
38 return GreaterThan;
39 }
40
41 /* Final comparison */
42 if (NameA->Length < NameB->Length)
43 return LessThan;
44 else if (NameA->Length > NameB->Length)
45 return GreaterThan;
46 else
47 return EqualTo;
48 }
49
50 PFCB
51 NTAPI
52 FatFindFcb(PFAT_IRP_CONTEXT IrpContext,
53 PRTL_SPLAY_LINKS *RootNode,
54 PSTRING AnsiName,
55 PBOOLEAN IsDosName)
56 {
57 PFCB_NAME_LINK Node;
58 FSRTL_COMPARISON_RESULT Comparison;
59 PRTL_SPLAY_LINKS Links;
60
61 Links = *RootNode;
62
63 while (Links)
64 {
65 Node = CONTAINING_RECORD(Links, FCB_NAME_LINK, Links);
66
67 /* Compare the prefix */
68 if (*(PUCHAR)Node->Name.Ansi.Buffer != *(PUCHAR)AnsiName->Buffer)
69 {
70 if (*(PUCHAR)Node->Name.Ansi.Buffer < *(PUCHAR)AnsiName->Buffer)
71 Comparison = LessThan;
72 else
73 Comparison = GreaterThan;
74 }
75 else
76 {
77 /* Perform real comparison */
78 Comparison = FatiCompareNames(&Node->Name.Ansi, AnsiName);
79 }
80
81 /* Do they match? */
82 if (Comparison == GreaterThan)
83 {
84 /* No, it's greater, go to the left child */
85 Links = RtlLeftChild(Links);
86 }
87 else if (Comparison == LessThan)
88 {
89 /* No, it's lesser, go to the right child */
90 Links = RtlRightChild(Links);
91 }
92 else
93 {
94 /* Exact match, balance the tree */
95 *RootNode = RtlSplay(Links);
96
97 /* Save type of the name, if needed */
98 if (IsDosName)
99 *IsDosName = Node->IsDosName;
100
101 /* Return the found fcb */
102 return Node->Fcb;
103 }
104 }
105
106 /* Nothing found */
107 return NULL;
108 }
109
110 PFCB
111 NTAPI
112 FatCreateFcb(IN PFAT_IRP_CONTEXT IrpContext,
113 IN PVCB Vcb,
114 IN PFCB ParentDcb,
115 IN FF_FILE *FileHandle)
116 {
117 PFCB Fcb;
118
119 /* Allocate it and zero it */
120 Fcb = ExAllocatePoolWithTag(NonPagedPool, sizeof(FCB), TAG_FCB);
121 RtlZeroMemory(Fcb, sizeof(FCB));
122
123 /* Set node types */
124 Fcb->Header.NodeTypeCode = FAT_NTC_FCB;
125 Fcb->Header.NodeByteSize = sizeof(FCB);
126 Fcb->Condition = FcbGood;
127
128 /* Initialize resources */
129 Fcb->Header.Resource = &Fcb->Resource;
130 ExInitializeResourceLite(Fcb->Header.Resource);
131
132 Fcb->Header.PagingIoResource = &Fcb->PagingIoResource;
133 ExInitializeResourceLite(Fcb->Header.PagingIoResource);
134
135 /* Initialize mutexes */
136 Fcb->Header.FastMutex = &Fcb->HeaderMutex;
137 ExInitializeFastMutex(&Fcb->HeaderMutex);
138 FsRtlSetupAdvancedHeader(&Fcb->Header, &Fcb->HeaderMutex);
139
140 /* Insert into parent's DCB list */
141 InsertTailList(&ParentDcb->Dcb.ParentDcbList, &Fcb->ParentDcbLinks);
142
143 /* Set backlinks */
144 Fcb->ParentFcb = ParentDcb;
145 Fcb->Vcb = Vcb;
146
147 /* Set file handle and sizes */
148 Fcb->Header.FileSize.LowPart = FileHandle->Filesize;
149 Fcb->Header.ValidDataLength.LowPart = FileHandle->Filesize;
150 Fcb->FatHandle = FileHandle;
151
152 /* Set names */
153 FatSetFcbNames(IrpContext, Fcb);
154
155 return Fcb;
156 }
157
158 PCCB
159 NTAPI
160 FatCreateCcb()
161 {
162 PCCB Ccb;
163
164 /* Allocate the CCB and zero it */
165 Ccb = ExAllocatePoolWithTag(NonPagedPool, sizeof(CCB), TAG_CCB);
166 RtlZeroMemory(Ccb, sizeof(CCB));
167
168 /* Set mandatory header */
169 Ccb->NodeTypeCode = FAT_NTC_FCB;
170 Ccb->NodeByteSize = sizeof(CCB);
171
172 return Ccb;
173 }
174
175 IO_STATUS_BLOCK
176 NTAPI
177 FatiOpenExistingFcb(IN PFAT_IRP_CONTEXT IrpContext,
178 IN PFILE_OBJECT FileObject,
179 IN PVCB Vcb,
180 IN PFCB Fcb,
181 IN PACCESS_MASK DesiredAccess,
182 IN USHORT ShareAccess,
183 IN ULONG AllocationSize,
184 IN PFILE_FULL_EA_INFORMATION EaBuffer,
185 IN ULONG EaLength,
186 IN UCHAR FileAttributes,
187 IN ULONG CreateDisposition,
188 IN BOOLEAN NoEaKnowledge,
189 IN BOOLEAN DeleteOnClose,
190 IN BOOLEAN OpenedAsDos,
191 OUT PBOOLEAN OplockPostIrp)
192 {
193 IO_STATUS_BLOCK Iosb = {{0}};
194
195 Iosb.Status = STATUS_NOT_IMPLEMENTED;
196 UNIMPLEMENTED;
197
198 return Iosb;
199 }
200
201 VOID
202 NTAPI
203 FatGetFcbUnicodeName(IN PFAT_IRP_CONTEXT IrpContext,
204 IN PFCB Fcb,
205 OUT PUNICODE_STRING LongName)
206 {
207 FF_DIRENT DirEnt;
208 FF_ERROR Err;
209 OEM_STRING ShortName;
210 CHAR ShortNameBuf[13];
211 UCHAR EntryBuffer[32];
212 UCHAR NumLFNs;
213 OEM_STRING LongNameOem;
214 NTSTATUS Status;
215
216 /* We support only files now, not directories */
217 if (Fcb->Header.NodeTypeCode != FAT_NTC_FCB)
218 {
219 UNIMPLEMENTED;
220 ASSERT(FALSE);
221 }
222
223 /* Get the dir entry */
224 Err = FF_GetEntry(Fcb->Vcb->Ioman,
225 Fcb->FatHandle->DirEntry,
226 Fcb->FatHandle->DirCluster,
227 &DirEnt);
228
229 if (Err != FF_ERR_NONE)
230 {
231 DPRINT1("Error %d getting dirent of a file\n", Err);
232 return;
233 }
234
235 /* Read the dirent to fetch the raw short name */
236 FF_FetchEntry(Fcb->Vcb->Ioman,
237 Fcb->FatHandle->DirCluster,
238 Fcb->FatHandle->DirEntry,
239 EntryBuffer);
240 NumLFNs = (UCHAR)(EntryBuffer[0] & ~0x40);
241
242 /* Check if we only have a short name.
243 Convert it to unicode and return if that's the case */
244 if (NumLFNs == 0)
245 {
246 /* Initialize short name string */
247 ShortName.Buffer = ShortNameBuf;
248 ShortName.Length = 0;
249 ShortName.MaximumLength = 12;
250
251 /* Convert raw short name to a proper string */
252 Fati8dot3ToString((PCHAR)EntryBuffer, FALSE, &ShortName);
253
254 /* Convert it to unicode */
255 Status = RtlOemStringToCountedUnicodeString(LongName,
256 &ShortName,
257 FALSE);
258
259 /* Ensure conversion was successful */
260 ASSERT(Status == STATUS_SUCCESS);
261
262 /* Exit */
263 return;
264 }
265
266 /* Convert LFN from OEM to unicode and return */
267 LongNameOem.Buffer = DirEnt.FileName;
268 LongNameOem.MaximumLength = FF_MAX_FILENAME;
269 LongNameOem.Length = strlen(DirEnt.FileName);
270
271 /* Convert it to unicode */
272 Status = RtlOemStringToUnicodeString(LongName, &LongNameOem, FALSE);
273
274 /* Ensure conversion was successful */
275 ASSERT(Status == STATUS_SUCCESS);
276 }
277
278
279 VOID
280 NTAPI
281 FatSetFullNameInFcb(PFCB Fcb,
282 PUNICODE_STRING Name)
283 {
284 PUNICODE_STRING ParentName;
285
286 /* Make sure this FCB's name wasn't already set */
287 ASSERT(Fcb->FullFileName.Buffer == NULL);
288
289 /* First of all, check exact case name */
290 if (Fcb->ExactCaseLongName.Buffer)
291 {
292 ASSERT(Fcb->ExactCaseLongName.Length != 0);
293
294 /* Use exact case name */
295 Name = &Fcb->ExactCaseLongName;
296 }
297
298 /* Treat root dir different */
299 if (FatNodeType(Fcb->ParentFcb) == FAT_NTC_ROOT_DCB)
300 {
301 /* Set lengths */
302 Fcb->FullFileName.MaximumLength = sizeof(WCHAR) + Name->Length;
303 Fcb->FullFileName.Length = Fcb->FullFileName.MaximumLength;
304
305 /* Allocate a buffer */
306 Fcb->FullFileName.Buffer = FsRtlAllocatePoolWithTag(PagedPool,
307 Fcb->FullFileName.Length,
308 TAG_FILENAME);
309
310 /* Prefix with a backslash */
311 Fcb->FullFileName.Buffer[0] = L'\\';
312
313 /* Copy the name here */
314 RtlCopyMemory(&Fcb->FullFileName.Buffer[1],
315 &Name->Buffer[0],
316 Name->Length );
317 }
318 else
319 {
320 ParentName = &Fcb->ParentFcb->FullFileName;
321
322 /* Check if parent's name is set */
323 if (!ParentName->Buffer)
324 return;
325
326 /* Set lengths */
327 Fcb->FullFileName.MaximumLength =
328 ParentName->Length + sizeof(WCHAR) + Name->Length;
329 Fcb->FullFileName.Length = Fcb->FullFileName.MaximumLength;
330
331 /* Allocate a buffer */
332 Fcb->FullFileName.Buffer = FsRtlAllocatePoolWithTag(PagedPool,
333 Fcb->FullFileName.Length,
334 TAG_FILENAME );
335
336 /* Copy parent's name here */
337 RtlCopyMemory(&Fcb->FullFileName.Buffer[0],
338 &ParentName->Buffer[0],
339 ParentName->Length );
340
341 /* Add a backslash */
342 Fcb->FullFileName.Buffer[ParentName->Length / sizeof(WCHAR)] = L'\\';
343
344 /* Copy given name here */
345 RtlCopyMemory(&Fcb->FullFileName.Buffer[(ParentName->Length / sizeof(WCHAR)) + 1],
346 &Name->Buffer[0],
347 Name->Length );
348 }
349 }
350
351 VOID
352 NTAPI
353 FatSetFullFileNameInFcb(IN PFAT_IRP_CONTEXT IrpContext,
354 IN PFCB Fcb)
355 {
356 UNICODE_STRING LongName;
357 PFCB CurFcb = Fcb;
358 PFCB StopFcb;
359 PWCHAR TmpBuffer;
360 ULONG PathLength = 0;
361
362 /* Do nothing if it's already set */
363 if (Fcb->FullFileName.Buffer) return;
364
365 /* Allocate a temporary buffer */
366 LongName.Length = 0;
367 LongName.MaximumLength = FF_MAX_FILENAME * sizeof(WCHAR);
368 LongName.Buffer =
369 FsRtlAllocatePoolWithTag(PagedPool,
370 FF_MAX_FILENAME * sizeof(WCHAR),
371 TAG_FILENAME);
372
373 /* Go through all parents to calculate needed length */
374 while (CurFcb != Fcb->Vcb->RootDcb)
375 {
376 /* Does current FCB have FullFileName set? */
377 if (CurFcb != Fcb &&
378 CurFcb->FullFileName.Buffer)
379 {
380 /* Yes, just use it! */
381 PathLength += CurFcb->FullFileName.Length;
382
383 Fcb->FullFileName.Buffer =
384 FsRtlAllocatePoolWithTag(PagedPool,
385 PathLength,
386 TAG_FILENAME);
387
388 RtlCopyMemory(Fcb->FullFileName.Buffer,
389 CurFcb->FullFileName.Buffer,
390 CurFcb->FullFileName.Length);
391
392 break;
393 }
394
395 /* Sum up length of a current item */
396 PathLength += CurFcb->FileNameLength + sizeof(WCHAR);
397
398 /* Go to the parent */
399 CurFcb = CurFcb->ParentFcb;
400 }
401
402 /* Allocate FullFileName if it wasn't already allocated above */
403 if (!Fcb->FullFileName.Buffer)
404 {
405 Fcb->FullFileName.Buffer =
406 FsRtlAllocatePoolWithTag(PagedPool,
407 PathLength,
408 TAG_FILENAME);
409 }
410
411 StopFcb = CurFcb;
412
413 CurFcb = Fcb;
414 TmpBuffer = Fcb->FullFileName.Buffer + PathLength / sizeof(WCHAR);
415
416 /* Set lengths */
417 Fcb->FullFileName.Length = PathLength;
418 Fcb->FullFileName.MaximumLength = PathLength;
419
420 while (CurFcb != StopFcb)
421 {
422 /* Get its unicode name */
423 FatGetFcbUnicodeName(IrpContext,
424 CurFcb,
425 &LongName);
426
427 /* Copy it */
428 TmpBuffer -= LongName.Length / sizeof(WCHAR);
429 RtlCopyMemory(TmpBuffer, LongName.Buffer, LongName.Length);
430
431 /* Append with a backslash */
432 TmpBuffer -= 1;
433 *TmpBuffer = L'\\';
434
435 /* Go to the parent */
436 CurFcb = CurFcb->ParentFcb;
437 }
438
439 /* Free the temp buffer */
440 ExFreePool(LongName.Buffer);
441 }
442
443
444 VOID
445 NTAPI
446 FatSetFcbNames(IN PFAT_IRP_CONTEXT IrpContext,
447 IN PFCB Fcb)
448 {
449 FF_DIRENT DirEnt;
450 FF_ERROR Err;
451 POEM_STRING ShortName;
452 CHAR ShortNameRaw[13];
453 UCHAR EntryBuffer[32];
454 UCHAR NumLFNs;
455 PUNICODE_STRING UnicodeName;
456 OEM_STRING LongNameOem;
457 NTSTATUS Status;
458
459 /* Get the dir entry */
460 Err = FF_GetEntry(Fcb->Vcb->Ioman,
461 Fcb->FatHandle->DirEntry,
462 Fcb->FatHandle->DirCluster,
463 &DirEnt);
464
465 if (Err != FF_ERR_NONE)
466 {
467 DPRINT1("Error %d getting dirent of a file\n", Err);
468 return;
469 }
470
471 /* Read the dirent to fetch the raw short name */
472 FF_FetchEntry(Fcb->Vcb->Ioman,
473 Fcb->FatHandle->DirCluster,
474 Fcb->FatHandle->DirEntry,
475 EntryBuffer);
476 NumLFNs = (UCHAR)(EntryBuffer[0] & ~0x40);
477 RtlCopyMemory(ShortNameRaw, EntryBuffer, 11);
478
479 /* Initialize short name string */
480 ShortName = &Fcb->ShortName.Name.Ansi;
481 ShortName->Buffer = Fcb->ShortNameBuffer;
482 ShortName->Length = 0;
483 ShortName->MaximumLength = sizeof(Fcb->ShortNameBuffer);
484
485 /* Convert raw short name to a proper string */
486 Fati8dot3ToString(ShortNameRaw, FALSE, ShortName);
487
488 /* Add the short name link */
489 FatInsertName(IrpContext, &Fcb->ParentFcb->Dcb.SplayLinksAnsi, &Fcb->ShortName);
490 Fcb->ShortName.Fcb = Fcb;
491
492 /* Get the long file name (if any) */
493 if (NumLFNs > 0)
494 {
495 /* Prepare the oem string */
496 LongNameOem.Buffer = DirEnt.FileName;
497 LongNameOem.MaximumLength = FF_MAX_FILENAME;
498 LongNameOem.Length = strlen(DirEnt.FileName);
499
500 /* Prepare the unicode string */
501 UnicodeName = &Fcb->LongName.Name.String;
502 UnicodeName->Length = (LongNameOem.Length + 1) * sizeof(WCHAR);
503 UnicodeName->MaximumLength = UnicodeName->Length;
504 UnicodeName->Buffer = FsRtlAllocatePool(PagedPool, UnicodeName->Length);
505
506 /* Convert it to unicode */
507 Status = RtlOemStringToUnicodeString(UnicodeName, &LongNameOem, FALSE);
508 if (!NT_SUCCESS(Status))
509 {
510 ASSERT(FALSE);
511 }
512
513 /* Set its length */
514 Fcb->FileNameLength = UnicodeName->Length;
515
516 /* Save case-preserved copy */
517 Fcb->ExactCaseLongName.Length = UnicodeName->Length;
518 Fcb->ExactCaseLongName.MaximumLength = UnicodeName->Length;
519 Fcb->ExactCaseLongName.Buffer =
520 FsRtlAllocatePoolWithTag(PagedPool, UnicodeName->Length, TAG_FILENAME);
521
522 RtlCopyMemory(Fcb->ExactCaseLongName.Buffer,
523 UnicodeName->Buffer,
524 UnicodeName->Length);
525
526 /* Perform a trick which is done by MS's FASTFAT driver to monocase
527 the filename */
528 RtlDowncaseUnicodeString(UnicodeName, UnicodeName, FALSE);
529 RtlUpcaseUnicodeString(UnicodeName, UnicodeName, FALSE);
530
531 DPRINT("Converted long name: %wZ\n", UnicodeName);
532
533 /* Add the long unicode name link */
534 FatInsertName(IrpContext, &Fcb->ParentFcb->Dcb.SplayLinksUnicode, &Fcb->LongName);
535 Fcb->LongName.Fcb = Fcb;
536
537 /* Indicate that this FCB has a unicode long name */
538 SetFlag(Fcb->State, FCB_STATE_HAS_UNICODE_NAME);
539 }
540 else
541 {
542 /* No LFN, set exact case name to 0 length */
543 Fcb->ExactCaseLongName.Length = 0;
544 Fcb->ExactCaseLongName.MaximumLength = 0;
545
546 /* Set the length based on the short name */
547 Fcb->FileNameLength = RtlOemStringToCountedUnicodeSize(ShortName);
548 }
549
550 /* Mark the fact that names were added to splay trees*/
551 SetFlag(Fcb->State, FCB_STATE_HAS_NAMES);
552 }
553
554 VOID
555 NTAPI
556 Fati8dot3ToString(IN PCHAR FileName,
557 IN BOOLEAN DownCase,
558 OUT POEM_STRING OutString)
559 {
560 ULONG BaseLen, ExtLen;
561 CHAR *cString = OutString->Buffer;
562 ULONG i;
563
564 /* Calc base and ext lens */
565 for (BaseLen = 8; BaseLen > 0; BaseLen--)
566 {
567 if (FileName[BaseLen - 1] != ' ') break;
568 }
569
570 for (ExtLen = 3; ExtLen > 0; ExtLen--)
571 {
572 if (FileName[8 + ExtLen - 1] != ' ') break;
573 }
574
575 /* Process base name */
576 if (BaseLen)
577 {
578 RtlCopyMemory(cString, FileName, BaseLen);
579
580 /* Substitute the e5 thing */
581 if (cString[0] == 0x05) cString[0] = 0xe5;
582
583 /* Downcase if asked to */
584 if (DownCase)
585 {
586 /* Do it manually */
587 for (i = 0; i < BaseLen; i++)
588 {
589 if (cString[i] >= 'A' &&
590 cString[i] <= 'Z')
591 {
592 /* Lowercase it */
593 cString[i] += 'a' - 'A';
594 }
595
596 }
597 }
598 }
599
600 /* Process extension */
601 if (ExtLen)
602 {
603 /* Add the dot */
604 cString[BaseLen] = '.';
605 BaseLen++;
606
607 /* Copy the extension */
608 for (i = 0; i < ExtLen; i++)
609 {
610 cString[BaseLen + i] = FileName[8 + i];
611 }
612
613 /* Lowercase the extension if asked to */
614 if (DownCase)
615 {
616 /* Do it manually */
617 for (i = BaseLen; i < BaseLen + ExtLen; i++)
618 {
619 if (cString[i] >= 'A' &&
620 cString[i] <= 'Z')
621 {
622 /* Lowercase it */
623 cString[i] += 'a' - 'A';
624 }
625 }
626 }
627 }
628
629 /* Set the length */
630 OutString->Length = BaseLen + ExtLen;
631
632 DPRINT("'%s', len %d\n", OutString->Buffer, OutString->Length);
633 }
634
635 VOID
636 NTAPI
637 FatInsertName(IN PFAT_IRP_CONTEXT IrpContext,
638 IN PRTL_SPLAY_LINKS *RootNode,
639 IN PFCB_NAME_LINK Name)
640 {
641 PFCB_NAME_LINK NameLink;
642 FSRTL_COMPARISON_RESULT Comparison;
643
644 /* Initialize the splay links */
645 RtlInitializeSplayLinks(&Name->Links);
646
647 /* Is this the first entry? */
648 if (*RootNode == NULL)
649 {
650 /* Yes, become root and return */
651 *RootNode = &Name->Links;
652 return;
653 }
654
655 /* Get the name link */
656 NameLink = CONTAINING_RECORD(*RootNode, FCB_NAME_LINK, Links);
657 while (TRUE)
658 {
659 /* Compare prefixes */
660 Comparison = FatiCompareNames(&NameLink->Name.Ansi, &Name->Name.Ansi);
661
662 /* Check the bad case first */
663 if (Comparison == EqualTo)
664 {
665 /* Must not happen */
666 ASSERT(FALSE);
667 }
668
669 /* Check comparison result */
670 if (Comparison == GreaterThan)
671 {
672 /* Go to the left child */
673 if (!RtlLeftChild(&NameLink->Links))
674 {
675 /* It's absent, insert here and break */
676 RtlInsertAsLeftChild(&NameLink->Links, &NameLink->Links);
677 break;
678 }
679 else
680 {
681 /* It's present, go inside it */
682 NameLink = CONTAINING_RECORD(RtlLeftChild(&NameLink->Links),
683 FCB_NAME_LINK,
684 Links);
685 }
686 }
687 else
688 {
689 /* Go to the right child */
690 if (!RtlRightChild(&NameLink->Links))
691 {
692 /* It's absent, insert here and break */
693 RtlInsertAsRightChild(&NameLink->Links, &Name->Links);
694 break;
695 }
696 else
697 {
698 /* It's present, go inside it */
699 NameLink = CONTAINING_RECORD(RtlRightChild(&NameLink->Links),
700 FCB_NAME_LINK,
701 Links);
702 }
703 }
704 }
705 }
706
707 VOID
708 NTAPI
709 FatRemoveNames(IN PFAT_IRP_CONTEXT IrpContext,
710 IN PFCB Fcb)
711 {
712 PRTL_SPLAY_LINKS RootNew;
713 PFCB Parent;
714
715 /* Reference the parent for simplicity */
716 Parent = Fcb->ParentFcb;
717
718 /* If this FCB hasn't been added to splay trees - just return */
719 if (!FlagOn( Fcb->State, FCB_STATE_HAS_NAMES ))
720 return;
721
722 /* Delete the short name link */
723 RootNew = RtlDelete(&Fcb->ShortName.Links);
724
725 /* Set the new root */
726 Parent->Dcb.SplayLinksAnsi = RootNew;
727
728 /* Deal with a unicode name if it exists */
729 if (FlagOn( Fcb->State, FCB_STATE_HAS_UNICODE_NAME ))
730 {
731 /* Delete the long unicode name link */
732 RootNew = RtlDelete(&Fcb->LongName.Links);
733
734 /* Set the new root */
735 Parent->Dcb.SplayLinksUnicode = RootNew;
736
737 /* Free the long name string's buffer*/
738 RtlFreeUnicodeString(&Fcb->LongName.Name.String);
739
740 /* Clear the "has unicode name" flag */
741 ClearFlag(Fcb->State, FCB_STATE_HAS_UNICODE_NAME);
742 }
743
744 /* This FCB has no names added to splay trees now */
745 ClearFlag(Fcb->State, FCB_STATE_HAS_NAMES);
746 }
747
748
749 /* EOF */