xref: /reactos/drivers/filesystems/fs_rec/fatx.c (revision 542e9f2b)
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