Author: pschweitzer
Date: Sat Feb 18 21:24:31 2017
New Revision: 73830
URL:
http://svn.reactos.org/svn/reactos?rev=73830&view=rev
Log:
[FASTFAT]
Modify ReadVolumeLabel() so that it is able to read the volume label, even without using
the VCB, the root FCB, Cc, the universe.
This is important, because in case of device verifying, you cannot rely on these elements
anylonger, but you need to read the label.
A readme has been attached to the function, to indicate how to call it (I wish I could
have put more asserts!). It's ugly, I know.
This allows fixing a FIXME in VfatVerify(): we can also check the volume label for FATX
volumes.
The FIXME comment was misleading: MS FastFAT doesn't make any checksum or whatever of
FAT root. Let's not do it.
Modified:
trunk/reactos/drivers/filesystems/fastfat/fsctl.c
trunk/reactos/drivers/filesystems/fastfat/vfat.h
Modified: trunk/reactos/drivers/filesystems/fastfat/fsctl.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfa…
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat/fsctl.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/fastfat/fsctl.c [iso-8859-1] Sat Feb 18 21:24:31
2017
@@ -340,31 +340,38 @@
/*
* FUNCTION: Read the volume label
+ * WARNING: Read this comment carefully before using it (and using it wrong)
+ * Device parameter is expected to be the lower DO is start isn't 0
+ * otherwise, it is expected to be the VCB is start is 0
+ * Start parameter is expected to be, in bytes, the beginning of the root start.
+ * Set it to 0 if you wish to use the associated FCB with caching.
+ * In that specific case, Device parameter is expected to be the VCB!
+ * VolumeLabel parameter is expected to be a preallocated UNICODE_STRING (ie, with
buffer)
+ * Its buffer has to be able to contain MAXIMUM_VOLUME_LABEL_LENGTH
bytes
*/
static
NTSTATUS
ReadVolumeLabel(
- PDEVICE_EXTENSION DeviceExt,
- PVPB Vpb)
+ PVOID Device,
+ ULONG Start,
+ BOOLEAN IsFatX,
+ PUNICODE_STRING VolumeLabel)
{
+ PDEVICE_EXTENSION DeviceExt;
+ PDEVICE_OBJECT DeviceObject;
PVOID Context = NULL;
ULONG DirIndex = 0;
PDIR_ENTRY Entry;
PVFATFCB pFcb;
LARGE_INTEGER FileOffset;
- UNICODE_STRING NameU;
ULONG SizeDirEntry;
ULONG EntriesPerPage;
OEM_STRING StringO;
+ BOOLEAN NoCache = (Start != 0);
+ PVOID Buffer;
NTSTATUS Status = STATUS_SUCCESS;
- NameU.Buffer = Vpb->VolumeLabel;
- NameU.Length = 0;
- NameU.MaximumLength = sizeof(Vpb->VolumeLabel);
- *(Vpb->VolumeLabel) = 0;
- Vpb->VolumeLabelLength = 0;
-
- if (vfatVolumeIsFatX(DeviceExt))
+ if (IsFatX)
{
SizeDirEntry = sizeof(FATX_DIR_ENTRY);
EntriesPerPage = FATX_ENTRIES_PER_PAGE;
@@ -375,41 +382,71 @@
EntriesPerPage = FAT_ENTRIES_PER_PAGE;
}
- ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, TRUE);
- pFcb = vfatOpenRootFCB(DeviceExt);
- ExReleaseResourceLite(&DeviceExt->DirResource);
-
- FileOffset.QuadPart = 0;
- _SEH2_TRY
- {
- CcMapData(pFcb->FileObject, &FileOffset, SizeDirEntry, MAP_WAIT,
&Context, (PVOID*)&Entry);
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END;
+ FileOffset.QuadPart = Start;
+ if (!NoCache)
+ {
+ DeviceExt = Device;
+
+ /* FIXME: Check we really have a VCB
+ ASSERT();
+ */
+
+ ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, TRUE);
+ pFcb = vfatOpenRootFCB(DeviceExt);
+ ExReleaseResourceLite(&DeviceExt->DirResource);
+
+ _SEH2_TRY
+ {
+ CcMapData(pFcb->FileObject, &FileOffset, SizeDirEntry, MAP_WAIT,
&Context, (PVOID*)&Entry);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+ }
+ else
+ {
+ DeviceObject = Device;
+
+ ASSERT(DeviceObject->Type == 3);
+
+ Buffer = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, TAG_VFAT);
+ if (Buffer != NULL)
+ {
+ Status = VfatReadDisk(DeviceObject, &FileOffset, PAGE_SIZE,
(PUCHAR)Buffer, TRUE);
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePoolWithTag(Entry, TAG_VFAT);
+ }
+ Entry = Buffer;
+ }
+ else
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+
if (NT_SUCCESS(Status))
{
while (TRUE)
{
- if (ENTRY_VOLUME(DeviceExt, Entry))
+ if (ENTRY_VOLUME2(IsFatX, Entry))
{
/* copy volume label */
- if (vfatVolumeIsFatX(DeviceExt))
+ if (IsFatX)
{
StringO.Buffer = (PCHAR)Entry->FatX.Filename;
StringO.MaximumLength = StringO.Length =
Entry->FatX.FilenameLength;
- RtlOemStringToUnicodeString(&NameU, &StringO, FALSE);
+ RtlOemStringToUnicodeString(VolumeLabel, &StringO, FALSE);
}
else
{
- vfat8Dot3ToString(&Entry->Fat, &NameU);
- }
- Vpb->VolumeLabelLength = NameU.Length;
+ vfat8Dot3ToString(&Entry->Fat, VolumeLabel);
+ }
break;
}
- if (ENTRY_END(DeviceExt, Entry))
+ if (ENTRY_END2(IsFatX, Entry))
{
break;
}
@@ -417,21 +454,35 @@
Entry = (PDIR_ENTRY)((ULONG_PTR)Entry + SizeDirEntry);
if ((DirIndex % EntriesPerPage) == 0)
{
- CcUnpinData(Context);
FileOffset.u.LowPart += PAGE_SIZE;
- _SEH2_TRY
- {
- CcMapData(pFcb->FileObject, &FileOffset, SizeDirEntry,
MAP_WAIT, &Context, (PVOID*)&Entry);
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END;
- if (!NT_SUCCESS(Status))
- {
- Context = NULL;
- break;
+
+ if (!NoCache)
+ {
+ CcUnpinData(Context);
+
+ _SEH2_TRY
+ {
+ CcMapData(pFcb->FileObject, &FileOffset, SizeDirEntry,
MAP_WAIT, &Context, (PVOID*)&Entry);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+ if (!NT_SUCCESS(Status))
+ {
+ Context = NULL;
+ break;
+ }
+ }
+ else
+ {
+ Status = VfatReadDisk(DeviceObject, &FileOffset, PAGE_SIZE,
(PUCHAR)Buffer, TRUE);
+ if (!NT_SUCCESS(Status))
+ {
+ break;
+ }
+ Entry = Buffer;
}
}
}
@@ -439,10 +490,18 @@
{
CcUnpinData(Context);
}
- }
- ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, TRUE);
- vfatReleaseFCB(DeviceExt, pFcb);
- ExReleaseResourceLite(&DeviceExt->DirResource);
+ else if (NoCache)
+ {
+ ExFreePoolWithTag(Buffer, TAG_VFAT);
+ }
+ }
+
+ if (!NoCache)
+ {
+ ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, TRUE);
+ vfatReleaseFCB(DeviceExt, pFcb);
+ ExReleaseResourceLite(&DeviceExt->DirResource);
+ }
return STATUS_SUCCESS;
}
@@ -467,6 +526,7 @@
PVPB Vpb;
UNICODE_STRING NameU = RTL_CONSTANT_STRING(L"\\$$Fat$$");
UNICODE_STRING VolumeNameU = RTL_CONSTANT_STRING(L"\\$$Volume$$");
+ UNICODE_STRING VolumeLabelU;
ULONG HashTableSize;
ULONG eocMark;
FATINFO FatInfo;
@@ -676,7 +736,11 @@
DeviceObject->Vpb->SerialNumber = DeviceExt->FatInfo.VolumeID;
/* read volume label */
- ReadVolumeLabel(DeviceExt, DeviceObject->Vpb);
+ VolumeLabelU.Buffer = DeviceObject->Vpb->VolumeLabel;
+ VolumeLabelU.Length = 0;
+ VolumeLabelU.MaximumLength = sizeof(DeviceObject->Vpb->VolumeLabel);
+ ReadVolumeLabel(DeviceExt, 0, vfatVolumeIsFatX(DeviceExt), &VolumeLabelU);
+ Vpb->VolumeLabelLength = VolumeLabelU.Length;
/* read clean shutdown bit status */
Status = GetNextCluster(DeviceExt, 1, &eocMark);
@@ -769,21 +833,41 @@
if (!NT_SUCCESS(Status) || RecognizedFS == FALSE)
{
if (NT_SUCCESS(Status) || AllowRaw)
+ {
Status = STATUS_WRONG_VOLUME;
+ }
}
else if (sizeof(FATINFO) == RtlCompareMemory(&FatInfo,
&DeviceExt->FatInfo, sizeof(FATINFO)))
{
- DPRINT1("Same volume\n");
- /*
- * FIXME:
- * Preformatted floppy disks have very often a serial number of 0000:0000.
- * We should calculate a crc sum over the sectors from the root directory
as secondary volume number.
- * Each write to the root directory must update this crc sum.
- */
- /* HACK */
- if (!FatInfo.FixedMedia && FatInfo.FatType >= FATX16)
- {
- Status = STATUS_WRONG_VOLUME;
+ WCHAR BufferU[MAXIMUM_VOLUME_LABEL_LENGTH / sizeof(WCHAR)];
+ UNICODE_STRING VolumeLabelU;
+ UNICODE_STRING VpbLabelU;
+
+ VolumeLabelU.Buffer = BufferU;
+ VolumeLabelU.Length = 0;
+ VolumeLabelU.MaximumLength = sizeof(BufferU);
+ Status = ReadVolumeLabel(DeviceExt->StorageDevice, FatInfo.rootStart *
FatInfo.BytesPerSector, (FatInfo.FatType >= FATX16), &VolumeLabelU);
+ if (!NT_SUCCESS(Status))
+ {
+ if (AllowRaw)
+ {
+ Status = STATUS_WRONG_VOLUME;
+ }
+ }
+ else
+ {
+ VpbLabelU.Buffer = Vpb->VolumeLabel;
+ VpbLabelU.Length = Vpb->VolumeLabelLength;
+ VpbLabelU.MaximumLength = sizeof(Vpb->VolumeLabel);
+
+ if (RtlCompareUnicodeString(&VpbLabelU, &VolumeLabelU, FALSE) !=
0)
+ {
+ Status = STATUS_WRONG_VOLUME;
+ }
+ else
+ {
+ DPRINT1("Same volume\n");
+ }
}
}
else
Modified: trunk/reactos/drivers/filesystems/fastfat/vfat.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfa…
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat/vfat.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/fastfat/vfat.h [iso-8859-1] Sat Feb 18 21:24:31
2017
@@ -201,6 +201,10 @@
#define ENTRY_VOLUME(DeviceExt, DirEntry) (vfatVolumeIsFatX(DeviceExt) ?
FATX_ENTRY_VOLUME(&((DirEntry)->FatX)) :
FAT_ENTRY_VOLUME(&((DirEntry)->Fat)))
#define ENTRY_END(DeviceExt, DirEntry) (vfatVolumeIsFatX(DeviceExt) ?
FATX_ENTRY_END(&((DirEntry)->FatX)) : FAT_ENTRY_END(&((DirEntry)->Fat)))
+#define ENTRY_DELETED2(IsFatX, DirEntry) (IsFatX ?
FATX_ENTRY_DELETED(&((DirEntry)->FatX)) :
FAT_ENTRY_DELETED(&((DirEntry)->Fat)))
+#define ENTRY_VOLUME2(IsFatX, DirEntry) (IsFatX ?
FATX_ENTRY_VOLUME(&((DirEntry)->FatX)) :
FAT_ENTRY_VOLUME(&((DirEntry)->Fat)))
+#define ENTRY_END2(IsFatX, DirEntry) (IsFatX ? FATX_ENTRY_END(&((DirEntry)->FatX))
: FAT_ENTRY_END(&((DirEntry)->Fat)))
+
#define FAT_ENTRY_DELETED(DirEntry) ((DirEntry)->Filename[0] == 0xe5)
#define FAT_ENTRY_END(DirEntry) ((DirEntry)->Filename[0] == 0)
#define FAT_ENTRY_LONG(DirEntry) (((DirEntry)->Attrib & 0x3f) == 0x0f)