1 /* 2 * ReactOS kernel 3 * Copyright (C) 2002, 2014 ReactOS Team 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. 18 * 19 * COPYRIGHT: See COPYING in the top level directory 20 * PROJECT: ReactOS kernel 21 * FILE: drivers/filesystem/ntfs/fcb.c 22 * PURPOSE: NTFS filesystem driver 23 * PROGRAMMERS: Eric Kohl 24 * Pierre Schweitzer (pierre@reactos.org) 25 * Hervé Poussineau (hpoussin@reactos.org) 26 */ 27 28 /* INCLUDES *****************************************************************/ 29 30 #include "ntfs.h" 31 32 #define NDEBUG 33 #include <debug.h> 34 35 /* FUNCTIONS ****************************************************************/ 36 37 static 38 PCWSTR 39 NtfsGetNextPathElement(PCWSTR FileName) 40 { 41 if (*FileName == L'\0') 42 { 43 return NULL; 44 } 45 46 while (*FileName != L'\0' && *FileName != L'\\') 47 { 48 FileName++; 49 } 50 51 return FileName; 52 } 53 54 55 static 56 VOID 57 NtfsWSubString(PWCHAR pTarget, 58 PCWSTR pSource, 59 size_t pLength) 60 { 61 wcsncpy(pTarget, pSource, pLength); 62 pTarget[pLength] = L'\0'; 63 } 64 65 66 PNTFS_FCB 67 NtfsCreateFCB(PCWSTR FileName, 68 PCWSTR Stream, 69 PNTFS_VCB Vcb) 70 { 71 PNTFS_FCB Fcb; 72 73 ASSERT(Vcb); 74 ASSERT(Vcb->Identifier.Type == NTFS_TYPE_VCB); 75 76 Fcb = ExAllocateFromNPagedLookasideList(&NtfsGlobalData->FcbLookasideList); 77 RtlZeroMemory(Fcb, sizeof(NTFS_FCB)); 78 79 Fcb->Identifier.Type = NTFS_TYPE_FCB; 80 Fcb->Identifier.Size = sizeof(NTFS_TYPE_FCB); 81 82 Fcb->Vcb = Vcb; 83 84 if (FileName) 85 { 86 wcscpy(Fcb->PathName, FileName); 87 if (wcsrchr(Fcb->PathName, '\\') != 0) 88 { 89 Fcb->ObjectName = wcsrchr(Fcb->PathName, '\\'); 90 } 91 else 92 { 93 Fcb->ObjectName = Fcb->PathName; 94 } 95 } 96 97 if (Stream) 98 { 99 wcscpy(Fcb->Stream, Stream); 100 } 101 else 102 { 103 Fcb->Stream[0] = UNICODE_NULL; 104 } 105 106 ExInitializeResourceLite(&Fcb->MainResource); 107 108 Fcb->RFCB.Resource = &(Fcb->MainResource); 109 110 return Fcb; 111 } 112 113 114 VOID 115 NtfsDestroyFCB(PNTFS_FCB Fcb) 116 { 117 ASSERT(Fcb); 118 ASSERT(Fcb->Identifier.Type == NTFS_TYPE_FCB); 119 120 ExDeleteResourceLite(&Fcb->MainResource); 121 122 ExFreeToNPagedLookasideList(&NtfsGlobalData->FcbLookasideList, Fcb); 123 } 124 125 126 BOOLEAN 127 NtfsFCBIsDirectory(PNTFS_FCB Fcb) 128 { 129 return ((Fcb->Entry.FileAttributes & NTFS_FILE_TYPE_DIRECTORY) == NTFS_FILE_TYPE_DIRECTORY); 130 } 131 132 133 BOOLEAN 134 NtfsFCBIsReparsePoint(PNTFS_FCB Fcb) 135 { 136 return ((Fcb->Entry.FileAttributes & NTFS_FILE_TYPE_REPARSE) == NTFS_FILE_TYPE_REPARSE); 137 } 138 139 140 BOOLEAN 141 NtfsFCBIsCompressed(PNTFS_FCB Fcb) 142 { 143 return ((Fcb->Entry.FileAttributes & NTFS_FILE_TYPE_COMPRESSED) == NTFS_FILE_TYPE_COMPRESSED); 144 } 145 146 BOOLEAN 147 NtfsFCBIsRoot(PNTFS_FCB Fcb) 148 { 149 return (wcscmp(Fcb->PathName, L"\\") == 0); 150 } 151 152 153 VOID 154 NtfsGrabFCB(PNTFS_VCB Vcb, 155 PNTFS_FCB Fcb) 156 { 157 KIRQL oldIrql; 158 159 DPRINT("grabbing FCB at %p: %S, refCount:%d\n", 160 Fcb, 161 Fcb->PathName, 162 Fcb->RefCount); 163 164 KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql); 165 Fcb->RefCount++; 166 KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); 167 } 168 169 170 VOID 171 NtfsReleaseFCB(PNTFS_VCB Vcb, 172 PNTFS_FCB Fcb) 173 { 174 KIRQL oldIrql; 175 176 DPRINT("releasing FCB at %p: %S, refCount:%d\n", 177 Fcb, 178 Fcb->PathName, 179 Fcb->RefCount); 180 181 KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql); 182 Fcb->RefCount--; 183 if (Fcb->RefCount <= 0 && !NtfsFCBIsDirectory(Fcb)) 184 { 185 RemoveEntryList(&Fcb->FcbListEntry); 186 KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); 187 CcUninitializeCacheMap(Fcb->FileObject, NULL, NULL); 188 NtfsDestroyFCB(Fcb); 189 } 190 else 191 { 192 KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); 193 } 194 } 195 196 197 VOID 198 NtfsAddFCBToTable(PNTFS_VCB Vcb, 199 PNTFS_FCB Fcb) 200 { 201 KIRQL oldIrql; 202 203 KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql); 204 Fcb->Vcb = Vcb; 205 InsertTailList(&Vcb->FcbListHead, &Fcb->FcbListEntry); 206 KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); 207 } 208 209 210 PNTFS_FCB 211 NtfsGrabFCBFromTable(PNTFS_VCB Vcb, 212 PCWSTR FileName) 213 { 214 KIRQL oldIrql; 215 PNTFS_FCB Fcb; 216 PLIST_ENTRY current_entry; 217 218 KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql); 219 220 if (FileName == NULL || *FileName == 0) 221 { 222 DPRINT("Return FCB for stream file object\n"); 223 Fcb = Vcb->StreamFileObject->FsContext; 224 Fcb->RefCount++; 225 KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); 226 return Fcb; 227 } 228 229 current_entry = Vcb->FcbListHead.Flink; 230 while (current_entry != &Vcb->FcbListHead) 231 { 232 Fcb = CONTAINING_RECORD(current_entry, NTFS_FCB, FcbListEntry); 233 234 DPRINT("Comparing '%S' and '%S'\n", FileName, Fcb->PathName); 235 if (_wcsicmp(FileName, Fcb->PathName) == 0) 236 { 237 Fcb->RefCount++; 238 KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); 239 return Fcb; 240 } 241 242 //FIXME: need to compare against short name in FCB here 243 244 current_entry = current_entry->Flink; 245 } 246 247 KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); 248 249 return NULL; 250 } 251 252 253 NTSTATUS 254 NtfsFCBInitializeCache(PNTFS_VCB Vcb, 255 PNTFS_FCB Fcb) 256 { 257 PFILE_OBJECT FileObject; 258 NTSTATUS Status; 259 PNTFS_CCB newCCB; 260 261 FileObject = IoCreateStreamFileObject(NULL, Vcb->StorageDevice); 262 263 newCCB = ExAllocatePoolWithTag(NonPagedPool, sizeof(NTFS_CCB), TAG_CCB); 264 if (newCCB == NULL) 265 { 266 return STATUS_INSUFFICIENT_RESOURCES; 267 } 268 269 RtlZeroMemory(newCCB, sizeof(NTFS_CCB)); 270 271 newCCB->Identifier.Type = NTFS_TYPE_CCB; 272 newCCB->Identifier.Size = sizeof(NTFS_TYPE_CCB); 273 274 FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers; 275 FileObject->FsContext = Fcb; 276 FileObject->FsContext2 = newCCB; 277 newCCB->PtrFileObject = FileObject; 278 Fcb->FileObject = FileObject; 279 Fcb->Vcb = Vcb; 280 281 Status = STATUS_SUCCESS; 282 _SEH2_TRY 283 { 284 CcInitializeCacheMap(FileObject, 285 (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize), 286 FALSE, 287 &(NtfsGlobalData->CacheMgrCallbacks), 288 Fcb); 289 } 290 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 291 { 292 FileObject->FsContext2 = NULL; 293 ExFreePoolWithTag(newCCB, TAG_CCB); 294 ObDereferenceObject(FileObject); 295 Fcb->FileObject = NULL; 296 return _SEH2_GetExceptionCode(); 297 } 298 _SEH2_END; 299 300 ObDereferenceObject(FileObject); 301 Fcb->Flags |= FCB_CACHE_INITIALIZED; 302 303 return Status; 304 } 305 306 307 PNTFS_FCB 308 NtfsMakeRootFCB(PNTFS_VCB Vcb) 309 { 310 PNTFS_FCB Fcb; 311 PFILE_RECORD_HEADER MftRecord; 312 PFILENAME_ATTRIBUTE FileName; 313 314 MftRecord = ExAllocateFromNPagedLookasideList(&Vcb->FileRecLookasideList); 315 if (MftRecord == NULL) 316 { 317 return NULL; 318 } 319 320 if (!NT_SUCCESS(ReadFileRecord(Vcb, NTFS_FILE_ROOT, MftRecord))) 321 { 322 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord); 323 return NULL; 324 } 325 326 FileName = GetFileNameFromRecord(Vcb, MftRecord, NTFS_FILE_NAME_WIN32); 327 if (!FileName) 328 { 329 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord); 330 return NULL; 331 } 332 333 Fcb = NtfsCreateFCB(L"\\", NULL, Vcb); 334 if (!Fcb) 335 { 336 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord); 337 return NULL; 338 } 339 340 memcpy(&Fcb->Entry, FileName, FIELD_OFFSET(FILENAME_ATTRIBUTE, NameLength)); 341 Fcb->Entry.NameType = FileName->NameType; 342 Fcb->Entry.NameLength = 0; 343 Fcb->Entry.Name[0] = UNICODE_NULL; 344 Fcb->RefCount = 1; 345 Fcb->DirIndex = 0; 346 Fcb->RFCB.FileSize.QuadPart = FileName->DataSize; 347 Fcb->RFCB.ValidDataLength.QuadPart = FileName->DataSize; 348 Fcb->RFCB.AllocationSize.QuadPart = FileName->AllocatedSize; 349 Fcb->MFTIndex = NTFS_FILE_ROOT; 350 Fcb->LinkCount = MftRecord->LinkCount; 351 352 NtfsFCBInitializeCache(Vcb, Fcb); 353 NtfsAddFCBToTable(Vcb, Fcb); 354 NtfsGrabFCB(Vcb, Fcb); 355 356 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord); 357 358 return Fcb; 359 } 360 361 362 PNTFS_FCB 363 NtfsOpenRootFCB(PNTFS_VCB Vcb) 364 { 365 PNTFS_FCB Fcb; 366 367 Fcb = NtfsGrabFCBFromTable(Vcb, L"\\"); 368 if (Fcb == NULL) 369 { 370 Fcb = NtfsMakeRootFCB(Vcb); 371 } 372 373 return Fcb; 374 } 375 376 377 NTSTATUS 378 NtfsMakeFCBFromDirEntry(PNTFS_VCB Vcb, 379 PNTFS_FCB DirectoryFCB, 380 PUNICODE_STRING Name, 381 PCWSTR Stream, 382 PFILE_RECORD_HEADER Record, 383 ULONGLONG MFTIndex, 384 PNTFS_FCB * fileFCB) 385 { 386 WCHAR pathName[MAX_PATH]; 387 PFILENAME_ATTRIBUTE FileName; 388 PSTANDARD_INFORMATION StdInfo; 389 PNTFS_FCB rcFCB; 390 ULONGLONG Size, AllocatedSize; 391 392 DPRINT1("NtfsMakeFCBFromDirEntry(%p, %p, %wZ, %p, %p, %p)\n", Vcb, DirectoryFCB, Name, Stream, Record, fileFCB); 393 394 FileName = GetBestFileNameFromRecord(Vcb, Record); 395 if (!FileName) 396 { 397 return STATUS_OBJECT_NAME_NOT_FOUND; // Not sure that's the best here 398 } 399 400 if (DirectoryFCB && Name) 401 { 402 if (Name->Buffer[0] != 0 && wcslen(DirectoryFCB->PathName) + 403 sizeof(WCHAR) + Name->Length / sizeof(WCHAR) > MAX_PATH) 404 { 405 return STATUS_OBJECT_NAME_INVALID; 406 } 407 408 wcscpy(pathName, DirectoryFCB->PathName); 409 if (!NtfsFCBIsRoot(DirectoryFCB)) 410 { 411 wcscat(pathName, L"\\"); 412 } 413 wcscat(pathName, Name->Buffer); 414 } 415 else 416 { 417 RtlCopyMemory(pathName, FileName->Name, FileName->NameLength * sizeof (WCHAR)); 418 pathName[FileName->NameLength] = UNICODE_NULL; 419 } 420 421 Size = NtfsGetFileSize(Vcb, Record, (Stream ? Stream : L""), (Stream ? wcslen(Stream) : 0), &AllocatedSize); 422 423 rcFCB = NtfsCreateFCB(pathName, Stream, Vcb); 424 if (!rcFCB) 425 { 426 return STATUS_INSUFFICIENT_RESOURCES; 427 } 428 429 memcpy(&rcFCB->Entry, FileName, FIELD_OFFSET(FILENAME_ATTRIBUTE, NameLength)); 430 rcFCB->Entry.NameType = FileName->NameType; 431 rcFCB->RFCB.FileSize.QuadPart = Size; 432 rcFCB->RFCB.ValidDataLength.QuadPart = Size; 433 rcFCB->RFCB.AllocationSize.QuadPart = AllocatedSize; 434 435 StdInfo = GetStandardInformationFromRecord(Vcb, Record); 436 if (StdInfo != NULL) 437 { 438 rcFCB->Entry.FileAttributes |= StdInfo->FileAttribute; 439 } 440 441 NtfsFCBInitializeCache(Vcb, rcFCB); 442 rcFCB->RefCount = 1; 443 rcFCB->MFTIndex = MFTIndex; 444 rcFCB->LinkCount = Record->LinkCount; 445 NtfsAddFCBToTable(Vcb, rcFCB); 446 *fileFCB = rcFCB; 447 448 return STATUS_SUCCESS; 449 } 450 451 452 NTSTATUS 453 NtfsAttachFCBToFileObject(PNTFS_VCB Vcb, 454 PNTFS_FCB Fcb, 455 PFILE_OBJECT FileObject) 456 { 457 PNTFS_CCB newCCB; 458 459 newCCB = ExAllocatePoolWithTag(NonPagedPool, sizeof(NTFS_CCB), TAG_CCB); 460 if (newCCB == NULL) 461 { 462 return STATUS_INSUFFICIENT_RESOURCES; 463 } 464 465 RtlZeroMemory(newCCB, sizeof(NTFS_CCB)); 466 467 newCCB->Identifier.Type = NTFS_TYPE_CCB; 468 newCCB->Identifier.Size = sizeof(NTFS_TYPE_CCB); 469 470 FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers; 471 FileObject->FsContext = Fcb; 472 FileObject->FsContext2 = newCCB; 473 newCCB->PtrFileObject = FileObject; 474 Fcb->Vcb = Vcb; 475 476 if (!(Fcb->Flags & FCB_CACHE_INITIALIZED)) 477 { 478 _SEH2_TRY 479 { 480 CcInitializeCacheMap(FileObject, 481 (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize), 482 FALSE, 483 &(NtfsGlobalData->CacheMgrCallbacks), 484 Fcb); 485 } 486 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 487 { 488 FileObject->FsContext2 = NULL; 489 ExFreePoolWithTag(newCCB, TAG_CCB); 490 return _SEH2_GetExceptionCode(); 491 } 492 _SEH2_END; 493 494 Fcb->Flags |= FCB_CACHE_INITIALIZED; 495 } 496 497 //DPRINT("file open: fcb:%x file size: %d\n", Fcb, Fcb->Entry.DataLengthL); 498 499 return STATUS_SUCCESS; 500 } 501 502 503 static NTSTATUS 504 NtfsDirFindFile(PNTFS_VCB Vcb, 505 PNTFS_FCB DirectoryFcb, 506 PWSTR FileToFind, 507 BOOLEAN CaseSensitive, 508 PNTFS_FCB *FoundFCB) 509 { 510 NTSTATUS Status; 511 ULONGLONG CurrentDir; 512 UNICODE_STRING File; 513 PFILE_RECORD_HEADER FileRecord; 514 ULONGLONG MFTIndex; 515 PWSTR Colon, OldColon; 516 PNTFS_ATTR_CONTEXT DataContext; 517 USHORT Length = 0; 518 519 DPRINT1("NtfsDirFindFile(%p, %p, %S, %s, %p)\n", 520 Vcb, 521 DirectoryFcb, 522 FileToFind, 523 CaseSensitive ? "TRUE" : "FALSE", 524 FoundFCB); 525 526 *FoundFCB = NULL; 527 RtlInitUnicodeString(&File, FileToFind); 528 CurrentDir = DirectoryFcb->MFTIndex; 529 530 Colon = wcsrchr(FileToFind, L':'); 531 if (Colon != NULL) 532 { 533 Length = File.Length; 534 File.Length = (Colon - FileToFind) * sizeof(WCHAR); 535 536 if (_wcsicmp(Colon + 1, L"$DATA") == 0) 537 { 538 OldColon = Colon; 539 Colon[0] = UNICODE_NULL; 540 Colon = wcsrchr(FileToFind, L':'); 541 if (Colon != NULL) 542 { 543 Length = File.Length; 544 File.Length = (Colon - FileToFind) * sizeof(WCHAR); 545 } 546 else 547 { 548 Colon = OldColon; 549 Colon[0] = L':'; 550 } 551 } 552 553 /* Skip colon */ 554 ++Colon; 555 DPRINT1("Will now look for file '%wZ' with stream '%S'\n", &File, Colon); 556 } 557 558 Status = NtfsLookupFileAt(Vcb, &File, CaseSensitive, &FileRecord, &MFTIndex, CurrentDir); 559 if (!NT_SUCCESS(Status)) 560 { 561 return Status; 562 } 563 564 if (Length != 0) 565 { 566 File.Length = Length; 567 } 568 569 if ((FileRecord->Flags & FRH_DIRECTORY) && Colon != 0) 570 { 571 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord); 572 return STATUS_INVALID_PARAMETER; 573 } 574 else if (Colon != 0) 575 { 576 Status = FindAttribute(Vcb, FileRecord, AttributeData, Colon, wcslen(Colon), &DataContext, NULL); 577 if (!NT_SUCCESS(Status)) 578 { 579 return STATUS_OBJECT_NAME_NOT_FOUND; 580 } 581 ReleaseAttributeContext(DataContext); 582 } 583 584 Status = NtfsMakeFCBFromDirEntry(Vcb, DirectoryFcb, &File, Colon, FileRecord, MFTIndex, FoundFCB); 585 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord); 586 587 return Status; 588 } 589 590 591 NTSTATUS 592 NtfsGetFCBForFile(PNTFS_VCB Vcb, 593 PNTFS_FCB *pParentFCB, 594 PNTFS_FCB *pFCB, 595 PCWSTR pFileName, 596 BOOLEAN CaseSensitive) 597 { 598 NTSTATUS Status; 599 WCHAR pathName [MAX_PATH]; 600 WCHAR elementName [MAX_PATH]; 601 PCWSTR currentElement; 602 PNTFS_FCB FCB; 603 PNTFS_FCB parentFCB; 604 605 DPRINT("NtfsGetFCBForFile(%p, %p, %p, '%S', %s)\n", 606 Vcb, 607 pParentFCB, 608 pFCB, 609 pFileName, 610 CaseSensitive ? "TRUE" : "FALSE"); 611 612 /* Dummy code */ 613 // FCB = NtfsOpenRootFCB(Vcb); 614 // *pFCB = FCB; 615 // *pParentFCB = NULL; 616 617 #if 1 618 /* Trivial case, open of the root directory on volume */ 619 if (pFileName[0] == L'\0' || wcscmp(pFileName, L"\\") == 0) 620 { 621 DPRINT("returning root FCB\n"); 622 623 FCB = NtfsOpenRootFCB(Vcb); 624 *pFCB = FCB; 625 *pParentFCB = NULL; 626 627 return (FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND; 628 } 629 else 630 { 631 currentElement = pFileName + 1; 632 wcscpy (pathName, L"\\"); 633 FCB = NtfsOpenRootFCB (Vcb); 634 } 635 636 parentFCB = NULL; 637 638 /* Parse filename and check each path element for existence and access */ 639 while (NtfsGetNextPathElement(currentElement) != 0) 640 { 641 /* Skip blank directory levels */ 642 if ((NtfsGetNextPathElement(currentElement) - currentElement) == 0) 643 { 644 currentElement++; 645 continue; 646 } 647 648 DPRINT("Parsing, currentElement:%S\n", currentElement); 649 DPRINT(" parentFCB:%p FCB:%p\n", parentFCB, FCB); 650 651 /* Descend to next directory level */ 652 if (parentFCB) 653 { 654 NtfsReleaseFCB(Vcb, parentFCB); 655 parentFCB = NULL; 656 } 657 658 /* fail if element in FCB is not a directory */ 659 if (!NtfsFCBIsDirectory(FCB)) 660 { 661 DPRINT("Element in requested path is not a directory\n"); 662 663 NtfsReleaseFCB(Vcb, FCB); 664 FCB = 0; 665 *pParentFCB = NULL; 666 *pFCB = NULL; 667 668 return STATUS_OBJECT_PATH_NOT_FOUND; 669 } 670 671 parentFCB = FCB; 672 673 /* Extract next directory level into dirName */ 674 NtfsWSubString(pathName, 675 pFileName, 676 NtfsGetNextPathElement(currentElement) - pFileName); 677 DPRINT(" pathName:%S\n", pathName); 678 679 FCB = NtfsGrabFCBFromTable(Vcb, pathName); 680 if (FCB == NULL) 681 { 682 NtfsWSubString(elementName, 683 currentElement, 684 NtfsGetNextPathElement(currentElement) - currentElement); 685 DPRINT(" elementName:%S\n", elementName); 686 687 Status = NtfsDirFindFile(Vcb, parentFCB, elementName, CaseSensitive, &FCB); 688 if (Status == STATUS_OBJECT_NAME_NOT_FOUND) 689 { 690 *pParentFCB = parentFCB; 691 *pFCB = NULL; 692 currentElement = NtfsGetNextPathElement(currentElement); 693 if (*currentElement == L'\0' || NtfsGetNextPathElement(currentElement + 1) == 0) 694 { 695 return STATUS_OBJECT_NAME_NOT_FOUND; 696 } 697 else 698 { 699 return STATUS_OBJECT_PATH_NOT_FOUND; 700 } 701 } 702 else if (!NT_SUCCESS(Status)) 703 { 704 NtfsReleaseFCB(Vcb, parentFCB); 705 *pParentFCB = NULL; 706 *pFCB = NULL; 707 708 return Status; 709 } 710 } 711 712 currentElement = NtfsGetNextPathElement(currentElement); 713 } 714 715 *pParentFCB = parentFCB; 716 *pFCB = FCB; 717 #endif 718 719 return STATUS_SUCCESS; 720 } 721 722 723 NTSTATUS 724 NtfsReadFCBAttribute(PNTFS_VCB Vcb, 725 PNTFS_FCB pFCB, 726 ULONG Type, 727 PCWSTR Name, 728 ULONG NameLength, 729 PVOID * Data) 730 { 731 NTSTATUS Status; 732 PFILE_RECORD_HEADER FileRecord; 733 PNTFS_ATTR_CONTEXT AttrCtxt; 734 ULONGLONG AttrLength; 735 736 FileRecord = ExAllocateFromNPagedLookasideList(&Vcb->FileRecLookasideList); 737 if (FileRecord == NULL) 738 { 739 return STATUS_INSUFFICIENT_RESOURCES; 740 } 741 742 Status = ReadFileRecord(Vcb, pFCB->MFTIndex, FileRecord); 743 if (!NT_SUCCESS(Status)) 744 { 745 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord); 746 return Status; 747 } 748 749 Status = FindAttribute(Vcb, FileRecord, Type, Name, NameLength, &AttrCtxt, NULL); 750 if (!NT_SUCCESS(Status)) 751 { 752 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord); 753 return Status; 754 } 755 756 AttrLength = AttributeDataLength(AttrCtxt->pRecord); 757 *Data = ExAllocatePoolWithTag(NonPagedPool, AttrLength, TAG_NTFS); 758 if (*Data == NULL) 759 { 760 ReleaseAttributeContext(AttrCtxt); 761 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord); 762 return STATUS_INSUFFICIENT_RESOURCES; 763 } 764 765 ReadAttribute(Vcb, AttrCtxt, 0, *Data, AttrLength); 766 767 ReleaseAttributeContext(AttrCtxt); 768 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord); 769 770 return STATUS_SUCCESS; 771 } 772 773 /* EOF */ 774