Added some modifications for asyncronous i/o requests (for vfatfs).
[reactos.git] / reactos / ntoskrnl / io / vpb.c
1 /* $Id: vpb.c,v 1.14 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/vpb.c
6 * PURPOSE: Volume Parameter Block managment
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/mm.h>
17 #include <internal/pool.h>
18
19
20 #define NDEBUG
21 #include <internal/debug.h>
22
23 /* GLOBALS *******************************************************************/
24
25 static KSPIN_LOCK IoVpbLock;
26
27 #define TAG_VPB TAG('V', 'P', 'B', ' ')
28 #define TAG_SYSB TAG('S', 'Y', 'S', 'B')
29
30 /* FUNCTIONS *****************************************************************/
31
32 VOID
33 IoInitVpbImplementation(VOID)
34 {
35 KeInitializeSpinLock(&IoVpbLock);
36 }
37
38 NTSTATUS
39 IoAttachVpb(PDEVICE_OBJECT DeviceObject)
40 {
41 PVPB Vpb;
42
43 Vpb = ExAllocatePoolWithTag(NonPagedPool,
44 sizeof(VPB),
45 TAG_VPB);
46 if (Vpb == NULL)
47 {
48 return(STATUS_UNSUCCESSFUL);
49 }
50
51 Vpb->Type = 0;
52 Vpb->Size = sizeof(VPB) / sizeof(DWORD);
53 Vpb->Flags = 0;
54 Vpb->VolumeLabelLength = 0;
55 Vpb->DeviceObject = NULL;
56 Vpb->RealDevice = DeviceObject;
57 Vpb->SerialNumber = 0;
58 Vpb->ReferenceCount = 0;
59 RtlZeroMemory(Vpb->VolumeLabel,
60 sizeof(WCHAR) * MAXIMUM_VOLUME_LABEL_LENGTH);
61
62 DeviceObject->Vpb = Vpb;
63
64 return(STATUS_SUCCESS);
65 }
66
67
68 NTSTATUS STDCALL
69 NtQueryVolumeInformationFile(IN HANDLE FileHandle,
70 OUT PIO_STATUS_BLOCK IoStatusBlock,
71 OUT PVOID FsInformation,
72 IN ULONG Length,
73 IN FS_INFORMATION_CLASS FsInformationClass)
74
75 /*
76 * FUNCTION: Queries the volume information
77 * ARGUMENTS:
78 * FileHandle = Handle to a file object on the target volume
79 * ReturnLength = DataWritten
80 * FsInformation = Caller should supply storage for the information
81 * structure.
82 * Length = Size of the information structure
83 * FsInformationClass = Index to a information structure
84 *
85 * FileFsVolumeInformation FILE_FS_VOLUME_INFORMATION
86 * FileFsLabelInformation FILE_FS_LABEL_INFORMATION
87 * FileFsSizeInformation FILE_FS_SIZE_INFORMATION
88 * FileFsDeviceInformation FILE_FS_DEVICE_INFORMATION
89 * FileFsAttributeInformation FILE_FS_ATTRIBUTE_INFORMATION
90 * FileFsControlInformation
91 * FileFsQuotaQueryInformation --
92 * FileFsQuotaSetInformation --
93 * FileFsMaximumInformation
94 *
95 * RETURNS: Status
96 */
97 {
98 PFILE_OBJECT FileObject;
99 PDEVICE_OBJECT DeviceObject;
100 PIRP Irp;
101 KEVENT Event;
102 NTSTATUS Status;
103 PIO_STACK_LOCATION StackPtr;
104 PVOID SystemBuffer;
105 IO_STATUS_BLOCK IoSB;
106
107 assert(IoStatusBlock != NULL);
108 assert(FsInformation != NULL);
109
110 DPRINT("FsInformation %p\n", FsInformation);
111
112 Status = ObReferenceObjectByHandle(FileHandle,
113 FILE_READ_ATTRIBUTES,
114 NULL,
115 UserMode,
116 (PVOID*)&FileObject,
117 NULL);
118 if (!NT_SUCCESS(Status))
119 {
120 return(Status);
121 }
122
123 DeviceObject = FileObject->DeviceObject;
124
125 KeInitializeEvent(&Event,
126 NotificationEvent,
127 FALSE);
128
129 Irp = IoAllocateIrp(DeviceObject->StackSize,
130 TRUE);
131 if (Irp == NULL)
132 {
133 ObDereferenceObject(FileObject);
134 return(STATUS_INSUFFICIENT_RESOURCES);
135 }
136
137 SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
138 Length,
139 TAG_SYSB);
140 if (SystemBuffer == NULL)
141 {
142 IoFreeIrp(Irp);
143 ObDereferenceObject(FileObject);
144 return(STATUS_INSUFFICIENT_RESOURCES);
145 }
146
147 Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
148 Irp->UserEvent = &Event;
149 Irp->UserIosb = &IoSB;
150 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
151
152 StackPtr = IoGetNextIrpStackLocation(Irp);
153 StackPtr->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION;
154 StackPtr->MinorFunction = 0;
155 StackPtr->Flags = 0;
156 StackPtr->Control = 0;
157 StackPtr->DeviceObject = DeviceObject;
158 StackPtr->FileObject = FileObject;
159 StackPtr->Parameters.QueryVolume.Length = Length;
160 StackPtr->Parameters.QueryVolume.FsInformationClass =
161 FsInformationClass;
162
163 Status = IoCallDriver(DeviceObject,
164 Irp);
165 if (Status == STATUS_PENDING)
166 {
167 KeWaitForSingleObject(&Event,
168 UserRequest,
169 KernelMode,
170 FALSE,
171 NULL);
172 Status = IoSB.Status;
173 }
174 DPRINT("Status %x\n", Status);
175
176 if (NT_SUCCESS(Status))
177 {
178 DPRINT("Information %lu\n", IoStatusBlock->Information);
179 MmSafeCopyToUser(FsInformation,
180 SystemBuffer,
181 IoSB.Information);
182 }
183 if (IoStatusBlock)
184 {
185 *IoStatusBlock = IoSB;
186 }
187 ExFreePool(SystemBuffer);
188 ObDereferenceObject(FileObject);
189
190 return(Status);
191 }
192
193
194 NTSTATUS STDCALL
195 IoQueryVolumeInformation(IN PFILE_OBJECT FileObject,
196 IN FS_INFORMATION_CLASS FsInformationClass,
197 IN ULONG Length,
198 OUT PVOID FsInformation,
199 OUT PULONG ReturnedLength)
200 {
201 IO_STATUS_BLOCK IoStatusBlock;
202 PIO_STACK_LOCATION StackPtr;
203 PDEVICE_OBJECT DeviceObject;
204 PIRP Irp;
205 KEVENT Event;
206 NTSTATUS Status;
207
208 assert(FsInformation != NULL);
209
210 DPRINT("FsInformation %p\n", FsInformation);
211
212 Status = ObReferenceObjectByPointer(FileObject,
213 FILE_READ_ATTRIBUTES,
214 IoFileObjectType,
215 KernelMode);
216 if (!NT_SUCCESS(Status))
217 {
218 return(Status);
219 }
220
221 DeviceObject = FileObject->DeviceObject;
222
223 KeInitializeEvent(&Event,
224 NotificationEvent,
225 FALSE);
226
227 Irp = IoAllocateIrp(DeviceObject->StackSize,
228 TRUE);
229 if (Irp == NULL)
230 {
231 ObDereferenceObject(FileObject);
232 return(STATUS_INSUFFICIENT_RESOURCES);
233 }
234
235 Irp->AssociatedIrp.SystemBuffer = FsInformation;
236 Irp->UserEvent = &Event;
237 Irp->UserIosb = &IoStatusBlock;
238 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
239
240 StackPtr = IoGetNextIrpStackLocation(Irp);
241 StackPtr->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION;
242 StackPtr->MinorFunction = 0;
243 StackPtr->Flags = 0;
244 StackPtr->Control = 0;
245 StackPtr->DeviceObject = DeviceObject;
246 StackPtr->FileObject = FileObject;
247 StackPtr->Parameters.QueryVolume.Length = Length;
248 StackPtr->Parameters.QueryVolume.FsInformationClass =
249 FsInformationClass;
250
251 Status = IoCallDriver(DeviceObject,
252 Irp);
253 if (Status == STATUS_PENDING)
254 {
255 KeWaitForSingleObject(&Event,
256 UserRequest,
257 KernelMode,
258 FALSE,
259 NULL);
260 Status = IoStatusBlock.Status;
261 }
262 DPRINT("Status %x\n", Status);
263
264 if (ReturnedLength != NULL)
265 {
266 *ReturnedLength = IoStatusBlock.Information;
267 }
268 ObDereferenceObject(FileObject);
269
270 return(Status);
271 }
272
273
274 NTSTATUS STDCALL
275 NtSetVolumeInformationFile(IN HANDLE FileHandle,
276 OUT PIO_STATUS_BLOCK IoStatusBlock,
277 IN PVOID FsInformation,
278 IN ULONG Length,
279 IN FS_INFORMATION_CLASS FsInformationClass)
280 {
281 PFILE_OBJECT FileObject;
282 PDEVICE_OBJECT DeviceObject;
283 PIRP Irp;
284 KEVENT Event;
285 NTSTATUS Status;
286 PIO_STACK_LOCATION StackPtr;
287 PVOID SystemBuffer;
288 IO_STATUS_BLOCK IoSB;
289
290 Status = ObReferenceObjectByHandle(FileHandle,
291 FILE_WRITE_ATTRIBUTES,
292 NULL,
293 UserMode,
294 (PVOID*)&FileObject,
295 NULL);
296 if (Status != STATUS_SUCCESS)
297 {
298 return(Status);
299 }
300
301 DeviceObject = FileObject->DeviceObject;
302
303 KeInitializeEvent(&Event,
304 NotificationEvent,
305 FALSE);
306
307 Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE);
308 if (Irp == NULL)
309 {
310 ObDereferenceObject(FileObject);
311 return(STATUS_INSUFFICIENT_RESOURCES);
312 }
313
314 SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
315 Length,
316 TAG_SYSB);
317 if (SystemBuffer == NULL)
318 {
319 IoFreeIrp(Irp);
320 ObDereferenceObject(FileObject);
321 return(STATUS_INSUFFICIENT_RESOURCES);
322 }
323
324 MmSafeCopyFromUser(SystemBuffer,
325 FsInformation,
326 Length);
327
328 Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
329 Irp->UserEvent = &Event;
330 Irp->UserIosb = &IoSB;
331 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
332
333 StackPtr = IoGetNextIrpStackLocation(Irp);
334 StackPtr->MajorFunction = IRP_MJ_SET_VOLUME_INFORMATION;
335 StackPtr->MinorFunction = 0;
336 StackPtr->Flags = 0;
337 StackPtr->Control = 0;
338 StackPtr->DeviceObject = DeviceObject;
339 StackPtr->FileObject = FileObject;
340 StackPtr->Parameters.SetVolume.Length = Length;
341 StackPtr->Parameters.SetVolume.FsInformationClass =
342 FsInformationClass;
343
344 Status = IoCallDriver(DeviceObject,Irp);
345 if (Status == STATUS_PENDING)
346 {
347 KeWaitForSingleObject(&Event,
348 UserRequest,
349 KernelMode,
350 FALSE,
351 NULL);
352 Status = IoSB.Status;
353 }
354 if (IoStatusBlock)
355 {
356 *IoStatusBlock = IoSB;
357 }
358 ExFreePool(SystemBuffer);
359
360 return(Status);
361 }
362
363
364 VOID STDCALL
365 IoAcquireVpbSpinLock(OUT PKIRQL Irql)
366 {
367 KeAcquireSpinLock(&IoVpbLock,
368 Irql);
369 }
370
371
372 VOID STDCALL
373 IoReleaseVpbSpinLock(IN KIRQL Irql)
374 {
375 KeReleaseSpinLock(&IoVpbLock,
376 Irql);
377 }
378
379
380 NTSTATUS STDCALL
381 IoVerifyVolume(IN PDEVICE_OBJECT DeviceObject,
382 IN BOOLEAN AllowRawMount)
383 {
384 UNIMPLEMENTED;
385 return(STATUS_NOT_IMPLEMENTED);
386 }
387
388
389 /* EOF */