925d83adc3943a3b2889ca4c6855ccd33209647b
[reactos.git] / reactos / drivers / filesystems / fastfat_new / fastfat.c
1 /*
2 * PROJECT: ReactOS FAT file system driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/filesystems/fastfat/fastfat.c
5 * PURPOSE: Initialization routines
6 * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #define NDEBUG
12 #include "fastfat.h"
13
14 /* GLOBALS ******************************************************************/
15
16 FAT_GLOBAL_DATA FatGlobalData;
17
18 /* FUNCTIONS ****************************************************************/
19
20
21 NTSTATUS
22 NTAPI
23 DriverEntry(PDRIVER_OBJECT DriverObject,
24 PUNICODE_STRING RegistryPath)
25 {
26 PDEVICE_OBJECT DeviceObject;
27 UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Fat");
28 NTSTATUS Status;
29
30 /* Create a device object */
31 Status = IoCreateDevice(DriverObject,
32 0,
33 &DeviceName,
34 FILE_DEVICE_DISK_FILE_SYSTEM,
35 0,
36 FALSE,
37 &DeviceObject);
38
39 if (!NT_SUCCESS(Status)) return Status;
40
41 /* Zero global storage */
42 RtlZeroMemory(&FatGlobalData, sizeof(FAT_GLOBAL_DATA));
43 FatGlobalData.DriverObject = DriverObject;
44 FatGlobalData.DiskDeviceObject = DeviceObject;
45
46 /* Fill major function handlers */
47 DriverObject->MajorFunction[IRP_MJ_CLOSE] = FatClose;
48 DriverObject->MajorFunction[IRP_MJ_CREATE] = FatCreate;
49 DriverObject->MajorFunction[IRP_MJ_READ] = FatRead;
50 DriverObject->MajorFunction[IRP_MJ_WRITE] = FatWrite;
51 DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FatFileSystemControl;
52 DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = FatQueryInformation;
53 DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = FatSetInformation;
54 DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = FatDirectoryControl;
55 DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = FatQueryVolumeInfo;
56 DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = FatSetVolumeInfo;
57 DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = FatShutdown;
58 DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = FatLockControl;
59 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = FatDeviceControl;
60 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FatCleanup;
61 DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = FatFlushBuffers;
62 //DriverObject->MajorFunction[IRP_MJ_QUERY_EA]
63 //DriverObject->MajorFunction[IRP_MJ_SET_EA]
64 //DriverObject->MajorFunction[IRP_MJ_PNP]
65
66 DriverObject->DriverUnload = NULL;
67
68 /* Initialize cache manager callbacks */
69 FatGlobalData.CacheMgrCallbacks.AcquireForLazyWrite = FatAcquireForLazyWrite;
70 FatGlobalData.CacheMgrCallbacks.ReleaseFromLazyWrite = FatReleaseFromLazyWrite;
71 FatGlobalData.CacheMgrCallbacks.AcquireForReadAhead = FatAcquireForReadAhead;
72 FatGlobalData.CacheMgrCallbacks.ReleaseFromReadAhead = FatReleaseFromReadAhead;
73
74 FatGlobalData.CacheMgrNoopCallbacks.AcquireForLazyWrite = FatNoopAcquire;
75 FatGlobalData.CacheMgrNoopCallbacks.ReleaseFromLazyWrite = FatNoopRelease;
76 FatGlobalData.CacheMgrNoopCallbacks.AcquireForReadAhead = FatNoopAcquire;
77 FatGlobalData.CacheMgrNoopCallbacks.ReleaseFromReadAhead = FatNoopRelease;
78
79 /* Initialize Fast I/O dispatchers */
80 FatInitFastIoRoutines(&FatGlobalData.FastIoDispatch);
81 DriverObject->FastIoDispatch = &FatGlobalData.FastIoDispatch;
82
83 /* Initialize lookaside lists */
84 ExInitializeNPagedLookasideList(&FatGlobalData.NonPagedFcbList,
85 NULL,
86 NULL,
87 0,
88 sizeof(FCB),
89 TAG_FCB,
90 0);
91
92 ExInitializeNPagedLookasideList(&FatGlobalData.ResourceList,
93 NULL,
94 NULL,
95 0,
96 sizeof(ERESOURCE),
97 TAG_CCB,
98 0);
99
100 ExInitializeNPagedLookasideList(&FatGlobalData.IrpContextList,
101 NULL,
102 NULL,
103 0,
104 sizeof(FAT_IRP_CONTEXT),
105 TAG_IRP,
106 0);
107
108 /* Initialize synchronization resource for the global data */
109 ExInitializeResourceLite(&FatGlobalData.Resource);
110
111 /* Initialize global VCB list */
112 InitializeListHead(&FatGlobalData.VcbListHead);
113
114 /* Register and reference our filesystem */
115 IoRegisterFileSystem(DeviceObject);
116 ObReferenceObject(DeviceObject);
117 return STATUS_SUCCESS;
118 }
119
120 PFAT_IRP_CONTEXT
121 NTAPI
122 FatBuildIrpContext(PIRP Irp,
123 BOOLEAN CanWait)
124 {
125 PIO_STACK_LOCATION IrpSp;
126 PFAT_IRP_CONTEXT IrpContext;
127 PVOLUME_DEVICE_OBJECT VolumeObject;
128
129 /* Get current IRP stack location */
130 IrpSp = IoGetCurrentIrpStackLocation(Irp);
131
132 /* Allocate memory for the Irp context */
133 IrpContext = ExAllocateFromNPagedLookasideList(&FatGlobalData.IrpContextList);
134
135 /* Zero init memory */
136 RtlZeroMemory(IrpContext, sizeof(FAT_IRP_CONTEXT));
137
138 /* Save IRP, MJ and MN */
139 IrpContext->Irp = Irp;
140 IrpContext->MajorFunction = IrpSp->MajorFunction;
141 IrpContext->MinorFunction = IrpSp->MinorFunction;
142
143 /* Set DeviceObject */
144 if (IrpSp->FileObject)
145 {
146 IrpContext->DeviceObject = IrpSp->FileObject->DeviceObject;
147
148 /* Save VCB pointer */
149 VolumeObject = (PVOLUME_DEVICE_OBJECT)IrpSp->DeviceObject;
150 IrpContext->Vcb = &VolumeObject->Vcb;
151
152 /* TODO: Handle write-through */
153 }
154 else if (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL)
155 {
156 /* Handle FSCTRL case */
157 IrpContext->DeviceObject = IrpSp->Parameters.MountVolume.Vpb->RealDevice;
158 }
159
160 /* Set Wait flag */
161 if (CanWait) IrpContext->Flags |= IRPCONTEXT_CANWAIT;
162
163 /* Return prepared context */
164 return IrpContext;
165 }
166
167 VOID
168 NTAPI
169 FatDestroyIrpContext(PFAT_IRP_CONTEXT IrpContext)
170 {
171 PAGED_CODE();
172
173 /* Make sure it has no pinned stuff */
174 ASSERT(IrpContext->PinCount == 0);
175
176 /* If there is a FatIo context associated with it - free it */
177 if (IrpContext->FatIoContext)
178 {
179 if (!(IrpContext->Flags & IRPCONTEXT_STACK_IO_CONTEXT))
180 {
181 /* If a zero mdl was allocated - free it */
182 if (IrpContext->FatIoContext->ZeroMdl)
183 IoFreeMdl(IrpContext->FatIoContext->ZeroMdl);
184
185 /* Free memory of FatIo context */
186 ExFreePool(IrpContext->FatIoContext);
187 }
188 }
189
190 /* Free memory */
191 ExFreeToNPagedLookasideList(&FatGlobalData.IrpContextList, IrpContext);
192 }
193
194 VOID
195 NTAPI
196 FatCompleteRequest(PFAT_IRP_CONTEXT IrpContext OPTIONAL,
197 PIRP Irp OPTIONAL,
198 NTSTATUS Status)
199 {
200 PAGED_CODE();
201
202 if (IrpContext)
203 {
204 /* TODO: Unpin repinned BCBs */
205 //ASSERT(IrpContext->Repinned.Bcb[0] == NULL);
206 //FatUnpinRepinnedBcbs( IrpContext );
207
208 /* Destroy IRP context */
209 FatDestroyIrpContext(IrpContext);
210 }
211
212 /* Complete the IRP */
213 if (Irp)
214 {
215 /* Cleanup IoStatus.Information in case of error input operation */
216 if (NT_ERROR(Status) && (Irp->Flags & IRP_INPUT_OPERATION))
217 {
218 Irp->IoStatus.Information = 0;
219 }
220
221 /* Save status and complete this IRP */
222 Irp->IoStatus.Status = Status;
223 IoCompleteRequest( Irp, IO_DISK_INCREMENT );
224 }
225 }
226
227 VOID
228 NTAPI
229 FatDequeueRequest(IN PVOID Context)
230 {
231 PFAT_IRP_CONTEXT IrpContext;
232
233 IrpContext = (PFAT_IRP_CONTEXT) Context;
234
235 /* Enter critical region. */
236 FsRtlEnterFileSystem();
237
238 /* Handle top level IRP Correctly. */
239 if (!FlagOn(IrpContext->Flags, IRPCONTEXT_TOPLEVEL))
240 IoSetTopLevelIrp((PIRP) FSRTL_FSP_TOP_LEVEL_IRP);
241
242 /* Enable Synchronous IO. */
243 SetFlag(IrpContext->Flags, IRPCONTEXT_CANWAIT);
244
245 /* Invoke the handler routine. */
246 IrpContext->QueuedOperationHandler(IrpContext);
247
248 /* Restore top level IRP. */
249 IoSetTopLevelIrp(NULL);
250
251 /* Leave critical region. */
252 FsRtlExitFileSystem();
253 }
254
255 VOID
256 NTAPI
257 FatQueueRequest(IN PFAT_IRP_CONTEXT IrpContext,
258 IN PFAT_OPERATION_HANDLER OperationHandler)
259 {
260 /* Save the worker routine. */
261 IrpContext->QueuedOperationHandler = OperationHandler;
262
263 /* Indicate if top level IRP was set. */
264 if (IoGetTopLevelIrp() == IrpContext->Irp)
265 SetFlag(IrpContext->Flags, IRPCONTEXT_TOPLEVEL);
266
267 /* Initialize work item. */
268 ExInitializeWorkItem(&IrpContext->WorkQueueItem,
269 FatDequeueRequest,
270 IrpContext);
271 ExQueueWorkItem(&IrpContext->WorkQueueItem,
272 DelayedWorkQueue);
273 }
274
275 TYPE_OF_OPEN
276 NTAPI
277 FatDecodeFileObject(IN PFILE_OBJECT FileObject,
278 OUT PVCB *Vcb,
279 OUT PFCB *FcbOrDcb,
280 OUT PCCB *Ccb)
281 {
282 TYPE_OF_OPEN TypeOfOpen = UnopenedFileObject;
283 PVOID FsContext = FileObject->FsContext;
284 PVOID FsContext2 = FileObject->FsContext2;
285
286 /* If FsContext is NULL, then everything is NULL */
287 if (!FsContext)
288 {
289 *Ccb = NULL;
290 *FcbOrDcb = NULL;
291 *Vcb = NULL;
292
293 return TypeOfOpen;
294 }
295
296 /* CCB is always stored in FsContext2 */
297 *Ccb = FsContext2;
298
299 /* Switch according to the NodeType */
300 switch (FatNodeType(FsContext))
301 {
302 /* Volume */
303 case FAT_NTC_VCB:
304 *FcbOrDcb = NULL;
305 *Vcb = FsContext;
306
307 TypeOfOpen = ( *Ccb == NULL ? VirtualVolumeFile : UserVolumeOpen );
308
309 break;
310
311 /* Root or normal directory*/
312 case FAT_NTC_ROOT_DCB:
313 case FAT_NTC_DCB:
314 *FcbOrDcb = FsContext;
315 *Vcb = (*FcbOrDcb)->Vcb;
316
317 TypeOfOpen = (*Ccb == NULL ? DirectoryFile : UserDirectoryOpen);
318
319 DPRINT1("Referencing a directory: %Z\n", &(*FcbOrDcb)->FullFileName);
320 break;
321
322 /* File */
323 case FAT_NTC_FCB:
324 *FcbOrDcb = FsContext;
325 *Vcb = (*FcbOrDcb)->Vcb;
326
327 TypeOfOpen = (*Ccb == NULL ? EaFile : UserFileOpen);
328
329 DPRINT1("Referencing a file: %Z\n", &(*FcbOrDcb)->FullFileName);
330
331 break;
332
333 default:
334 DPRINT1("Unknown node type %x\n", FatNodeType(FsContext));
335 ASSERT(FALSE);
336 }
337
338 return TypeOfOpen;
339 }
340
341
342 BOOLEAN
343 NTAPI
344 FatAcquireExclusiveVcb(IN PFAT_IRP_CONTEXT IrpContext,
345 IN PVCB Vcb)
346 {
347 /* Acquire VCB's resource if possible */
348 if (ExAcquireResourceExclusiveLite(&Vcb->Resource,
349 BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT)))
350 {
351 return TRUE;
352 }
353 else
354 {
355 return FALSE;
356 }
357 }
358
359 VOID
360 NTAPI
361 FatReleaseVcb(IN PFAT_IRP_CONTEXT IrpContext,
362 IN PVCB Vcb)
363 {
364 /* Release VCB's resource */
365 ExReleaseResourceLite(&Vcb->Resource);
366 }
367
368
369 /* EOF */