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