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
8 * PROGRAMMERS: David Welch (welch@mcmail.com)
11 /* INCLUDES *****************************************************************/
15 #include <internal/debug.h>
17 /* GLOBALS *******************************************************************/
19 static KSPIN_LOCK IoVpbLock
;
21 #define TAG_VPB TAG('V', 'P', 'B', ' ')
22 #define TAG_SYSB TAG('S', 'Y', 'S', 'B')
24 /* FUNCTIONS *****************************************************************/
27 IoInitVpbImplementation(VOID
)
29 KeInitializeSpinLock(&IoVpbLock
);
33 IoAttachVpb(PDEVICE_OBJECT DeviceObject
)
37 Vpb
= ExAllocatePoolWithTag(NonPagedPool
,
42 return(STATUS_UNSUCCESSFUL
);
46 Vpb
->Size
= sizeof(VPB
) / sizeof(DWORD
);
48 Vpb
->VolumeLabelLength
= 0;
49 Vpb
->DeviceObject
= NULL
;
50 Vpb
->RealDevice
= DeviceObject
;
51 Vpb
->SerialNumber
= 0;
52 Vpb
->ReferenceCount
= 0;
53 RtlZeroMemory(Vpb
->VolumeLabel
,
54 sizeof(WCHAR
) * MAXIMUM_VOLUME_LABEL_LENGTH
);
56 DeviceObject
->Vpb
= Vpb
;
58 return(STATUS_SUCCESS
);
63 * FUNCTION: Queries the volume information
65 * FileHandle = Handle to a file object on the target volume
66 * ReturnLength = DataWritten
67 * FsInformation = Caller should supply storage for the information
69 * Length = Size of the information structure
70 * FsInformationClass = Index to a information structure
72 * FileFsVolumeInformation FILE_FS_VOLUME_INFORMATION
73 * FileFsLabelInformation FILE_FS_LABEL_INFORMATION
74 * FileFsSizeInformation FILE_FS_SIZE_INFORMATION
75 * FileFsDeviceInformation FILE_FS_DEVICE_INFORMATION
76 * FileFsAttributeInformation FILE_FS_ATTRIBUTE_INFORMATION
77 * FileFsControlInformation
78 * FileFsQuotaQueryInformation --
79 * FileFsQuotaSetInformation --
80 * FileFsMaximumInformation
88 NtQueryVolumeInformationFile(IN HANDLE FileHandle
,
89 OUT PIO_STATUS_BLOCK IoStatusBlock
,
90 OUT PVOID FsInformation
,
92 IN FS_INFORMATION_CLASS FsInformationClass
)
94 PFILE_OBJECT FileObject
;
95 PDEVICE_OBJECT DeviceObject
;
98 PIO_STACK_LOCATION StackPtr
;
100 KPROCESSOR_MODE PreviousMode
;
102 ASSERT(IoStatusBlock
!= NULL
);
103 ASSERT(FsInformation
!= NULL
);
105 DPRINT("FsInformation %p\n", FsInformation
);
107 PreviousMode
= ExGetPreviousMode();
109 Status
= ObReferenceObjectByHandle(FileHandle
,
110 FILE_READ_ATTRIBUTES
,
115 if (!NT_SUCCESS(Status
))
120 DeviceObject
= FileObject
->DeviceObject
;
122 Irp
= IoAllocateIrp(DeviceObject
->StackSize
,
126 ObDereferenceObject(FileObject
);
127 return(STATUS_INSUFFICIENT_RESOURCES
);
130 SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
133 if (SystemBuffer
== NULL
)
136 ObDereferenceObject(FileObject
);
137 return(STATUS_INSUFFICIENT_RESOURCES
);
140 /* Trigger FileObject/Event dereferencing */
141 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
143 Irp
->RequestorMode
= PreviousMode
;
144 Irp
->AssociatedIrp
.SystemBuffer
= SystemBuffer
;
145 KeResetEvent( &FileObject
->Event
);
146 Irp
->UserEvent
= &FileObject
->Event
;
147 Irp
->UserIosb
= IoStatusBlock
;
148 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
150 StackPtr
= IoGetNextIrpStackLocation(Irp
);
151 StackPtr
->MajorFunction
= IRP_MJ_QUERY_VOLUME_INFORMATION
;
152 StackPtr
->MinorFunction
= 0;
154 StackPtr
->Control
= 0;
155 StackPtr
->DeviceObject
= DeviceObject
;
156 StackPtr
->FileObject
= FileObject
;
157 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
158 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
=
161 Status
= IoCallDriver(DeviceObject
,
163 if (Status
== STATUS_PENDING
)
165 KeWaitForSingleObject(&FileObject
->Event
,
170 Status
= IoStatusBlock
->Status
;
172 DPRINT("Status %x\n", Status
);
174 if (NT_SUCCESS(Status
))
176 DPRINT("Information %lu\n", IoStatusBlock
->Information
);
177 MmSafeCopyToUser(FsInformation
,
179 IoStatusBlock
->Information
);
182 ExFreePool(SystemBuffer
);
192 IoQueryVolumeInformation(IN PFILE_OBJECT FileObject
,
193 IN FS_INFORMATION_CLASS FsInformationClass
,
195 OUT PVOID FsInformation
,
196 OUT PULONG ReturnedLength
)
198 IO_STATUS_BLOCK IoStatusBlock
;
199 PIO_STACK_LOCATION StackPtr
;
200 PDEVICE_OBJECT DeviceObject
;
204 ASSERT(FsInformation
!= NULL
);
206 DPRINT("FsInformation %p\n", FsInformation
);
208 Status
= ObReferenceObjectByPointer(FileObject
,
209 FILE_READ_ATTRIBUTES
,
212 if (!NT_SUCCESS(Status
))
217 DeviceObject
= FileObject
->DeviceObject
;
219 Irp
= IoAllocateIrp(DeviceObject
->StackSize
,
223 ObDereferenceObject(FileObject
);
224 return(STATUS_INSUFFICIENT_RESOURCES
);
227 /* Trigger FileObject/Event dereferencing */
228 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
229 Irp
->RequestorMode
= KernelMode
;
230 Irp
->AssociatedIrp
.SystemBuffer
= FsInformation
;
231 KeResetEvent( &FileObject
->Event
);
232 Irp
->UserEvent
= &FileObject
->Event
;
233 Irp
->UserIosb
= &IoStatusBlock
;
234 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
236 StackPtr
= IoGetNextIrpStackLocation(Irp
);
237 StackPtr
->MajorFunction
= IRP_MJ_QUERY_VOLUME_INFORMATION
;
238 StackPtr
->MinorFunction
= 0;
240 StackPtr
->Control
= 0;
241 StackPtr
->DeviceObject
= DeviceObject
;
242 StackPtr
->FileObject
= FileObject
;
243 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
244 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
=
247 Status
= IoCallDriver(DeviceObject
,
249 if (Status
== STATUS_PENDING
)
251 KeWaitForSingleObject(&FileObject
->Event
,
256 Status
= IoStatusBlock
.Status
;
258 DPRINT("Status %x\n", Status
);
260 if (ReturnedLength
!= NULL
)
262 *ReturnedLength
= IoStatusBlock
.Information
;
273 NtSetVolumeInformationFile(IN HANDLE FileHandle
,
274 OUT PIO_STATUS_BLOCK IoStatusBlock
,
275 IN PVOID FsInformation
,
277 IN FS_INFORMATION_CLASS FsInformationClass
)
279 PFILE_OBJECT FileObject
;
280 PDEVICE_OBJECT DeviceObject
;
283 PIO_STACK_LOCATION StackPtr
;
285 KPROCESSOR_MODE PreviousMode
;
287 ASSERT(IoStatusBlock
!= NULL
);
288 ASSERT(FsInformation
!= NULL
);
290 PreviousMode
= ExGetPreviousMode();
292 Status
= ObReferenceObjectByHandle(FileHandle
,
293 FILE_WRITE_ATTRIBUTES
,
298 if (Status
!= STATUS_SUCCESS
)
303 DeviceObject
= FileObject
->DeviceObject
;
305 Irp
= IoAllocateIrp(DeviceObject
->StackSize
,TRUE
);
308 ObDereferenceObject(FileObject
);
309 return(STATUS_INSUFFICIENT_RESOURCES
);
312 SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
315 if (SystemBuffer
== NULL
)
318 ObDereferenceObject(FileObject
);
319 return(STATUS_INSUFFICIENT_RESOURCES
);
322 MmSafeCopyFromUser(SystemBuffer
,
326 /* Trigger FileObject/Event dereferencing */
327 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
328 Irp
->RequestorMode
= PreviousMode
;
329 Irp
->AssociatedIrp
.SystemBuffer
= SystemBuffer
;
330 KeResetEvent( &FileObject
->Event
);
331 Irp
->UserEvent
= &FileObject
->Event
;
332 Irp
->UserIosb
= IoStatusBlock
;
333 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
335 StackPtr
= IoGetNextIrpStackLocation(Irp
);
336 StackPtr
->MajorFunction
= IRP_MJ_SET_VOLUME_INFORMATION
;
337 StackPtr
->MinorFunction
= 0;
339 StackPtr
->Control
= 0;
340 StackPtr
->DeviceObject
= DeviceObject
;
341 StackPtr
->FileObject
= FileObject
;
342 StackPtr
->Parameters
.SetVolume
.Length
= Length
;
343 StackPtr
->Parameters
.SetVolume
.FsInformationClass
=
346 Status
= IoCallDriver(DeviceObject
,Irp
);
347 if (Status
== STATUS_PENDING
)
349 KeWaitForSingleObject(&FileObject
->Event
,
354 Status
= IoStatusBlock
->Status
;
357 ExFreePool(SystemBuffer
);
367 IoAcquireVpbSpinLock(OUT PKIRQL Irql
)
369 KeAcquireSpinLock(&IoVpbLock
,
378 IoReleaseVpbSpinLock(IN KIRQL Irql
)
380 KeReleaseSpinLock(&IoVpbLock
,