1428bae9e5f2b01622b5810c26f38d59138a8a07
[reactos.git] / reactos / drivers / fs / vfat / iface.c
1 /* $Id: iface.c,v 1.39 1999/12/11 21:14:49 dwelch Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: services/fs/vfat/iface.c
6 * PURPOSE: VFAT Filesystem
7 * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
8 * UPDATE HISTORY:
9 * ?? Created
10 * 24-10-1998 Fixed bugs in long filename support
11 * Fixed a bug that prevented unsuccessful file open requests being reported
12 * Now works with long filenames that span over a sector boundary
13 * 28-10-1998 Reads entire FAT into memory
14 * VFatReadSector modified to read in more than one sector at a time
15 * 7-11-1998 Fixed bug that assumed that directory data could be fragmented
16 * 8-12-1998 Added FAT32 support
17 * Added initial writability functions
18 * WARNING: DO NOT ATTEMPT TO TEST WRITABILITY FUNCTIONS!!!
19 * 12-12-1998 Added basic support for FILE_STANDARD_INFORMATION request
20 *
21 */
22
23 /* INCLUDES *****************************************************************/
24
25 #include <wchar.h>
26 #include <internal/string.h>
27 #include <ddk/ntddk.h>
28 #include <ddk/cctypes.h>
29
30 #define NDEBUG
31 #include <internal/debug.h>
32
33 #include "vfat.h"
34
35 /* GLOBALS *****************************************************************/
36
37 static PDRIVER_OBJECT VfatDriverObject;
38
39 /* FUNCTIONS ****************************************************************/
40
41 BOOLEAN FsdHasFileSystem(PDEVICE_OBJECT DeviceToMount)
42 /*
43 * FUNCTION: Tests if the device contains a filesystem that can be mounted
44 * by this fsd
45 */
46 {
47 BootSector* Boot;
48
49 Boot = ExAllocatePool(NonPagedPool,512);
50
51 VFATReadSectors(DeviceToMount, 0, 1, (UCHAR *)Boot);
52
53 if (strncmp(Boot->SysType,"FAT12",5)==0 ||
54 strncmp(Boot->SysType,"FAT16",5)==0 ||
55 strncmp(((struct _BootSector32 *)(Boot))->SysType,"FAT32",5)==0)
56 {
57 ExFreePool(Boot);
58 return(TRUE);
59 }
60 ExFreePool(Boot);
61 return(FALSE);
62 }
63
64 NTSTATUS FsdMountDevice(PDEVICE_EXTENSION DeviceExt,
65 PDEVICE_OBJECT DeviceToMount)
66 /*
67 * FUNCTION: Mounts the device
68 */
69 {
70 DPRINT("Mounting VFAT device...");
71 DPRINT("DeviceExt %x\n",DeviceExt);
72
73 DeviceExt->Boot = ExAllocatePool(NonPagedPool,512);
74 VFATReadSectors(DeviceToMount, 0, 1, (UCHAR *)DeviceExt->Boot);
75
76 DPRINT("DeviceExt->Boot->BytesPerSector %x\n",
77 DeviceExt->Boot->BytesPerSector);
78
79 DeviceExt->FATStart=DeviceExt->Boot->ReservedSectors;
80 DeviceExt->rootDirectorySectors=
81 (DeviceExt->Boot->RootEntries*32)/DeviceExt->Boot->BytesPerSector;
82 DeviceExt->rootStart=
83 DeviceExt->FATStart+DeviceExt->Boot->FATCount*DeviceExt->Boot->FATSectors;
84 DeviceExt->dataStart=DeviceExt->rootStart+DeviceExt->rootDirectorySectors;
85 DeviceExt->FATEntriesPerSector=DeviceExt->Boot->BytesPerSector/32;
86 DeviceExt->BytesPerCluster = DeviceExt->Boot->SectorsPerCluster *
87 DeviceExt->Boot->BytesPerSector;
88
89 if (strncmp(DeviceExt->Boot->SysType,"FAT12",5)==0)
90 {
91 DeviceExt->FatType = FAT12;
92 }
93 else if (strncmp(((struct _BootSector32 *)(DeviceExt->Boot))->SysType,"FAT32",5)==0)
94 {
95 DeviceExt->FatType = FAT32;
96 DeviceExt->rootDirectorySectors=DeviceExt->Boot->SectorsPerCluster;
97 DeviceExt->rootStart=
98 DeviceExt->FATStart+DeviceExt->Boot->FATCount
99 *((struct _BootSector32 *)( DeviceExt->Boot))->FATSectors32;
100 DeviceExt->dataStart=DeviceExt->rootStart;
101 }
102 else
103 {
104 DeviceExt->FatType = FAT16;
105 }
106
107 // with FAT32 it's not a good idea to load always fat in memory
108 // because on a 8GB partition with 2 KO clusters, the fat = 8 MO
109 if(DeviceExt->FatType!=FAT32)
110 {
111 DeviceExt->FAT = ExAllocatePool(NonPagedPool, BLOCKSIZE*DeviceExt->Boot->FATSectors);
112 VFATReadSectors(DeviceToMount, DeviceExt->FATStart, DeviceExt->Boot->FATSectors, (UCHAR *)DeviceExt->FAT);
113 }
114 return STATUS_SUCCESS;
115 }
116
117 NTSTATUS FsdMount(PDEVICE_OBJECT DeviceToMount)
118 /*
119 * FUNCTION: Mount the filesystem
120 */
121 {
122 PDEVICE_OBJECT DeviceObject;
123 PDEVICE_EXTENSION DeviceExt;
124
125 IoCreateDevice(VfatDriverObject,
126 sizeof(DEVICE_EXTENSION),
127 NULL,
128 FILE_DEVICE_FILE_SYSTEM,
129 0,
130 FALSE,
131 &DeviceObject);
132 DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO;
133 DeviceExt = (PVOID)DeviceObject->DeviceExtension;
134 // use same vpb as device disk
135 DeviceObject->Vpb=DeviceToMount->Vpb;
136 FsdMountDevice(DeviceExt,DeviceToMount);
137 DeviceObject->Vpb->Flags |= VPB_MOUNTED;
138 DeviceExt->StorageDevice = IoAttachDeviceToDeviceStack(DeviceObject,
139 DeviceToMount);
140 ExInitializeResourceLite(&DeviceExt->DirResource);
141 ExInitializeResourceLite(&DeviceExt->FatResource);
142
143 KeInitializeSpinLock(&DeviceExt->FcbListLock);
144 InitializeListHead(&DeviceExt->FcbListHead);
145
146 /* read serial number */
147 if (DeviceExt->FatType == FAT12 || DeviceExt->FatType == FAT16)
148 DeviceObject->Vpb->SerialNumber =
149 ((struct _BootSector *)(DeviceExt->Boot))->VolumeID;
150 else if (DeviceExt->FatType == FAT32)
151 DeviceObject->Vpb->SerialNumber =
152 ((struct _BootSector32 *)(DeviceExt->Boot))->VolumeID;
153
154 /* read volume label */
155 ReadVolumeLabel (DeviceExt, DeviceObject->Vpb);
156
157 return(STATUS_SUCCESS);
158 }
159
160 NTSTATUS FsdFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
161 /*
162 * FUNCTION: File system control
163 */
164 {
165 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
166 // PVPB vpb = Stack->Parameters.Mount.Vpb;
167 PDEVICE_OBJECT DeviceToMount = Stack->Parameters.Mount.DeviceObject;
168 NTSTATUS Status;
169
170 // DPRINT("VFAT FSC\n");
171 DbgPrint("VFAT FSC\n");
172
173 /* FIXME: should make sure that this is actually a mount request! */
174
175 if (FsdHasFileSystem(DeviceToMount))
176 {
177 Status = FsdMount(DeviceToMount);
178 }
179 else
180 {
181 DPRINT("VFAT: Unrecognized Volume\n");
182 Status = STATUS_UNRECOGNIZED_VOLUME;
183 }
184 DPRINT("VFAT File system successfully mounted\n");
185
186 Irp->IoStatus.Status = Status;
187 Irp->IoStatus.Information = 0;
188
189 IoCompleteRequest(Irp, IO_NO_INCREMENT);
190 return(Status);
191 }
192
193 NTSTATUS STDCALL DriverEntry(PDRIVER_OBJECT _DriverObject,
194 PUNICODE_STRING RegistryPath)
195 /*
196 * FUNCTION: Called by the system to initalize the driver
197 * ARGUMENTS:
198 * DriverObject = object describing this driver
199 * RegistryPath = path to our configuration entries
200 * RETURNS: Success or failure
201 */
202 {
203 PDEVICE_OBJECT DeviceObject;
204 NTSTATUS ret;
205 UNICODE_STRING DeviceName;
206
207 DbgPrint("VFAT 0.0.6\n");
208
209 VfatDriverObject = _DriverObject;
210
211 RtlInitUnicodeString(&DeviceName, L"\\Device\\Vfat");
212 ret = IoCreateDevice(VfatDriverObject,0,&DeviceName,
213 FILE_DEVICE_FILE_SYSTEM,0,FALSE,&DeviceObject);
214 if (ret!=STATUS_SUCCESS)
215 {
216 return(ret);
217 }
218
219 DeviceObject->Flags = DO_DIRECT_IO;
220 VfatDriverObject->MajorFunction[IRP_MJ_CLOSE] = FsdClose;
221 VfatDriverObject->MajorFunction[IRP_MJ_CREATE] = FsdCreate;
222 VfatDriverObject->MajorFunction[IRP_MJ_READ] = FsdRead;
223 VfatDriverObject->MajorFunction[IRP_MJ_WRITE] = FsdWrite;
224 VfatDriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] =
225 FsdFileSystemControl;
226 VfatDriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] =
227 FsdQueryInformation;
228 VfatDriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] =
229 VfatSetInformation;
230 VfatDriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] =
231 FsdDirectoryControl;
232 VfatDriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] =
233 VfatQueryVolumeInformation;
234
235 VfatDriverObject->DriverUnload = NULL;
236
237 IoRegisterFileSystem(DeviceObject);
238
239 return(STATUS_SUCCESS);
240 }
241