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