- replaced IopCreateUnicodeString with RtlCreateUnicodeString
[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 _SEH_TRY
324 {
325 if (IoStatusBlock != NULL)
326 {
327 ProbeForWrite(IoStatusBlock,
328 sizeof(IO_STATUS_BLOCK),
329 sizeof(ULONG));
330 }
331
332 if (Length != 0)
333 {
334 ProbeForRead(FsInformation,
335 Length,
336 1);
337 }
338 }
339 _SEH_HANDLE
340 {
341 Status = _SEH_GetExceptionCode();
342 }
343 _SEH_END;
344
345 if (!NT_SUCCESS(Status))
346 {
347 return Status;
348 }
349 }
350 else
351 {
352 ASSERT(IoStatusBlock != NULL);
353 ASSERT(FsInformation != NULL);
354 }
355
356 Status = ObReferenceObjectByHandle(FileHandle,
357 FILE_WRITE_ATTRIBUTES,
358 NULL,
359 PreviousMode,
360 (PVOID*)&FileObject,
361 NULL);
362 if (Status != STATUS_SUCCESS)
363 {
364 return(Status);
365 }
366
367 DeviceObject = FileObject->DeviceObject;
368
369 Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE);
370 if (Irp == NULL)
371 {
372 ObDereferenceObject(FileObject);
373 return(STATUS_INSUFFICIENT_RESOURCES);
374 }
375
376 SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
377 Length,
378 TAG_SYSB);
379 if (SystemBuffer == NULL)
380 {
381 Status = STATUS_INSUFFICIENT_RESOURCES;
382 goto failfreeirp;
383 }
384
385 if (PreviousMode != KernelMode)
386 {
387 _SEH_TRY
388 {
389 /* no need to probe again */
390 RtlCopyMemory(SystemBuffer,
391 FsInformation,
392 Length);
393 }
394 _SEH_HANDLE
395 {
396 Status = _SEH_GetExceptionCode();
397 }
398 _SEH_END;
399
400 if (!NT_SUCCESS(Status))
401 {
402 ExFreePoolWithTag(SystemBuffer,
403 TAG_SYSB);
404 failfreeirp:
405 IoFreeIrp(Irp);
406 ObDereferenceObject(FileObject);
407 return Status;
408 }
409 }
410 else
411 {
412 RtlCopyMemory(SystemBuffer,
413 FsInformation,
414 Length);
415 }
416
417 /* Trigger FileObject/Event dereferencing */
418 Irp->Tail.Overlay.OriginalFileObject = FileObject;
419 Irp->RequestorMode = PreviousMode;
420 Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
421 KeResetEvent( &FileObject->Event );
422 Irp->UserEvent = &FileObject->Event;
423 Irp->UserIosb = IoStatusBlock;
424 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
425
426 StackPtr = IoGetNextIrpStackLocation(Irp);
427 StackPtr->MajorFunction = IRP_MJ_SET_VOLUME_INFORMATION;
428 StackPtr->MinorFunction = 0;
429 StackPtr->Flags = 0;
430 StackPtr->Control = 0;
431 StackPtr->DeviceObject = DeviceObject;
432 StackPtr->FileObject = FileObject;
433 StackPtr->Parameters.SetVolume.Length = Length;
434 StackPtr->Parameters.SetVolume.FsInformationClass =
435 FsInformationClass;
436
437 Status = IoCallDriver(DeviceObject,Irp);
438 if (Status == STATUS_PENDING)
439 {
440 KeWaitForSingleObject(&FileObject->Event,
441 UserRequest,
442 PreviousMode,
443 FALSE,
444 NULL);
445 _SEH_TRY
446 {
447 Status = IoStatusBlock->Status;
448 }
449 _SEH_HANDLE
450 {
451 Status = _SEH_GetExceptionCode();
452 }
453 _SEH_END;
454 }
455
456 ExFreePool(SystemBuffer);
457
458 return(Status);
459 }
460
461
462 /*
463 * @implemented
464 */
465 VOID STDCALL
466 IoAcquireVpbSpinLock(OUT PKIRQL Irql)
467 {
468 KeAcquireSpinLock(&IoVpbLock,
469 Irql);
470 }
471
472
473 /*
474 * @implemented
475 */
476 VOID STDCALL
477 IoReleaseVpbSpinLock(IN KIRQL Irql)
478 {
479 KeReleaseSpinLock(&IoVpbLock,
480 Irql);
481 }
482
483 /*
484 * @unimplemented
485 */
486 NTSTATUS
487 STDCALL
488 IoCheckQuerySetVolumeInformation(IN FS_INFORMATION_CLASS FsInformationClass,
489 IN ULONG Length,
490 IN BOOLEAN SetOperation)
491 {
492 UNIMPLEMENTED;
493 return STATUS_NOT_IMPLEMENTED;
494 }
495
496 /* EOF */