Lots of changes to the kernel
[reactos.git] / reactos / ntoskrnl / io / fs.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/io/fs.c
5 * PURPOSE: Filesystem functions
6 * PROGRAMMER: David Welch (welch@mcmail.com)
7 * UPDATE HISTORY:
8 * Created 22/05/98
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ddk/ntddk.h>
14 #include <internal/io.h>
15
16 #define NDEBUG
17 #include <internal/debug.h>
18
19 /* TYPES *******************************************************************/
20
21 typedef struct
22 {
23 PDEVICE_OBJECT DeviceObject;
24 LIST_ENTRY Entry;
25 } FILE_SYSTEM_OBJECT;
26
27 /* GLOBALS ******************************************************************/
28
29 static KSPIN_LOCK FileSystemListLock = {0,};
30 static LIST_ENTRY FileSystemListHead = {NULL,NULL};
31
32 /* FUNCTIONS *****************************************************************/
33
34 NTSTATUS
35 STDCALL
36 NtFsControlFile(
37 IN HANDLE DeviceHandle,
38 IN HANDLE EventHandle OPTIONAL,
39 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
40 IN PVOID ApcContext OPTIONAL,
41 OUT PIO_STATUS_BLOCK IoStatusBlock,
42 IN ULONG IoControlCode,
43 IN PVOID InputBuffer,
44 IN ULONG InputBufferSize,
45 OUT PVOID OutputBuffer,
46 IN ULONG OutputBufferSize
47 )
48 {
49 return(ZwFsControlFile(DeviceHandle,
50 EventHandle,
51 ApcRoutine,
52 ApcContext,
53 IoStatusBlock,
54 IoControlCode,
55 InputBuffer,
56 InputBufferSize,
57 OutputBuffer,
58 OutputBufferSize));
59 }
60
61 NTSTATUS STDCALL ZwFsControlFile(IN HANDLE DeviceHandle,
62 IN HANDLE EventHandle OPTIONAL,
63 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
64 IN PVOID ApcContext OPTIONAL,
65 OUT PIO_STATUS_BLOCK IoStatusBlock,
66 IN ULONG IoControlCode,
67 IN PVOID InputBuffer,
68 IN ULONG InputBufferSize,
69 OUT PVOID OutputBuffer,
70 IN ULONG OutputBufferSize)
71 {
72 NTSTATUS Status = -1;
73 PFILE_OBJECT FileObject;
74 PIRP Irp;
75 PIO_STACK_LOCATION StackPtr;
76 KEVENT Event;
77
78 if (InputBufferSize > 0)
79 {
80 Status = ObReferenceObjectByHandle(DeviceHandle,
81 FILE_WRITE_DATA|FILE_READ_DATA,
82 NULL,
83 UserMode,
84 (PVOID *) &FileObject,
85 NULL);
86 if (Status != STATUS_SUCCESS)
87 {
88 return(Status);
89 }
90
91 KeInitializeEvent(&Event,NotificationEvent,FALSE);
92 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_DEVICE_CONTROL,
93 FileObject->DeviceObject,
94 InputBuffer,
95 InputBufferSize,
96 0,
97 &Event,
98 IoStatusBlock);
99 if (Irp == NULL)
100 {
101 ObDereferenceObject(FileObject);
102 return(STATUS_UNSUCCESSFUL);
103 }
104 StackPtr = IoGetNextIrpStackLocation(Irp);
105 if (StackPtr == NULL)
106 {
107 ObDereferenceObject(FileObject);
108 return(STATUS_UNSUCCESSFUL);
109 }
110 StackPtr->Parameters.DeviceIoControl.IoControlCode = IoControlCode;
111 StackPtr->FileObject = FileObject;
112 StackPtr->Parameters.Write.Length = InputBufferSize;
113 DPRINT("FileObject->DeviceObject %x\n",FileObject->DeviceObject);
114 Status = IoCallDriver(FileObject->DeviceObject,Irp);
115 if (Status==STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
116 {
117 KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL);
118 }
119 ObDereferenceObject(FileObject);
120 return(Irp->IoStatus.Status);
121 }
122
123 if (OutputBufferSize > 0)
124 {
125 CHECKPOINT;
126 Status = ObReferenceObjectByHandle(DeviceHandle,
127 FILE_WRITE_DATA|FILE_READ_DATA,
128 NULL,
129 UserMode,
130 (PVOID *) &FileObject,
131 NULL);
132 if (Status != STATUS_SUCCESS)
133 {
134 return(Status);
135 }
136 CHECKPOINT;
137 KeInitializeEvent(&Event,NotificationEvent,FALSE);
138 CHECKPOINT;
139 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_DEVICE_CONTROL,
140 FileObject->DeviceObject,
141 OutputBuffer,
142 OutputBufferSize,
143 0,
144 &Event,
145 IoStatusBlock);
146 if (Irp == NULL)
147 {
148 ObDereferenceObject(FileObject);
149 return(STATUS_UNSUCCESSFUL);
150 }
151 StackPtr = IoGetNextIrpStackLocation(Irp);
152 if (StackPtr == NULL)
153 {
154 return(STATUS_UNSUCCESSFUL);
155 }
156 StackPtr->Parameters.DeviceIoControl.IoControlCode = IoControlCode;
157 StackPtr->FileObject = FileObject;
158 StackPtr->Parameters.Read.Length = OutputBufferSize;
159 DPRINT("FileObject->DeviceObject %x\n",FileObject->DeviceObject);
160 Status = IoCallDriver(FileObject->DeviceObject,Irp);
161 if (Status==STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
162 {
163 KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL);
164 }
165 return(Irp->IoStatus.Status);
166 }
167 return(Status);
168 }
169
170 VOID IoInitFileSystemImplementation(VOID)
171 {
172 InitializeListHead(&FileSystemListHead);
173 KeInitializeSpinLock(&FileSystemListLock);
174 }
175
176 NTSTATUS IoAskFileSystemToMountDevice(PDEVICE_OBJECT DeviceObject,
177 PDEVICE_OBJECT DeviceToMount)
178 {
179 PIRP Irp;
180 KEVENT Event;
181 IO_STATUS_BLOCK IoStatusBlock;
182 NTSTATUS Status;
183
184 DPRINT("IoAskFileSystemToMountDevice(DeviceObject %x, DeviceToMount %x)\n",
185 DeviceObject,DeviceToMount);
186
187 assert_irql(PASSIVE_LEVEL);
188
189 KeInitializeEvent(&Event,NotificationEvent,FALSE);
190 Irp = IoBuildFilesystemControlRequest(IRP_MN_MOUNT_VOLUME,
191 DeviceObject,
192 &Event,
193 &IoStatusBlock,
194 DeviceToMount);
195 Status = IoCallDriver(DeviceObject,Irp);
196 if (Status==STATUS_PENDING)
197 {
198 KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL);
199 Status = IoStatusBlock.Status;
200 }
201 return(Status);
202 }
203
204 NTSTATUS IoAskFileSystemToLoad(PDEVICE_OBJECT DeviceObject)
205 {
206 UNIMPLEMENTED;
207 }
208
209 NTSTATUS IoTryToMountStorageDevice(PDEVICE_OBJECT DeviceObject)
210 /*
211 * FUNCTION: Trys to mount a storage device
212 * ARGUMENTS:
213 * DeviceObject = Device to try and mount
214 * RETURNS: Status
215 */
216 {
217 KIRQL oldlvl;
218 PLIST_ENTRY current_entry;
219 FILE_SYSTEM_OBJECT* current;
220 NTSTATUS Status;
221
222 assert_irql(PASSIVE_LEVEL);
223
224 DPRINT("IoTryToMountStorageDevice(DeviceObject %x)\n",DeviceObject);
225
226 KeAcquireSpinLock(&FileSystemListLock,&oldlvl);
227 current_entry = FileSystemListHead.Flink;
228 while (current_entry!=(&FileSystemListHead))
229 {
230 current = CONTAINING_RECORD(current_entry,FILE_SYSTEM_OBJECT,Entry);
231 KeReleaseSpinLock(&FileSystemListLock,oldlvl);
232 Status = IoAskFileSystemToMountDevice(current->DeviceObject,
233 DeviceObject);
234 KeAcquireSpinLock(&FileSystemListLock,&oldlvl);
235 switch (Status)
236 {
237 case STATUS_FS_DRIVER_REQUIRED:
238 KeReleaseSpinLock(&FileSystemListLock,oldlvl);
239 (void)IoAskFileSystemToLoad(DeviceObject);
240 KeAcquireSpinLock(&FileSystemListLock,&oldlvl);
241 current_entry = FileSystemListHead.Flink;
242 break;
243
244 case STATUS_SUCCESS:
245 DeviceObject->Vpb->Flags = DeviceObject->Vpb->Flags |
246 VPB_MOUNTED;
247 KeReleaseSpinLock(&FileSystemListLock,oldlvl);
248 return(STATUS_SUCCESS);
249
250 case STATUS_UNRECOGNIZED_VOLUME:
251 default:
252 current_entry = current_entry->Flink;
253 }
254 }
255 KeReleaseSpinLock(&FileSystemListLock,oldlvl);
256 return(STATUS_UNRECOGNIZED_VOLUME);
257 }
258
259 VOID IoRegisterFileSystem(PDEVICE_OBJECT DeviceObject)
260 {
261 FILE_SYSTEM_OBJECT* fs;
262
263 DPRINT("IoRegisterFileSystem(DeviceObject %x)\n",DeviceObject);
264
265 fs=ExAllocatePool(NonPagedPool,sizeof(FILE_SYSTEM_OBJECT));
266 assert(fs!=NULL);
267
268 fs->DeviceObject = DeviceObject;
269 ExInterlockedInsertTailList(&FileSystemListHead,&fs->Entry,
270 &FileSystemListLock);
271 }
272
273 VOID IoUnregisterFileSystem(PDEVICE_OBJECT DeviceObject)
274 {
275 KIRQL oldlvl;
276 PLIST_ENTRY current_entry;
277 FILE_SYSTEM_OBJECT* current;
278
279 DPRINT("IoUnregisterFileSystem(DeviceObject %x)\n",DeviceObject);
280
281 KeAcquireSpinLock(&FileSystemListLock,&oldlvl);
282 current_entry = FileSystemListHead.Flink;
283 while (current_entry!=(&FileSystemListHead))
284 {
285 current = CONTAINING_RECORD(current_entry,FILE_SYSTEM_OBJECT,Entry);
286 if (current->DeviceObject == DeviceObject)
287 {
288 RemoveEntryList(current_entry);
289 ExFreePool(current);
290 KeReleaseSpinLock(&FileSystemListLock,oldlvl);
291 return;
292 }
293 current_entry = current_entry->Flink;
294 }
295 KeReleaseSpinLock(&FileSystemListLock,oldlvl);
296 }
297
298