2 * PROJECT: ReactOS FAT file system driver
3 * LICENSE: GNU GPLv3 as published by the Free Software Foundation
4 * FILE: drivers/filesystems/fastfat/fastfat.c
5 * PURPOSE: Initialization routines
6 * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
9 /* INCLUDES *****************************************************************/
14 /* GLOBALS ******************************************************************/
16 FAT_GLOBAL_DATA FatGlobalData
;
17 FAST_MUTEX FatCloseQueueMutex
;
19 /* FUNCTIONS ****************************************************************/
24 DriverEntry(PDRIVER_OBJECT DriverObject
,
25 PUNICODE_STRING RegistryPath
)
27 PDEVICE_OBJECT DeviceObject
;
28 UNICODE_STRING DeviceName
= RTL_CONSTANT_STRING(L
"\\Fat");
31 /* Create a device object */
32 Status
= IoCreateDevice(DriverObject
,
35 FILE_DEVICE_DISK_FILE_SYSTEM
,
40 if (!NT_SUCCESS(Status
)) return Status
;
42 /* Zero global storage */
43 RtlZeroMemory(&FatGlobalData
, sizeof(FAT_GLOBAL_DATA
));
44 FatGlobalData
.DriverObject
= DriverObject
;
45 FatGlobalData
.DiskDeviceObject
= DeviceObject
;
46 FatGlobalData
.SystemProcess
= PsGetCurrentProcess();
48 /* Fill major function handlers */
49 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = FatClose
;
50 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = FatCreate
;
51 DriverObject
->MajorFunction
[IRP_MJ_READ
] = FatRead
;
52 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = FatWrite
;
53 DriverObject
->MajorFunction
[IRP_MJ_FILE_SYSTEM_CONTROL
] = FatFileSystemControl
;
54 DriverObject
->MajorFunction
[IRP_MJ_QUERY_INFORMATION
] = FatQueryInformation
;
55 DriverObject
->MajorFunction
[IRP_MJ_SET_INFORMATION
] = FatSetInformation
;
56 DriverObject
->MajorFunction
[IRP_MJ_DIRECTORY_CONTROL
] = FatDirectoryControl
;
57 DriverObject
->MajorFunction
[IRP_MJ_QUERY_VOLUME_INFORMATION
] = FatQueryVolumeInfo
;
58 DriverObject
->MajorFunction
[IRP_MJ_SET_VOLUME_INFORMATION
] = FatSetVolumeInfo
;
59 DriverObject
->MajorFunction
[IRP_MJ_SHUTDOWN
] = FatShutdown
;
60 DriverObject
->MajorFunction
[IRP_MJ_LOCK_CONTROL
] = FatLockControl
;
61 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = FatDeviceControl
;
62 DriverObject
->MajorFunction
[IRP_MJ_CLEANUP
] = FatCleanup
;
63 DriverObject
->MajorFunction
[IRP_MJ_FLUSH_BUFFERS
] = FatFlushBuffers
;
64 //DriverObject->MajorFunction[IRP_MJ_QUERY_EA]
65 //DriverObject->MajorFunction[IRP_MJ_SET_EA]
66 //DriverObject->MajorFunction[IRP_MJ_PNP]
68 DriverObject
->DriverUnload
= NULL
;
70 /* Initialize cache manager callbacks */
71 FatGlobalData
.CacheMgrCallbacks
.AcquireForLazyWrite
= FatAcquireForLazyWrite
;
72 FatGlobalData
.CacheMgrCallbacks
.ReleaseFromLazyWrite
= FatReleaseFromLazyWrite
;
73 FatGlobalData
.CacheMgrCallbacks
.AcquireForReadAhead
= FatAcquireForReadAhead
;
74 FatGlobalData
.CacheMgrCallbacks
.ReleaseFromReadAhead
= FatReleaseFromReadAhead
;
76 FatGlobalData
.CacheMgrNoopCallbacks
.AcquireForLazyWrite
= FatNoopAcquire
;
77 FatGlobalData
.CacheMgrNoopCallbacks
.ReleaseFromLazyWrite
= FatNoopRelease
;
78 FatGlobalData
.CacheMgrNoopCallbacks
.AcquireForReadAhead
= FatNoopAcquire
;
79 FatGlobalData
.CacheMgrNoopCallbacks
.ReleaseFromReadAhead
= FatNoopRelease
;
81 /* Initialize Fast I/O dispatchers */
82 FatInitFastIoRoutines(&FatGlobalData
.FastIoDispatch
);
83 DriverObject
->FastIoDispatch
= &FatGlobalData
.FastIoDispatch
;
85 /* Initialize lookaside lists */
86 ExInitializeNPagedLookasideList(&FatGlobalData
.NonPagedFcbList
,
94 ExInitializeNPagedLookasideList(&FatGlobalData
.ResourceList
,
102 ExInitializeNPagedLookasideList(&FatGlobalData
.IrpContextList
,
106 sizeof(FAT_IRP_CONTEXT
),
110 /* Initialize synchronization resource for the global data */
111 ExInitializeResourceLite(&FatGlobalData
.Resource
);
113 /* Initialize queued close stuff */
114 InitializeListHead(&FatGlobalData
.AsyncCloseList
);
115 InitializeListHead(&FatGlobalData
.DelayedCloseList
);
116 FatGlobalData
.FatCloseItem
= IoAllocateWorkItem(DeviceObject
);
117 ExInitializeFastMutex(&FatCloseQueueMutex
);
119 /* Initialize global VCB list */
120 InitializeListHead(&FatGlobalData
.VcbListHead
);
122 /* Register and reference our filesystem */
123 IoRegisterFileSystem(DeviceObject
);
124 ObReferenceObject(DeviceObject
);
125 return STATUS_SUCCESS
;
130 FatBuildIrpContext(PIRP Irp
,
133 PIO_STACK_LOCATION IrpSp
;
134 PFAT_IRP_CONTEXT IrpContext
;
135 PVOLUME_DEVICE_OBJECT VolumeObject
;
137 /* Get current IRP stack location */
138 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
140 /* Allocate memory for the Irp context */
141 IrpContext
= ExAllocateFromNPagedLookasideList(&FatGlobalData
.IrpContextList
);
143 /* Zero init memory */
144 RtlZeroMemory(IrpContext
, sizeof(FAT_IRP_CONTEXT
));
146 /* Save IRP, MJ and MN */
147 IrpContext
->Irp
= Irp
;
148 IrpContext
->Stack
= IrpSp
;
149 IrpContext
->MajorFunction
= IrpSp
->MajorFunction
;
150 IrpContext
->MinorFunction
= IrpSp
->MinorFunction
;
152 /* Set DeviceObject */
153 if (IrpSp
->FileObject
)
155 IrpContext
->DeviceObject
= IrpSp
->FileObject
->DeviceObject
;
157 /* Save VCB pointer */
158 VolumeObject
= (PVOLUME_DEVICE_OBJECT
)IrpSp
->DeviceObject
;
159 IrpContext
->Vcb
= &VolumeObject
->Vcb
;
161 /* TODO: Handle write-through */
163 else if (IrpContext
->MajorFunction
== IRP_MJ_FILE_SYSTEM_CONTROL
)
165 /* Handle FSCTRL case */
166 IrpContext
->DeviceObject
= IrpSp
->Parameters
.MountVolume
.Vpb
->RealDevice
;
170 if (CanWait
) IrpContext
->Flags
|= IRPCONTEXT_CANWAIT
;
172 /* Return prepared context */
178 FatDestroyIrpContext(PFAT_IRP_CONTEXT IrpContext
)
182 /* Make sure it has no pinned stuff */
183 ASSERT(IrpContext
->PinCount
== 0);
185 /* If there is a FatIo context associated with it - free it */
186 if (IrpContext
->FatIoContext
)
188 if (!(IrpContext
->Flags
& IRPCONTEXT_STACK_IO_CONTEXT
))
190 /* If a zero mdl was allocated - free it */
191 if (IrpContext
->FatIoContext
->ZeroMdl
)
192 IoFreeMdl(IrpContext
->FatIoContext
->ZeroMdl
);
194 /* Free memory of FatIo context */
195 ExFreePool(IrpContext
->FatIoContext
);
200 ExFreeToNPagedLookasideList(&FatGlobalData
.IrpContextList
, IrpContext
);
205 FatCompleteRequest(PFAT_IRP_CONTEXT IrpContext OPTIONAL
,
213 /* TODO: Unpin repinned BCBs */
214 //ASSERT(IrpContext->Repinned.Bcb[0] == NULL);
215 //FatUnpinRepinnedBcbs( IrpContext );
217 /* Destroy IRP context */
218 FatDestroyIrpContext(IrpContext
);
221 /* Complete the IRP */
224 /* Cleanup IoStatus.Information in case of error input operation */
225 if (NT_ERROR(Status
) && (Irp
->Flags
& IRP_INPUT_OPERATION
))
227 Irp
->IoStatus
.Information
= 0;
230 /* Save status and complete this IRP */
231 Irp
->IoStatus
.Status
= Status
;
232 IoCompleteRequest( Irp
, IO_DISK_INCREMENT
);
238 FatDequeueRequest(IN PVOID Context
)
240 PFAT_IRP_CONTEXT IrpContext
;
242 IrpContext
= (PFAT_IRP_CONTEXT
) Context
;
244 /* Enter critical region. */
245 FsRtlEnterFileSystem();
247 /* Handle top level IRP Correctly. */
248 if (!FlagOn(IrpContext
->Flags
, IRPCONTEXT_TOPLEVEL
))
249 IoSetTopLevelIrp((PIRP
) FSRTL_FSP_TOP_LEVEL_IRP
);
251 /* Enable Synchronous IO. */
252 SetFlag(IrpContext
->Flags
, IRPCONTEXT_CANWAIT
);
254 /* Invoke the handler routine. */
255 IrpContext
->QueuedOperationHandler(IrpContext
);
257 /* Restore top level IRP. */
258 IoSetTopLevelIrp(NULL
);
260 /* Leave critical region. */
261 FsRtlExitFileSystem();
266 FatQueueRequest(IN PFAT_IRP_CONTEXT IrpContext
,
267 IN PFAT_OPERATION_HANDLER OperationHandler
)
269 /* Save the worker routine. */
270 IrpContext
->QueuedOperationHandler
= OperationHandler
;
272 /* Indicate if top level IRP was set. */
273 if (IoGetTopLevelIrp() == IrpContext
->Irp
)
274 SetFlag(IrpContext
->Flags
, IRPCONTEXT_TOPLEVEL
);
276 /* Initialize work item. */
277 ExInitializeWorkItem(&IrpContext
->WorkQueueItem
,
280 ExQueueWorkItem(&IrpContext
->WorkQueueItem
,
286 FatDecodeFileObject(IN PFILE_OBJECT FileObject
,
291 TYPE_OF_OPEN TypeOfOpen
= UnopenedFileObject
;
292 PVOID FsContext
= FileObject
->FsContext
;
293 PVOID FsContext2
= FileObject
->FsContext2
;
295 /* If FsContext is NULL, then everything is NULL */
305 /* CCB is always stored in FsContext2 */
308 /* Switch according to the NodeType */
309 switch (FatNodeType(FsContext
))
316 TypeOfOpen
= ( *Ccb
== NULL
? VirtualVolumeFile
: UserVolumeOpen
);
320 /* Root or normal directory*/
321 case FAT_NTC_ROOT_DCB
:
323 *FcbOrDcb
= FsContext
;
324 *Vcb
= (*FcbOrDcb
)->Vcb
;
326 TypeOfOpen
= (*Ccb
== NULL
? DirectoryFile
: UserDirectoryOpen
);
328 DPRINT("Referencing a directory: %wZ\n", &(*FcbOrDcb
)->FullFileName
);
333 *FcbOrDcb
= FsContext
;
334 *Vcb
= (*FcbOrDcb
)->Vcb
;
336 TypeOfOpen
= (*Ccb
== NULL
? EaFile
: UserFileOpen
);
338 DPRINT("Referencing a file: %wZ\n", &(*FcbOrDcb
)->FullFileName
);
343 DPRINT1("Unknown node type %x\n", FatNodeType(FsContext
));
352 FatSetFileObject(PFILE_OBJECT FileObject
,
353 TYPE_OF_OPEN TypeOfOpen
,
359 /* Check Fcb's type */
360 if (FatNodeType(Fcb
) == FAT_NTC_VCB
)
362 FileObject
->Vpb
= ((PVCB
)Fcb
)->Vpb
;
366 FileObject
->Vpb
= ((PFCB
)Fcb
)->Vcb
->Vpb
;
373 FileObject
->FsContext
= Fcb
;
374 FileObject
->FsContext2
= Ccb
;
381 FatAcquireExclusiveVcb(IN PFAT_IRP_CONTEXT IrpContext
,
384 /* Acquire VCB's resource if possible */
385 if (ExAcquireResourceExclusiveLite(&Vcb
->Resource
,
386 BooleanFlagOn(IrpContext
->Flags
, IRPCONTEXT_CANWAIT
)))
398 FatAcquireSharedVcb(IN PFAT_IRP_CONTEXT IrpContext
,
401 /* Acquire VCB's resource if possible */
402 if (ExAcquireResourceSharedLite(&Vcb
->Resource
,
403 BooleanFlagOn(IrpContext
->Flags
, IRPCONTEXT_CANWAIT
)))
415 FatReleaseVcb(IN PFAT_IRP_CONTEXT IrpContext
,
418 /* Release VCB's resource */
419 ExReleaseResourceLite(&Vcb
->Resource
);
424 FatAcquireExclusiveFcb(IN PFAT_IRP_CONTEXT IrpContext
,
428 /* Try to acquire the exclusive lock*/
429 if (ExAcquireResourceExclusiveLite(Fcb
->Header
.Resource
,
430 BooleanFlagOn(IrpContext
->Flags
, IRPCONTEXT_CANWAIT
)))
432 /* Wait same way MS's FASTFAT wait, i.e.
433 checking that there are outstanding async writes,
434 or someone is waiting on it*/
435 if (Fcb
->OutstandingAsyncWrites
&&
436 ((IrpContext
->MajorFunction
!= IRP_MJ_WRITE
) ||
437 !FlagOn(IrpContext
->Irp
->Flags
, IRP_NOCACHE
) ||
438 ExGetSharedWaiterCount(Fcb
->Header
.Resource
) ||
439 ExGetExclusiveWaiterCount(Fcb
->Header
.Resource
)))
441 KeWaitForSingleObject(Fcb
->OutstandingAsyncEvent
,
447 /* Release the lock */
448 FatReleaseFcb(IrpContext
, Fcb
);
464 FatAcquireSharedFcb(IN PFAT_IRP_CONTEXT IrpContext
,
468 /* Try to acquire the shared lock*/
469 if (ExAcquireResourceSharedLite(Fcb
->Header
.Resource
,
470 BooleanFlagOn(IrpContext
->Flags
, IRPCONTEXT_CANWAIT
)))
472 /* Wait same way MS's FASTFAT wait, i.e.
473 checking that there are outstanding async writes,
474 or someone is waiting on it*/
475 if (Fcb
->OutstandingAsyncWrites
&&
476 ((IrpContext
->MajorFunction
!= IRP_MJ_WRITE
) ||
477 !FlagOn(IrpContext
->Irp
->Flags
, IRP_NOCACHE
) ||
478 ExGetSharedWaiterCount(Fcb
->Header
.Resource
) ||
479 ExGetExclusiveWaiterCount(Fcb
->Header
.Resource
)))
481 KeWaitForSingleObject(Fcb
->OutstandingAsyncEvent
,
487 /* Release the lock */
488 FatReleaseFcb(IrpContext
, Fcb
);
504 FatReleaseFcb(IN PFAT_IRP_CONTEXT IrpContext
,
507 /* Release FCB's resource */
508 ExReleaseResourceLite(Fcb
->Header
.Resource
);
513 FatMapUserBuffer(PIRP Irp
)
515 if (!Irp
->MdlAddress
)
516 return Irp
->UserBuffer
;
518 return MmGetSystemAddressForMdlSafe(Irp
->MdlAddress
, NormalPagePriority
);
523 FatIsTopLevelIrp(IN PIRP Irp
)
525 if (!IoGetTopLevelIrp())
527 IoSetTopLevelIrp(Irp
);
536 FatNotifyReportChange(IN PFAT_IRP_CONTEXT IrpContext
,
542 if (Fcb
->FullFileName
.Buffer
== NULL
)
543 FatSetFullFileNameInFcb(IrpContext
, Fcb
);
545 ASSERT(Fcb
->FullFileName
.Length
!= 0 );
546 ASSERT(Fcb
->FileNameLength
!= 0 );
547 ASSERT(Fcb
->FullFileName
.Length
> Fcb
->FileNameLength
);
548 ASSERT(Fcb
->FullFileName
.Buffer
[(Fcb
->FullFileName
.Length
- Fcb
->FileNameLength
)/sizeof(WCHAR
) - 1] == L
'\\' );
550 FsRtlNotifyFullReportChange(Vcb
->NotifySync
,
552 (PSTRING
)&Fcb
->FullFileName
,
553 (USHORT
)(Fcb
->FullFileName
.Length
-
554 Fcb
->FileNameLength
),