ReactOS 0.4.17-dev-1190-g4c812f4
create.c File Reference
#include "ntfs.h"
#include <debug.h>
Include dependency graph for create.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

static NTSTATUS NtfsMakeAbsoluteFilename (PFILE_OBJECT pFileObject, PWSTR pRelativeFileName, PWSTR *pAbsoluteFilename)
 
static NTSTATUS NtfsMoonWalkID (PDEVICE_EXTENSION DeviceExt, ULONGLONG Id, PUNICODE_STRING OutPath)
 
static NTSTATUS NtfsOpenFileById (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, ULONGLONG MftId, PNTFS_FCB *FoundFCB)
 
static NTSTATUS NtfsOpenFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, PWSTR FileName, BOOLEAN CaseSensitive, PNTFS_FCB *FoundFCB)
 
NtfsGrantShareAccess

Records a new open of Fcb against its share access, or fails it with a sharing violation.

static NTSTATUS NtfsGrantShareAccess (_In_ PDEVICE_EXTENSION DeviceExt, _In_ PNTFS_FCB Fcb, _In_ PFILE_OBJECT FileObject, _In_ PIO_STACK_LOCATION Stack)
 
NtfsOpenTargetDirectory

Serves SL_OPEN_TARGET_DIRECTORY, the open the I/O manager does ahead of a rename: opens the parent of the named file, reports whether the final component exists, and leaves only that component in the file object's name, where the rename reads it.

Parameters
DeviceExtVolume being opened on.
FileObjectFile object of the create, naming the rename target.
CaseSensitiveTRUE for POSIX semantics.
InformationReceives FILE_EXISTS or FILE_DOES_NOT_EXIST for the final component.
Returns
STATUS_SUCCESS with the directory attached to FileObject, or an error.
static NTSTATUS NtfsOpenTargetDirectory (_In_ PDEVICE_EXTENSION DeviceExt, _In_ PFILE_OBJECT FileObject, _In_ BOOLEAN CaseSensitive, _Out_ PULONG_PTR Information)
 
static NTSTATUS NtfsCreateFile (PDEVICE_OBJECT DeviceObject, PNTFS_IRP_CONTEXT IrpContext)
 
NTSTATUS NtfsCreate (PNTFS_IRP_CONTEXT IrpContext)
 
NtfsCreateDirectory()

@implemented

Creates a file record for a new directory and saves it to the MFT. Adds the filename attribute of the created directory to the parent directory's index.

Parameters
DeviceExtPoints to the target disk's DEVICE_EXTENSION
FileObjectPointer to a FILE_OBJECT describing the directory to be created
CaseSensitiveBoolean indicating if the function should operate in case-sensitive mode. This will be TRUE if an application created the folder with the FILE_FLAG_POSIX_SEMANTICS flag.
CanWaitBoolean indicating if the function is allowed to wait for exclusive access to the master file table. This will only be relevant if the MFT doesn't have any free file records and needs to be enlarged.
Returns
STATUS_SUCCESS on success. STATUS_INSUFFICIENT_RESOURCES if unable to allocate memory for the file record. STATUS_CANT_WAIT if CanWait was FALSE and the function needed to resize the MFT but couldn't get immediate, exclusive access to it.
NTSTATUS NtfsCreateDirectory (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, BOOLEAN CaseSensitive, BOOLEAN CanWait)
 
NtfsCreateEmptyFileRecord

@implemented

Creates a new, empty file record, with no attributes.

Parameters
DeviceExtPointer to the DEVICE_EXTENSION of the target volume the file record will be stored on.
Returns
A pointer to the newly-created FILE_RECORD_HEADER if the function succeeds, NULL otherwise.
PFILE_RECORD_HEADER NtfsCreateEmptyFileRecord (PDEVICE_EXTENSION DeviceExt)
 
NtfsCreateFileRecord()

@implemented

Creates a file record and saves it to the MFT. Adds the filename attribute of the created file to the parent directory's index.

Parameters
DeviceExtPoints to the target disk's DEVICE_EXTENSION
FileObjectPointer to a FILE_OBJECT describing the file to be created
CanWaitBoolean indicating if the function is allowed to wait for exclusive access to the master file table. This will only be relevant if the MFT doesn't have any free file records and needs to be enlarged.
Returns
STATUS_SUCCESS on success. STATUS_INSUFFICIENT_RESOURCES if unable to allocate memory for the file record. STATUS_CANT_WAIT if CanWait was FALSE and the function needed to resize the MFT but couldn't get immediate, exclusive access to it.
NTSTATUS NtfsCreateFileRecord (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, BOOLEAN CaseSensitive, BOOLEAN CanWait)
 

Variables

static PCWSTR MftIdToName []
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 31 of file create.c.

Function Documentation

◆ NtfsCreate()

NTSTATUS NtfsCreate ( PNTFS_IRP_CONTEXT  IrpContext)

Definition at line 824 of file create.c.

825{
826 PDEVICE_EXTENSION DeviceExt;
829
830 DeviceObject = IrpContext->DeviceObject;
832 {
833 /* DeviceObject represents FileSystem instead of logical volume */
834 DPRINT("Opening file system\n");
835 IrpContext->Irp->IoStatus.Information = FILE_OPENED;
836 return STATUS_SUCCESS;
837 }
838
839 DeviceExt = DeviceObject->DeviceExtension;
840
841 if (!(IrpContext->Flags & IRPCONTEXT_CANWAIT))
842 {
843 return NtfsMarkIrpContextForQueue(IrpContext);
844 }
845
846 ExAcquireResourceExclusiveLite(&DeviceExt->DirResource,
847 TRUE);
849 IrpContext);
850 ExReleaseResourceLite(&DeviceExt->DirResource);
851
852 return Status;
853}
LONG NTSTATUS
Definition: precomp.h:26
#define TRUE
Definition: types.h:120
static NTSTATUS NtfsCreateFile(PDEVICE_OBJECT DeviceObject, PNTFS_IRP_CONTEXT IrpContext)
Definition: create.c:497
PNTFS_GLOBAL_DATA NtfsGlobalData
Definition: ntfs.c:36
FORCEINLINE NTSTATUS NtfsMarkIrpContextForQueue(PNTFS_IRP_CONTEXT IrpContext)
Definition: ntfs.h:652
#define IRPCONTEXT_CANWAIT
Definition: ntfs.h:505
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
Status
Definition: gdiplustypes.h:24
#define FILE_OPENED
Definition: nt_native.h:769
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
PDEVICE_OBJECT DeviceObject
Definition: ntfs.h:175
ULONG Flags
Definition: ntfs.h:556
PDEVICE_OBJECT DeviceObject
Definition: ntfs.h:563
IO_STATUS_BLOCK IoStatus
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2061

Referenced by NtfsDispatch().

◆ NtfsCreateDirectory()

NTSTATUS NtfsCreateDirectory ( PDEVICE_EXTENSION  DeviceExt,
PFILE_OBJECT  FileObject,
BOOLEAN  CaseSensitive,
BOOLEAN  CanWait 
)

Definition at line 883 of file create.c.

887{
888
890 PFILE_RECORD_HEADER FileRecord;
891 PNTFS_ATTR_RECORD NextAttribute;
892 PFILENAME_ATTRIBUTE FilenameAttribute;
893 ULONGLONG ParentMftIndex;
894 ULONGLONG FileMftIndex;
896 PINDEX_ROOT_ATTRIBUTE NewIndexRoot;
897 ULONG MaxIndexRootSize;
898 ULONG RootLength;
899
900 DPRINT("NtfsCreateFileRecord(%p, %p, %s, %s)\n",
901 DeviceExt,
903 CaseSensitive ? "TRUE" : "FALSE",
904 CanWait ? "TRUE" : "FALSE");
905
906 // Start with an empty file record
907 FileRecord = NtfsCreateEmptyFileRecord(DeviceExt);
908 if (!FileRecord)
909 {
910 DPRINT1("ERROR: Unable to allocate memory for file record!\n");
912 }
913
914 // Set the directory flag
915 FileRecord->Flags |= FRH_DIRECTORY;
916
917 // find where the first attribute will be added
918 NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset);
919
920 // add first attribute, $STANDARD_INFORMATION
921 AddStandardInformation(FileRecord, NextAttribute);
922
923 // advance NextAttribute pointer to the next attribute
924 NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)NextAttribute + (ULONG_PTR)NextAttribute->Length);
925
926 // Add the $FILE_NAME attribute
927 Status = AddFileName(FileRecord, NextAttribute, DeviceExt, FileObject, CaseSensitive, &ParentMftIndex);
928 if (!NT_SUCCESS(Status))
929 {
930 DPRINT1("ERROR: Failed to add the $FILE_NAME attribute for '%wZ'!\n", &FileObject->FileName);
931 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
932 return Status;
933 }
934
935 // save a pointer to the filename attribute
936 FilenameAttribute = (PFILENAME_ATTRIBUTE)((ULONG_PTR)NextAttribute + NextAttribute->Resident.ValueOffset);
937
938 // advance NextAttribute pointer to the next attribute
939 NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)NextAttribute + (ULONG_PTR)NextAttribute->Length);
940
941 // Create an empty b-tree to represent our new index
943 if (!NT_SUCCESS(Status))
944 {
945 DPRINT1("ERROR: Failed to create empty B-Tree!\n");
946 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
947 return Status;
948 }
949
950 // Calculate maximum size of index root
951 MaxIndexRootSize = DeviceExt->NtfsInfo.BytesPerFileRecord
952 - ((ULONG_PTR)NextAttribute - (ULONG_PTR)FileRecord)
953 - sizeof(ULONG) * 2;
954
955 // Create a new index record from the tree
957 Tree,
958 MaxIndexRootSize,
959 &NewIndexRoot,
960 &RootLength);
961 if (!NT_SUCCESS(Status))
962 {
963 DPRINT1("ERROR: Unable to create empty index root!\n");
965 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
966 return Status;
967 }
968
969 // We're done with the B-Tree
971
972 // add the $INDEX_ROOT attribute
973 Status = AddIndexRoot(DeviceExt, FileRecord, NextAttribute, NewIndexRoot, RootLength, L"$I30", 4);
974 if (!NT_SUCCESS(Status))
975 {
976 DPRINT1("ERROR: Failed to add index root to new file record!\n");
977 ExFreePoolWithTag(NewIndexRoot, TAG_NTFS);
978 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
979 return Status;
980 }
981
982
983#ifndef NDEBUG
984 NtfsDumpFileRecord(DeviceExt, FileRecord);
985#endif
986
987 // Now that we've built the file record in memory, we need to store it in the MFT.
988 Status = AddNewMftEntry(FileRecord, DeviceExt, &FileMftIndex, CanWait);
989 if (NT_SUCCESS(Status))
990 {
991 // The highest 2 bytes should be the sequence number, unless the parent happens to be root
992 if (FileMftIndex == NTFS_FILE_ROOT)
993 FileMftIndex = FileMftIndex + ((ULONGLONG)NTFS_FILE_ROOT << 48);
994 else
995 FileMftIndex = FileMftIndex + ((ULONGLONG)FileRecord->SequenceNumber << 48);
996
997 DPRINT("New File Reference: 0x%016I64x\n", FileMftIndex);
998
999 // Add the filename attribute to the filename-index of the parent directory
1001 ParentMftIndex,
1002 FileMftIndex,
1003 FilenameAttribute,
1004 CaseSensitive);
1005 }
1006
1007 ExFreePoolWithTag(NewIndexRoot, TAG_NTFS);
1008 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
1009
1010 return Status;
1011}
CRegistryTree Tree
#define DPRINT1
Definition: precomp.h:8
struct NTFS_ATTR_RECORD * PNTFS_ATTR_RECORD
#define NTFS_FILE_ROOT
Definition: ntfs.h:28
VOID DestroyBTree(PB_TREE Tree)
Definition: btree.c:1549
NTSTATUS CreateEmptyBTree(PB_TREE *NewTree)
Definition: btree.c:353
NTSTATUS CreateIndexRootFromBTree(PDEVICE_EXTENSION DeviceExt, PB_TREE Tree, ULONG MaxIndexSize, PINDEX_ROOT_ATTRIBUTE *IndexRoot, ULONG *Length)
Definition: btree.c:915
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define L(x)
Definition: resources.c:13
NTSTATUS AddIndexRoot(PNTFS_VCB Vcb, PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress, PINDEX_ROOT_ATTRIBUTE NewIndexRoot, ULONG RootLength, PCWSTR Name, USHORT NameLength)
Definition: attrib.c:487
NTSTATUS AddFileName(PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress, PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, BOOLEAN CaseSensitive, PULONGLONG ParentMftIndex)
Definition: attrib.c:234
NTSTATUS AddStandardInformation(PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress)
Definition: attrib.c:783
PFILE_RECORD_HEADER NtfsCreateEmptyFileRecord(PDEVICE_EXTENSION DeviceExt)
Definition: create.c:1026
struct FILENAME_ATTRIBUTE * PFILENAME_ATTRIBUTE
#define FRH_DIRECTORY
Definition: ntfs.h:299
#define TAG_NTFS
Definition: ntfs.h:12
#define ULONG_PTR
Definition: config.h:101
NTSTATUS NtfsAddFilenameToDirectory(PDEVICE_EXTENSION DeviceExt, ULONGLONG DirectoryMftIndex, ULONGLONG FileReferenceNumber, PFILENAME_ATTRIBUTE FilenameAttribute, BOOLEAN CaseSensitive)
Definition: mft.c:3049
NTSTATUS AddNewMftEntry(PFILE_RECORD_HEADER FileRecord, PDEVICE_EXTENSION DeviceExt, PULONGLONG DestinationIndex, BOOLEAN CanWait)
Definition: mft.c:2482
VOID NtfsDumpFileRecord(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord)
Definition: mft.c:4342
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
Definition: ntfs.h:485
struct NTFS_ATTR_RECORD::@170::@172 Resident
ULONG Length
Definition: ntfs.h:135
USHORT SequenceNumber
Definition: ntfs.h:284
USHORT Flags
Definition: ntfs.h:287
USHORT AttributeOffset
Definition: ntfs.h:286
uint64_t ULONGLONG
Definition: typedefs.h:67
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550

Referenced by NtfsCreateFile().

◆ NtfsCreateEmptyFileRecord()

PFILE_RECORD_HEADER NtfsCreateEmptyFileRecord ( PDEVICE_EXTENSION  DeviceExt)

Definition at line 1026 of file create.c.

1027{
1028 PFILE_RECORD_HEADER FileRecord;
1029 PNTFS_ATTR_RECORD NextAttribute;
1030
1031 DPRINT("NtfsCreateEmptyFileRecord(%p)\n", DeviceExt);
1032
1033 // allocate memory for file record
1034 FileRecord = ExAllocateFromNPagedLookasideList(&DeviceExt->FileRecLookasideList);
1035 if (!FileRecord)
1036 {
1037 DPRINT1("ERROR: Unable to allocate memory for file record!\n");
1038 return NULL;
1039 }
1040
1041 RtlZeroMemory(FileRecord, DeviceExt->NtfsInfo.BytesPerFileRecord);
1042
1043 FileRecord->Ntfs.Type = NRH_FILE_TYPE;
1044
1045 // calculate USA offset and count
1046 FileRecord->Ntfs.UsaOffset = FIELD_OFFSET(FILE_RECORD_HEADER, MFTRecordNumber) + sizeof(ULONG);
1047
1048 // size of USA (in ULONG's) will be 1 (for USA number) + 1 for every sector the file record uses
1049 FileRecord->BytesAllocated = DeviceExt->NtfsInfo.BytesPerFileRecord;
1050 FileRecord->Ntfs.UsaCount = (FileRecord->BytesAllocated / DeviceExt->NtfsInfo.BytesPerSector) + 1;
1051
1052 // setup other file record fields
1053 FileRecord->SequenceNumber = 1;
1054 FileRecord->AttributeOffset = FileRecord->Ntfs.UsaOffset + (2 * FileRecord->Ntfs.UsaCount);
1056 FileRecord->Flags = FRH_IN_USE;
1057 FileRecord->BytesInUse = FileRecord->AttributeOffset + sizeof(ULONG) * 2;
1058
1059 // find where the first attribute will be added
1060 NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset);
1061
1062 // mark the (temporary) end of the file-record
1063 NextAttribute->Type = AttributeEnd;
1064 NextAttribute->Length = FILE_RECORD_END;
1065
1066 return FileRecord;
1067}
#define ALIGN_UP_BY(size, align)
#define NULL
Definition: types.h:112
#define NRH_FILE_TYPE
Definition: ntfs.h:277
#define FILE_RECORD_END
Definition: ntfs.h:209
@ AttributeEnd
Definition: ntfs.h:204
#define ATTR_RECORD_ALIGNMENT
Definition: ntfs.h:351
#define FRH_IN_USE
Definition: ntfs.h:298
ULONG Type
Definition: ntfs.h:134
USHORT UsaCount
Definition: ntfs.h:272
USHORT UsaOffset
Definition: ntfs.h:271
NTFS_RECORD_HEADER Ntfs
Definition: ntfs.h:283
ULONG BytesInUse
Definition: ntfs.h:288
ULONG BytesAllocated
Definition: ntfs.h:289
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262

Referenced by IncreaseMftSize(), NtfsCreateDirectory(), and NtfsCreateFileRecord().

◆ NtfsCreateFile()

static NTSTATUS NtfsCreateFile ( PDEVICE_OBJECT  DeviceObject,
PNTFS_IRP_CONTEXT  IrpContext 
)
static

Definition at line 497 of file create.c.

499{
500 PDEVICE_EXTENSION DeviceExt;
503 ULONG RequestedDisposition;
504 ULONG RequestedOptions;
506// PWSTR FileName;
508 UNICODE_STRING FullPath;
509 PIRP Irp = IrpContext->Irp;
510
511 DPRINT("NtfsCreateFile(%p, %p) called\n", DeviceObject, IrpContext);
512
513 DeviceExt = DeviceObject->DeviceExtension;
514 ASSERT(DeviceExt);
516 ASSERT(Stack);
517
518 RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff);
519 RequestedOptions = Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
520// PagingFileCreate = (Stack->Flags & SL_OPEN_PAGING_FILE) ? TRUE : FALSE;
521 if (RequestedOptions & FILE_DIRECTORY_FILE &&
522 RequestedDisposition == FILE_SUPERSEDE)
523 {
525 }
526
527 /* Deny create if the volume is locked */
528 if (DeviceExt->Flags & VCB_VOLUME_LOCKED)
529 {
531 }
532
533 FileObject = Stack->FileObject;
534
535 /* The I/O manager opening a rename's destination directory */
536 if (Stack->Flags & SL_OPEN_TARGET_DIRECTORY)
537 {
539
540 if (RequestedOptions & FILE_OPEN_BY_FILE_ID)
542
546 &Information);
547 if (!NT_SUCCESS(Status))
548 return Status;
549
550 Status = NtfsGrantShareAccess(DeviceExt, FileObject->FsContext, FileObject, Stack);
551 if (!NT_SUCCESS(Status))
552 {
553 NtfsCloseFile(DeviceExt, FileObject);
554 return Status;
555 }
556
557 Irp->IoStatus.Information = Information;
558 return STATUS_SUCCESS;
559 }
560
561 if ((RequestedOptions & FILE_OPEN_BY_FILE_ID) == FILE_OPEN_BY_FILE_ID)
562 {
563 ULONGLONG MFTId;
564
565 if (FileObject->FileName.Length != sizeof(ULONGLONG))
567
568 MFTId = (*(PULONGLONG)FileObject->FileName.Buffer) & NTFS_MFT_MASK;
569 if (MFTId < NTFS_FILE_FIRST_USER_FILE)
570 {
571 Status = NtfsOpenFileById(DeviceExt, FileObject, MFTId, &Fcb);
572 }
573 else
574 {
575 Status = NtfsMoonWalkID(DeviceExt, MFTId, &FullPath);
576 }
577
578 if (!NT_SUCCESS(Status))
579 {
580 return Status;
581 }
582
583 DPRINT("Open by ID: %I64x -> %wZ\n", (*(PULONGLONG)FileObject->FileName.Buffer) & NTFS_MFT_MASK, &FullPath);
584 }
585
586 /* This a open operation for the volume itself */
587 if (FileObject->FileName.Length == 0 &&
588 (FileObject->RelatedFileObject == NULL || FileObject->RelatedFileObject->FsContext2 != NULL))
589 {
590 if (RequestedDisposition != FILE_OPEN &&
591 RequestedDisposition != FILE_OPEN_IF)
592 {
594 }
595
596 if (RequestedOptions & FILE_DIRECTORY_FILE)
597 {
599 }
600
601 NtfsAttachFCBToFileObject(DeviceExt, DeviceExt->VolumeFcb, FileObject);
602 DeviceExt->VolumeFcb->RefCount++;
603
604 Irp->IoStatus.Information = FILE_OPENED;
605 return STATUS_SUCCESS;
606 }
607
608 if (Fcb == NULL)
609 {
610 Status = NtfsOpenFile(DeviceExt,
612 ((RequestedOptions & FILE_OPEN_BY_FILE_ID) ? FullPath.Buffer : FileObject->FileName.Buffer),
614 &Fcb);
615
616 if (RequestedOptions & FILE_OPEN_BY_FILE_ID)
617 {
619 }
620 }
621
622 if (NT_SUCCESS(Status))
623 {
624 if (RequestedDisposition == FILE_CREATE)
625 {
626 Irp->IoStatus.Information = FILE_EXISTS;
627 NtfsCloseFile(DeviceExt, FileObject);
629 }
630
631 if (RequestedOptions & FILE_NON_DIRECTORY_FILE &&
633 {
634 NtfsCloseFile(DeviceExt, FileObject);
636 }
637
638 if (RequestedOptions & FILE_DIRECTORY_FILE &&
640 {
641 NtfsCloseFile(DeviceExt, FileObject);
643 }
644
645 /*
646 * If it is a reparse point & FILE_OPEN_REPARSE_POINT, then allow opening it
647 * as a normal file.
648 * Otherwise, attempt to read reparse data and hand them to the Io manager
649 * with status reparse to force a reparse.
650 */
652 ((RequestedOptions & FILE_OPEN_REPARSE_POINT) != FILE_OPEN_REPARSE_POINT))
653 {
654 PREPARSE_DATA_BUFFER ReparseData = NULL;
655
656 Status = NtfsReadFCBAttribute(DeviceExt, Fcb,
658 (PVOID *)&Irp->Tail.Overlay.AuxiliaryBuffer);
659 if (NT_SUCCESS(Status))
660 {
661 ReparseData = (PREPARSE_DATA_BUFFER)Irp->Tail.Overlay.AuxiliaryBuffer;
663 {
665 }
666 else
667 {
669 ExFreePoolWithTag(ReparseData, TAG_NTFS);
670 }
671 }
672
673 Irp->IoStatus.Information = ((Status == STATUS_REPARSE) ? ReparseData->ReparseTag : 0);
674
675 NtfsCloseFile(DeviceExt, FileObject);
676 return Status;
677 }
678
679 if (RequestedDisposition == FILE_OVERWRITE ||
680 RequestedDisposition == FILE_OVERWRITE_IF ||
681 RequestedDisposition == FILE_SUPERSEDE)
682 {
683 PFILE_RECORD_HEADER fileRecord = NULL;
684 PNTFS_ATTR_CONTEXT dataContext = NULL;
685 ULONG DataAttributeOffset;
687 Zero.QuadPart = 0;
688
690 {
691 DPRINT1("NTFS write-support is EXPERIMENTAL and is disabled by default!\n");
692 NtfsCloseFile(DeviceExt, FileObject);
694 }
695
696 // TODO: check for appropriate access
697
699
700 fileRecord = ExAllocateFromNPagedLookasideList(&Fcb->Vcb->FileRecLookasideList);
701 if (fileRecord)
702 {
703
705 Fcb->MFTIndex,
706 fileRecord);
707 if (!NT_SUCCESS(Status))
708 goto DoneOverwriting;
709
710 // find the data attribute and set it's length to 0 (TODO: Handle Alternate Data Streams)
711 Status = FindAttribute(Fcb->Vcb, fileRecord, AttributeData, L"", 0, &dataContext, &DataAttributeOffset);
712 if (!NT_SUCCESS(Status))
713 goto DoneOverwriting;
714
715 Status = SetAttributeDataLength(FileObject, Fcb, dataContext, DataAttributeOffset, fileRecord, &Zero);
716 }
717 else
718 {
720 }
721
722 DoneOverwriting:
723 if (fileRecord)
724 ExFreeToNPagedLookasideList(&Fcb->Vcb->FileRecLookasideList, fileRecord);
725 if (dataContext)
726 ReleaseAttributeContext(dataContext);
727
729
730 if (!NT_SUCCESS(Status))
731 {
732 NtfsCloseFile(DeviceExt, FileObject);
733 return Status;
734 }
735
736 if (RequestedDisposition == FILE_SUPERSEDE)
737 {
738 Irp->IoStatus.Information = FILE_SUPERSEDED;
739 }
740 else
741 {
742 Irp->IoStatus.Information = FILE_OVERWRITTEN;
743 }
744 }
745 }
746 else
747 {
748 /* HUGLY HACK: Can't create new files yet... */
749 if (RequestedDisposition == FILE_CREATE ||
750 RequestedDisposition == FILE_OPEN_IF ||
751 RequestedDisposition == FILE_OVERWRITE_IF ||
752 RequestedDisposition == FILE_SUPERSEDE)
753 {
755 {
756 DPRINT1("NTFS write-support is EXPERIMENTAL and is disabled by default!\n");
757 NtfsCloseFile(DeviceExt, FileObject);
759 }
760
761 // Was the user trying to create a directory?
762 if (RequestedOptions & FILE_DIRECTORY_FILE)
763 {
764 // Create the directory on disk
765 Status = NtfsCreateDirectory(DeviceExt,
769 }
770 else
771 {
772 // Create the file record on disk
773 Status = NtfsCreateFileRecord(DeviceExt,
777 }
778
779 if (!NT_SUCCESS(Status))
780 {
781 DPRINT1("ERROR: Couldn't create '%wZ' (Status %lx)\n",
782 &FileObject->FileName, Status);
783 return Status;
784 }
785
786 // Before we open the file/directory we just created, we need to change the disposition (upper 8 bits of ULONG)
787 // from create to open, since we already created the file
788 Stack->Parameters.Create.Options = (ULONG)FILE_OPEN << 24 | RequestedOptions;
789
790 // Now we should be able to open the file using NtfsCreateFile()
791 Status = NtfsCreateFile(DeviceObject, IrpContext);
792 if (NT_SUCCESS(Status))
793 {
794 // We need to change Irp->IoStatus.Information to reflect creation
795 Irp->IoStatus.Information = FILE_CREATED;
796 }
797 return Status;
798 }
799 }
800
801 if (NT_SUCCESS(Status))
802 {
804 if (!NT_SUCCESS(Status))
805 {
806 DPRINT("Sharing violation opening '%wZ'\n", &FileObject->FileName);
807 NtfsCloseFile(DeviceExt, FileObject);
808 Irp->IoStatus.Information = 0;
809 return Status;
810 }
811 }
812
813 /*
814 * If the directory containing the file to open doesn't exist then
815 * fail immediately
816 */
817 Irp->IoStatus.Information = (NT_SUCCESS(Status)) ? FILE_OPENED : 0;
818
819 return Status;
820}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
#define NTFS_MFT_MASK
Definition: ntfs.h:76
_In_ PFCB Fcb
Definition: cdprocs.h:159
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
NTSTATUS NtfsCloseFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject)
Definition: close.c:40
static NTSTATUS NtfsOpenFileById(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, ULONGLONG MftId, PNTFS_FCB *FoundFCB)
Definition: create.c:175
static NTSTATUS NtfsOpenFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, PWSTR FileName, BOOLEAN CaseSensitive, PNTFS_FCB *FoundFCB)
Definition: create.c:242
static NTSTATUS NtfsMoonWalkID(PDEVICE_EXTENSION DeviceExt, ULONGLONG Id, PUNICODE_STRING OutPath)
Definition: create.c:104
NTSTATUS NtfsCreateFileRecord(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, BOOLEAN CaseSensitive, BOOLEAN CanWait)
Definition: create.c:1094
NTSTATUS NtfsCreateDirectory(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, BOOLEAN CaseSensitive, BOOLEAN CanWait)
Definition: create.c:883
static NTSTATUS NtfsOpenTargetDirectory(_In_ PDEVICE_EXTENSION DeviceExt, _In_ PFILE_OBJECT FileObject, _In_ BOOLEAN CaseSensitive, _Out_ PULONG_PTR Information)
Definition: create.c:394
static NTSTATUS NtfsGrantShareAccess(_In_ PDEVICE_EXTENSION DeviceExt, _In_ PNTFS_FCB Fcb, _In_ PFILE_OBJECT FileObject, _In_ PIO_STACK_LOCATION Stack)
Definition: create.c:331
#define NTFS_FILE_FIRST_USER_FILE
Definition: ntfs.h:223
@ AttributeReparsePoint
Definition: ntfs.h:199
@ AttributeData
Definition: ntfs.h:195
#define VCB_VOLUME_LOCKED
Definition: ext2fs.h:789
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
IN PVCB IN VBO IN ULONG OUT PBCB OUT PVOID IN BOOLEAN IN BOOLEAN Zero
Definition: fatprocs.h:419
#define FILE_OPEN_BY_FILE_ID
Definition: from_kernel.h:41
#define FILE_OPEN
Definition: from_kernel.h:54
#define FILE_CREATE
Definition: from_kernel.h:55
#define FILE_OVERWRITE_IF
Definition: from_kernel.h:58
#define FILE_OPEN_REPARSE_POINT
Definition: from_kernel.h:46
#define FILE_OVERWRITE
Definition: from_kernel.h:57
#define FILE_OPEN_IF
Definition: from_kernel.h:56
#define FILE_SUPERSEDE
Definition: from_kernel.h:53
_In_ PIRP Irp
Definition: kse.h:79
if(dx< 0)
Definition: linetemp.h:194
NTSTATUS ReadFileRecord(PDEVICE_EXTENSION Vcb, ULONGLONG index, PFILE_RECORD_HEADER file)
Definition: mft.c:1936
VOID ReleaseAttributeContext(PNTFS_ATTR_CONTEXT Context)
Definition: mft.c:104
NTSTATUS FindAttribute(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER MftRecord, ULONG Type, PCWSTR Name, ULONG NameLength, PNTFS_ATTR_CONTEXT *AttrCtx, PULONG Offset)
Definition: mft.c:131
NTSTATUS SetAttributeDataLength(PFILE_OBJECT FileObject, PNTFS_FCB Fcb, PNTFS_ATTR_CONTEXT AttrContext, ULONG AttrOffset, PFILE_RECORD_HEADER FileRecord, PLARGE_INTEGER DataSize)
Definition: mft.c:615
#define ASSERT(a)
Definition: mode.c:44
#define FILE_CREATED
Definition: nt_native.h:770
#define FILE_OVERWRITTEN
Definition: nt_native.h:771
#define FILE_SUPERSEDED
Definition: nt_native.h:768
#define FILE_EXISTS
Definition: nt_native.h:772
#define FILE_VALID_OPTION_FLAGS
Definition: nt_native.h:759
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:395
BOOLEAN NtfsFCBIsDirectory(PNTFS_FCB Fcb)
Definition: fcb.c:144
NTSTATUS NtfsReadFCBAttribute(PNTFS_VCB Vcb, PNTFS_FCB pFCB, ULONG Type, PCWSTR Name, ULONG NameLength, PVOID *Data)
Definition: fcb.c:806
BOOLEAN NtfsFCBIsReparsePoint(PNTFS_FCB Fcb)
Definition: fcb.c:166
NTSTATUS NtfsAttachFCBToFileObject(PNTFS_VCB Vcb, PNTFS_FCB Fcb, PFILE_OBJECT FileObject)
Definition: fcb.c:533
#define STATUS_REPARSE
Definition: ntstatus.h:136
struct _REPARSE_DATA_BUFFER * PREPARSE_DATA_BUFFER
BOOLEAN EnableWriteSupport
Definition: ntfs.h:182
Definition: cdstruc.h:902
PVCB Vcb
Definition: cdstruc.h:933
ULONGLONG MFTIndex
Definition: ntfs.h:622
ERESOURCE MainResource
Definition: ntfs.h:607
#define STATUS_FILE_IS_A_DIRECTORY
Definition: udferr_usr.h:164
#define STATUS_NOT_A_DIRECTORY
Definition: udferr_usr.h:169
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
_In_ WDFREQUEST _In_ NTSTATUS _In_ ULONG_PTR Information
Definition: wdfrequest.h:1049
* PFILE_OBJECT
Definition: iotypes.h:1998
#define IO_REPARSE_TAG_MOUNT_POINT
Definition: iotypes.h:7247
#define SL_OPEN_TARGET_DIRECTORY
Definition: iotypes.h:1818
#define SL_CASE_SENSITIVE
Definition: iotypes.h:1820

Referenced by NtfsCreate(), and NtfsCreateFile().

◆ NtfsCreateFileRecord()

NTSTATUS NtfsCreateFileRecord ( PDEVICE_EXTENSION  DeviceExt,
PFILE_OBJECT  FileObject,
BOOLEAN  CaseSensitive,
BOOLEAN  CanWait 
)

Definition at line 1094 of file create.c.

1098{
1100 PFILE_RECORD_HEADER FileRecord;
1101 PNTFS_ATTR_RECORD NextAttribute;
1102 PFILENAME_ATTRIBUTE FilenameAttribute;
1103 ULONGLONG ParentMftIndex;
1104 ULONGLONG FileMftIndex;
1105
1106 DPRINT("NtfsCreateFileRecord(%p, %p, %s, %s)\n",
1107 DeviceExt,
1108 FileObject,
1109 CaseSensitive ? "TRUE" : "FALSE",
1110 CanWait ? "TRUE" : "FALSE");
1111
1112 // allocate memory for file record
1113 FileRecord = NtfsCreateEmptyFileRecord(DeviceExt);
1114 if (!FileRecord)
1115 {
1116 DPRINT1("ERROR: Unable to allocate memory for file record!\n");
1118 }
1119
1120 // find where the first attribute will be added
1121 NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset);
1122
1123 // add first attribute, $STANDARD_INFORMATION
1124 AddStandardInformation(FileRecord, NextAttribute);
1125
1126 // advance NextAttribute pointer to the next attribute
1127 NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)NextAttribute + (ULONG_PTR)NextAttribute->Length);
1128
1129 // Add the $FILE_NAME attribute
1130 Status = AddFileName(FileRecord, NextAttribute, DeviceExt, FileObject, CaseSensitive, &ParentMftIndex);
1131 if (!NT_SUCCESS(Status))
1132 {
1133 DPRINT1("ERROR: Failed to add the $FILE_NAME attribute for '%wZ'!\n", &FileObject->FileName);
1134 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
1135 return Status;
1136 }
1137
1138 // save a pointer to the filename attribute
1139 FilenameAttribute = (PFILENAME_ATTRIBUTE)((ULONG_PTR)NextAttribute + NextAttribute->Resident.ValueOffset);
1140
1141 // advance NextAttribute pointer to the next attribute
1142 NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)NextAttribute + (ULONG_PTR)NextAttribute->Length);
1143
1144 // add the $DATA attribute
1145 AddData(FileRecord, NextAttribute);
1146
1147#ifndef NDEBUG
1148 // dump file record in memory (for debugging)
1149 NtfsDumpFileRecord(DeviceExt, FileRecord);
1150#endif
1151
1152 // Now that we've built the file record in memory, we need to store it in the MFT.
1153 Status = AddNewMftEntry(FileRecord, DeviceExt, &FileMftIndex, CanWait);
1154 if (NT_SUCCESS(Status))
1155 {
1156 // The highest 2 bytes should be the sequence number, unless the parent happens to be root
1157 if (FileMftIndex == NTFS_FILE_ROOT)
1158 FileMftIndex = FileMftIndex + ((ULONGLONG)NTFS_FILE_ROOT << 48);
1159 else
1160 FileMftIndex = FileMftIndex + ((ULONGLONG)FileRecord->SequenceNumber << 48);
1161
1162 DPRINT("New File Reference: 0x%016I64x\n", FileMftIndex);
1163
1164 // Add the filename attribute to the filename-index of the parent directory
1166 ParentMftIndex,
1167 FileMftIndex,
1168 FilenameAttribute,
1169 CaseSensitive);
1170 }
1171
1172 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
1173
1174 return Status;
1175}
NTSTATUS AddData(PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress)
Definition: attrib.c:164

Referenced by NtfsCreateFile().

◆ NtfsGrantShareAccess()

static NTSTATUS NtfsGrantShareAccess ( _In_ PDEVICE_EXTENSION  DeviceExt,
_In_ PNTFS_FCB  Fcb,
_In_ PFILE_OBJECT  FileObject,
_In_ PIO_STACK_LOCATION  Stack 
)
static

Definition at line 331 of file create.c.

336{
338 ULONG ShareAccess = Stack->Parameters.Create.ShareAccess;
340
341 if (Stack->Parameters.Create.SecurityContext != NULL)
342 DesiredAccess = Stack->Parameters.Create.SecurityContext->DesiredAccess;
343
344 if (Fcb->OpenHandleCount > 0)
345 {
350 TRUE);
351 }
352 else
353 {
357 &Fcb->ShareAccess);
358 }
359
360 if (NT_SUCCESS(Status))
361 {
363 DeviceExt->OpenHandleCount++;
364 }
365
366 return Status;
367}
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB _In_ PDCB _In_ PDIRENT _In_ ULONG _In_ ULONG _In_ PUNICODE_STRING _In_ PACCESS_MASK _In_ USHORT ShareAccess
Definition: create.c:4148
ULONG ACCESS_MASK
Definition: nt_native.h:40
VOID NTAPI IoSetShareAccess(IN ACCESS_MASK DesiredAccess, IN ULONG DesiredShareAccess, IN PFILE_OBJECT FileObject, OUT PSHARE_ACCESS ShareAccess)
Definition: file.c:3516
NTSTATUS NTAPI IoCheckShareAccess(IN ACCESS_MASK DesiredAccess, IN ULONG DesiredShareAccess, IN PFILE_OBJECT FileObject, IN PSHARE_ACCESS ShareAccess, IN BOOLEAN Update)
Definition: file.c:3389
SHARE_ACCESS ShareAccess
Definition: cdstruc.h:1009
ULONG OpenHandleCount
Definition: ntfs.h:619
union _IO_STACK_LOCATION::@1814 Parameters
struct _IO_STACK_LOCATION::@5020::@5021 Create
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2664

Referenced by NtfsCreateFile().

◆ NtfsMakeAbsoluteFilename()

static NTSTATUS NtfsMakeAbsoluteFilename ( PFILE_OBJECT  pFileObject,
PWSTR  pRelativeFileName,
PWSTR *  pAbsoluteFilename 
)
static

Definition at line 53 of file create.c.

56{
57 PWSTR rcName;
59
60 DPRINT("try related for %S\n", pRelativeFileName);
61 Fcb = pFileObject->FsContext;
62 ASSERT(Fcb);
63
64 if (Fcb->Flags & FCB_IS_VOLUME)
65 {
66 /* This is likely to be an opening by ID, return ourselves */
67 if (pRelativeFileName[0] == L'\\')
68 {
69 *pAbsoluteFilename = NULL;
70 return STATUS_SUCCESS;
71 }
72
74 }
75
76 /* verify related object is a directory and target name
77 don't start with \. */
79 pRelativeFileName[0] == L'\\')
80 {
82 }
83
84 /* construct absolute path name */
85 ASSERT(wcslen (Fcb->PathName) + 1 + wcslen (pRelativeFileName) + 1 <= MAX_PATH);
87 if (!rcName)
88 {
90 }
91
92 wcscpy(rcName, Fcb->PathName);
93 if (!NtfsFCBIsRoot(Fcb))
94 wcscat (rcName, L"\\");
95 wcscat (rcName, pRelativeFileName);
96 *pAbsoluteFilename = rcName;
97
98 return STATUS_SUCCESS;
99}
#define FALSE
Definition: types.h:117
#define MAX_PATH
Definition: compat.h:34
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2988
#define FCB_IS_VOLUME
Definition: ntfs.h:585
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define NonPagedPool
Definition: env_spec_w32.h:307
BOOLEAN NtfsFCBIsRoot(PNTFS_FCB Fcb)
Definition: fcb.c:185
short WCHAR
Definition: pedump.c:58
wcscat
wcscpy
ULONG Flags
Definition: ntfs.h:618
WCHAR PathName[MAX_PATH]
Definition: ntfs.h:604
uint16_t * PWSTR
Definition: typedefs.h:56

Referenced by NtfsOpenFile(), and NtfsOpenTargetDirectory().

◆ NtfsMoonWalkID()

static NTSTATUS NtfsMoonWalkID ( PDEVICE_EXTENSION  DeviceExt,
ULONGLONG  Id,
PUNICODE_STRING  OutPath 
)
static

Definition at line 104 of file create.c.

107{
109 PFILE_RECORD_HEADER MftRecord;
111 WCHAR FullPath[MAX_PATH];
112 ULONG WritePosition = MAX_PATH - 1;
113
114 DPRINT("NtfsMoonWalkID(%p, %I64x, %p)\n", DeviceExt, Id, OutPath);
115
116 RtlZeroMemory(FullPath, sizeof(FullPath));
117 MftRecord = ExAllocateFromNPagedLookasideList(&DeviceExt->FileRecLookasideList);
118 if (MftRecord == NULL)
119 {
121 }
122
123 while (TRUE)
124 {
125 Status = ReadFileRecord(DeviceExt, Id, MftRecord);
126 if (!NT_SUCCESS(Status))
127 break;
128
129 ASSERT(MftRecord->Ntfs.Type == NRH_FILE_TYPE);
130 if (!(MftRecord->Flags & FRH_IN_USE))
131 {
133 break;
134 }
135
136 FileName = GetBestFileNameFromRecord(DeviceExt, MftRecord);
137 if (FileName == NULL)
138 {
139 DPRINT1("$FILE_NAME attribute not found for %I64x\n", Id);
141 break;
142 }
143
144 WritePosition -= FileName->NameLength;
145 ASSERT(WritePosition < MAX_PATH);
146 RtlCopyMemory(FullPath + WritePosition, FileName->Name, FileName->NameLength * sizeof(WCHAR));
147 WritePosition -= 1;
148 ASSERT(WritePosition < MAX_PATH);
149 FullPath[WritePosition] = L'\\';
150
151 Id = FileName->DirectoryFileReferenceNumber & NTFS_MFT_MASK;
152 if (Id == NTFS_FILE_ROOT)
153 break;
154 }
155
156 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, MftRecord);
157
158 if (!NT_SUCCESS(Status))
159 return Status;
160
161 OutPath->Length = (MAX_PATH - WritePosition - 1) * sizeof(WCHAR);
162 OutPath->MaximumLength = (MAX_PATH - WritePosition) * sizeof(WCHAR);
164 if (OutPath->Buffer == NULL)
165 {
167 }
168 RtlCopyMemory(OutPath->Buffer, FullPath + WritePosition, OutPath->MaximumLength);
169
170 return Status;
171}
DWORD Id
PFILENAME_ATTRIBUTE GetBestFileNameFromRecord(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord)
Definition: attrib.c:2015
struct _FileName FileName
Definition: fatprocs.h:897
TCHAR Name[MAX_PATH]
Definition: filecomp.c:349
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_OBJECT_PATH_NOT_FOUND
Definition: udferr_usr.h:151

Referenced by NtfsCreateFile().

◆ NtfsOpenFile()

static NTSTATUS NtfsOpenFile ( PDEVICE_EXTENSION  DeviceExt,
PFILE_OBJECT  FileObject,
PWSTR  FileName,
BOOLEAN  CaseSensitive,
PNTFS_FCB *  FoundFCB 
)
static

Definition at line 242 of file create.c.

247{
251 PWSTR AbsFileName = NULL;
252
253 DPRINT("NtfsOpenFile(%p, %p, %S, %s, %p)\n",
254 DeviceExt,
256 FileName,
257 CaseSensitive ? "TRUE" : "FALSE",
258 FoundFCB);
259
260 *FoundFCB = NULL;
261
262 if (FileObject->RelatedFileObject)
263 {
264 DPRINT("Converting relative filename to absolute filename\n");
265
266 Status = NtfsMakeAbsoluteFilename(FileObject->RelatedFileObject,
267 FileName,
268 &AbsFileName);
269 if (AbsFileName) FileName = AbsFileName;
270 if (!NT_SUCCESS(Status))
271 {
272 return Status;
273 }
274 }
275
276 //FIXME: Get canonical path name (remove .'s, ..'s and extra separators)
277
278 DPRINT("PathName to open: %S\n", FileName);
279
280 /* try first to find an existing FCB in memory */
281 DPRINT("Checking for existing FCB in memory\n");
282 Fcb = NtfsGrabFCBFromTable(DeviceExt,
283 FileName);
284 if (Fcb == NULL)
285 {
286 DPRINT("No existing FCB found, making a new one if file exists.\n");
287 Status = NtfsGetFCBForFile(DeviceExt,
288 &ParentFcb,
289 &Fcb,
290 FileName,
291 CaseSensitive);
292 if (ParentFcb != NULL)
293 {
294 NtfsReleaseFCB(DeviceExt,
295 ParentFcb);
296 }
297
298 if (!NT_SUCCESS(Status))
299 {
300 DPRINT("Open of '%S' failed with %lx\n", FileName, Status);
301
302 if (AbsFileName)
303 ExFreePoolWithTag(AbsFileName, TAG_NTFS);
304
305 return Status;
306 }
307 }
308
309 DPRINT("Attaching FCB to fileObject\n");
311 Fcb,
312 FileObject);
313
314 if (AbsFileName)
315 ExFreePool(AbsFileName);
316
317 *FoundFCB = Fcb;
318
319 return Status;
320}
_In_ PFCB ParentFcb
Definition: cdprocs.h:736
static NTSTATUS NtfsMakeAbsoluteFilename(PFILE_OBJECT pFileObject, PWSTR pRelativeFileName, PWSTR *pAbsoluteFilename)
Definition: create.c:53
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
PNTFS_FCB NtfsGrabFCBFromTable(PNTFS_VCB Vcb, PCWSTR FileName)
Definition: fcb.c:291
NTSTATUS NtfsGetFCBForFile(PNTFS_VCB Vcb, PNTFS_FCB *pParentFCB, PNTFS_FCB *pFCB, PCWSTR pFileName, BOOLEAN CaseSensitive)
Definition: fcb.c:674
VOID NtfsReleaseFCB(PNTFS_VCB Vcb, PNTFS_FCB Fcb)
Definition: fcb.c:209

Referenced by NtfsCreateFile().

◆ NtfsOpenFileById()

static NTSTATUS NtfsOpenFileById ( PDEVICE_EXTENSION  DeviceExt,
PFILE_OBJECT  FileObject,
ULONGLONG  MftId,
PNTFS_FCB *  FoundFCB 
)
static

Definition at line 175 of file create.c.

179{
182 PFILE_RECORD_HEADER MftRecord;
183
184 DPRINT("NtfsOpenFileById(%p, %p, %I64x, %p)\n", DeviceExt, FileObject, MftId, FoundFCB);
185
187 if (MftId > 0xb) /* No entries are used yet beyond this */
188 {
190 }
191
192 MftRecord = ExAllocateFromNPagedLookasideList(&DeviceExt->FileRecLookasideList);
193 if (MftRecord == NULL)
194 {
196 }
197
198 Status = ReadFileRecord(DeviceExt, MftId, MftRecord);
199 if (!NT_SUCCESS(Status))
200 {
201 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, MftRecord);
202 return Status;
203 }
204
205 if (!(MftRecord->Flags & FRH_IN_USE))
206 {
207 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, MftRecord);
209 }
210
211 FCB = NtfsGrabFCBFromTable(DeviceExt, MftIdToName[MftId]);
212 if (FCB == NULL)
213 {
215
217 Status = NtfsMakeFCBFromDirEntry(DeviceExt, NULL, &Name, NULL, MftRecord, MftId, &FCB);
218 if (!NT_SUCCESS(Status))
219 {
220 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, MftRecord);
221 return Status;
222 }
223 }
224
225 ASSERT(FCB != NULL);
226
227 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, MftRecord);
228
230 FCB,
231 FileObject);
232 *FoundFCB = FCB;
233
234 return Status;
235}
struct _FCB FCB
LPWSTR Name
Definition: desk.c:124
static PCWSTR MftIdToName[]
Definition: create.c:34
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSTATUS NtfsMakeFCBFromDirEntry(PNTFS_VCB Vcb, PNTFS_FCB DirectoryFCB, PUNICODE_STRING Name, PCWSTR Stream, PFILE_RECORD_HEADER Record, ULONGLONG MFTIndex, PNTFS_FCB *fileFCB)
Definition: fcb.c:458
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149

Referenced by NtfsCreateFile().

◆ NtfsOpenTargetDirectory()

static NTSTATUS NtfsOpenTargetDirectory ( _In_ PDEVICE_EXTENSION  DeviceExt,
_In_ PFILE_OBJECT  FileObject,
_In_ BOOLEAN  CaseSensitive,
_Out_ PULONG_PTR  Information 
)
static

Definition at line 394 of file create.c.

399{
401 WCHAR FinalBuffer[MAX_PATH];
402 PWSTR AbsFileName = NULL;
403 PWSTR LastSeparator;
404 UNICODE_STRING FinalName;
405 ULONGLONG ExistingMft;
406 ULONG FirstEntry = 0;
411
412 *Information = 0;
413
414 if (FileObject->FileName.Length == 0 || FileObject->FileName.Length >= sizeof(Path))
416
417 RtlCopyMemory(Path, FileObject->FileName.Buffer, FileObject->FileName.Length);
418 Path[FileObject->FileName.Length / sizeof(WCHAR)] = UNICODE_NULL;
419
420 if (FileObject->RelatedFileObject)
421 {
422 Status = NtfsMakeAbsoluteFilename(FileObject->RelatedFileObject, Path, &AbsFileName);
423 if (!NT_SUCCESS(Status))
424 return Status;
425
426 if (AbsFileName)
427 {
428 if (wcslen(AbsFileName) >= MAX_PATH)
429 {
430 ExFreePoolWithTag(AbsFileName, TAG_NTFS);
432 }
433
434 wcscpy(Path, AbsFileName);
435 ExFreePoolWithTag(AbsFileName, TAG_NTFS);
436 }
437 }
438
439 /* A trailing separator names nothing */
440 Length = wcslen(Path);
441 while (Length > 1 && Path[Length - 1] == L'\\')
443
444 LastSeparator = wcsrchr(Path, L'\\');
445 if (LastSeparator == NULL || LastSeparator[1] == UNICODE_NULL)
447
448 wcscpy(FinalBuffer, LastSeparator + 1);
449 RtlInitUnicodeString(&FinalName, FinalBuffer);
450
451 /* Cut the path down to the directory, keeping the root's separator */
452 if (LastSeparator == Path)
453 LastSeparator[1] = UNICODE_NULL;
454 else
455 *LastSeparator = UNICODE_NULL;
456
457 Fcb = NtfsGrabFCBFromTable(DeviceExt, Path);
458 if (Fcb == NULL)
459 {
460 Status = NtfsGetFCBForFile(DeviceExt, &ParentFcb, &Fcb, Path, CaseSensitive);
461 if (ParentFcb != NULL)
462 NtfsReleaseFCB(DeviceExt, ParentFcb);
463
464 if (!NT_SUCCESS(Status))
466 }
467
469 {
470 NtfsReleaseFCB(DeviceExt, Fcb);
472 }
473
474 Status = NtfsFindMftRecord(DeviceExt, Fcb->MFTIndex, &FinalName, &FirstEntry, FALSE, CaseSensitive, &ExistingMft);
476
478 if (!NT_SUCCESS(Status))
479 {
480 NtfsReleaseFCB(DeviceExt, Fcb);
481 return Status;
482 }
483
484 /* The final component is a suffix of the original name, so it fits */
485 RtlMoveMemory(FileObject->FileName.Buffer, FinalName.Buffer, FinalName.Length);
486 FileObject->FileName.Length = FinalName.Length;
487
488 return STATUS_SUCCESS;
489}
PRTL_UNICODE_STRING_BUFFER Path
static BOOLEAN NtfsFindMftRecord(_In_ PNTFS_VOLUME_INFO Volume, _In_ ULONGLONG MFTIndex, _In_ PCSTR FileName, _Out_ PULONGLONG OutMFTIndex, _Out_ PULONG FileAttributes)
Definition: ntfs.c:675
#define wcsrchr
Definition: compat.h:16
#define FILE_DOES_NOT_EXIST
Definition: nt_native.h:773
#define UNICODE_NULL
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define STATUS_NAME_TOO_LONG
Definition: ntstatus.h:592
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
#define STATUS_OBJECT_NAME_INVALID
Definition: udferr_usr.h:148

Referenced by NtfsCreateFile().

Variable Documentation

◆ MftIdToName

PCWSTR MftIdToName[]
static
Initial value:
= {
L"$MFT",
L"$MFTMirr",
L"$LogFile",
L"$Volume",
L"AttrDef",
L".",
L"$Bitmap",
L"$Boot",
L"$BadClus",
L"$Quota",
L"$UpCase",
L"$Extended",
}

Definition at line 34 of file create.c.

Referenced by NtfsOpenFileById().