*/
/*
* PROJECT: ReactOS kernel
- * FILE: drivers/fs/vfat/create.c
+ * FILE: drivers/filesystems/fastfat/create.c
* PURPOSE: VFAT Filesystem
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
+ * Pierre Schweitzer (pierre@reactos.org)
*/
/* INCLUDES *****************************************************************/
DPRINT("'%wZ'\n", &FileObject->RelatedFileObject->FileName);
*ParentFcb = FileObject->RelatedFileObject->FsContext;
- (*ParentFcb)->RefCount++;
}
else
{
if (*ParentFcb)
{
- (*ParentFcb)->RefCount++;
+ vfatGrabFCB(DeviceExt, *ParentFcb);
}
/* try first to find an existing FCB in memory */
DPRINT ("Could not make a new FCB, status: %x\n", Status);
return Status;
}
+
if (Fcb->Flags & FCB_DELETE_PENDING)
{
vfatReleaseFCB(DeviceExt, Fcb);
PVFATFCB pFcb = NULL;
PVFATFCB ParentFcb = NULL;
PWCHAR c, last;
- BOOLEAN PagingFileCreate = FALSE;
+ BOOLEAN PagingFileCreate;
BOOLEAN Dots;
+ BOOLEAN OpenTargetDir;
UNICODE_STRING FileNameU;
UNICODE_STRING PathNameU;
ULONG Attributes;
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;
return STATUS_INVALID_PARAMETER;
}
+ /* Deny create if the volume is locked */
+ if (DeviceExt->Flags & VCB_VOLUME_LOCKED)
+ {
+ return STATUS_ACCESS_DENIED;
+ }
+
/* This a open operation for the volume itself */
if (FileObject->FileName.Length == 0 &&
(FileObject->RelatedFileObject == NULL || FileObject->RelatedFileObject->FsContext2 != NULL))
{
+ DPRINT("Volume opening\n");
+
if (RequestedDisposition != FILE_OPEN &&
RequestedDisposition != FILE_OPEN_IF)
{
}
#endif
+ if (OpenTargetDir)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
pFcb = DeviceExt->VolumeFcb;
+
+ if (pFcb->OpenHandleCount == 0)
+ {
+ IoSetShareAccess(Stack->Parameters.Create.SecurityContext->DesiredAccess,
+ Stack->Parameters.Create.ShareAccess,
+ FileObject,
+ &pFcb->FCBShareAccess);
+ }
+ else
+ {
+ Status = IoCheckShareAccess(Stack->Parameters.Create.SecurityContext->DesiredAccess,
+ Stack->Parameters.Create.ShareAccess,
+ FileObject,
+ &pFcb->FCBShareAccess,
+ FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+
vfatAttachFCBToFileObject(DeviceExt, pFcb, FileObject);
- pFcb->RefCount++;
+ DeviceExt->OpenHandleCount++;
+ pFcb->OpenHandleCount++;
Irp->IoStatus.Information = FILE_OPENED;
return STATUS_SUCCESS;
}
}
+ /* 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;
}
/* Try opening the file. */
- Status = VfatOpenFile(DeviceExt, &PathNameU, FileObject, RequestedDisposition, &ParentFcb);
+ if (!OpenTargetDir)
+ {
+ Status = VfatOpenFile(DeviceExt, &PathNameU, FileObject, RequestedDisposition, &ParentFcb);
+ }
+ else
+ {
+ PVFATFCB TargetFcb;
+ LONG idx, FileNameLen;
+
+ ParentFcb = (FileObject->RelatedFileObject != NULL) ? FileObject->RelatedFileObject->FsContext : NULL;
+ if (ParentFcb)
+ {
+ vfatGrabFCB(DeviceExt, ParentFcb);
+ }
+ Status = vfatGetFCBForFile(DeviceExt, &ParentFcb, &TargetFcb, &PathNameU);
+
+ if (NT_SUCCESS(Status))
+ {
+ vfatReleaseFCB(DeviceExt, TargetFcb);
+ Irp->IoStatus.Information = FILE_EXISTS;
+ }
+ else
+ {
+ Irp->IoStatus.Information = FILE_DOES_NOT_EXIST;
+ }
+
+ idx = FileObject->FileName.Length / sizeof(WCHAR) - 1;
+
+ /* Skip trailing \ - 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 || PathNameU.Buffer[0] == L'\\')
+ {
+ /* We don't want to include / in the name */
+ FileNameLen = PathNameU.Length - ((idx + 1) * sizeof(WCHAR));
+
+ /* Update FO just to keep file name */
+ /* Skip first slash */
+ ++idx;
+ FileObject->FileName.Length = FileNameLen;
+ RtlMoveMemory(&PathNameU.Buffer[0], &PathNameU.Buffer[idx], FileObject->FileName.Length);
+ }
+ else
+ {
+ /* This is a relative open and we have only the filename, so open the parent directory
+ * It is in RelatedFileObject
+ */
+ ASSERT(FileObject->RelatedFileObject != NULL);
+
+ /* No need to modify the FO, it already has the name */
+ }
+
+ /* We're done with opening! */
+ if (ParentFcb != NULL)
+ {
+ Status = vfatAttachFCBToFileObject(DeviceExt, ParentFcb, FileObject);
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ pFcb = FileObject->FsContext;
+ ASSERT(pFcb == ParentFcb);
+
+ if (pFcb->OpenHandleCount == 0)
+ {
+ IoSetShareAccess(Stack->Parameters.Create.SecurityContext->DesiredAccess,
+ Stack->Parameters.Create.ShareAccess,
+ FileObject,
+ &pFcb->FCBShareAccess);
+ }
+ else
+ {
+ Status = IoCheckShareAccess(Stack->Parameters.Create.SecurityContext->DesiredAccess,
+ Stack->Parameters.Create.ShareAccess,
+ FileObject,
+ &pFcb->FCBShareAccess,
+ FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ VfatCloseFile(DeviceExt, FileObject);
+ return Status;
+ }
+ }
+
+ pFcb->OpenHandleCount++;
+ DeviceExt->OpenHandleCount++;
+ }
+ else if (ParentFcb != NULL)
+ {
+ vfatReleaseFCB(DeviceExt, ParentFcb);
+ }
+
+ return Status;
+ }
/*
* If the directory containing the file to open doesn't exist then
if (!NT_SUCCESS(Status) && ParentFcb == NULL)
{
- DPRINT1("VfatOpenFile faild for '%wZ', status %x\n", &PathNameU, Status);
+ DPRINT1("VfatOpenFile failed for '%wZ', status %x\n", &PathNameU, Status);
return Status;
}
Attributes |= FILE_ATTRIBUTE_ARCHIVE;
vfatSplitPathName(&PathNameU, NULL, &FileNameU);
Status = VfatAddEntry(DeviceExt, &FileNameU, &pFcb, ParentFcb, RequestedOptions,
- (UCHAR)(Attributes & FILE_ATTRIBUTE_VALID_FLAGS));
+ (UCHAR)(Attributes & FILE_ATTRIBUTE_VALID_FLAGS), NULL);
vfatReleaseFCB(DeviceExt, ParentFcb);
if (NT_SUCCESS(Status))
{
pFcb->PathNameU.Length - pFcb->LongNameU.Length,
NULL,
NULL,
- FILE_NOTIFY_CHANGE_FILE_NAME,
+ ((*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY) ?
+ FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME),
FILE_ACTION_ADDED,
NULL);
}
pFcb->OpenHandleCount++;
+ DeviceExt->OpenHandleCount++;
/* FIXME : test write access if requested */