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