Author: pschweitzer
Date: Mon Apr 28 19:40:26 2014
New Revision: 63034
URL:
http://svn.reactos.org/svn/reactos?rev=63034&view=rev
Log:
[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.
Modified:
trunk/reactos/drivers/filesystems/fastfat/create.c
Modified: trunk/reactos/drivers/filesystems/fastfat/create.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfa…
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat/create.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/fastfat/create.c [iso-8859-1] Mon Apr 28 19:40:26
2014
@@ -352,6 +352,7 @@
PUNICODE_STRING PathNameU,
PFILE_OBJECT FileObject,
ULONG RequestedDisposition,
+ BOOLEAN OpenTargetDir,
PVFATFCB *ParentFcb)
{
PVFATFCB Fcb;
@@ -402,6 +403,14 @@
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 @@
PWCHAR c, last;
BOOLEAN PagingFileCreate = FALSE;
BOOLEAN Dots;
+ BOOLEAN OpenTargetDir = FALSE;
UNICODE_STRING FileNameU;
UNICODE_STRING PathNameU;
ULONG Attributes;
@@ -452,6 +462,7 @@
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;
@@ -484,6 +495,11 @@
return STATUS_NOT_A_DIRECTORY;
}
#endif
+
+ if (OpenTargetDir)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
pFcb = DeviceExt->VolumeFcb;
vfatAttachFCBToFileObject(DeviceExt, pFcb, FileObject);
@@ -520,6 +536,13 @@
}
}
+ /* 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 @@
}
/* 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