- Support INIT section pragmas for msvc. Patch by Brezenbak.
[reactos.git] / reactos / ntoskrnl / io / vpb.c
1 /* $Id$
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 *
8 * PROGRAMMERS: David Welch (welch@mcmail.com)
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 #if defined (ALLOC_PRAGMA)
18 #pragma alloc_text(INIT, IoInitVpbImplementation)
19 #endif
20
21
22 /* GLOBALS *******************************************************************/
23
24 static KSPIN_LOCK IoVpbLock;
25
26 /* FUNCTIONS *****************************************************************/
27
28 VOID INIT_FUNCTION
29 IoInitVpbImplementation(VOID)
30 {
31 KeInitializeSpinLock(&IoVpbLock);
32 }
33
34 NTSTATUS
35 STDCALL
36 IopAttachVpb(PDEVICE_OBJECT DeviceObject)
37 {
38 PVPB Vpb;
39
40 /* Allocate the Vpb */
41 Vpb = ExAllocatePoolWithTag(NonPagedPool,
42 sizeof(VPB),
43 TAG_VPB);
44 if (Vpb == NULL) return(STATUS_UNSUCCESSFUL);
45
46 /* Clear it so we don't waste time manually */
47 RtlZeroMemory(Vpb, sizeof(VPB));
48
49 /* Set the Header and Device Field */
50 Vpb->Type = IO_TYPE_VPB;
51 Vpb->Size = sizeof(VPB);
52 Vpb->RealDevice = DeviceObject;
53
54 /* link it to the Device Object */
55 DeviceObject->Vpb = Vpb;
56 return(STATUS_SUCCESS);
57 }
58
59 /*
60 * FUNCTION: Queries the volume information
61 * ARGUMENTS:
62 * FileHandle = Handle to a file object on the target volume
63 * ReturnLength = DataWritten
64 * FsInformation = Caller should supply storage for the information
65 * structure.
66 * Length = Size of the information structure
67 * FsInformationClass = Index to a information structure
68 *
69 * FileFsVolumeInformation FILE_FS_VOLUME_INFORMATION
70 * FileFsLabelInformation FILE_FS_LABEL_INFORMATION
71 * FileFsSizeInformation FILE_FS_SIZE_INFORMATION
72 * FileFsDeviceInformation FILE_FS_DEVICE_INFORMATION
73 * FileFsAttributeInformation FILE_FS_ATTRIBUTE_INFORMATION
74 * FileFsControlInformation
75 * FileFsQuotaQueryInformation --
76 * FileFsQuotaSetInformation --
77 * FileFsMaximumInformation
78 *
79 * RETURNS: Status
80 *
81 * @implemented
82 */
83
84 NTSTATUS STDCALL
85 NtQueryVolumeInformationFile(IN HANDLE FileHandle,
86 OUT PIO_STATUS_BLOCK IoStatusBlock,
87 OUT PVOID FsInformation,
88 IN ULONG Length,
89 IN FS_INFORMATION_CLASS FsInformationClass)
90 {
91 PFILE_OBJECT FileObject;
92 PDEVICE_OBJECT DeviceObject;
93 PIRP Irp;
94 NTSTATUS Status = STATUS_SUCCESS;
95 PIO_STACK_LOCATION StackPtr;
96 PVOID SystemBuffer;
97 KPROCESSOR_MODE PreviousMode;
98
99 DPRINT("FsInformation %p\n", FsInformation);
100
101 PreviousMode = ExGetPreviousMode();
102
103 if (PreviousMode != KernelMode)
104 {
105 _SEH_TRY
106 {
107 if (IoStatusBlock != NULL)
108 {
109 ProbeForWrite(IoStatusBlock,
110 sizeof(IO_STATUS_BLOCK),
111 sizeof(ULONG));
112 }
113
114 if (Length != 0)
115 {
116 ProbeForWrite(FsInformation,
117 Length,
118 1);
119 }
120 }
121 _SEH_HANDLE
122 {
123 Status = _SEH_GetExceptionCode();
124 }
125 _SEH_END;
126
127 if (!NT_SUCCESS(Status))
128 {
129 return Status;
130 }
131 }
132 else
133 {
134 ASSERT(IoStatusBlock != NULL);
135 ASSERT(FsInformation != NULL);
136 }
137
138 Status = ObReferenceObjectByHandle(FileHandle,
139 0, /* FIXME - depends on the information class! */
140 IoFileObjectType,
141 PreviousMode,
142 (PVOID*)&FileObject,
143 NULL);
144 if (!NT_SUCCESS(Status))
145 {
146 return(Status);
147 }
148
149 DeviceObject = FileObject->DeviceObject;
150
151 Irp = IoAllocateIrp(DeviceObject->StackSize,
152 TRUE);
153 if (Irp == NULL)
154 {
155 ObDereferenceObject(FileObject);
156 return(STATUS_INSUFFICIENT_RESOURCES);
157 }
158
159 SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
160 Length,
161 TAG_SYSB);
162 if (SystemBuffer == NULL)
163 {
164 IoFreeIrp(Irp);
165 ObDereferenceObject(FileObject);
166 return(STATUS_INSUFFICIENT_RESOURCES);
167 }
168
169 /* Trigger FileObject/Event dereferencing */
170 Irp->Tail.Overlay.OriginalFileObject = FileObject;
171
172 Irp->RequestorMode = PreviousMode;
173 Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
174 KeResetEvent( &FileObject->Event );
175 Irp->UserEvent = &FileObject->Event;
176 Irp->UserIosb = IoStatusBlock;
177 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
178
179 StackPtr = IoGetNextIrpStackLocation(Irp);
180 StackPtr->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION;
181 StackPtr->MinorFunction = 0;
182 StackPtr->Flags = 0;
183 StackPtr->Control = 0;
184 StackPtr->DeviceObject = DeviceObject;
185 StackPtr->FileObject = FileObject;
186 StackPtr->Parameters.QueryVolume.Length = Length;
187 StackPtr->Parameters.QueryVolume.FsInformationClass =
188 FsInformationClass;
189
190 Status = IoCallDriver(DeviceObject,
191 Irp);
192 if (Status == STATUS_PENDING)
193 {
194 KeWaitForSingleObject(&FileObject->Event,
195 UserRequest,
196 PreviousMode,
197 FALSE,
198 NULL);
199 Status = IoStatusBlock->Status;
200 }
201 DPRINT("Status %x\n", Status);
202
203 if (NT_SUCCESS(Status))
204 {
205 _SEH_TRY
206 {
207 DPRINT("Information %lu\n", IoStatusBlock->Information);
208 RtlCopyMemory(FsInformation,
209 SystemBuffer,
210 IoStatusBlock->Information);
211 }
212 _SEH_HANDLE
213 {
214 Status = _SEH_GetExceptionCode();
215 }
216 _SEH_END;
217 }
218
219 ExFreePool(SystemBuffer);
220
221 return(Status);
222 }
223
224
225 /*
226 * @implemented
227 */
228 NTSTATUS STDCALL
229 IoQueryVolumeInformation(IN PFILE_OBJECT FileObject,
230 IN FS_INFORMATION_CLASS FsInformationClass,
231 IN ULONG Length,
232 OUT PVOID FsInformation,
233 OUT PULONG ReturnedLength)
234 {
235 IO_STATUS_BLOCK IoStatusBlock;
236 PIO_STACK_LOCATION StackPtr;
237 PDEVICE_OBJECT DeviceObject;
238 PIRP Irp;
239 NTSTATUS Status;
240
241 ASSERT(FsInformation != NULL);
242
243 DPRINT("FsInformation %p\n", FsInformation);
244
245 Status = ObReferenceObjectByPointer(FileObject,
246 FILE_READ_ATTRIBUTES,
247 IoFileObjectType,
248 KernelMode);
249 if (!NT_SUCCESS(Status))
250 {
251 return(Status);
252 }
253
254 DeviceObject = FileObject->DeviceObject;
255
256 Irp = IoAllocateIrp(DeviceObject->StackSize,
257 TRUE);
258 if (Irp == NULL)
259 {
260 ObDereferenceObject(FileObject);
261 return(STATUS_INSUFFICIENT_RESOURCES);
262 }
263
264 /* Trigger FileObject/Event dereferencing */
265 Irp->Tail.Overlay.OriginalFileObject = FileObject;
266 Irp->RequestorMode = KernelMode;
267 Irp->AssociatedIrp.SystemBuffer = FsInformation;
268 KeResetEvent( &FileObject->Event );
269 Irp->UserEvent = &FileObject->Event;
270 Irp->UserIosb = &IoStatusBlock;
271 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
272
273 StackPtr = IoGetNextIrpStackLocation(Irp);
274 StackPtr->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION;
275 StackPtr->MinorFunction = 0;
276 StackPtr->Flags = 0;
277 StackPtr->Control = 0;
278 StackPtr->DeviceObject = DeviceObject;
279 StackPtr->FileObject = FileObject;
280 StackPtr->Parameters.QueryVolume.Length = Length;
281 StackPtr->Parameters.QueryVolume.FsInformationClass =
282 FsInformationClass;
283
284 Status = IoCallDriver(DeviceObject,
285 Irp);
286 if (Status == STATUS_PENDING)
287 {
288 KeWaitForSingleObject(&FileObject->Event,
289 UserRequest,
290 KernelMode,
291 FALSE,
292 NULL);
293 Status = IoStatusBlock.Status;
294 }
295 DPRINT("Status %x\n", Status);
296
297 if (ReturnedLength != NULL)
298 {
299 *ReturnedLength = IoStatusBlock.Information;
300 }
301
302 return(Status);
303 }
304
305
306 /*
307 * @implemented
308 */
309 NTSTATUS STDCALL
310 NtSetVolumeInformationFile(IN HANDLE FileHandle,
311 OUT PIO_STATUS_BLOCK IoStatusBlock,
312 IN PVOID FsInformation,
313 IN ULONG Length,
314 IN FS_INFORMATION_CLASS FsInformationClass)
315 {
316 PFILE_OBJECT FileObject;
317 PDEVICE_OBJECT DeviceObject;
318 PIRP Irp;
319 NTSTATUS Status;
320 PIO_STACK_LOCATION StackPtr;
321 PVOID SystemBuffer;
322 KPROCESSOR_MODE PreviousMode;
323
324 PreviousMode = ExGetPreviousMode();
325
326 if (PreviousMode != KernelMode)
327 {
328 Status = STATUS_SUCCESS;
329 _SEH_TRY
330 {
331 if (IoStatusBlock != NULL)
332 {
333 ProbeForWrite(IoStatusBlock,
334 sizeof(IO_STATUS_BLOCK),
335 sizeof(ULONG));
336 }
337
338 if (Length != 0)
339 {
340 ProbeForRead(FsInformation,
341 Length,
342 1);
343 }
344 }
345 _SEH_HANDLE
346 {
347 Status = _SEH_GetExceptionCode();
348 }
349 _SEH_END;
350
351 if (!NT_SUCCESS(Status))
352 {
353 return Status;
354 }
355 }
356 else
357 {
358 ASSERT(IoStatusBlock != NULL);
359 ASSERT(FsInformation != NULL);
360 }
361
362 Status = ObReferenceObjectByHandle(FileHandle,
363 FILE_WRITE_ATTRIBUTES,
364 NULL,
365 PreviousMode,
366 (PVOID*)&FileObject,
367 NULL);
368 if (Status != STATUS_SUCCESS)
369 {
370 return(Status);
371 }
372
373 DeviceObject = FileObject->DeviceObject;
374
375 Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE);
376 if (Irp == NULL)
377 {
378 ObDereferenceObject(FileObject);
379 return(STATUS_INSUFFICIENT_RESOURCES);
380 }
381
382 SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
383 Length,
384 TAG_SYSB);
385 if (SystemBuffer == NULL)
386 {
387 Status = STATUS_INSUFFICIENT_RESOURCES;
388 goto failfreeirp;
389 }
390
391 if (PreviousMode != KernelMode)
392 {
393 _SEH_TRY
394 {
395 /* no need to probe again */
396 RtlCopyMemory(SystemBuffer,
397 FsInformation,
398 Length);
399 }
400 _SEH_HANDLE
401 {
402 Status = _SEH_GetExceptionCode();
403 }
404 _SEH_END;
405
406 if (!NT_SUCCESS(Status))
407 {
408 ExFreePoolWithTag(SystemBuffer,
409 TAG_SYSB);
410 failfreeirp:
411 IoFreeIrp(Irp);
412 ObDereferenceObject(FileObject);
413 return Status;
414 }
415 }
416 else
417 {
418 RtlCopyMemory(SystemBuffer,
419 FsInformation,
420 Length);
421 }
422
423 /* Trigger FileObject/Event dereferencing */
424 Irp->Tail.Overlay.OriginalFileObject = FileObject;
425 Irp->RequestorMode = PreviousMode;
426 Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
427 KeResetEvent( &FileObject->Event );
428 Irp->UserEvent = &FileObject->Event;
429 Irp->UserIosb = IoStatusBlock;
430 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
431
432 StackPtr = IoGetNextIrpStackLocation(Irp);
433 StackPtr->MajorFunction = IRP_MJ_SET_VOLUME_INFORMATION;
434 StackPtr->MinorFunction = 0;
435 StackPtr->Flags = 0;
436 StackPtr->Control = 0;
437 StackPtr->DeviceObject = DeviceObject;
438 StackPtr->FileObject = FileObject;
439 StackPtr->Parameters.SetVolume.Length = Length;
440 StackPtr->Parameters.SetVolume.FsInformationClass =
441 FsInformationClass;
442
443 Status = IoCallDriver(DeviceObject,Irp);
444 if (Status == STATUS_PENDING)
445 {
446 KeWaitForSingleObject(&FileObject->Event,
447 UserRequest,
448 PreviousMode,
449 FALSE,
450 NULL);
451 _SEH_TRY
452 {
453 Status = IoStatusBlock->Status;
454 }
455 _SEH_HANDLE
456 {
457 Status = _SEH_GetExceptionCode();
458 }
459 _SEH_END;
460 }
461
462 ExFreePool(SystemBuffer);
463
464 return(Status);
465 }
466
467
468 /*
469 * @implemented
470 */
471 VOID STDCALL
472 IoAcquireVpbSpinLock(OUT PKIRQL Irql)
473 {
474 KeAcquireSpinLock(&IoVpbLock,
475 Irql);
476 }
477
478
479 /*
480 * @implemented
481 */
482 VOID STDCALL
483 IoReleaseVpbSpinLock(IN KIRQL Irql)
484 {
485 KeReleaseSpinLock(&IoVpbLock,
486 Irql);
487 }
488
489 /*
490 * @unimplemented
491 */
492 NTSTATUS
493 STDCALL
494 IoCheckQuerySetVolumeInformation(IN FS_INFORMATION_CLASS FsInformationClass,
495 IN ULONG Length,
496 IN BOOLEAN SetOperation)
497 {
498 UNIMPLEMENTED;
499 return STATUS_NOT_IMPLEMENTED;
500 }
501
502 /* EOF */