NtfsOpenFile(PDEVICE_EXTENSION DeviceExt,
PFILE_OBJECT FileObject,
PWSTR FileName,
+ BOOLEAN CaseSensitive,
PNTFS_FCB * FoundFCB)
{
PNTFS_FCB ParentFcb;
NTSTATUS Status;
PWSTR AbsFileName = NULL;
- DPRINT1("NtfsOpenFile(%p, %p, %S, %p)\n", DeviceExt, FileObject, FileName, FoundFCB);
+ DPRINT1("NtfsOpenFile(%p, %p, %S, %s, %p)\n",
+ DeviceExt,
+ FileObject,
+ FileName,
+ CaseSensitive ? "TRUE" : "FALSE",
+ FoundFCB);
*FoundFCB = NULL;
Status = NtfsGetFCBForFile(DeviceExt,
&ParentFcb,
&Fcb,
- FileName);
+ FileName,
+ CaseSensitive);
if (ParentFcb != NULL)
{
NtfsReleaseFCB(DeviceExt,
static
NTSTATUS
NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
- PIRP Irp)
+ PNTFS_IRP_CONTEXT IrpContext)
{
PDEVICE_EXTENSION DeviceExt;
PIO_STACK_LOCATION Stack;
// PWSTR FileName;
NTSTATUS Status;
UNICODE_STRING FullPath;
+ PIRP Irp = IrpContext->Irp;
- DPRINT1("NtfsCreateFile(%p, %p) called\n", DeviceObject, Irp);
+ DPRINT1("NtfsCreateFile(%p, %p) called\n", DeviceObject, IrpContext);
DeviceExt = DeviceObject->DeviceExtension;
ASSERT(DeviceExt);
Status = NtfsOpenFile(DeviceExt,
FileObject,
((RequestedOptions & FILE_OPEN_BY_FILE_ID) ? FullPath.Buffer : FileObject->FileName.Buffer),
+ (Stack->Flags & SL_CASE_SENSITIVE),
&Fcb);
if (RequestedOptions & FILE_OPEN_BY_FILE_ID)
DoneOverwriting:
if (fileRecord)
- ExFreePool(fileRecord);
+ ExFreePoolWithTag(fileRecord, TAG_NTFS);
if (dataContext)
ReleaseAttributeContext(dataContext);
}
// Create the file record on disk
- Status = NtfsCreateFileRecord(DeviceExt, FileObject);
-
- // Update the parent directory index
- // Still TODO
-
- // Call NtfsOpenFile()
+ Status = NtfsCreateFileRecord(DeviceExt,
+ FileObject,
+ (Stack->Flags & SL_CASE_SENSITIVE),
+ BooleanFlagOn(IrpContext->Flags,IRPCONTEXT_CANWAIT));
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("ERROR: Couldn't create file record!\n");
+ return Status;
+ }
- return STATUS_CANNOT_MAKE;
+ // Now we should be able to open the file
+ return NtfsCreateFile(DeviceObject, IrpContext);
}
}
ExAcquireResourceExclusiveLite(&DeviceExt->DirResource,
TRUE);
Status = NtfsCreateFile(DeviceObject,
- IrpContext->Irp);
+ IrpContext);
ExReleaseResourceLite(&DeviceExt->DirResource);
return Status;
* @name NtfsCreateFileRecord()
* @implemented
*
-* Creates a file record and saves it to the MFT.
+* Creates a file record and saves it to the MFT. Adds the filename attribute of the
+* created file to the parent directory's index.
*
* @param DeviceExt
* Points to the target disk's DEVICE_EXTENSION
* @param FileObject
* Pointer to a FILE_OBJECT describing the file to be created
*
+* @param CanWait
+* Boolean 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.
+*
* @return
* 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)
+ PFILE_OBJECT FileObject,
+ BOOLEAN CaseSensitive,
+ BOOLEAN CanWait)
{
NTSTATUS Status = STATUS_SUCCESS;
PFILE_RECORD_HEADER FileRecord;
PNTFS_ATTR_RECORD NextAttribute;
+ PFILENAME_ATTRIBUTE FilenameAttribute;
+ ULONGLONG ParentMftIndex;
+ ULONGLONG FileMftIndex;
+
+ DPRINT1("NtfsCreateFileRecord(%p, %p, %s, %s)\n",
+ DeviceExt,
+ FileObject,
+ CaseSensitive ? "TRUE" : "FALSE",
+ CanWait ? "TRUE" : "FALSE");
// allocate memory for file record
FileRecord = ExAllocatePoolWithTag(NonPagedPool,
NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)NextAttribute + (ULONG_PTR)NextAttribute->Length);
// Add the $FILE_NAME attribute
- AddFileName(FileRecord, NextAttribute, DeviceExt, FileObject);
+ AddFileName(FileRecord, NextAttribute, DeviceExt, FileObject, CaseSensitive, &ParentMftIndex);
+
+ // save a pointer to the filename attribute
+ FilenameAttribute = (PFILENAME_ATTRIBUTE)((ULONG_PTR)NextAttribute + NextAttribute->Resident.ValueOffset);
// advance NextAttribute pointer to the next attribute
NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)NextAttribute + (ULONG_PTR)NextAttribute->Length);
NtfsDumpFileRecord(DeviceExt, FileRecord);
// Now that we've built the file record in memory, we need to store it in the MFT.
- Status = AddNewMftEntry(FileRecord, DeviceExt);
+ Status = AddNewMftEntry(FileRecord, DeviceExt, &FileMftIndex, CanWait);
+ if (NT_SUCCESS(Status))
+ {
+ // The highest 2 bytes should be the sequence number, unless the parent happens to be root
+ if (FileMftIndex == NTFS_FILE_ROOT)
+ FileMftIndex = FileMftIndex + ((ULONGLONG)NTFS_FILE_ROOT << 48);
+ else
+ FileMftIndex = FileMftIndex + ((ULONGLONG)FileRecord->SequenceNumber << 48);
+
+ DPRINT1("New File Reference: 0x%016I64x\n", FileMftIndex);
+
+ // Add the filename attribute to the filename-index of the parent directory
+ Status = NtfsAddFilenameToDirectory(DeviceExt,
+ ParentMftIndex,
+ FileMftIndex,
+ FilenameAttribute);
+ }
ExFreePoolWithTag(FileRecord, TAG_NTFS);