1 /* $Id: fs.c,v 1.20 2001/12/05 12:14:13 ekohl Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/fs.c
6 * PURPOSE: Filesystem functions
7 * PROGRAMMER: David Welch (welch@mcmail.com)
12 /* INCLUDES *****************************************************************/
14 #include <ddk/ntddk.h>
15 #include <internal/io.h>
16 #include <internal/pool.h>
19 #include <internal/debug.h>
21 /* TYPES *******************************************************************/
25 PDEVICE_OBJECT DeviceObject
;
31 LIST_ENTRY FsChangeNotifyList
;
32 PDRIVER_OBJECT DriverObject
;
33 PFSDNOTIFICATIONPROC FSDNotificationProc
;
34 } FS_CHANGE_NOTIFY_ENTRY
, *PFS_CHANGE_NOTIFY_ENTRY
;
36 /* GLOBALS ******************************************************************/
38 static KSPIN_LOCK FileSystemListLock
;
39 static LIST_ENTRY FileSystemListHead
;
41 static KSPIN_LOCK FsChangeNotifyListLock
;
42 static LIST_ENTRY FsChangeNotifyListHead
;
44 #define TAG_FILE_SYSTEM TAG('F', 'S', 'Y', 'S')
45 #define TAG_FS_CHANGE_NOTIFY TAG('F', 'S', 'C', 'N')
48 static VOID
IopNotifyFileSystemChange(PDEVICE_OBJECT DeviceObject
,
49 BOOLEAN DriverActive
);
51 /* FUNCTIONS *****************************************************************/
55 IN HANDLE DeviceHandle
,
56 IN HANDLE EventHandle OPTIONAL
,
57 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
58 IN PVOID ApcContext OPTIONAL
,
59 OUT PIO_STATUS_BLOCK IoStatusBlock
,
60 IN ULONG IoControlCode
,
62 IN ULONG InputBufferSize
,
63 OUT PVOID OutputBuffer
,
64 IN ULONG OutputBufferSize
68 PFILE_OBJECT FileObject
;
69 PDEVICE_OBJECT DeviceObject
;
71 PIO_STACK_LOCATION StackPtr
;
75 DPRINT("NtFsControlFile(DeviceHandle %x EventHandle %x ApcRoutine %x "
76 "ApcContext %x IoStatusBlock %x IoControlCode %x "
77 "InputBuffer %x InputBufferSize %x OutputBuffer %x "
78 "OutputBufferSize %x)\n",
79 DeviceHandle
,EventHandle
,ApcRoutine
,ApcContext
,IoStatusBlock
,
80 IoControlCode
,InputBuffer
,InputBufferSize
,OutputBuffer
,
83 Status
= ObReferenceObjectByHandle(DeviceHandle
,
84 FILE_READ_DATA
| FILE_WRITE_DATA
,
87 (PVOID
*) &FileObject
,
90 if (!NT_SUCCESS(Status
))
95 DeviceObject
= FileObject
->DeviceObject
;
97 KeInitializeEvent(&KEvent
,NotificationEvent
,TRUE
);
99 Irp
= IoBuildDeviceIoControlRequest(IoControlCode
,
109 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
110 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
112 StackPtr
= IoGetNextIrpStackLocation(Irp
);
113 StackPtr
->FileObject
= FileObject
;
114 StackPtr
->DeviceObject
= DeviceObject
;
115 StackPtr
->Parameters
.FileSystemControl
.InputBufferLength
= InputBufferSize
;
116 StackPtr
->Parameters
.FileSystemControl
.OutputBufferLength
=
118 StackPtr
->MajorFunction
= IRP_MJ_FILE_SYSTEM_CONTROL
;
120 Status
= IoCallDriver(DeviceObject
,Irp
);
121 if (Status
== STATUS_PENDING
&& !(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
123 KeWaitForSingleObject(&KEvent
,Executive
,KernelMode
,FALSE
,NULL
);
124 Status
= IoSB
.Status
;
128 *IoStatusBlock
= IoSB
;
133 VOID
IoInitFileSystemImplementation(VOID
)
135 InitializeListHead(&FileSystemListHead
);
136 KeInitializeSpinLock(&FileSystemListLock
);
138 InitializeListHead(&FsChangeNotifyListHead
);
139 KeInitializeSpinLock(&FsChangeNotifyListLock
);
142 VOID
IoShutdownRegisteredFileSystems(VOID
)
145 PLIST_ENTRY current_entry
;
146 FILE_SYSTEM_OBJECT
* current
;
149 IO_STATUS_BLOCK IoStatusBlock
;
152 DPRINT("IoShutdownRegisteredFileSystems()\n");
154 KeAcquireSpinLock(&FileSystemListLock
,&oldlvl
);
155 KeInitializeEvent(&Event
,NotificationEvent
,FALSE
);
157 current_entry
= FileSystemListHead
.Flink
;
158 while (current_entry
!=(&FileSystemListHead
))
160 current
= CONTAINING_RECORD(current_entry
,FILE_SYSTEM_OBJECT
,Entry
);
162 /* send IRP_MJ_SHUTDOWN */
163 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN
,
164 current
->DeviceObject
,
171 Status
= IoCallDriver(current
->DeviceObject
,Irp
);
172 if (Status
==STATUS_PENDING
)
174 KeWaitForSingleObject(&Event
,Executive
,KernelMode
,FALSE
,NULL
);
177 current_entry
= current_entry
->Flink
;
180 KeReleaseSpinLock(&FileSystemListLock
,oldlvl
);
183 NTSTATUS
IoAskFileSystemToMountDevice(PDEVICE_OBJECT DeviceObject
,
184 PDEVICE_OBJECT DeviceToMount
)
188 IO_STATUS_BLOCK IoStatusBlock
;
191 DPRINT("IoAskFileSystemToMountDevice(DeviceObject %x, DeviceToMount %x)\n",
192 DeviceObject
,DeviceToMount
);
194 assert_irql(PASSIVE_LEVEL
);
196 KeInitializeEvent(&Event
,NotificationEvent
,FALSE
);
197 Irp
= IoBuildFilesystemControlRequest(IRP_MN_MOUNT_VOLUME
,
202 Status
= IoCallDriver(DeviceObject
,Irp
);
203 if (Status
==STATUS_PENDING
)
205 KeWaitForSingleObject(&Event
,Executive
,KernelMode
,FALSE
,NULL
);
206 Status
= IoStatusBlock
.Status
;
211 NTSTATUS
IoAskFileSystemToLoad(PDEVICE_OBJECT DeviceObject
)
216 NTSTATUS
IoTryToMountStorageDevice(PDEVICE_OBJECT DeviceObject
)
218 * FUNCTION: Trys to mount a storage device
220 * DeviceObject = Device to try and mount
225 PLIST_ENTRY current_entry
;
226 FILE_SYSTEM_OBJECT
* current
;
229 assert_irql(PASSIVE_LEVEL
);
231 DPRINT("IoTryToMountStorageDevice(DeviceObject %x)\n",DeviceObject
);
233 KeAcquireSpinLock(&FileSystemListLock
,&oldlvl
);
234 current_entry
= FileSystemListHead
.Flink
;
235 while (current_entry
!=(&FileSystemListHead
))
237 current
= CONTAINING_RECORD(current_entry
,FILE_SYSTEM_OBJECT
,Entry
);
238 KeReleaseSpinLock(&FileSystemListLock
,oldlvl
);
239 Status
= IoAskFileSystemToMountDevice(current
->DeviceObject
,
241 KeAcquireSpinLock(&FileSystemListLock
,&oldlvl
);
244 case STATUS_FS_DRIVER_REQUIRED
:
245 KeReleaseSpinLock(&FileSystemListLock
,oldlvl
);
246 (void)IoAskFileSystemToLoad(DeviceObject
);
247 KeAcquireSpinLock(&FileSystemListLock
,&oldlvl
);
248 current_entry
= FileSystemListHead
.Flink
;
252 DeviceObject
->Vpb
->Flags
= DeviceObject
->Vpb
->Flags
|
254 KeReleaseSpinLock(&FileSystemListLock
,oldlvl
);
255 return(STATUS_SUCCESS
);
257 case STATUS_UNRECOGNIZED_VOLUME
:
259 current_entry
= current_entry
->Flink
;
262 KeReleaseSpinLock(&FileSystemListLock
,oldlvl
);
263 return(STATUS_UNRECOGNIZED_VOLUME
);
267 IoRegisterFileSystem(PDEVICE_OBJECT DeviceObject
)
269 FILE_SYSTEM_OBJECT
* fs
;
271 DPRINT("IoRegisterFileSystem(DeviceObject %x)\n",DeviceObject
);
273 fs
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(FILE_SYSTEM_OBJECT
),
277 fs
->DeviceObject
= DeviceObject
;
278 ExInterlockedInsertTailList(&FileSystemListHead
,&fs
->Entry
,
279 &FileSystemListLock
);
280 IopNotifyFileSystemChange(DeviceObject
, TRUE
);
284 IoUnregisterFileSystem(PDEVICE_OBJECT DeviceObject
)
287 PLIST_ENTRY current_entry
;
288 FILE_SYSTEM_OBJECT
* current
;
290 DPRINT("IoUnregisterFileSystem(DeviceObject %x)\n",DeviceObject
);
292 KeAcquireSpinLock(&FileSystemListLock
,&oldlvl
);
293 current_entry
= FileSystemListHead
.Flink
;
294 while (current_entry
!=(&FileSystemListHead
))
296 current
= CONTAINING_RECORD(current_entry
,FILE_SYSTEM_OBJECT
,Entry
);
297 if (current
->DeviceObject
== DeviceObject
)
299 RemoveEntryList(current_entry
);
301 KeReleaseSpinLock(&FileSystemListLock
,oldlvl
);
302 IopNotifyFileSystemChange(DeviceObject
, FALSE
);
305 current_entry
= current_entry
->Flink
;
307 KeReleaseSpinLock(&FileSystemListLock
,oldlvl
);
311 /**********************************************************************
313 * IoGetBaseFileSystemDeviceObject@4
316 * Get the DEVICE_OBJECT associated to
325 * From Bo Branten's ntifs.h v13.
327 PDEVICE_OBJECT STDCALL
328 IoGetBaseFileSystemDeviceObject(IN PFILE_OBJECT FileObject
)
330 PDEVICE_OBJECT DeviceObject
= NULL
;
334 * If the FILE_OBJECT's VPB is defined,
335 * get the device from it.
337 if (NULL
!= (Vpb
= FileObject
->Vpb
))
339 if (NULL
!= (DeviceObject
= Vpb
->DeviceObject
))
341 /* Vpb->DeviceObject DEFINED! */
346 * If that failed, try the VPB
347 * in the FILE_OBJECT's DeviceObject.
349 DeviceObject
= FileObject
->DeviceObject
;
350 if (NULL
== (Vpb
= DeviceObject
->Vpb
))
352 /* DeviceObject->Vpb UNDEFINED! */
356 * If that pointer to the VPB is again
357 * undefined, return directly the
358 * device object from the FILE_OBJECT.
361 (NULL
== Vpb
->DeviceObject
)
369 IopNotifyFileSystemChange(PDEVICE_OBJECT DeviceObject
,
370 BOOLEAN DriverActive
)
372 PFS_CHANGE_NOTIFY_ENTRY ChangeEntry
;
376 KeAcquireSpinLock(&FsChangeNotifyListLock
,&oldlvl
);
377 Entry
= FsChangeNotifyListHead
.Flink
;
378 while (Entry
!= &FsChangeNotifyListHead
)
380 ChangeEntry
= CONTAINING_RECORD(Entry
, FS_CHANGE_NOTIFY_ENTRY
, FsChangeNotifyList
);
382 (ChangeEntry
->FSDNotificationProc
)(DeviceObject
, DriverActive
);
384 Entry
= Entry
->Flink
;
386 KeReleaseSpinLock(&FsChangeNotifyListLock
,oldlvl
);
391 IoRegisterFsRegistrationChange(IN PDRIVER_OBJECT DriverObject
,
392 IN PFSDNOTIFICATIONPROC FSDNotificationProc
)
394 PFS_CHANGE_NOTIFY_ENTRY Entry
;
396 Entry
= ExAllocatePoolWithTag(NonPagedPool
,
397 sizeof(FS_CHANGE_NOTIFY_ENTRY
),
398 TAG_FS_CHANGE_NOTIFY
);
400 return(STATUS_INSUFFICIENT_RESOURCES
);
402 Entry
->DriverObject
= DriverObject
;
403 Entry
->FSDNotificationProc
= FSDNotificationProc
;
405 ExInterlockedInsertHeadList(&FsChangeNotifyListHead
,
406 &Entry
->FsChangeNotifyList
,
407 &FsChangeNotifyListLock
);
409 return(STATUS_SUCCESS
);
414 IoUnregisterFsRegistrationChange(IN PDRIVER_OBJECT DriverObject
,
415 IN PFSDNOTIFICATIONPROC FSDNotificationProc
)
417 PFS_CHANGE_NOTIFY_ENTRY ChangeEntry
;
421 Entry
= FsChangeNotifyListHead
.Flink
;
422 while (Entry
!= &FsChangeNotifyListHead
)
424 ChangeEntry
= CONTAINING_RECORD(Entry
, FS_CHANGE_NOTIFY_ENTRY
, FsChangeNotifyList
);
425 if (ChangeEntry
->DriverObject
== DriverObject
&&
426 ChangeEntry
->FSDNotificationProc
== FSDNotificationProc
)
428 KeAcquireSpinLock(&FsChangeNotifyListLock
,&oldlvl
);
429 RemoveEntryList(Entry
);
430 KeReleaseSpinLock(&FsChangeNotifyListLock
,oldlvl
);
436 Entry
= Entry
->Flink
;