1 /*
2 * PROJECT: ReactOS File System Recognizer
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: FATX Recognizer
5 * COPYRIGHT: Copyright 2022 Hervé Poussineau <hpoussin@reactos.org>
6 */
7
8 /* INCLUDES *****************************************************************/
9
10 #include "fs_rec.h"
11
12 #define NDEBUG
13 #include <debug.h>
14
15 /* TYPES ****************************************************************/
16
17 #include <pshpack1.h>
18 typedef struct _FATX_BOOT_SECTOR
19 {
20 UCHAR SysType[4];
21 ULONG VolumeId;
22 ULONG SectorsPerCluster;
23 USHORT FatCount;
24 ULONG Reserved;
25 UCHAR Unused[4078];
26 } FATX_BOOT_SECTOR, *PFATX_BOOT_SECTOR;
27 #include <poppack.h>
28
29 /* FUNCTIONS ****************************************************************/
30
31 BOOLEAN
32 NTAPI
FsRecIsFatxVolume(IN PFATX_BOOT_SECTOR BootSector)33 FsRecIsFatxVolume(IN PFATX_BOOT_SECTOR BootSector)
34 {
35 BOOLEAN Result = TRUE;
36
37 PAGED_CODE();
38
39 if (BootSector->SysType[0] != 'F' ||
40 BootSector->SysType[1] != 'A' ||
41 BootSector->SysType[2] != 'T' ||
42 BootSector->SysType[3] != 'X')
43 {
44 /* Fail */
45 Result = FALSE;
46 }
47 else if (BootSector->SectorsPerCluster != 1 &&
48 BootSector->SectorsPerCluster != 2 &&
49 BootSector->SectorsPerCluster != 4 &&
50 BootSector->SectorsPerCluster != 8 &&
51 BootSector->SectorsPerCluster != 16 &&
52 BootSector->SectorsPerCluster != 32 &&
53 BootSector->SectorsPerCluster != 64 &&
54 BootSector->SectorsPerCluster != 128)
55 {
56 /* Fail */
57 Result = FALSE;
58 }
59
60 /* Return the result */
61 return Result;
62 }
63
64 NTSTATUS
65 NTAPI
FsRecFatxFsControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)66 FsRecFatxFsControl(IN PDEVICE_OBJECT DeviceObject,
67 IN PIRP Irp)
68 {
69 PIO_STACK_LOCATION Stack;
70 NTSTATUS Status;
71 PDEVICE_OBJECT MountDevice;
72 PFATX_BOOT_SECTOR Bpb = NULL;
73 ULONG SectorSize;
74 LARGE_INTEGER Offset = {{0, 0}};
75 BOOLEAN DeviceError = FALSE;
76 PAGED_CODE();
77
78 /* Get the I/O Stack and check the function type */
79 Stack = IoGetCurrentIrpStackLocation(Irp);
80 switch (Stack->MinorFunction)
81 {
82 case IRP_MN_MOUNT_VOLUME:
83
84 /* Assume failure */
85 Status = STATUS_UNRECOGNIZED_VOLUME;
86
87 /* Get the device object and request the sector size */
88 MountDevice = Stack->Parameters.MountVolume.DeviceObject;
89 if (FsRecGetDeviceSectorSize(MountDevice, &SectorSize))
90 {
91 /* Try to read the BPB */
92 if (FsRecReadBlock(MountDevice,
93 &Offset,
94 512,
95 SectorSize,
96 (PVOID)&Bpb,
97 &DeviceError))
98 {
99 /* Check if it's an actual FAT volume */
100 if (FsRecIsFatxVolume(Bpb))
101 {
102 /* It is! */
103 Status = STATUS_FS_DRIVER_REQUIRED;
104 }
105 }
106
107 /* Free the boot sector if we have one */
108 ExFreePool(Bpb);
109 }
110
111 break;
112
113 case IRP_MN_LOAD_FILE_SYSTEM:
114
115 /* Load the file system */
116 Status = FsRecLoadFileSystem(DeviceObject,
117 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\vfatfs");
118 break;
119
120 default:
121
122 /* Invalid request */
123 Status = STATUS_INVALID_DEVICE_REQUEST;
124 }
125
126 /* Return Status */
127 return Status;
128 }
129
130 /* EOF */
131