/*
* FUNCTION: Retrieve the standard file information
*/
-static
NTSTATUS
VfatGetStandardInformation(
PVFATFCB FCB,
return STATUS_SUCCESS;
}
-static
NTSTATUS
VfatGetBasicInformation(
PFILE_OBJECT FileObject,
(FCB->LongNameU.Length == sizeof(WCHAR) && FCB->LongNameU.Buffer[0] == L'.') ||
(FCB->LongNameU.Length == 2 * sizeof(WCHAR) && FCB->LongNameU.Buffer[0] == L'.' && FCB->LongNameU.Buffer[1] == L'.'))
{
- // we cannot delete a '.', '..' or the root directory
+ /* we cannot delete a '.', '..' or the root directory */
return STATUS_ACCESS_DENIED;
}
-
if (!MmFlushImageSection (FileObject->SectionObjectPointer, MmFlushForDelete))
{
/* can't delete a file if its mapped into a process */
return Status;
}
+static
+BOOLEAN
+IsThereAChildOpened(PVFATFCB FCB)
+{
+ PLIST_ENTRY Entry;
+ PVFATFCB VolFCB;
+
+ for (Entry = FCB->ParentListHead.Flink; Entry != &FCB->ParentListHead; Entry = Entry->Flink)
+ {
+ VolFCB = CONTAINING_RECORD(Entry, VFATFCB, ParentListEntry);
+ if (VolFCB->OpenHandleCount != 0)
+ {
+ ASSERT(VolFCB->parentFcb == FCB);
+ DPRINT1("At least one children file opened! %wZ (%u, %u)\n", &VolFCB->PathNameU, VolFCB->RefCount, VolFCB->OpenHandleCount);
+ return TRUE;
+ }
+
+ if (vfatFCBIsDirectory(VolFCB) && !IsListEmpty(&VolFCB->ParentListHead))
+ {
+ if (IsThereAChildOpened(VolFCB))
+ {
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+static
+VOID
+VfatRenameChildFCB(
+ PDEVICE_EXTENSION DeviceExt,
+ PVFATFCB FCB)
+{
+ PLIST_ENTRY Entry;
+ PVFATFCB Child;
+
+ if (IsListEmpty(&FCB->ParentListHead))
+ return;
+
+ for (Entry = FCB->ParentListHead.Flink; Entry != &FCB->ParentListHead; Entry = Entry->Flink)
+ {
+ NTSTATUS Status;
+
+ Child = CONTAINING_RECORD(Entry, VFATFCB, ParentListEntry);
+ DPRINT("Found %wZ with still %lu references (parent: %lu)!\n", &Child->PathNameU, Child->RefCount, FCB->RefCount);
+
+ Status = vfatSetFCBNewDirName(DeviceExt, Child, FCB);
+ if (!NT_SUCCESS(Status))
+ continue;
+
+ if (vfatFCBIsDirectory(Child))
+ {
+ VfatRenameChildFCB(DeviceExt, Child);
+ }
+ }
+}
+
/*
* FUNCTION: Set the file name information
*/
RootFCB = RootFileObject->FsContext;
}
+ RtlInitEmptyUnicodeString(&NewName, NULL, 0);
ParentFCB = NULL;
if (TargetFileObject == NULL)
vfatSplitPathName(&NewName, &NewPath, &NewFile);
DPRINT("New dir: %wZ, New file: %wZ\n", &NewPath, &NewFile);
+ if (vfatFCBIsDirectory(FCB) && !IsListEmpty(&FCB->ParentListHead))
+ {
+ if (IsThereAChildOpened(FCB))
+ {
+ Status = STATUS_ACCESS_DENIED;
+ ASSERT(OldReferences == FCB->parentFcb->RefCount);
+ goto Cleanup;
+ }
+ }
+
/* Are we working in place? */
if (FsRtlAreNamesEqual(&SourcePath, &NewPath, TRUE, NULL))
{
}
}
+ if (NT_SUCCESS(Status) && vfatFCBIsDirectory(FCB))
+ {
+ VfatRenameChildFCB(DeviceExt, FCB);
+ }
+
ASSERT(OldReferences == OldParent->RefCount + 1); // removed file
ASSERT(NewReferences == ParentFCB->RefCount - 1); // new file
Cleanup:
PULONG BufferLength)
{
NTSTATUS Status;
- ULONG InitialBufferLength = *BufferLength;
ASSERT(Info);
ASSERT(Fcb);
- if (*BufferLength < sizeof(FILE_ALL_INFORMATION) + Fcb->PathNameU.Length + sizeof(WCHAR))
- return(STATUS_BUFFER_OVERFLOW);
+ if (*BufferLength < FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName))
+ return STATUS_BUFFER_OVERFLOW;
/* Basic Information */
Status = VfatGetBasicInformation(FileObject, Fcb, DeviceObject, &Info->BasicInformation, BufferLength);
Status = VfatGetInternalInformation(Fcb, &Info->InternalInformation, BufferLength);
if (!NT_SUCCESS(Status)) return Status;
/* EA Information */
- Info->EaInformation.EaSize = 0;
+ Status = VfatGetEaInformation(FileObject, Fcb, DeviceObject, &Info->EaInformation, BufferLength);
+ if (!NT_SUCCESS(Status)) return Status;
/* Access Information: The IO-Manager adds this information */
+ *BufferLength -= sizeof(FILE_ACCESS_INFORMATION);
/* Position Information */
Status = VfatGetPositionInformation(FileObject, Fcb, DeviceObject, &Info->PositionInformation, BufferLength);
if (!NT_SUCCESS(Status)) return Status;
/* Mode Information: The IO-Manager adds this information */
+ *BufferLength -= sizeof(FILE_MODE_INFORMATION);
/* Alignment Information: The IO-Manager adds this information */
+ *BufferLength -= sizeof(FILE_ALIGNMENT_INFORMATION);
/* Name Information */
Status = VfatGetNameInformation(FileObject, Fcb, DeviceObject, &Info->NameInformation, BufferLength);
- if (!NT_SUCCESS(Status)) return Status;
-
- *BufferLength = InitialBufferLength - (sizeof(FILE_ALL_INFORMATION) + Fcb->PathNameU.Length + sizeof(WCHAR));
- return STATUS_SUCCESS;
+ return Status;
}
static
{
if (Size > 0)
{
- Fcb->RFCB.AllocationSize.QuadPart = ROUND_UP(Size, ClusterSize);
+ Fcb->RFCB.AllocationSize.QuadPart = ROUND_UP_64(Size, ClusterSize);
}
else
{
PVFAT_IRP_CONTEXT IrpContext)
{
FILE_INFORMATION_CLASS FileInformationClass;
- PVFATFCB FCB = NULL;
+ PVFATFCB FCB;
NTSTATUS Status = STATUS_SUCCESS;
PVOID SystemBuffer;
DPRINT("VfatQueryInformation is called for '%s'\n",
FileInformationClass >= FileMaximumInformation - 1 ? "????" : FileInformationClassNames[FileInformationClass]);
+ if (FCB == NULL)
+ {
+ DPRINT1("IRP_MJ_QUERY_INFORMATION without FCB!\n");
+ IrpContext->Irp->IoStatus.Information = 0;
+ return STATUS_INVALID_PARAMETER;
+ }
SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer;
BufferLength = IrpContext->Stack->Parameters.QueryFile.Length;
if (!(FCB->Flags & FCB_IS_PAGE_FILE))
{
if (!ExAcquireResourceSharedLite(&FCB->MainResource,
- (BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT)))
+ BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT)))
{
- return VfatQueueRequest(IrpContext);
+ return VfatMarkIrpContextForQueue(IrpContext);
}
}
ExReleaseResourceLite(&FCB->MainResource);
}
- IrpContext->Irp->IoStatus.Status = Status;
if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW)
IrpContext->Irp->IoStatus.Information =
IrpContext->Stack->Parameters.QueryFile.Length - BufferLength;
else
IrpContext->Irp->IoStatus.Information = 0;
- IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
- VfatFreeIrpContext(IrpContext);
return Status;
}
PVFAT_IRP_CONTEXT IrpContext)
{
FILE_INFORMATION_CLASS FileInformationClass;
- PVFATFCB FCB = NULL;
+ PVFATFCB FCB;
NTSTATUS Status = STATUS_SUCCESS;
PVOID SystemBuffer;
DPRINT("FileInformationClass %d\n", FileInformationClass);
DPRINT("SystemBuffer %p\n", SystemBuffer);
+ if (FCB == NULL)
+ {
+ DPRINT1("IRP_MJ_SET_INFORMATION without FCB!\n");
+ IrpContext->Irp->IoStatus.Information = 0;
+ return STATUS_INVALID_PARAMETER;
+ }
+
/* Special: We should call MmCanFileBeTruncated here to determine if changing
the file size would be allowed. If not, we bail with the right error.
We must do this before acquiring the lock. */
(PLARGE_INTEGER)SystemBuffer))
{
DPRINT("Couldn't set file size!\n");
- IrpContext->Irp->IoStatus.Status = STATUS_USER_MAPPED_FILE;
IrpContext->Irp->IoStatus.Information = 0;
- IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
- VfatFreeIrpContext(IrpContext);
return STATUS_USER_MAPPED_FILE;
}
DPRINT("Can set file size\n");
if (FileInformationClass == FileRenameInformation)
{
if (!ExAcquireResourceExclusiveLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource,
- (BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT)))
+ BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT)))
{
- return VfatQueueRequest(IrpContext);
+ return VfatMarkIrpContextForQueue(IrpContext);
}
}
if (!(FCB->Flags & FCB_IS_PAGE_FILE))
{
if (!ExAcquireResourceExclusiveLite(&FCB->MainResource,
- (BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT)))
+ BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT)))
{
if (FileInformationClass == FileRenameInformation)
{
ExReleaseResourceLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource);
}
- return VfatQueueRequest(IrpContext);
+
+ return VfatMarkIrpContextForQueue(IrpContext);
}
}
ExReleaseResourceLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource);
}
- IrpContext->Irp->IoStatus.Status = Status;
IrpContext->Irp->IoStatus.Information = 0;
- IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
- VfatFreeIrpContext(IrpContext);
-
return Status;
}