16d65da93SHervé Poussineau /*
26d65da93SHervé Poussineau * PROJECT: ReactOS File System Recognizer
36d65da93SHervé Poussineau * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
46d65da93SHervé Poussineau * PURPOSE: FATX Recognizer
5*542e9f2bSStanislav Motylkov * COPYRIGHT: Copyright 2022 Hervé Poussineau <hpoussin@reactos.org>
66d65da93SHervé Poussineau */
76d65da93SHervé Poussineau
86d65da93SHervé Poussineau /* INCLUDES *****************************************************************/
96d65da93SHervé Poussineau
106d65da93SHervé Poussineau #include "fs_rec.h"
116d65da93SHervé Poussineau
126d65da93SHervé Poussineau #define NDEBUG
136d65da93SHervé Poussineau #include <debug.h>
146d65da93SHervé Poussineau
156d65da93SHervé Poussineau /* TYPES ****************************************************************/
166d65da93SHervé Poussineau
176d65da93SHervé Poussineau #include <pshpack1.h>
186d65da93SHervé Poussineau typedef struct _FATX_BOOT_SECTOR
196d65da93SHervé Poussineau {
206d65da93SHervé Poussineau UCHAR SysType[4];
216d65da93SHervé Poussineau ULONG VolumeId;
226d65da93SHervé Poussineau ULONG SectorsPerCluster;
236d65da93SHervé Poussineau USHORT FatCount;
246d65da93SHervé Poussineau ULONG Reserved;
256d65da93SHervé Poussineau UCHAR Unused[4078];
266d65da93SHervé Poussineau } FATX_BOOT_SECTOR, *PFATX_BOOT_SECTOR;
276d65da93SHervé Poussineau #include <poppack.h>
286d65da93SHervé Poussineau
296d65da93SHervé Poussineau /* FUNCTIONS ****************************************************************/
306d65da93SHervé Poussineau
316d65da93SHervé Poussineau BOOLEAN
326d65da93SHervé Poussineau NTAPI
FsRecIsFatxVolume(IN PFATX_BOOT_SECTOR BootSector)336d65da93SHervé Poussineau FsRecIsFatxVolume(IN PFATX_BOOT_SECTOR BootSector)
346d65da93SHervé Poussineau {
356d65da93SHervé Poussineau BOOLEAN Result = TRUE;
366d65da93SHervé Poussineau
376d65da93SHervé Poussineau PAGED_CODE();
386d65da93SHervé Poussineau
396d65da93SHervé Poussineau if (BootSector->SysType[0] != 'F' ||
406d65da93SHervé Poussineau BootSector->SysType[1] != 'A' ||
416d65da93SHervé Poussineau BootSector->SysType[2] != 'T' ||
426d65da93SHervé Poussineau BootSector->SysType[3] != 'X')
436d65da93SHervé Poussineau {
446d65da93SHervé Poussineau /* Fail */
456d65da93SHervé Poussineau Result = FALSE;
466d65da93SHervé Poussineau }
476d65da93SHervé Poussineau else if (BootSector->SectorsPerCluster != 1 &&
486d65da93SHervé Poussineau BootSector->SectorsPerCluster != 2 &&
496d65da93SHervé Poussineau BootSector->SectorsPerCluster != 4 &&
506d65da93SHervé Poussineau BootSector->SectorsPerCluster != 8 &&
516d65da93SHervé Poussineau BootSector->SectorsPerCluster != 16 &&
526d65da93SHervé Poussineau BootSector->SectorsPerCluster != 32 &&
536d65da93SHervé Poussineau BootSector->SectorsPerCluster != 64 &&
546d65da93SHervé Poussineau BootSector->SectorsPerCluster != 128)
556d65da93SHervé Poussineau {
566d65da93SHervé Poussineau /* Fail */
576d65da93SHervé Poussineau Result = FALSE;
586d65da93SHervé Poussineau }
596d65da93SHervé Poussineau
606d65da93SHervé Poussineau /* Return the result */
616d65da93SHervé Poussineau return Result;
626d65da93SHervé Poussineau }
636d65da93SHervé Poussineau
646d65da93SHervé Poussineau NTSTATUS
656d65da93SHervé Poussineau NTAPI
FsRecFatxFsControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)666d65da93SHervé Poussineau FsRecFatxFsControl(IN PDEVICE_OBJECT DeviceObject,
676d65da93SHervé Poussineau IN PIRP Irp)
686d65da93SHervé Poussineau {
696d65da93SHervé Poussineau PIO_STACK_LOCATION Stack;
706d65da93SHervé Poussineau NTSTATUS Status;
716d65da93SHervé Poussineau PDEVICE_OBJECT MountDevice;
726d65da93SHervé Poussineau PFATX_BOOT_SECTOR Bpb = NULL;
736d65da93SHervé Poussineau ULONG SectorSize;
746d65da93SHervé Poussineau LARGE_INTEGER Offset = {{0, 0}};
756d65da93SHervé Poussineau BOOLEAN DeviceError = FALSE;
766d65da93SHervé Poussineau PAGED_CODE();
776d65da93SHervé Poussineau
786d65da93SHervé Poussineau /* Get the I/O Stack and check the function type */
796d65da93SHervé Poussineau Stack = IoGetCurrentIrpStackLocation(Irp);
806d65da93SHervé Poussineau switch (Stack->MinorFunction)
816d65da93SHervé Poussineau {
826d65da93SHervé Poussineau case IRP_MN_MOUNT_VOLUME:
836d65da93SHervé Poussineau
846d65da93SHervé Poussineau /* Assume failure */
856d65da93SHervé Poussineau Status = STATUS_UNRECOGNIZED_VOLUME;
866d65da93SHervé Poussineau
876d65da93SHervé Poussineau /* Get the device object and request the sector size */
886d65da93SHervé Poussineau MountDevice = Stack->Parameters.MountVolume.DeviceObject;
896d65da93SHervé Poussineau if (FsRecGetDeviceSectorSize(MountDevice, &SectorSize))
906d65da93SHervé Poussineau {
916d65da93SHervé Poussineau /* Try to read the BPB */
926d65da93SHervé Poussineau if (FsRecReadBlock(MountDevice,
936d65da93SHervé Poussineau &Offset,
946d65da93SHervé Poussineau 512,
956d65da93SHervé Poussineau SectorSize,
966d65da93SHervé Poussineau (PVOID)&Bpb,
976d65da93SHervé Poussineau &DeviceError))
986d65da93SHervé Poussineau {
996d65da93SHervé Poussineau /* Check if it's an actual FAT volume */
1006d65da93SHervé Poussineau if (FsRecIsFatxVolume(Bpb))
1016d65da93SHervé Poussineau {
1026d65da93SHervé Poussineau /* It is! */
1036d65da93SHervé Poussineau Status = STATUS_FS_DRIVER_REQUIRED;
1046d65da93SHervé Poussineau }
1056d65da93SHervé Poussineau }
1066d65da93SHervé Poussineau
1076d65da93SHervé Poussineau /* Free the boot sector if we have one */
1086d65da93SHervé Poussineau ExFreePool(Bpb);
1096d65da93SHervé Poussineau }
1106d65da93SHervé Poussineau
1116d65da93SHervé Poussineau break;
1126d65da93SHervé Poussineau
1136d65da93SHervé Poussineau case IRP_MN_LOAD_FILE_SYSTEM:
1146d65da93SHervé Poussineau
1156d65da93SHervé Poussineau /* Load the file system */
1166d65da93SHervé Poussineau Status = FsRecLoadFileSystem(DeviceObject,
1176d65da93SHervé Poussineau L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\vfatfs");
1186d65da93SHervé Poussineau break;
1196d65da93SHervé Poussineau
1206d65da93SHervé Poussineau default:
1216d65da93SHervé Poussineau
1226d65da93SHervé Poussineau /* Invalid request */
1236d65da93SHervé Poussineau Status = STATUS_INVALID_DEVICE_REQUEST;
1246d65da93SHervé Poussineau }
1256d65da93SHervé Poussineau
1266d65da93SHervé Poussineau /* Return Status */
1276d65da93SHervé Poussineau return Status;
1286d65da93SHervé Poussineau }
1296d65da93SHervé Poussineau
1306d65da93SHervé Poussineau /* EOF */
131