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