mirror of
https://github.com/reactos/reactos.git
synced 2025-05-20 01:24:11 +00:00
[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:
parent
c06ae88245
commit
56a5ebef81
1 changed files with 103 additions and 1 deletions
|
@ -352,6 +352,7 @@ VfatOpenFile(
|
||||||
PUNICODE_STRING PathNameU,
|
PUNICODE_STRING PathNameU,
|
||||||
PFILE_OBJECT FileObject,
|
PFILE_OBJECT FileObject,
|
||||||
ULONG RequestedDisposition,
|
ULONG RequestedDisposition,
|
||||||
|
BOOLEAN OpenTargetDir,
|
||||||
PVFATFCB *ParentFcb)
|
PVFATFCB *ParentFcb)
|
||||||
{
|
{
|
||||||
PVFATFCB Fcb;
|
PVFATFCB Fcb;
|
||||||
|
@ -402,6 +403,14 @@ VfatOpenFile(
|
||||||
DPRINT ("Could not make a new FCB, status: %x\n", Status);
|
DPRINT ("Could not make a new FCB, status: %x\n", Status);
|
||||||
return 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)
|
if (Fcb->Flags & FCB_DELETE_PENDING)
|
||||||
{
|
{
|
||||||
vfatReleaseFCB(DeviceExt, Fcb);
|
vfatReleaseFCB(DeviceExt, Fcb);
|
||||||
|
@ -443,6 +452,7 @@ VfatCreateFile(
|
||||||
PWCHAR c, last;
|
PWCHAR c, last;
|
||||||
BOOLEAN PagingFileCreate = FALSE;
|
BOOLEAN PagingFileCreate = FALSE;
|
||||||
BOOLEAN Dots;
|
BOOLEAN Dots;
|
||||||
|
BOOLEAN OpenTargetDir = FALSE;
|
||||||
UNICODE_STRING FileNameU;
|
UNICODE_STRING FileNameU;
|
||||||
UNICODE_STRING PathNameU;
|
UNICODE_STRING PathNameU;
|
||||||
ULONG Attributes;
|
ULONG Attributes;
|
||||||
|
@ -452,6 +462,7 @@ VfatCreateFile(
|
||||||
RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff);
|
RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff);
|
||||||
RequestedOptions = Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
|
RequestedOptions = Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
|
||||||
PagingFileCreate = (Stack->Flags & SL_OPEN_PAGING_FILE) ? TRUE : FALSE;
|
PagingFileCreate = (Stack->Flags & SL_OPEN_PAGING_FILE) ? TRUE : FALSE;
|
||||||
|
OpenTargetDir = (Stack->Flags & SL_OPEN_TARGET_DIRECTORY) ? TRUE : FALSE;
|
||||||
FileObject = Stack->FileObject;
|
FileObject = Stack->FileObject;
|
||||||
DeviceExt = DeviceObject->DeviceExtension;
|
DeviceExt = DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
@ -485,6 +496,11 @@ VfatCreateFile(
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (OpenTargetDir)
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
pFcb = DeviceExt->VolumeFcb;
|
pFcb = DeviceExt->VolumeFcb;
|
||||||
vfatAttachFCBToFileObject(DeviceExt, pFcb, FileObject);
|
vfatAttachFCBToFileObject(DeviceExt, pFcb, FileObject);
|
||||||
pFcb->RefCount++;
|
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'\\')
|
if (FileObject->RelatedFileObject && PathNameU.Length >= sizeof(WCHAR) && PathNameU.Buffer[0] == L'\\')
|
||||||
{
|
{
|
||||||
return STATUS_OBJECT_NAME_INVALID;
|
return STATUS_OBJECT_NAME_INVALID;
|
||||||
|
@ -531,7 +554,86 @@ VfatCreateFile(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try opening the file. */
|
/* 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
|
* If the directory containing the file to open doesn't exist then
|
||||||
|
|
Loading…
Reference in a new issue