static NTSTATUS
VfatGetStandardInformation(PVFATFCB FCB,
- PDEVICE_OBJECT DeviceObject,
PFILE_STANDARD_INFORMATION StandardInfo,
PULONG BufferLength)
/*
* FUNCTION: Retrieve the standard file information
*/
{
- PDEVICE_EXTENSION DeviceExtension;
if (*BufferLength < sizeof(FILE_STANDARD_INFORMATION))
return STATUS_BUFFER_OVERFLOW;
- DeviceExtension = DeviceObject->DeviceExtension;
/* PRECONDITION */
- assert (DeviceExtension != NULL);
- assert (DeviceExtension->FatInfo.BytesPerCluster != 0);
assert (StandardInfo != NULL);
assert (FCB != NULL);
static NTSTATUS
VfatSetPositionInformation(PFILE_OBJECT FileObject,
- PVFATFCB FCB,
- PDEVICE_OBJECT DeviceObject,
PFILE_POSITION_INFORMATION PositionInfo)
{
DPRINT ("FsdSetPositionInformation()\n");
}
static NTSTATUS
+VfatSetBasicInformation(PFILE_OBJECT FileObject,
+ PVFATFCB FCB,
+ PDEVICE_EXTENSION DeviceExt,
+ PFILE_BASIC_INFORMATION BasicInfo)
+{
+ DPRINT("VfatSetBasicInformation()\n");
+
+ assert (NULL != FileObject);
+ assert (NULL != FCB);
+ assert (NULL != DeviceExt);
+ assert (NULL != BasicInfo);
+ /* Check volume label bit */
+ assert(0 == (FCB->entry.Attrib & 0x08));
+
+ FsdFileTimeToDosDateTime(&(BasicInfo->CreationTime),
+ &(FCB->entry.CreationDate),
+ &(FCB->entry.CreationTime));
+ FsdFileTimeToDosDateTime(&(BasicInfo->LastAccessTime),
+ &(FCB->entry.AccessDate),
+ NULL);
+ FsdFileTimeToDosDateTime(&(BasicInfo->LastWriteTime),
+ &(FCB->entry.UpdateDate),
+ &(FCB->entry.UpdateTime));
+
+ FCB->entry.Attrib = (FCB->entry.Attrib &
+ (FILE_ATTRIBUTE_DIRECTORY | 0x48)) |
+ (BasicInfo->FileAttributes &
+ (FILE_ATTRIBUTE_ARCHIVE |
+ FILE_ATTRIBUTE_SYSTEM |
+ FILE_ATTRIBUTE_HIDDEN |
+ FILE_ATTRIBUTE_READONLY));
+ DPRINT("Setting attributes 0x%02x\n", FCB->entry.Attrib);
+
+ VfatUpdateEntry(DeviceExt, FileObject);
+
+ return(STATUS_SUCCESS);
+}
+
+static NTSTATUS
VfatGetBasicInformation(PFILE_OBJECT FileObject,
PVFATFCB FCB,
PDEVICE_OBJECT DeviceObject,
FsdDosDateTimeToFileTime(FCB->entry.UpdateDate,
FCB->entry.UpdateTime,
&BasicInfo->LastWriteTime);
- FsdDosDateTimeToFileTime(FCB->entry.UpdateDate,
- FCB->entry.UpdateTime,
- &BasicInfo->ChangeTime);
+ BasicInfo->ChangeTime = BasicInfo->LastWriteTime;
BasicInfo->FileAttributes = FCB->entry.Attrib;
- DPRINT("Getting attributes %x\n", BasicInfo->FileAttributes);
+ /* Synthesize FILE_ATTRIBUTE_NORMAL */
+ if (0 == (BasicInfo->FileAttributes & (FILE_ATTRIBUTE_DIRECTORY |
+ FILE_ATTRIBUTE_ARCHIVE |
+ FILE_ATTRIBUTE_SYSTEM |
+ FILE_ATTRIBUTE_HIDDEN |
+ FILE_ATTRIBUTE_READONLY)))
+ {
+ BasicInfo->FileAttributes |= FILE_ATTRIBUTE_NORMAL;
+ }
+ DPRINT("Getting attributes 0x%02x\n", BasicInfo->FileAttributes);
*BufferLength -= sizeof(FILE_BASIC_INFORMATION);
return(STATUS_SUCCESS);
}
if (DispositionInfo->DoDeleteFile)
{
- KeAcquireSpinLock (&DeviceExt->FcbListLock, &oldIrql);
- count = FCB->RefCount;
- if (FCB->RefCount > 1)
- Status = STATUS_ACCESS_DENIED;
+ if (MmFlushImageSection (FileObject->SectionObjectPointers, MmFlushForDelete))
+ {
+ KeAcquireSpinLock (&DeviceExt->FcbListLock, &oldIrql);
+ count = FCB->RefCount;
+ if (FCB->RefCount > 1)
+ {
+ DPRINT1("%d %x\n", FCB->RefCount, CcGetFileObjectFromSectionPtrs(FileObject->SectionObjectPointers));
+ Status = STATUS_ACCESS_DENIED;
+ }
+ else
+ {
+ FCB->Flags |= FCB_DELETE_PENDING;
+ FileObject->DeletePending = TRUE;
+ }
+ KeReleaseSpinLock(&DeviceExt->FcbListLock, oldIrql);
+ }
else
{
- FCB->Flags |= FCB_DELETE_PENDING;
- FileObject->DeletePending = TRUE;
+ DPRINT1("MmFlushImageSection returned FALSE\n");
+ Status = STATUS_ACCESS_DENIED;
}
- KeReleaseSpinLock(&DeviceExt->FcbListLock, oldIrql);
DPRINT("RefCount:%d\n", count);
- if (NT_SUCCESS(Status) && vfatFCBIsDirectory(DeviceExt, FCB))
+ if (NT_SUCCESS(Status) && vfatFCBIsDirectory(FCB))
{
memset (&tmpFcb, 0, sizeof(VFATFCB));
tmpFcb.ObjectName = tmpFcb.PathName;
assert (FCB != NULL);
NameLength = wcslen(FCB->PathName) * sizeof(WCHAR);
- if (*BufferLength < sizeof(FILE_NAME_INFORMATION) + NameLength)
+ if (*BufferLength < sizeof(FILE_NAME_INFORMATION) + NameLength + sizeof(WCHAR))
return STATUS_BUFFER_OVERFLOW;
NameInfo->FileNameLength = NameLength;
- memcpy(NameInfo->FileName,
- FCB->PathName,
- NameLength + sizeof(WCHAR));
+ memcpy(NameInfo->FileName, FCB->PathName, NameLength + sizeof(WCHAR));
- *BufferLength -=
- (sizeof(FILE_NAME_INFORMATION) + NameLength + sizeof(WCHAR));
+ *BufferLength -= (sizeof(FILE_NAME_INFORMATION) + NameLength + sizeof(WCHAR));
return STATUS_SUCCESS;
}
FsdDosDateTimeToFileTime(Fcb->entry.UpdateDate,
Fcb->entry.UpdateTime,
&NetworkInfo->LastWriteTime);
- FsdDosDateTimeToFileTime(Fcb->entry.UpdateDate,
- Fcb->entry.UpdateTime,
- &NetworkInfo->ChangeTime);
+ NetworkInfo->ChangeTime = NetworkInfo->LastWriteTime;
NetworkInfo->AllocationSize = Fcb->RFCB.AllocationSize;
NetworkInfo->EndOfFile = Fcb->RFCB.FileSize;
NetworkInfo->FileAttributes = Fcb->entry.Attrib;
assert (Fcb);
NameLength = wcslen(Fcb->PathName) * sizeof(WCHAR);
- if (*BufferLength < sizeof(FILE_ALL_INFORMATION) + NameLength)
+ if (*BufferLength < sizeof(FILE_ALL_INFORMATION) + NameLength + sizeof(WCHAR))
return(STATUS_BUFFER_OVERFLOW);
/* Basic Information */
FsdDosDateTimeToFileTime(Fcb->entry.UpdateDate,
Fcb->entry.UpdateTime,
&Info->BasicInformation.LastWriteTime);
- FsdDosDateTimeToFileTime(Fcb->entry.UpdateDate,
- Fcb->entry.UpdateTime,
- &Info->BasicInformation.ChangeTime);
+ Info->BasicInformation.ChangeTime = Info->BasicInformation.LastWriteTime;
Info->BasicInformation.FileAttributes = Fcb->entry.Attrib;
/* Standard Information */
/* Name Information */
Info->NameInformation.FileNameLength = NameLength;
- RtlCopyMemory(Info->NameInformation.FileName,
- Fcb->PathName,
- NameLength + sizeof(WCHAR));
+ RtlCopyMemory(Info->NameInformation.FileName, Fcb->PathName, NameLength + sizeof(WCHAR));
*BufferLength -= (sizeof(FILE_ALL_INFORMATION) + NameLength + sizeof(WCHAR));
return STATUS_SUCCESS;
}
+VOID UpdateFileSize(PFILE_OBJECT FileObject, PVFATFCB Fcb, ULONG Size, ULONG ClusterSize)
+{
+ if (Size > 0)
+ {
+ Fcb->RFCB.AllocationSize.QuadPart = ROUND_UP(Size, ClusterSize);
+ }
+ else
+ {
+ Fcb->RFCB.AllocationSize.QuadPart = 0LL;
+ }
+ if (!vfatFCBIsDirectory(Fcb))
+ {
+ Fcb->entry.FileSize = Size;
+ }
+ Fcb->RFCB.FileSize.QuadPart = Size;
+ Fcb->RFCB.ValidDataLength.QuadPart = Size;
+
+ if (FileObject->SectionObjectPointers->SharedCacheMap != NULL)
+ {
+ CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->RFCB.AllocationSize);
+ }
+}
+
NTSTATUS
VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject,
PVFATFCB Fcb,
Status = NextCluster (DeviceExt, Fcb, FirstCluster, &FirstCluster, TRUE);
if (!NT_SUCCESS(Status))
{
- DPRINT1("NextCluster failed.\n");
+ DPRINT1("NextCluster failed. Status = %x\n", Status);
return Status;
}
if (FirstCluster == 0xffffffff)
Status = OffsetToCluster(DeviceExt, Fcb, FirstCluster,
ROUND_DOWN(NewSize - 1, ClusterSize),
&NCluster, TRUE);
- if (NCluster == 0xffffffff)
+ if (NCluster == 0xffffffff || !NT_SUCCESS(Status))
{
/* disk is full */
NCluster = Cluster = FirstCluster;
- while (Cluster != 0xffffffff)
+ Status = STATUS_SUCCESS;
+ while (NT_SUCCESS(Status) && Cluster != 0xffffffff && Cluster > 1)
{
- NextCluster (DeviceExt, Fcb, Cluster, &NCluster, FALSE);
+ Status = NextCluster (DeviceExt, Fcb, FirstCluster, &NCluster, FALSE);
WriteCluster (DeviceExt, Cluster, 0);
Cluster = NCluster;
}
Status = OffsetToCluster(DeviceExt, Fcb, FirstCluster,
Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize,
&Cluster, FALSE);
+ /* FIXME: Check status */
/* Cluster points now to the last cluster within the chain */
Status = OffsetToCluster(DeviceExt, Fcb, FirstCluster,
ROUND_DOWN(NewSize - 1, ClusterSize),
&NCluster, TRUE);
- if (NCluster == 0xffffffff)
+ if (NCluster == 0xffffffff || !NT_SUCCESS(Status))
{
/* disk is full */
NCluster = Cluster;
- NextCluster (DeviceExt, Fcb, Cluster, &NCluster, FALSE);
+ Status = NextCluster (DeviceExt, Fcb, FirstCluster, &NCluster, FALSE);
WriteCluster(DeviceExt, Cluster, 0xffffffff);
Cluster = NCluster;
- while (Cluster != 0xffffffff)
+ while (NT_SUCCESS(Status) && Cluster != 0xffffffff && Cluster > 1)
{
- NextCluster (DeviceExt, Fcb, Cluster, &NCluster, FALSE);
- WriteCluster (DeviceExt, Cluster, 0);
- Cluster = NCluster;
+ Status = NextCluster (DeviceExt, Fcb, FirstCluster, &NCluster, FALSE);
+ WriteCluster (DeviceExt, Cluster, 0);
+ Cluster = NCluster;
}
return STATUS_DISK_FULL;
}
}
+ UpdateFileSize(FileObject, Fcb, NewSize, ClusterSize);
}
- else if (NewSize <= Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize)
+ else if (NewSize + ClusterSize <= Fcb->RFCB.AllocationSize.u.LowPart)
{
- if (NewSize > 0)
- {
- Status = OffsetToCluster(DeviceExt, Fcb, Cluster,
+ UpdateFileSize(FileObject, Fcb, NewSize, ClusterSize);
+ if (NewSize > 0)
+ {
+ Status = OffsetToCluster(DeviceExt, Fcb, Cluster,
ROUND_DOWN(NewSize - 1, ClusterSize),
&Cluster, FALSE);
- }
- NCluster = Cluster;
- Status = NextCluster (DeviceExt, Fcb, Cluster, &NCluster, FALSE);
- WriteCluster(DeviceExt, Cluster, 0xffffffff);
- Cluster = NCluster;
- while (Cluster != 0xffffffff)
- {
- NextCluster (DeviceExt, Fcb, Cluster, &NCluster, FALSE);
- WriteCluster (DeviceExt, Cluster, 0);
- Cluster = NCluster;
- }
- }
- if (!vfatFCBIsDirectory(DeviceExt, Fcb))
- {
- Fcb->entry.FileSize = NewSize;
- }
- if (NewSize > 0)
- {
- Fcb->RFCB.AllocationSize.QuadPart = ROUND_UP(NewSize - 1, ClusterSize);
+ NCluster = Cluster;
+ Status = NextCluster (DeviceExt, Fcb, FirstCluster, &NCluster, FALSE);
+ WriteCluster(DeviceExt, Cluster, 0xffffffff);
+ Cluster = NCluster;
+ }
+ else
+ {
+ Fcb->entry.FirstCluster = 0;
+ Fcb->entry.FirstClusterHigh = 0;
+
+ NCluster = Cluster = FirstCluster;
+ Status = STATUS_SUCCESS;
+ }
+ while (NT_SUCCESS(Status) && 0xffffffff != Cluster && Cluster > 1)
+ {
+ Status = NextCluster (DeviceExt, Fcb, FirstCluster, &NCluster, FALSE);
+ WriteCluster (DeviceExt, Cluster, 0);
+ Cluster = NCluster;
+ }
}
else
{
- Fcb->RFCB.AllocationSize.QuadPart = 0LL;
- Fcb->entry.FirstCluster = 0;
- Fcb->entry.FirstClusterHigh = 0;
- }
- Fcb->RFCB.FileSize.QuadPart = NewSize;
- Fcb->RFCB.ValidDataLength.QuadPart = NewSize;
-
- if (FileObject->SectionObjectPointers->SharedCacheMap != NULL)
- {
- CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->RFCB.AllocationSize);
+ UpdateFileSize(FileObject, Fcb, NewSize, ClusterSize);
}
/* Update the on-disk directory entry */
VfatUpdateEntry(DeviceExt, FileObject);
{
case FileStandardInformation:
RC = VfatGetStandardInformation(FCB,
- IrpContext->DeviceObject,
SystemBuffer,
&BufferLength);
break;
{
case FilePositionInformation:
RC = VfatSetPositionInformation(IrpContext->FileObject,
- FCB,
- IrpContext->DeviceObject,
SystemBuffer);
break;
case FileDispositionInformation:
(PLARGE_INTEGER)SystemBuffer);
break;
case FileBasicInformation:
+ RC = VfatSetBasicInformation(IrpContext->FileObject,
+ FCB,
+ IrpContext->DeviceExt,
+ SystemBuffer);
+ break;
case FileRenameInformation:
RC = STATUS_NOT_IMPLEMENTED;
break;