[FASTFAT]

Implement part 2/3 (first part was in ntoskrnl, remember ;-)) of renaming support in ReactOS.

Here, we implement support for SL_OPEN_TARGET_DIRECTORY for IRP_MJ_CREATE in fastfat. The code is not the best ever, but we can't do miracles with fastfat.
This fixes a few tests in KmTests:IoCreateFile and also shows failures I still don't get and that will require deeper attention.

Last part will be to effectively bring support of FileRenameInformation in IRP_MJ_SET_INFORMATION. But this is yet another story.

svn path=/trunk/; revision=63034
This commit is contained in:
Pierre Schweitzer 2014-04-28 19:40:26 +00:00
parent c06ae88245
commit 56a5ebef81

View file

@ -352,6 +352,7 @@ VfatOpenFile(
PUNICODE_STRING PathNameU,
PFILE_OBJECT FileObject,
ULONG RequestedDisposition,
BOOLEAN OpenTargetDir,
PVFATFCB *ParentFcb)
{
PVFATFCB Fcb;
@ -402,6 +403,14 @@ VfatOpenFile(
DPRINT ("Could not make a new FCB, status: %x\n", Status);
return Status;
}
/* In case we're to open target, just check whether file exist, but don't open it */
if (OpenTargetDir)
{
vfatReleaseFCB(DeviceExt, Fcb);
return STATUS_OBJECT_NAME_COLLISION;
}
if (Fcb->Flags & FCB_DELETE_PENDING)
{
vfatReleaseFCB(DeviceExt, Fcb);
@ -443,6 +452,7 @@ VfatCreateFile(
PWCHAR c, last;
BOOLEAN PagingFileCreate = FALSE;
BOOLEAN Dots;
BOOLEAN OpenTargetDir = FALSE;
UNICODE_STRING FileNameU;
UNICODE_STRING PathNameU;
ULONG Attributes;
@ -452,6 +462,7 @@ VfatCreateFile(
RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff);
RequestedOptions = Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
PagingFileCreate = (Stack->Flags & SL_OPEN_PAGING_FILE) ? TRUE : FALSE;
OpenTargetDir = (Stack->Flags & SL_OPEN_TARGET_DIRECTORY) ? TRUE : FALSE;
FileObject = Stack->FileObject;
DeviceExt = DeviceObject->DeviceExtension;
@ -485,6 +496,11 @@ VfatCreateFile(
}
#endif
if (OpenTargetDir)
{
return STATUS_INVALID_PARAMETER;
}
pFcb = DeviceExt->VolumeFcb;
vfatAttachFCBToFileObject(DeviceExt, pFcb, FileObject);
pFcb->RefCount++;
@ -520,6 +536,13 @@ VfatCreateFile(
}
}
/* Check if we try to open target directory of root dir */
if (OpenTargetDir && FileObject->RelatedFileObject == NULL && PathNameU.Length == sizeof(WCHAR) &&
PathNameU.Buffer[0] == L'\\')
{
return STATUS_INVALID_PARAMETER;
}
if (FileObject->RelatedFileObject && PathNameU.Length >= sizeof(WCHAR) && PathNameU.Buffer[0] == L'\\')
{
return STATUS_OBJECT_NAME_INVALID;
@ -531,7 +554,86 @@ VfatCreateFile(
}
/* Try opening the file. */
Status = VfatOpenFile(DeviceExt, &PathNameU, FileObject, RequestedDisposition, &ParentFcb);
Status = VfatOpenFile(DeviceExt, &PathNameU, FileObject, RequestedDisposition, OpenTargetDir, &ParentFcb);
if (OpenTargetDir)
{
LONG idx, FileNameLen;
if (Status == STATUS_OBJECT_NAME_COLLISION)
{
Irp->IoStatus.Information = FILE_EXISTS;
}
else
{
Irp->IoStatus.Information = FILE_DOES_NOT_EXIST;
}
idx = FileObject->FileName.Length / sizeof(WCHAR) - 1;
/* Skip tailing \ - if any */
if (PathNameU.Buffer[idx] == L'\\')
{
--idx;
PathNameU.Length -= sizeof(WCHAR);
}
/* Get file name */
while (idx >= 0 && PathNameU.Buffer[idx] != L'\\')
{
--idx;
}
if (idx > 0)
{
/* We don't want to include / in the name */
FileNameLen = PathNameU.Length - ((idx + 1) * sizeof(WCHAR));
/* Try to open parent */
PathNameU.Length -= (PathNameU.Length - idx * sizeof(WCHAR));
Status = VfatOpenFile(DeviceExt, &PathNameU, FileObject, RequestedDisposition, FALSE, &ParentFcb);
/* Update FO just to keep file name */
/* Skip first slash */
++idx;
PathNameU.Length = FileNameLen;
RtlMoveMemory(&PathNameU.Buffer[0], &PathNameU.Buffer[idx], PathNameU.Length);
}
else
{
/* This is a relative open and we have only the filename, so open the parent directory
* It is in RelatedFileObject
*/
BOOLEAN Chomp = FALSE;
PFILE_OBJECT RelatedFileObject = FileObject->RelatedFileObject;
DPRINT("%wZ\n", &PathNameU);
ASSERT(RelatedFileObject != NULL);
DPRINT("Relative opening\n");
DPRINT("FileObject->RelatedFileObject->FileName: %wZ\n", &RelatedFileObject->FileName);
/* VfatOpenFile() doesn't like our name ends with \, so chomp it if there's one */
if (RelatedFileObject->FileName.Buffer[RelatedFileObject->FileName.Length / sizeof(WCHAR) - 1] == L'\\')
{
Chomp = FALSE;
RelatedFileObject->FileName.Length -= sizeof(WCHAR);
}
/* Tricky part - fake our FO. It's NOT relative, we want to open the complete file path */
FileObject->RelatedFileObject = NULL;
Status = VfatOpenFile(DeviceExt, &RelatedFileObject->FileName, FileObject, RequestedDisposition, FALSE, &ParentFcb);
/* We're done opening, restore what we broke */
FileObject->RelatedFileObject = RelatedFileObject;
if (Chomp) RelatedFileObject->FileName.Length += sizeof(WCHAR);
/* No need to modify the FO, it already has the name */
}
return Status;
}
/*
* If the directory containing the file to open doesn't exist then