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 NtfsFCBIsEncrypted(PNTFS_FCB Fcb) 148 { 149 return ((Fcb->Entry.FileAttributes & NTFS_FILE_TYPE_ENCRYPTED) == NTFS_FILE_TYPE_ENCRYPTED); 150 } 151 152 BOOLEAN 153 NtfsFCBIsRoot(PNTFS_FCB Fcb) 154 { 155 return (wcscmp(Fcb->PathName, L"\\") == 0); 156 } 157 158 159 VOID 160 NtfsGrabFCB(PNTFS_VCB Vcb, 161 PNTFS_FCB Fcb) 162 { 163 KIRQL oldIrql; 164 165 DPRINT("grabbing FCB at %p: %S, refCount:%d\n", 166 Fcb, 167 Fcb->PathName, 168 Fcb->RefCount); 169 170 KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql); 171 Fcb->RefCount++; 172 KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); 173 } 174 175 176 VOID 177 NtfsReleaseFCB(PNTFS_VCB Vcb, 178 PNTFS_FCB Fcb) 179 { 180 KIRQL oldIrql; 181 182 DPRINT("releasing FCB at %p: %S, refCount:%d\n", 183 Fcb, 184 Fcb->PathName, 185 Fcb->RefCount); 186 187 KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql); 188 Fcb->RefCount--; 189 if (Fcb->RefCount <= 0 && !NtfsFCBIsDirectory(Fcb)) 190 { 191 RemoveEntryList(&Fcb->FcbListEntry); 192 KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); 193 CcUninitializeCacheMap(Fcb->FileObject, NULL, NULL); 194 NtfsDestroyFCB(Fcb); 195 } 196 else 197 { 198 KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); 199 } 200 } 201 202 203 VOID 204 NtfsAddFCBToTable(PNTFS_VCB Vcb, 205 PNTFS_FCB Fcb) 206 { 207 KIRQL oldIrql; 208 209 KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql); 210 Fcb->Vcb = Vcb; 211 InsertTailList(&Vcb->FcbListHead, &Fcb->FcbListEntry); 212 KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); 213 } 214 215 216 PNTFS_FCB 217 NtfsGrabFCBFromTable(PNTFS_VCB Vcb, 218 PCWSTR FileName) 219 { 220 KIRQL oldIrql; 221 PNTFS_FCB Fcb; 222 PLIST_ENTRY current_entry; 223 224 KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql); 225 226 if (FileName == NULL || *FileName == 0) 227 { 228 DPRINT("Return FCB for stream file object\n"); 229 Fcb = Vcb->StreamFileObject->FsContext; 230 Fcb->RefCount++; 231 KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); 232 return Fcb; 233 } 234 235 current_entry = Vcb->FcbListHead.Flink; 236 while (current_entry != &Vcb->FcbListHead) 237 { 238 Fcb = CONTAINING_RECORD(current_entry, NTFS_FCB, FcbListEntry); 239 240 DPRINT("Comparing '%S' and '%S'\n", FileName, Fcb->PathName); 241 if (_wcsicmp(FileName, Fcb->PathName) == 0) 242 { 243 Fcb->RefCount++; 244 KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); 245 return Fcb; 246 } 247 248 //FIXME: need to compare against short name in FCB here 249 250 current_entry = current_entry->Flink; 251 } 252 253 KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); 254 255 return NULL; 256 } 257 258 259 NTSTATUS 260 NtfsFCBInitializeCache(PNTFS_VCB Vcb, 261 PNTFS_FCB Fcb) 262 { 263 PFILE_OBJECT FileObject; 264 NTSTATUS Status; 265 PNTFS_CCB newCCB; 266 267 FileObject = IoCreateStreamFileObject(NULL, Vcb->StorageDevice); 268 269 newCCB = ExAllocatePoolWithTag(NonPagedPool, sizeof(NTFS_CCB), TAG_CCB); 270 if (newCCB == NULL) 271 { 272 return STATUS_INSUFFICIENT_RESOURCES; 273 } 274 275 RtlZeroMemory(newCCB, sizeof(NTFS_CCB)); 276 277 newCCB->Identifier.Type = NTFS_TYPE_CCB; 278 newCCB->Identifier.Size = sizeof(NTFS_TYPE_CCB); 279 280 FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers; 281 FileObject->FsContext = Fcb; 282 FileObject->FsContext2 = newCCB; 283 newCCB->PtrFileObject = FileObject; 284 Fcb->FileObject = FileObject; 285 Fcb->Vcb = Vcb; 286 287 Status = STATUS_SUCCESS; 288 _SEH2_TRY 289 { 290 CcInitializeCacheMap(FileObject, 291 (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize), 292 FALSE, 293 &(NtfsGlobalData->CacheMgrCallbacks), 294 Fcb); 295 } 296 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 297 { 298 FileObject->FsContext2 = NULL; 299 ExFreePoolWithTag(newCCB, TAG_CCB); 300 ObDereferenceObject(FileObject); 301 Fcb->FileObject = NULL; 302 return _SEH2_GetExceptionCode(); 303 } 304 _SEH2_END; 305 306 ObDereferenceObject(FileObject); 307 Fcb->Flags |= FCB_CACHE_INITIALIZED; 308 309 return Status; 310 } 311 312 313 PNTFS_FCB 314 NtfsMakeRootFCB(PNTFS_VCB Vcb) 315 { 316 PNTFS_FCB Fcb; 317 PFILE_RECORD_HEADER MftRecord; 318 PFILENAME_ATTRIBUTE FileName; 319 320 MftRecord = ExAllocateFromNPagedLookasideList(&Vcb->FileRecLookasideList); 321 if (MftRecord == NULL) 322 { 323 return NULL; 324 } 325 326 if (!NT_SUCCESS(ReadFileRecord(Vcb, NTFS_FILE_ROOT, MftRecord))) 327 { 328 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord); 329 return NULL; 330 } 331 332 FileName = GetFileNameFromRecord(Vcb, MftRecord, NTFS_FILE_NAME_WIN32); 333 if (!FileName) 334 { 335 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord); 336 return NULL; 337 } 338 339 Fcb = NtfsCreateFCB(L"\\", NULL, Vcb); 340 if (!Fcb) 341 { 342 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord); 343 return NULL; 344 } 345 346 memcpy(&Fcb->Entry, FileName, FIELD_OFFSET(FILENAME_ATTRIBUTE, NameLength)); 347 Fcb->Entry.NameType = FileName->NameType; 348 Fcb->Entry.NameLength = 0; 349 Fcb->Entry.Name[0] = UNICODE_NULL; 350 Fcb->RefCount = 1; 351 Fcb->DirIndex = 0; 352 Fcb->RFCB.FileSize.QuadPart = FileName->DataSize; 353 Fcb->RFCB.ValidDataLength.QuadPart = FileName->DataSize; 354 Fcb->RFCB.AllocationSize.QuadPart = FileName->AllocatedSize; 355 Fcb->MFTIndex = NTFS_FILE_ROOT; 356 Fcb->LinkCount = MftRecord->LinkCount; 357 358 NtfsFCBInitializeCache(Vcb, Fcb); 359 NtfsAddFCBToTable(Vcb, Fcb); 360 NtfsGrabFCB(Vcb, Fcb); 361 362 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord); 363 364 return Fcb; 365 } 366 367 368 PNTFS_FCB 369 NtfsOpenRootFCB(PNTFS_VCB Vcb) 370 { 371 PNTFS_FCB Fcb; 372 373 Fcb = NtfsGrabFCBFromTable(Vcb, L"\\"); 374 if (Fcb == NULL) 375 { 376 Fcb = NtfsMakeRootFCB(Vcb); 377 } 378 379 return Fcb; 380 } 381 382 383 NTSTATUS 384 NtfsMakeFCBFromDirEntry(PNTFS_VCB Vcb, 385 PNTFS_FCB DirectoryFCB, 386 PUNICODE_STRING Name, 387 PCWSTR Stream, 388 PFILE_RECORD_HEADER Record, 389 ULONGLONG MFTIndex, 390 PNTFS_FCB * fileFCB) 391 { 392 WCHAR pathName[MAX_PATH]; 393 PFILENAME_ATTRIBUTE FileName; 394 PSTANDARD_INFORMATION StdInfo; 395 PNTFS_FCB rcFCB; 396 ULONGLONG Size, AllocatedSize; 397 398 DPRINT("NtfsMakeFCBFromDirEntry(%p, %p, %wZ, %p, %p, %p)\n", Vcb, DirectoryFCB, Name, Stream, Record, fileFCB); 399 400 FileName = GetBestFileNameFromRecord(Vcb, Record); 401 if (!FileName) 402 { 403 return STATUS_OBJECT_NAME_NOT_FOUND; // Not sure that's the best here 404 } 405 406 if (DirectoryFCB && Name) 407 { 408 if (Name->Buffer[0] != 0 && wcslen(DirectoryFCB->PathName) + 409 sizeof(WCHAR) + Name->Length / sizeof(WCHAR) > MAX_PATH) 410 { 411 return STATUS_OBJECT_NAME_INVALID; 412 } 413 414 wcscpy(pathName, DirectoryFCB->PathName); 415 if (!NtfsFCBIsRoot(DirectoryFCB)) 416 { 417 wcscat(pathName, L"\\"); 418 } 419 wcscat(pathName, Name->Buffer); 420 } 421 else 422 { 423 RtlCopyMemory(pathName, FileName->Name, FileName->NameLength * sizeof (WCHAR)); 424 pathName[FileName->NameLength] = UNICODE_NULL; 425 } 426 427 Size = NtfsGetFileSize(Vcb, Record, (Stream ? Stream : L""), (Stream ? wcslen(Stream) : 0), &AllocatedSize); 428 429 rcFCB = NtfsCreateFCB(pathName, Stream, Vcb); 430 if (!rcFCB) 431 { 432 return STATUS_INSUFFICIENT_RESOURCES; 433 } 434 435 memcpy(&rcFCB->Entry, FileName, FIELD_OFFSET(FILENAME_ATTRIBUTE, NameLength)); 436 rcFCB->Entry.NameType = FileName->NameType; 437 rcFCB->RFCB.FileSize.QuadPart = Size; 438 rcFCB->RFCB.ValidDataLength.QuadPart = Size; 439 rcFCB->RFCB.AllocationSize.QuadPart = AllocatedSize; 440 441 StdInfo = GetStandardInformationFromRecord(Vcb, Record); 442 if (StdInfo != NULL) 443 { 444 rcFCB->Entry.FileAttributes |= StdInfo->FileAttribute; 445 } 446 447 NtfsFCBInitializeCache(Vcb, rcFCB); 448 rcFCB->RefCount = 1; 449 rcFCB->MFTIndex = MFTIndex; 450 rcFCB->LinkCount = Record->LinkCount; 451 NtfsAddFCBToTable(Vcb, rcFCB); 452 *fileFCB = rcFCB; 453 454 return STATUS_SUCCESS; 455 } 456 457 458 NTSTATUS 459 NtfsAttachFCBToFileObject(PNTFS_VCB Vcb, 460 PNTFS_FCB Fcb, 461 PFILE_OBJECT FileObject) 462 { 463 PNTFS_CCB newCCB; 464 465 newCCB = ExAllocatePoolWithTag(NonPagedPool, sizeof(NTFS_CCB), TAG_CCB); 466 if (newCCB == NULL) 467 { 468 return STATUS_INSUFFICIENT_RESOURCES; 469 } 470 471 RtlZeroMemory(newCCB, sizeof(NTFS_CCB)); 472 473 newCCB->Identifier.Type = NTFS_TYPE_CCB; 474 newCCB->Identifier.Size = sizeof(NTFS_TYPE_CCB); 475 476 FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers; 477 FileObject->FsContext = Fcb; 478 FileObject->FsContext2 = newCCB; 479 newCCB->PtrFileObject = FileObject; 480 Fcb->Vcb = Vcb; 481 482 if (!(Fcb->Flags & FCB_CACHE_INITIALIZED)) 483 { 484 _SEH2_TRY 485 { 486 CcInitializeCacheMap(FileObject, 487 (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize), 488 FALSE, 489 &(NtfsGlobalData->CacheMgrCallbacks), 490 Fcb); 491 } 492 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 493 { 494 FileObject->FsContext2 = NULL; 495 ExFreePoolWithTag(newCCB, TAG_CCB); 496 return _SEH2_GetExceptionCode(); 497 } 498 _SEH2_END; 499 500 Fcb->Flags |= FCB_CACHE_INITIALIZED; 501 } 502 503 //DPRINT("file open: fcb:%x file size: %d\n", Fcb, Fcb->Entry.DataLengthL); 504 505 return STATUS_SUCCESS; 506 } 507 508 509 static NTSTATUS 510 NtfsDirFindFile(PNTFS_VCB Vcb, 511 PNTFS_FCB DirectoryFcb, 512 PWSTR FileToFind, 513 BOOLEAN CaseSensitive, 514 PNTFS_FCB *FoundFCB) 515 { 516 NTSTATUS Status; 517 ULONGLONG CurrentDir; 518 UNICODE_STRING File; 519 PFILE_RECORD_HEADER FileRecord; 520 ULONGLONG MFTIndex; 521 PWSTR Colon, OldColon; 522 PNTFS_ATTR_CONTEXT DataContext; 523 USHORT Length = 0; 524 525 DPRINT("NtfsDirFindFile(%p, %p, %S, %s, %p)\n", 526 Vcb, 527 DirectoryFcb, 528 FileToFind, 529 CaseSensitive ? "TRUE" : "FALSE", 530 FoundFCB); 531 532 *FoundFCB = NULL; 533 RtlInitUnicodeString(&File, FileToFind); 534 CurrentDir = DirectoryFcb->MFTIndex; 535 536 Colon = wcsrchr(FileToFind, L':'); 537 if (Colon != NULL) 538 { 539 Length = File.Length; 540 File.Length = (Colon - FileToFind) * sizeof(WCHAR); 541 542 if (_wcsicmp(Colon + 1, L"$DATA") == 0) 543 { 544 OldColon = Colon; 545 Colon[0] = UNICODE_NULL; 546 Colon = wcsrchr(FileToFind, L':'); 547 if (Colon != NULL) 548 { 549 Length = File.Length; 550 File.Length = (Colon - FileToFind) * sizeof(WCHAR); 551 } 552 else 553 { 554 Colon = OldColon; 555 Colon[0] = L':'; 556 } 557 } 558 559 /* Skip colon */ 560 ++Colon; 561 DPRINT1("Will now look for file '%wZ' with stream '%S'\n", &File, Colon); 562 } 563 564 Status = NtfsLookupFileAt(Vcb, &File, CaseSensitive, &FileRecord, &MFTIndex, CurrentDir); 565 if (!NT_SUCCESS(Status)) 566 { 567 return Status; 568 } 569 570 if (Length != 0) 571 { 572 File.Length = Length; 573 } 574 575 if ((FileRecord->Flags & FRH_DIRECTORY) && Colon != 0) 576 { 577 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord); 578 return STATUS_INVALID_PARAMETER; 579 } 580 else if (Colon != 0) 581 { 582 Status = FindAttribute(Vcb, FileRecord, AttributeData, Colon, wcslen(Colon), &DataContext, NULL); 583 if (!NT_SUCCESS(Status)) 584 { 585 return STATUS_OBJECT_NAME_NOT_FOUND; 586 } 587 ReleaseAttributeContext(DataContext); 588 } 589 590 Status = NtfsMakeFCBFromDirEntry(Vcb, DirectoryFcb, &File, Colon, FileRecord, MFTIndex, FoundFCB); 591 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord); 592 593 return Status; 594 } 595 596 597 NTSTATUS 598 NtfsGetFCBForFile(PNTFS_VCB Vcb, 599 PNTFS_FCB *pParentFCB, 600 PNTFS_FCB *pFCB, 601 PCWSTR pFileName, 602 BOOLEAN CaseSensitive) 603 { 604 NTSTATUS Status; 605 WCHAR pathName [MAX_PATH]; 606 WCHAR elementName [MAX_PATH]; 607 PCWSTR currentElement; 608 PNTFS_FCB FCB; 609 PNTFS_FCB parentFCB; 610 611 DPRINT("NtfsGetFCBForFile(%p, %p, %p, '%S', %s)\n", 612 Vcb, 613 pParentFCB, 614 pFCB, 615 pFileName, 616 CaseSensitive ? "TRUE" : "FALSE"); 617 618 /* Dummy code */ 619 // FCB = NtfsOpenRootFCB(Vcb); 620 // *pFCB = FCB; 621 // *pParentFCB = NULL; 622 623 #if 1 624 /* Trivial case, open of the root directory on volume */ 625 if (pFileName[0] == L'\0' || wcscmp(pFileName, L"\\") == 0) 626 { 627 DPRINT("returning root FCB\n"); 628 629 FCB = NtfsOpenRootFCB(Vcb); 630 *pFCB = FCB; 631 *pParentFCB = NULL; 632 633 return (FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND; 634 } 635 else 636 { 637 currentElement = pFileName + 1; 638 wcscpy (pathName, L"\\"); 639 FCB = NtfsOpenRootFCB (Vcb); 640 } 641 642 parentFCB = NULL; 643 644 /* Parse filename and check each path element for existence and access */ 645 while (NtfsGetNextPathElement(currentElement) != 0) 646 { 647 /* Skip blank directory levels */ 648 if ((NtfsGetNextPathElement(currentElement) - currentElement) == 0) 649 { 650 currentElement++; 651 continue; 652 } 653 654 DPRINT("Parsing, currentElement:%S\n", currentElement); 655 DPRINT(" parentFCB:%p FCB:%p\n", parentFCB, FCB); 656 657 /* Descend to next directory level */ 658 if (parentFCB) 659 { 660 NtfsReleaseFCB(Vcb, parentFCB); 661 parentFCB = NULL; 662 } 663 664 /* fail if element in FCB is not a directory */ 665 if (!NtfsFCBIsDirectory(FCB)) 666 { 667 DPRINT("Element in requested path is not a directory\n"); 668 669 NtfsReleaseFCB(Vcb, FCB); 670 FCB = 0; 671 *pParentFCB = NULL; 672 *pFCB = NULL; 673 674 return STATUS_OBJECT_PATH_NOT_FOUND; 675 } 676 677 parentFCB = FCB; 678 679 /* Extract next directory level into dirName */ 680 NtfsWSubString(pathName, 681 pFileName, 682 NtfsGetNextPathElement(currentElement) - pFileName); 683 DPRINT(" pathName:%S\n", pathName); 684 685 FCB = NtfsGrabFCBFromTable(Vcb, pathName); 686 if (FCB == NULL) 687 { 688 NtfsWSubString(elementName, 689 currentElement, 690 NtfsGetNextPathElement(currentElement) - currentElement); 691 DPRINT(" elementName:%S\n", elementName); 692 693 Status = NtfsDirFindFile(Vcb, parentFCB, elementName, CaseSensitive, &FCB); 694 if (Status == STATUS_OBJECT_NAME_NOT_FOUND) 695 { 696 *pParentFCB = parentFCB; 697 *pFCB = NULL; 698 currentElement = NtfsGetNextPathElement(currentElement); 699 if (*currentElement == L'\0' || NtfsGetNextPathElement(currentElement + 1) == 0) 700 { 701 return STATUS_OBJECT_NAME_NOT_FOUND; 702 } 703 else 704 { 705 return STATUS_OBJECT_PATH_NOT_FOUND; 706 } 707 } 708 else if (!NT_SUCCESS(Status)) 709 { 710 NtfsReleaseFCB(Vcb, parentFCB); 711 *pParentFCB = NULL; 712 *pFCB = NULL; 713 714 return Status; 715 } 716 } 717 718 currentElement = NtfsGetNextPathElement(currentElement); 719 } 720 721 *pParentFCB = parentFCB; 722 *pFCB = FCB; 723 #endif 724 725 return STATUS_SUCCESS; 726 } 727 728 729 NTSTATUS 730 NtfsReadFCBAttribute(PNTFS_VCB Vcb, 731 PNTFS_FCB pFCB, 732 ULONG Type, 733 PCWSTR Name, 734 ULONG NameLength, 735 PVOID * Data) 736 { 737 NTSTATUS Status; 738 PFILE_RECORD_HEADER FileRecord; 739 PNTFS_ATTR_CONTEXT AttrCtxt; 740 ULONGLONG AttrLength; 741 742 FileRecord = ExAllocateFromNPagedLookasideList(&Vcb->FileRecLookasideList); 743 if (FileRecord == NULL) 744 { 745 return STATUS_INSUFFICIENT_RESOURCES; 746 } 747 748 Status = ReadFileRecord(Vcb, pFCB->MFTIndex, FileRecord); 749 if (!NT_SUCCESS(Status)) 750 { 751 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord); 752 return Status; 753 } 754 755 Status = FindAttribute(Vcb, FileRecord, Type, Name, NameLength, &AttrCtxt, NULL); 756 if (!NT_SUCCESS(Status)) 757 { 758 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord); 759 return Status; 760 } 761 762 AttrLength = AttributeDataLength(AttrCtxt->pRecord); 763 *Data = ExAllocatePoolWithTag(NonPagedPool, AttrLength, TAG_NTFS); 764 if (*Data == NULL) 765 { 766 ReleaseAttributeContext(AttrCtxt); 767 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord); 768 return STATUS_INSUFFICIENT_RESOURCES; 769 } 770 771 ReadAttribute(Vcb, AttrCtxt, 0, *Data, AttrLength); 772 773 ReleaseAttributeContext(AttrCtxt); 774 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord); 775 776 return STATUS_SUCCESS; 777 } 778 779 /* EOF */ 780