Sync with trunk r63174.
[reactos.git] / drivers / filesystems / fs_rec / fat.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS File System Recognizer
4 * FILE: drivers/filesystems/fs_rec/fat.c
5 * PURPOSE: FAT Recognizer
6 * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
7 * Eric Kohl
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include "fs_rec.h"
13
14 #define NDEBUG
15 #include <debug.h>
16
17 /* FUNCTIONS ****************************************************************/
18
19 BOOLEAN
20 NTAPI
21 FsRecIsFatVolume(IN PPACKED_BOOT_SECTOR PackedBootSector)
22 {
23 BIOS_PARAMETER_BLOCK Bpb;
24 BOOLEAN Result = TRUE;
25 PAGED_CODE();
26
27 RtlZeroMemory(&Bpb, sizeof(BIOS_PARAMETER_BLOCK));
28
29 /* Unpack the BPB and do a small fix up */
30 FatUnpackBios(&Bpb, &PackedBootSector->PackedBpb);
31 if (Bpb.Sectors) Bpb.LargeSectors = 0;
32
33 /* Recognize jump */
34 if ((PackedBootSector->Jump[0] != 0x49) &&
35 (PackedBootSector->Jump[0] != 0xE9) &&
36 (PackedBootSector->Jump[0] != 0xEB))
37 {
38 /* Fail */
39 Result = FALSE;
40 }
41 else if ((Bpb.BytesPerSector != 128) &&
42 (Bpb.BytesPerSector != 256) &&
43 (Bpb.BytesPerSector != 512) &&
44 (Bpb.BytesPerSector != 1024) &&
45 (Bpb.BytesPerSector != 2048) &&
46 (Bpb.BytesPerSector != 4096))
47 {
48 /* Fail */
49 Result = FALSE;
50 }
51 else if ((Bpb.SectorsPerCluster != 1) &&
52 (Bpb.SectorsPerCluster != 2) &&
53 (Bpb.SectorsPerCluster != 4) &&
54 (Bpb.SectorsPerCluster != 8) &&
55 (Bpb.SectorsPerCluster != 16) &&
56 (Bpb.SectorsPerCluster != 32) &&
57 (Bpb.SectorsPerCluster != 64) &&
58 (Bpb.SectorsPerCluster != 128))
59 {
60 /* Fail */
61 Result = FALSE;
62 }
63 else if (!Bpb.ReservedSectors)
64 {
65 /* Fail */
66 Result = FALSE;
67 }
68 else if (!(Bpb.Sectors) && !(Bpb.LargeSectors))
69 {
70 /* Fail */
71 Result = FALSE;
72 }
73 else if ((Bpb.Media != 0x00) &&
74 (Bpb.Media != 0x01) &&
75 (Bpb.Media != 0xf0) &&
76 (Bpb.Media != 0xf8) &&
77 (Bpb.Media != 0xf9) &&
78 (Bpb.Media != 0xfa) &&
79 (Bpb.Media != 0xfb) &&
80 (Bpb.Media != 0xfc) &&
81 (Bpb.Media != 0xfd) &&
82 (Bpb.Media != 0xfe) &&
83 (Bpb.Media != 0xff))
84 {
85 /* Fail */
86 Result = FALSE;
87 }
88 else if ((Bpb.SectorsPerFat) && !(Bpb.RootEntries))
89 {
90 /* Fail */
91 Result = FALSE;
92 }
93
94 /* Return the result */
95 return Result;
96 }
97
98 NTSTATUS
99 NTAPI
100 FsRecVfatFsControl(IN PDEVICE_OBJECT DeviceObject,
101 IN PIRP Irp)
102 {
103 PIO_STACK_LOCATION Stack;
104 NTSTATUS Status;
105 PDEVICE_OBJECT MountDevice;
106 PPACKED_BOOT_SECTOR Bpb = NULL;
107 ULONG SectorSize;
108 LARGE_INTEGER Offset = {{0, 0}};
109 BOOLEAN DeviceError = FALSE;
110 PAGED_CODE();
111
112 /* Get the I/O Stack and check the function type */
113 Stack = IoGetCurrentIrpStackLocation(Irp);
114 switch (Stack->MinorFunction)
115 {
116 case IRP_MN_MOUNT_VOLUME:
117
118 /* Assume failure */
119 Status = STATUS_UNRECOGNIZED_VOLUME;
120
121 /* Get the device object and request the sector size */
122 MountDevice = Stack->Parameters.MountVolume.DeviceObject;
123 if (FsRecGetDeviceSectorSize(MountDevice, &SectorSize))
124 {
125 /* Try to read the BPB */
126 if (FsRecReadBlock(MountDevice,
127 &Offset,
128 512,
129 SectorSize,
130 (PVOID)&Bpb,
131 &DeviceError))
132 {
133 /* Check if it's an actual FAT volume */
134 if (FsRecIsFatVolume(Bpb))
135 {
136 /* It is! */
137 Status = STATUS_FS_DRIVER_REQUIRED;
138 }
139 }
140
141 /* Free the boot sector if we have one */
142 ExFreePool(Bpb);
143 }
144 else
145 {
146 /* We have some sort of failure in the storage stack */
147 DeviceError = TRUE;
148 }
149
150 /* Check if we have an error on the stack */
151 if (DeviceError)
152 {
153 /* Was this because of a floppy? */
154 if (MountDevice->Characteristics & FILE_FLOPPY_DISKETTE)
155 {
156 /* Let the FS try anyway */
157 Status = STATUS_FS_DRIVER_REQUIRED;
158 }
159 }
160
161 break;
162
163 case IRP_MN_LOAD_FILE_SYSTEM:
164
165 /* Load the file system */
166 Status = FsRecLoadFileSystem(DeviceObject,
167 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\fastfat");
168 break;
169
170 default:
171
172 /* Invalid request */
173 Status = STATUS_INVALID_DEVICE_REQUEST;
174 }
175
176 /* Return Status */
177 return Status;
178 }
179
180 /* EOF */