2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/fs/vfat/misc.c
5 * PURPOSE: VFAT Filesystem
10 /* INCLUDES *****************************************************************/
17 /* GLOBALS ******************************************************************/
19 const char* MajorFunctionNames
[] =
22 "IRP_MJ_CREATE_NAMED_PIPE",
26 "IRP_MJ_QUERY_INFORMATION",
27 "IRP_MJ_SET_INFORMATION",
30 "IRP_MJ_FLUSH_BUFFERS",
31 "IRP_MJ_QUERY_VOLUME_INFORMATION",
32 "IRP_MJ_SET_VOLUME_INFORMATION",
33 "IRP_MJ_DIRECTORY_CONTROL",
34 "IRP_MJ_FILE_SYSTEM_CONTROL",
35 "IRP_MJ_DEVICE_CONTROL",
36 "IRP_MJ_INTERNAL_DEVICE_CONTROL",
38 "IRP_MJ_LOCK_CONTROL",
40 "IRP_MJ_CREATE_MAILSLOT",
41 "IRP_MJ_QUERY_SECURITY",
42 "IRP_MJ_SET_SECURITY",
44 "IRP_MJ_SYSTEM_CONTROL",
45 "IRP_MJ_DEVICE_CHANGE",
49 "IRP_MJ_MAXIMUM_FUNCTION"
52 static LONG QueueCount
= 0;
54 static VOID
VfatFreeIrpContext(PVFAT_IRP_CONTEXT
);
55 static PVFAT_IRP_CONTEXT
VfatAllocateIrpContext(PDEVICE_OBJECT
, PIRP
);
56 static NTSTATUS
VfatQueueRequest(PVFAT_IRP_CONTEXT
);
58 /* FUNCTIONS ****************************************************************/
63 IN PVFAT_IRP_CONTEXT IrpContext
)
68 DPRINT("VfatLockControl(IrpContext %p)\n", IrpContext
);
72 Fcb
= (PVFATFCB
)IrpContext
->FileObject
->FsContext
;
74 if (IrpContext
->DeviceObject
== VfatGlobalData
->DeviceObject
)
76 return STATUS_INVALID_DEVICE_REQUEST
;
79 if (*Fcb
->Attributes
& FILE_ATTRIBUTE_DIRECTORY
)
81 return STATUS_INVALID_PARAMETER
;
84 IrpContext
->Flags
&= ~IRPCONTEXT_COMPLETE
;
85 Status
= FsRtlProcessFileLock(&Fcb
->FileLock
,
94 IN PVFAT_IRP_CONTEXT IrpContext
)
96 IoSkipCurrentIrpStackLocation(IrpContext
->Irp
);
98 IrpContext
->Flags
&= ~IRPCONTEXT_COMPLETE
;
100 return IoCallDriver(IrpContext
->DeviceExt
->StorageDevice
, IrpContext
->Irp
);
106 IN PVFAT_IRP_CONTEXT IrpContext
)
110 DPRINT("VfatDispatchRequest (IrpContext %p), is called for %s\n", IrpContext
,
111 IrpContext
->MajorFunction
>= IRP_MJ_MAXIMUM_FUNCTION
? "????" : MajorFunctionNames
[IrpContext
->MajorFunction
]);
115 switch (IrpContext
->MajorFunction
)
118 Status
= VfatClose(IrpContext
);
122 Status
= VfatCreate(IrpContext
);
126 Status
= VfatRead(IrpContext
);
130 Status
= VfatWrite (IrpContext
);
133 case IRP_MJ_FILE_SYSTEM_CONTROL
:
134 Status
= VfatFileSystemControl(IrpContext
);
137 case IRP_MJ_QUERY_INFORMATION
:
138 Status
= VfatQueryInformation (IrpContext
);
141 case IRP_MJ_SET_INFORMATION
:
142 Status
= VfatSetInformation (IrpContext
);
145 case IRP_MJ_DIRECTORY_CONTROL
:
146 Status
= VfatDirectoryControl(IrpContext
);
149 case IRP_MJ_QUERY_VOLUME_INFORMATION
:
150 Status
= VfatQueryVolumeInformation(IrpContext
);
153 case IRP_MJ_SET_VOLUME_INFORMATION
:
154 Status
= VfatSetVolumeInformation(IrpContext
);
157 case IRP_MJ_LOCK_CONTROL
:
158 Status
= VfatLockControl(IrpContext
);
161 case IRP_MJ_DEVICE_CONTROL
:
162 Status
= VfatDeviceControl(IrpContext
);
166 Status
= VfatCleanup(IrpContext
);
169 case IRP_MJ_FLUSH_BUFFERS
:
170 Status
= VfatFlush(IrpContext
);
174 Status
= VfatPnp(IrpContext
);
178 DPRINT1("Unexpected major function %x\n", IrpContext
->MajorFunction
);
179 Status
= STATUS_DRIVER_INTERNAL_ERROR
;
182 ASSERT((!(IrpContext
->Flags
& IRPCONTEXT_COMPLETE
) && !(IrpContext
->Flags
& IRPCONTEXT_QUEUE
)) ||
183 ((IrpContext
->Flags
& IRPCONTEXT_COMPLETE
) && !(IrpContext
->Flags
& IRPCONTEXT_QUEUE
)) ||
184 (!(IrpContext
->Flags
& IRPCONTEXT_COMPLETE
) && (IrpContext
->Flags
& IRPCONTEXT_QUEUE
)));
186 if (IrpContext
->Flags
& IRPCONTEXT_COMPLETE
)
188 IrpContext
->Irp
->IoStatus
.Status
= Status
;
189 IoCompleteRequest(IrpContext
->Irp
, IrpContext
->PriorityBoost
);
192 if (IrpContext
->Flags
& IRPCONTEXT_QUEUE
)
194 /* Reset our status flags before queueing the IRP */
195 IrpContext
->Flags
|= IRPCONTEXT_COMPLETE
;
196 IrpContext
->Flags
&= ~IRPCONTEXT_QUEUE
;
197 Status
= VfatQueueRequest(IrpContext
);
201 /* Unless the IRP was queued, always free the IRP context */
202 VfatFreeIrpContext(IrpContext
);
211 IN PDEVICE_OBJECT DeviceObject
,
215 PVFAT_IRP_CONTEXT IrpContext
;
217 DPRINT("VfatBuildRequest (DeviceObject %p, Irp %p)\n", DeviceObject
, Irp
);
219 ASSERT(DeviceObject
);
222 IrpContext
= VfatAllocateIrpContext(DeviceObject
, Irp
);
223 if (IrpContext
== NULL
)
225 Status
= STATUS_INSUFFICIENT_RESOURCES
;
226 Irp
->IoStatus
.Status
= Status
;
227 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
231 FsRtlEnterFileSystem();
232 Status
= VfatDispatchRequest(IrpContext
);
233 FsRtlExitFileSystem();
241 PVFAT_IRP_CONTEXT IrpContext
)
244 ExFreeToNPagedLookasideList(&VfatGlobalData
->IrpContextLookasideList
, IrpContext
);
249 VfatAllocateIrpContext(
250 PDEVICE_OBJECT DeviceObject
,
253 PVFAT_IRP_CONTEXT IrpContext
;
254 /*PIO_STACK_LOCATION Stack;*/
257 DPRINT("VfatAllocateIrpContext(DeviceObject %p, Irp %p)\n", DeviceObject
, Irp
);
259 ASSERT(DeviceObject
);
262 IrpContext
= ExAllocateFromNPagedLookasideList(&VfatGlobalData
->IrpContextLookasideList
);
265 RtlZeroMemory(IrpContext
, sizeof(VFAT_IRP_CONTEXT
));
266 IrpContext
->Irp
= Irp
;
267 IrpContext
->DeviceObject
= DeviceObject
;
268 IrpContext
->DeviceExt
= DeviceObject
->DeviceExtension
;
269 IrpContext
->Stack
= IoGetCurrentIrpStackLocation(Irp
);
270 ASSERT(IrpContext
->Stack
);
271 MajorFunction
= IrpContext
->MajorFunction
= IrpContext
->Stack
->MajorFunction
;
272 IrpContext
->MinorFunction
= IrpContext
->Stack
->MinorFunction
;
273 IrpContext
->FileObject
= IrpContext
->Stack
->FileObject
;
274 IrpContext
->Flags
= IRPCONTEXT_COMPLETE
;
275 if (MajorFunction
== IRP_MJ_FILE_SYSTEM_CONTROL
||
276 MajorFunction
== IRP_MJ_DEVICE_CONTROL
||
277 MajorFunction
== IRP_MJ_SHUTDOWN
)
279 IrpContext
->Flags
|= IRPCONTEXT_CANWAIT
;
281 else if (MajorFunction
!= IRP_MJ_CLEANUP
&&
282 MajorFunction
!= IRP_MJ_CLOSE
&&
283 IoIsOperationSynchronous(Irp
))
285 IrpContext
->Flags
|= IRPCONTEXT_CANWAIT
;
287 KeInitializeEvent(&IrpContext
->Event
, NotificationEvent
, FALSE
);
288 IrpContext
->RefCount
= 0;
289 IrpContext
->PriorityBoost
= IO_NO_INCREMENT
;
294 static WORKER_THREAD_ROUTINE VfatDoRequest
;
302 InterlockedDecrement(&QueueCount
);
303 DPRINT("VfatDoRequest(IrpContext %p), MajorFunction %x, %d\n",
304 IrpContext
, ((PVFAT_IRP_CONTEXT
)IrpContext
)->MajorFunction
, QueueCount
);
305 FsRtlEnterFileSystem();
306 VfatDispatchRequest((PVFAT_IRP_CONTEXT
)IrpContext
);
307 FsRtlExitFileSystem();
313 PVFAT_IRP_CONTEXT IrpContext
)
315 InterlockedIncrement(&QueueCount
);
316 DPRINT("VfatQueueRequest(IrpContext %p), %d\n", IrpContext
, QueueCount
);
318 ASSERT(IrpContext
!= NULL
);
319 ASSERT(IrpContext
->Irp
!= NULL
);
321 IrpContext
->Flags
|= IRPCONTEXT_CANWAIT
;
322 IoMarkIrpPending(IrpContext
->Irp
);
323 ExInitializeWorkItem(&IrpContext
->WorkQueueItem
, VfatDoRequest
, IrpContext
);
324 ExQueueWorkItem(&IrpContext
->WorkQueueItem
, CriticalWorkQueue
);
325 return STATUS_PENDING
;
337 return MmGetSystemAddressForMdlSafe(Irp
->MdlAddress
, (Paging
? HighPagePriority
: NormalPagePriority
));
341 return Irp
->UserBuffer
;
349 IN LOCK_OPERATION Operation
)
355 return STATUS_SUCCESS
;
358 IoAllocateMdl(Irp
->UserBuffer
, Length
, FALSE
, FALSE
, Irp
);
360 if (!Irp
->MdlAddress
)
362 return STATUS_INSUFFICIENT_RESOURCES
;
365 MmProbeAndLockPages(Irp
->MdlAddress
, Irp
->RequestorMode
, Operation
);
367 return STATUS_SUCCESS
;
371 VfatCheckForDismount(
372 IN PDEVICE_EXTENSION DeviceExt
,
379 DPRINT1("VfatCheckForDismount(%p, %u)\n", DeviceExt
, Create
);
382 IoAcquireVpbSpinLock(&OldIrql
);
384 /* Reference it and check if a create is being done */
385 Vpb
= DeviceExt
->IoVPB
;
386 if (Vpb
->ReferenceCount
!= Create
)
388 /* Copy the VPB to our local own to prepare later dismount */
389 if (DeviceExt
->SpareVPB
!= NULL
)
391 RtlZeroMemory(DeviceExt
->SpareVPB
, sizeof(VPB
));
392 DeviceExt
->SpareVPB
->Type
= IO_TYPE_VPB
;
393 DeviceExt
->SpareVPB
->Size
= sizeof(VPB
);
394 DeviceExt
->SpareVPB
->RealDevice
= DeviceExt
->IoVPB
->RealDevice
;
395 DeviceExt
->SpareVPB
->DeviceObject
= NULL
;
396 DeviceExt
->SpareVPB
->Flags
= DeviceExt
->IoVPB
->Flags
& VPB_REMOVE_PENDING
;
397 DeviceExt
->IoVPB
->RealDevice
->Vpb
= DeviceExt
->SpareVPB
;
398 DeviceExt
->SpareVPB
= NULL
;
399 DeviceExt
->IoVPB
->Flags
|= VPB_PERSISTENT
;
402 /* Don't do anything */
407 /* Otherwise, delete the volume */
410 /* Check if it has a VPB and unmount it */
411 if (Vpb
->RealDevice
->Vpb
== Vpb
)
413 Vpb
->DeviceObject
= NULL
;
414 Vpb
->Flags
&= ~VPB_MOUNTED
;
418 /* Release lock and return status */
419 IoReleaseVpbSpinLock(OldIrql
);
421 /* If we were to delete, delete volume */
426 /* If we have a local VPB, we'll have to delete it
427 * but we won't dismount us - something went bad before
429 if (DeviceExt
->SpareVPB
)
431 DelVpb
= DeviceExt
->SpareVPB
;
433 /* Otherwise, dismount our device if possible */
436 if (DeviceExt
->IoVPB
->ReferenceCount
)
438 ObfDereferenceObject(DeviceExt
->StorageDevice
);
439 IoDeleteDevice(DeviceExt
->VolumeDevice
);
443 DelVpb
= DeviceExt
->IoVPB
;
446 /* Delete any of the available VPB and dismount */
448 ObfDereferenceObject(DeviceExt
->StorageDevice
);
449 IoDeleteDevice(DeviceExt
->VolumeDevice
);