xref: /reactos/drivers/filesystems/fs_rec/fat.c (revision 4561998a)
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 */
181