mirror of
https://github.com/reactos/reactos.git
synced 2025-05-19 00:54:18 +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,
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue