mirror of
https://github.com/reactos/reactos.git
synced 2025-01-01 03:54:02 +00:00
[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. svn path=/trunk/; revision=73830
This commit is contained in:
parent
9c5c0b479a
commit
1dc27a26be
2 changed files with 139 additions and 51 deletions
|
@ -340,31 +340,38 @@ VfatHasFileSystem(
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Read the volume label
|
* 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
|
static
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
ReadVolumeLabel(
|
ReadVolumeLabel(
|
||||||
PDEVICE_EXTENSION DeviceExt,
|
PVOID Device,
|
||||||
PVPB Vpb)
|
ULONG Start,
|
||||||
|
BOOLEAN IsFatX,
|
||||||
|
PUNICODE_STRING VolumeLabel)
|
||||||
{
|
{
|
||||||
|
PDEVICE_EXTENSION DeviceExt;
|
||||||
|
PDEVICE_OBJECT DeviceObject;
|
||||||
PVOID Context = NULL;
|
PVOID Context = NULL;
|
||||||
ULONG DirIndex = 0;
|
ULONG DirIndex = 0;
|
||||||
PDIR_ENTRY Entry;
|
PDIR_ENTRY Entry;
|
||||||
PVFATFCB pFcb;
|
PVFATFCB pFcb;
|
||||||
LARGE_INTEGER FileOffset;
|
LARGE_INTEGER FileOffset;
|
||||||
UNICODE_STRING NameU;
|
|
||||||
ULONG SizeDirEntry;
|
ULONG SizeDirEntry;
|
||||||
ULONG EntriesPerPage;
|
ULONG EntriesPerPage;
|
||||||
OEM_STRING StringO;
|
OEM_STRING StringO;
|
||||||
|
BOOLEAN NoCache = (Start != 0);
|
||||||
|
PVOID Buffer;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
NameU.Buffer = Vpb->VolumeLabel;
|
if (IsFatX)
|
||||||
NameU.Length = 0;
|
|
||||||
NameU.MaximumLength = sizeof(Vpb->VolumeLabel);
|
|
||||||
*(Vpb->VolumeLabel) = 0;
|
|
||||||
Vpb->VolumeLabelLength = 0;
|
|
||||||
|
|
||||||
if (vfatVolumeIsFatX(DeviceExt))
|
|
||||||
{
|
{
|
||||||
SizeDirEntry = sizeof(FATX_DIR_ENTRY);
|
SizeDirEntry = sizeof(FATX_DIR_ENTRY);
|
||||||
EntriesPerPage = FATX_ENTRIES_PER_PAGE;
|
EntriesPerPage = FATX_ENTRIES_PER_PAGE;
|
||||||
|
@ -375,41 +382,71 @@ ReadVolumeLabel(
|
||||||
EntriesPerPage = FAT_ENTRIES_PER_PAGE;
|
EntriesPerPage = FAT_ENTRIES_PER_PAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, TRUE);
|
FileOffset.QuadPart = Start;
|
||||||
pFcb = vfatOpenRootFCB(DeviceExt);
|
if (!NoCache)
|
||||||
ExReleaseResourceLite(&DeviceExt->DirResource);
|
{
|
||||||
|
DeviceExt = Device;
|
||||||
|
|
||||||
FileOffset.QuadPart = 0;
|
/* FIXME: Check we really have a VCB
|
||||||
_SEH2_TRY
|
ASSERT();
|
||||||
{
|
*/
|
||||||
CcMapData(pFcb->FileObject, &FileOffset, SizeDirEntry, MAP_WAIT, &Context, (PVOID*)&Entry);
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
else
|
||||||
{
|
{
|
||||||
Status = _SEH2_GetExceptionCode();
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_SEH2_END;
|
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
if (ENTRY_VOLUME(DeviceExt, Entry))
|
if (ENTRY_VOLUME2(IsFatX, Entry))
|
||||||
{
|
{
|
||||||
/* copy volume label */
|
/* copy volume label */
|
||||||
if (vfatVolumeIsFatX(DeviceExt))
|
if (IsFatX)
|
||||||
{
|
{
|
||||||
StringO.Buffer = (PCHAR)Entry->FatX.Filename;
|
StringO.Buffer = (PCHAR)Entry->FatX.Filename;
|
||||||
StringO.MaximumLength = StringO.Length = Entry->FatX.FilenameLength;
|
StringO.MaximumLength = StringO.Length = Entry->FatX.FilenameLength;
|
||||||
RtlOemStringToUnicodeString(&NameU, &StringO, FALSE);
|
RtlOemStringToUnicodeString(VolumeLabel, &StringO, FALSE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
vfat8Dot3ToString(&Entry->Fat, &NameU);
|
vfat8Dot3ToString(&Entry->Fat, VolumeLabel);
|
||||||
}
|
}
|
||||||
Vpb->VolumeLabelLength = NameU.Length;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ENTRY_END(DeviceExt, Entry))
|
if (ENTRY_END2(IsFatX, Entry))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -417,21 +454,35 @@ ReadVolumeLabel(
|
||||||
Entry = (PDIR_ENTRY)((ULONG_PTR)Entry + SizeDirEntry);
|
Entry = (PDIR_ENTRY)((ULONG_PTR)Entry + SizeDirEntry);
|
||||||
if ((DirIndex % EntriesPerPage) == 0)
|
if ((DirIndex % EntriesPerPage) == 0)
|
||||||
{
|
{
|
||||||
CcUnpinData(Context);
|
|
||||||
FileOffset.u.LowPart += PAGE_SIZE;
|
FileOffset.u.LowPart += PAGE_SIZE;
|
||||||
_SEH2_TRY
|
|
||||||
|
if (!NoCache)
|
||||||
{
|
{
|
||||||
CcMapData(pFcb->FileObject, &FileOffset, SizeDirEntry, MAP_WAIT, &Context, (PVOID*)&Entry);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
else
|
||||||
{
|
{
|
||||||
Status = _SEH2_GetExceptionCode();
|
Status = VfatReadDisk(DeviceObject, &FileOffset, PAGE_SIZE, (PUCHAR)Buffer, TRUE);
|
||||||
}
|
if (!NT_SUCCESS(Status))
|
||||||
_SEH2_END;
|
{
|
||||||
if (!NT_SUCCESS(Status))
|
break;
|
||||||
{
|
}
|
||||||
Context = NULL;
|
Entry = Buffer;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -439,10 +490,18 @@ ReadVolumeLabel(
|
||||||
{
|
{
|
||||||
CcUnpinData(Context);
|
CcUnpinData(Context);
|
||||||
}
|
}
|
||||||
|
else if (NoCache)
|
||||||
|
{
|
||||||
|
ExFreePoolWithTag(Buffer, TAG_VFAT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!NoCache)
|
||||||
|
{
|
||||||
|
ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, TRUE);
|
||||||
|
vfatReleaseFCB(DeviceExt, pFcb);
|
||||||
|
ExReleaseResourceLite(&DeviceExt->DirResource);
|
||||||
}
|
}
|
||||||
ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, TRUE);
|
|
||||||
vfatReleaseFCB(DeviceExt, pFcb);
|
|
||||||
ExReleaseResourceLite(&DeviceExt->DirResource);
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -467,6 +526,7 @@ VfatMount(
|
||||||
PVPB Vpb;
|
PVPB Vpb;
|
||||||
UNICODE_STRING NameU = RTL_CONSTANT_STRING(L"\\$$Fat$$");
|
UNICODE_STRING NameU = RTL_CONSTANT_STRING(L"\\$$Fat$$");
|
||||||
UNICODE_STRING VolumeNameU = RTL_CONSTANT_STRING(L"\\$$Volume$$");
|
UNICODE_STRING VolumeNameU = RTL_CONSTANT_STRING(L"\\$$Volume$$");
|
||||||
|
UNICODE_STRING VolumeLabelU;
|
||||||
ULONG HashTableSize;
|
ULONG HashTableSize;
|
||||||
ULONG eocMark;
|
ULONG eocMark;
|
||||||
FATINFO FatInfo;
|
FATINFO FatInfo;
|
||||||
|
@ -676,7 +736,11 @@ VfatMount(
|
||||||
DeviceObject->Vpb->SerialNumber = DeviceExt->FatInfo.VolumeID;
|
DeviceObject->Vpb->SerialNumber = DeviceExt->FatInfo.VolumeID;
|
||||||
|
|
||||||
/* read volume label */
|
/* 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 */
|
/* read clean shutdown bit status */
|
||||||
Status = GetNextCluster(DeviceExt, 1, &eocMark);
|
Status = GetNextCluster(DeviceExt, 1, &eocMark);
|
||||||
|
@ -769,21 +833,41 @@ VfatVerify(
|
||||||
if (!NT_SUCCESS(Status) || RecognizedFS == FALSE)
|
if (!NT_SUCCESS(Status) || RecognizedFS == FALSE)
|
||||||
{
|
{
|
||||||
if (NT_SUCCESS(Status) || AllowRaw)
|
if (NT_SUCCESS(Status) || AllowRaw)
|
||||||
|
{
|
||||||
Status = STATUS_WRONG_VOLUME;
|
Status = STATUS_WRONG_VOLUME;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (sizeof(FATINFO) == RtlCompareMemory(&FatInfo, &DeviceExt->FatInfo, sizeof(FATINFO)))
|
else if (sizeof(FATINFO) == RtlCompareMemory(&FatInfo, &DeviceExt->FatInfo, sizeof(FATINFO)))
|
||||||
{
|
{
|
||||||
DPRINT1("Same volume\n");
|
WCHAR BufferU[MAXIMUM_VOLUME_LABEL_LENGTH / sizeof(WCHAR)];
|
||||||
/*
|
UNICODE_STRING VolumeLabelU;
|
||||||
* FIXME:
|
UNICODE_STRING VpbLabelU;
|
||||||
* 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.
|
VolumeLabelU.Buffer = BufferU;
|
||||||
* Each write to the root directory must update this crc sum.
|
VolumeLabelU.Length = 0;
|
||||||
*/
|
VolumeLabelU.MaximumLength = sizeof(BufferU);
|
||||||
/* HACK */
|
Status = ReadVolumeLabel(DeviceExt->StorageDevice, FatInfo.rootStart * FatInfo.BytesPerSector, (FatInfo.FatType >= FATX16), &VolumeLabelU);
|
||||||
if (!FatInfo.FixedMedia && FatInfo.FatType >= FATX16)
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
Status = STATUS_WRONG_VOLUME;
|
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
|
else
|
||||||
|
|
|
@ -201,6 +201,10 @@ typedef struct _slot slot;
|
||||||
#define ENTRY_VOLUME(DeviceExt, DirEntry) (vfatVolumeIsFatX(DeviceExt) ? FATX_ENTRY_VOLUME(&((DirEntry)->FatX)) : FAT_ENTRY_VOLUME(&((DirEntry)->Fat)))
|
#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_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_DELETED(DirEntry) ((DirEntry)->Filename[0] == 0xe5)
|
||||||
#define FAT_ENTRY_END(DirEntry) ((DirEntry)->Filename[0] == 0)
|
#define FAT_ENTRY_END(DirEntry) ((DirEntry)->Filename[0] == 0)
|
||||||
#define FAT_ENTRY_LONG(DirEntry) (((DirEntry)->Attrib & 0x3f) == 0x0f)
|
#define FAT_ENTRY_LONG(DirEntry) (((DirEntry)->Attrib & 0x3f) == 0x0f)
|
||||||
|
|
Loading…
Reference in a new issue