eb5959558856df88c0014818868b9d0bee4a5c3d
[reactos.git] / reactos / ntoskrnl / io / fs.c
1 /* $Id: fs.c,v 1.18 2001/07/15 15:36:31 ekohl Exp $
2 *
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)
8 * UPDATE HISTORY:
9 * Created 22/05/98
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <internal/io.h>
16 #include <internal/pool.h>
17
18 #define NDEBUG
19 #include <internal/debug.h>
20
21 /* TYPES *******************************************************************/
22
23 typedef struct
24 {
25 PDEVICE_OBJECT DeviceObject;
26 LIST_ENTRY Entry;
27 } FILE_SYSTEM_OBJECT;
28
29 /* GLOBALS ******************************************************************/
30
31 static KSPIN_LOCK FileSystemListLock;
32 static LIST_ENTRY FileSystemListHead;
33
34 #define TAG_FILE_SYSTEM TAG('F', 'S', 'Y', 'S')
35
36 /* FUNCTIONS *****************************************************************/
37
38 NTSTATUS
39 STDCALL
40 NtFsControlFile (
41 IN HANDLE DeviceHandle,
42 IN HANDLE EventHandle OPTIONAL,
43 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
44 IN PVOID ApcContext OPTIONAL,
45 OUT PIO_STATUS_BLOCK IoStatusBlock,
46 IN ULONG IoControlCode,
47 IN PVOID InputBuffer,
48 IN ULONG InputBufferSize,
49 OUT PVOID OutputBuffer,
50 IN ULONG OutputBufferSize
51 )
52 {
53 NTSTATUS Status;
54 PFILE_OBJECT FileObject;
55 PDEVICE_OBJECT DeviceObject;
56 PIRP Irp;
57 PIO_STACK_LOCATION StackPtr;
58 KEVENT KEvent;
59
60 DPRINT("NtFsControlFile(DeviceHandle %x EventHandle %x ApcRoutine %x "
61 "ApcContext %x IoStatusBlock %x IoControlCode %x "
62 "InputBuffer %x InputBufferSize %x OutputBuffer %x "
63 "OutputBufferSize %x)\n",
64 DeviceHandle,EventHandle,ApcRoutine,ApcContext,IoStatusBlock,
65 IoControlCode,InputBuffer,InputBufferSize,OutputBuffer,
66 OutputBufferSize);
67
68 Status = ObReferenceObjectByHandle(DeviceHandle,
69 FILE_READ_DATA | FILE_WRITE_DATA,
70 NULL,
71 KernelMode,
72 (PVOID *) &FileObject,
73 NULL);
74
75 if (!NT_SUCCESS(Status))
76 {
77 return(Status);
78 }
79
80 DeviceObject = FileObject->DeviceObject;
81
82 KeInitializeEvent(&KEvent,NotificationEvent,TRUE);
83
84 Irp = IoBuildDeviceIoControlRequest(IoControlCode,
85 DeviceObject,
86 InputBuffer,
87 InputBufferSize,
88 OutputBuffer,
89 OutputBufferSize,
90 FALSE,
91 &KEvent,
92 IoStatusBlock);
93
94 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
95 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
96
97 StackPtr = IoGetNextIrpStackLocation(Irp);
98 StackPtr->FileObject = FileObject;
99 StackPtr->DeviceObject = DeviceObject;
100 StackPtr->Parameters.FileSystemControl.InputBufferLength = InputBufferSize;
101 StackPtr->Parameters.FileSystemControl.OutputBufferLength =
102 OutputBufferSize;
103 StackPtr->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
104
105 Status = IoCallDriver(DeviceObject,Irp);
106 if (Status == STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
107 {
108 KeWaitForSingleObject(&KEvent,Executive,KernelMode,FALSE,NULL);
109 return(IoStatusBlock->Status);
110 }
111 return(Status);
112 }
113
114 VOID IoInitFileSystemImplementation(VOID)
115 {
116 InitializeListHead(&FileSystemListHead);
117 KeInitializeSpinLock(&FileSystemListLock);
118 }
119
120 VOID IoShutdownRegisteredFileSystems(VOID)
121 {
122 KIRQL oldlvl;
123 PLIST_ENTRY current_entry;
124 FILE_SYSTEM_OBJECT* current;
125 PIRP Irp;
126 KEVENT Event;
127 IO_STATUS_BLOCK IoStatusBlock;
128 NTSTATUS Status;
129
130 DPRINT("IoShutdownRegisteredFileSystems()\n");
131
132 KeAcquireSpinLock(&FileSystemListLock,&oldlvl);
133 KeInitializeEvent(&Event,NotificationEvent,FALSE);
134
135 current_entry = FileSystemListHead.Flink;
136 while (current_entry!=(&FileSystemListHead))
137 {
138 current = CONTAINING_RECORD(current_entry,FILE_SYSTEM_OBJECT,Entry);
139
140 /* send IRP_MJ_SHUTDOWN */
141 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN,
142 current->DeviceObject,
143 NULL,
144 0,
145 0,
146 &Event,
147 &IoStatusBlock);
148
149 Status = IoCallDriver(current->DeviceObject,Irp);
150 if (Status==STATUS_PENDING)
151 {
152 KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL);
153 }
154
155 current_entry = current_entry->Flink;
156 }
157
158 KeReleaseSpinLock(&FileSystemListLock,oldlvl);
159 }
160
161 NTSTATUS IoAskFileSystemToMountDevice(PDEVICE_OBJECT DeviceObject,
162 PDEVICE_OBJECT DeviceToMount)
163 {
164 PIRP Irp;
165 KEVENT Event;
166 IO_STATUS_BLOCK IoStatusBlock;
167 NTSTATUS Status;
168
169 DPRINT("IoAskFileSystemToMountDevice(DeviceObject %x, DeviceToMount %x)\n",
170 DeviceObject,DeviceToMount);
171
172 assert_irql(PASSIVE_LEVEL);
173
174 KeInitializeEvent(&Event,NotificationEvent,FALSE);
175 Irp = IoBuildFilesystemControlRequest(IRP_MN_MOUNT_VOLUME,
176 DeviceObject,
177 &Event,
178 &IoStatusBlock,
179 DeviceToMount);
180 Status = IoCallDriver(DeviceObject,Irp);
181 if (Status==STATUS_PENDING)
182 {
183 KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL);
184 Status = IoStatusBlock.Status;
185 }
186 return(Status);
187 }
188
189 NTSTATUS IoAskFileSystemToLoad(PDEVICE_OBJECT DeviceObject)
190 {
191 UNIMPLEMENTED;
192 }
193
194 NTSTATUS IoTryToMountStorageDevice(PDEVICE_OBJECT DeviceObject)
195 /*
196 * FUNCTION: Trys to mount a storage device
197 * ARGUMENTS:
198 * DeviceObject = Device to try and mount
199 * RETURNS: Status
200 */
201 {
202 KIRQL oldlvl;
203 PLIST_ENTRY current_entry;
204 FILE_SYSTEM_OBJECT* current;
205 NTSTATUS Status;
206
207 assert_irql(PASSIVE_LEVEL);
208
209 DPRINT("IoTryToMountStorageDevice(DeviceObject %x)\n",DeviceObject);
210
211 KeAcquireSpinLock(&FileSystemListLock,&oldlvl);
212 current_entry = FileSystemListHead.Flink;
213 while (current_entry!=(&FileSystemListHead))
214 {
215 current = CONTAINING_RECORD(current_entry,FILE_SYSTEM_OBJECT,Entry);
216 KeReleaseSpinLock(&FileSystemListLock,oldlvl);
217 Status = IoAskFileSystemToMountDevice(current->DeviceObject,
218 DeviceObject);
219 KeAcquireSpinLock(&FileSystemListLock,&oldlvl);
220 switch (Status)
221 {
222 case STATUS_FS_DRIVER_REQUIRED:
223 KeReleaseSpinLock(&FileSystemListLock,oldlvl);
224 (void)IoAskFileSystemToLoad(DeviceObject);
225 KeAcquireSpinLock(&FileSystemListLock,&oldlvl);
226 current_entry = FileSystemListHead.Flink;
227 break;
228
229 case STATUS_SUCCESS:
230 DeviceObject->Vpb->Flags = DeviceObject->Vpb->Flags |
231 VPB_MOUNTED;
232 KeReleaseSpinLock(&FileSystemListLock,oldlvl);
233 return(STATUS_SUCCESS);
234
235 case STATUS_UNRECOGNIZED_VOLUME:
236 default:
237 current_entry = current_entry->Flink;
238 }
239 }
240 KeReleaseSpinLock(&FileSystemListLock,oldlvl);
241 return(STATUS_UNRECOGNIZED_VOLUME);
242 }
243
244 VOID STDCALL IoRegisterFileSystem(PDEVICE_OBJECT DeviceObject)
245 {
246 FILE_SYSTEM_OBJECT* fs;
247
248 DPRINT("IoRegisterFileSystem(DeviceObject %x)\n",DeviceObject);
249
250 fs = ExAllocatePoolWithTag(NonPagedPool, sizeof(FILE_SYSTEM_OBJECT),
251 TAG_FILE_SYSTEM);
252 assert(fs!=NULL);
253
254 fs->DeviceObject = DeviceObject;
255 ExInterlockedInsertTailList(&FileSystemListHead,&fs->Entry,
256 &FileSystemListLock);
257 }
258
259 VOID STDCALL IoUnregisterFileSystem(PDEVICE_OBJECT DeviceObject)
260 {
261 KIRQL oldlvl;
262 PLIST_ENTRY current_entry;
263 FILE_SYSTEM_OBJECT* current;
264
265 DPRINT("IoUnregisterFileSystem(DeviceObject %x)\n",DeviceObject);
266
267 KeAcquireSpinLock(&FileSystemListLock,&oldlvl);
268 current_entry = FileSystemListHead.Flink;
269 while (current_entry!=(&FileSystemListHead))
270 {
271 current = CONTAINING_RECORD(current_entry,FILE_SYSTEM_OBJECT,Entry);
272 if (current->DeviceObject == DeviceObject)
273 {
274 RemoveEntryList(current_entry);
275 ExFreePool(current);
276 KeReleaseSpinLock(&FileSystemListLock,oldlvl);
277 return;
278 }
279 current_entry = current_entry->Flink;
280 }
281 KeReleaseSpinLock(&FileSystemListLock,oldlvl);
282 }
283
284
285 /**********************************************************************
286 * NAME EXPORTED
287 * IoGetBaseFileSystemDeviceObject@4
288 *
289 * DESCRIPTION
290 * Get the DEVICE_OBJECT associated to
291 * a FILE_OBJECT.
292 *
293 * ARGUMENTS
294 * FileObject
295 *
296 * RETURN VALUE
297 *
298 * NOTE
299 * From Bo Branten's ntifs.h v13.
300 */
301 PDEVICE_OBJECT
302 STDCALL
303 IoGetBaseFileSystemDeviceObject (
304 IN PFILE_OBJECT FileObject
305 )
306 {
307 PDEVICE_OBJECT DeviceObject = NULL;
308 PVPB Vpb = NULL;
309
310 /*
311 * If the FILE_OBJECT's VPB is defined,
312 * get the device from it.
313 */
314 if (NULL != (Vpb = FileObject->Vpb))
315 {
316 if (NULL != (DeviceObject = Vpb->DeviceObject))
317 {
318 /* Vpb->DeviceObject DEFINED! */
319 return DeviceObject;
320 }
321 }
322 /*
323 * If that failed, try the VPB
324 * in the FILE_OBJECT's DeviceObject.
325 */
326 DeviceObject = FileObject->DeviceObject;
327 if (NULL == (Vpb = DeviceObject->Vpb))
328 {
329 /* DeviceObject->Vpb UNDEFINED! */
330 return DeviceObject;
331 }
332 /*
333 * If that pointer to the VPB is again
334 * undefined, return directly the
335 * device object from the FILE_OBJECT.
336 */
337 return (
338 (NULL == Vpb->DeviceObject)
339 ? DeviceObject
340 : Vpb->DeviceObject
341 );
342 }
343
344
345 NTSTATUS
346 STDCALL
347 IoRegisterFsRegistrationChange (
348 IN PDRIVER_OBJECT DriverObject,
349 IN PFSDNOTIFICATIONPROC FSDNotificationProc
350 )
351 {
352 UNIMPLEMENTED;
353 return (STATUS_NOT_IMPLEMENTED);
354 }
355
356
357 VOID
358 STDCALL
359 IoUnregisterFsRegistrationChange (
360 DWORD Unknown0,
361 DWORD Unknown1
362 )
363 {
364 UNIMPLEMENTED;
365 }
366
367
368 /* EOF */