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)
12 /* INCLUDES *****************************************************************/
16 #include <internal/debug.h>
18 /* GLOBALS *******************************************************************/
20 static KSPIN_LOCK IoVpbLock
;
22 #define TAG_VPB TAG('V', 'P', 'B', ' ')
23 #define TAG_SYSB TAG('S', 'Y', 'S', 'B')
25 /* FUNCTIONS *****************************************************************/
28 IoInitVpbImplementation(VOID
)
30 KeInitializeSpinLock(&IoVpbLock
);
34 IoAttachVpb(PDEVICE_OBJECT DeviceObject
)
38 Vpb
= ExAllocatePoolWithTag(NonPagedPool
,
43 return(STATUS_UNSUCCESSFUL
);
47 Vpb
->Size
= sizeof(VPB
) / sizeof(DWORD
);
49 Vpb
->VolumeLabelLength
= 0;
50 Vpb
->DeviceObject
= NULL
;
51 Vpb
->RealDevice
= DeviceObject
;
52 Vpb
->SerialNumber
= 0;
53 Vpb
->ReferenceCount
= 0;
54 RtlZeroMemory(Vpb
->VolumeLabel
,
55 sizeof(WCHAR
) * MAXIMUM_VOLUME_LABEL_LENGTH
);
57 DeviceObject
->Vpb
= Vpb
;
59 return(STATUS_SUCCESS
);
64 * FUNCTION: Queries the volume information
66 * FileHandle = Handle to a file object on the target volume
67 * ReturnLength = DataWritten
68 * FsInformation = Caller should supply storage for the information
70 * Length = Size of the information structure
71 * FsInformationClass = Index to a information structure
73 * FileFsVolumeInformation FILE_FS_VOLUME_INFORMATION
74 * FileFsLabelInformation FILE_FS_LABEL_INFORMATION
75 * FileFsSizeInformation FILE_FS_SIZE_INFORMATION
76 * FileFsDeviceInformation FILE_FS_DEVICE_INFORMATION
77 * FileFsAttributeInformation FILE_FS_ATTRIBUTE_INFORMATION
78 * FileFsControlInformation
79 * FileFsQuotaQueryInformation --
80 * FileFsQuotaSetInformation --
81 * FileFsMaximumInformation
89 NtQueryVolumeInformationFile(IN HANDLE FileHandle
,
90 OUT PIO_STATUS_BLOCK IoStatusBlock
,
91 OUT PVOID FsInformation
,
93 IN FS_INFORMATION_CLASS FsInformationClass
)
95 PFILE_OBJECT FileObject
;
96 PDEVICE_OBJECT DeviceObject
;
99 PIO_STACK_LOCATION StackPtr
;
101 KPROCESSOR_MODE PreviousMode
;
103 ASSERT(IoStatusBlock
!= NULL
);
104 ASSERT(FsInformation
!= NULL
);
106 DPRINT("FsInformation %p\n", FsInformation
);
108 PreviousMode
= ExGetPreviousMode();
110 Status
= ObReferenceObjectByHandle(FileHandle
,
111 FILE_READ_ATTRIBUTES
,
116 if (!NT_SUCCESS(Status
))
121 DeviceObject
= FileObject
->DeviceObject
;
123 Irp
= IoAllocateIrp(DeviceObject
->StackSize
,
127 ObDereferenceObject(FileObject
);
128 return(STATUS_INSUFFICIENT_RESOURCES
);
131 SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
134 if (SystemBuffer
== NULL
)
137 ObDereferenceObject(FileObject
);
138 return(STATUS_INSUFFICIENT_RESOURCES
);
141 /* Trigger FileObject/Event dereferencing */
142 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
144 Irp
->RequestorMode
= PreviousMode
;
145 Irp
->AssociatedIrp
.SystemBuffer
= SystemBuffer
;
146 KeResetEvent( &FileObject
->Event
);
147 Irp
->UserEvent
= &FileObject
->Event
;
148 Irp
->UserIosb
= IoStatusBlock
;
149 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
151 StackPtr
= IoGetNextIrpStackLocation(Irp
);
152 StackPtr
->MajorFunction
= IRP_MJ_QUERY_VOLUME_INFORMATION
;
153 StackPtr
->MinorFunction
= 0;
155 StackPtr
->Control
= 0;
156 StackPtr
->DeviceObject
= DeviceObject
;
157 StackPtr
->FileObject
= FileObject
;
158 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
159 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
=
162 Status
= IoCallDriver(DeviceObject
,
164 if (Status
== STATUS_PENDING
)
166 KeWaitForSingleObject(&FileObject
->Event
,
171 Status
= IoStatusBlock
->Status
;
173 DPRINT("Status %x\n", Status
);
175 if (NT_SUCCESS(Status
))
177 DPRINT("Information %lu\n", IoStatusBlock
->Information
);
178 MmSafeCopyToUser(FsInformation
,
180 IoStatusBlock
->Information
);
183 ExFreePool(SystemBuffer
);
193 IoQueryVolumeInformation(IN PFILE_OBJECT FileObject
,
194 IN FS_INFORMATION_CLASS FsInformationClass
,
196 OUT PVOID FsInformation
,
197 OUT PULONG ReturnedLength
)
199 IO_STATUS_BLOCK IoStatusBlock
;
200 PIO_STACK_LOCATION StackPtr
;
201 PDEVICE_OBJECT DeviceObject
;
205 ASSERT(FsInformation
!= NULL
);
207 DPRINT("FsInformation %p\n", FsInformation
);
209 Status
= ObReferenceObjectByPointer(FileObject
,
210 FILE_READ_ATTRIBUTES
,
213 if (!NT_SUCCESS(Status
))
218 DeviceObject
= FileObject
->DeviceObject
;
220 Irp
= IoAllocateIrp(DeviceObject
->StackSize
,
224 ObDereferenceObject(FileObject
);
225 return(STATUS_INSUFFICIENT_RESOURCES
);
228 /* Trigger FileObject/Event dereferencing */
229 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
230 Irp
->RequestorMode
= KernelMode
;
231 Irp
->AssociatedIrp
.SystemBuffer
= FsInformation
;
232 KeResetEvent( &FileObject
->Event
);
233 Irp
->UserEvent
= &FileObject
->Event
;
234 Irp
->UserIosb
= &IoStatusBlock
;
235 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
237 StackPtr
= IoGetNextIrpStackLocation(Irp
);
238 StackPtr
->MajorFunction
= IRP_MJ_QUERY_VOLUME_INFORMATION
;
239 StackPtr
->MinorFunction
= 0;
241 StackPtr
->Control
= 0;
242 StackPtr
->DeviceObject
= DeviceObject
;
243 StackPtr
->FileObject
= FileObject
;
244 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
245 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
=
248 Status
= IoCallDriver(DeviceObject
,
250 if (Status
== STATUS_PENDING
)
252 KeWaitForSingleObject(&FileObject
->Event
,
257 Status
= IoStatusBlock
.Status
;
259 DPRINT("Status %x\n", Status
);
261 if (ReturnedLength
!= NULL
)
263 *ReturnedLength
= IoStatusBlock
.Information
;
274 NtSetVolumeInformationFile(IN HANDLE FileHandle
,
275 OUT PIO_STATUS_BLOCK IoStatusBlock
,
276 IN PVOID FsInformation
,
278 IN FS_INFORMATION_CLASS FsInformationClass
)
280 PFILE_OBJECT FileObject
;
281 PDEVICE_OBJECT DeviceObject
;
284 PIO_STACK_LOCATION StackPtr
;
286 KPROCESSOR_MODE PreviousMode
;
288 ASSERT(IoStatusBlock
!= NULL
);
289 ASSERT(FsInformation
!= NULL
);
291 PreviousMode
= ExGetPreviousMode();
293 Status
= ObReferenceObjectByHandle(FileHandle
,
294 FILE_WRITE_ATTRIBUTES
,
299 if (Status
!= STATUS_SUCCESS
)
304 DeviceObject
= FileObject
->DeviceObject
;
306 Irp
= IoAllocateIrp(DeviceObject
->StackSize
,TRUE
);
309 ObDereferenceObject(FileObject
);
310 return(STATUS_INSUFFICIENT_RESOURCES
);
313 SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
316 if (SystemBuffer
== NULL
)
319 ObDereferenceObject(FileObject
);
320 return(STATUS_INSUFFICIENT_RESOURCES
);
323 MmSafeCopyFromUser(SystemBuffer
,
327 /* Trigger FileObject/Event dereferencing */
328 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
329 Irp
->RequestorMode
= PreviousMode
;
330 Irp
->AssociatedIrp
.SystemBuffer
= SystemBuffer
;
331 KeResetEvent( &FileObject
->Event
);
332 Irp
->UserEvent
= &FileObject
->Event
;
333 Irp
->UserIosb
= IoStatusBlock
;
334 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
336 StackPtr
= IoGetNextIrpStackLocation(Irp
);
337 StackPtr
->MajorFunction
= IRP_MJ_SET_VOLUME_INFORMATION
;
338 StackPtr
->MinorFunction
= 0;
340 StackPtr
->Control
= 0;
341 StackPtr
->DeviceObject
= DeviceObject
;
342 StackPtr
->FileObject
= FileObject
;
343 StackPtr
->Parameters
.SetVolume
.Length
= Length
;
344 StackPtr
->Parameters
.SetVolume
.FsInformationClass
=
347 Status
= IoCallDriver(DeviceObject
,Irp
);
348 if (Status
== STATUS_PENDING
)
350 KeWaitForSingleObject(&FileObject
->Event
,
355 Status
= IoStatusBlock
->Status
;
358 ExFreePool(SystemBuffer
);
368 IoAcquireVpbSpinLock(OUT PKIRQL Irql
)
370 KeAcquireSpinLock(&IoVpbLock
,
379 IoReleaseVpbSpinLock(IN KIRQL Irql
)
381 KeReleaseSpinLock(&IoVpbLock
,