963f9b7aec5a3e0ef62955ed1acab57c12ed931f
[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 * PROGRAMMER: David Welch (welch@mcmail.com)
8 * UPDATE HISTORY:
9 * Created 22/05/98
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ntoskrnl.h>
15 #define NDEBUG
16 #include <internal/debug.h>
17
18 /* GLOBALS *******************************************************************/
19
20 static KSPIN_LOCK IoVpbLock;
21
22 #define TAG_VPB TAG('V', 'P', 'B', ' ')
23 #define TAG_SYSB TAG('S', 'Y', 'S', 'B')
24
25 /* FUNCTIONS *****************************************************************/
26
27 VOID INIT_FUNCTION
28 IoInitVpbImplementation(VOID)
29 {
30 KeInitializeSpinLock(&IoVpbLock);
31 }
32
33 NTSTATUS
34 IoAttachVpb(PDEVICE_OBJECT DeviceObject)
35 {
36 PVPB Vpb;
37
38 Vpb = ExAllocatePoolWithTag(NonPagedPool,
39 sizeof(VPB),
40 TAG_VPB);
41 if (Vpb == NULL)
42 {
43 return(STATUS_UNSUCCESSFUL);
44 }
45
46 Vpb->Type = 0;
47 Vpb->Size = sizeof(VPB) / sizeof(DWORD);
48 Vpb->Flags = 0;
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);
56
57 DeviceObject->Vpb = Vpb;
58
59 return(STATUS_SUCCESS);
60 }
61
62
63 /*
64 * FUNCTION: Queries the volume information
65 * ARGUMENTS:
66 * FileHandle = Handle to a file object on the target volume
67 * ReturnLength = DataWritten
68 * FsInformation = Caller should supply storage for the information
69 * structure.
70 * Length = Size of the information structure
71 * FsInformationClass = Index to a information structure
72 *
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
82 *
83 * RETURNS: Status
84 *
85 * @implemented
86 */
87
88 NTSTATUS STDCALL
89 NtQueryVolumeInformationFile(IN HANDLE FileHandle,
90 OUT PIO_STATUS_BLOCK IoStatusBlock,
91 OUT PVOID FsInformation,
92 IN ULONG Length,
93 IN FS_INFORMATION_CLASS FsInformationClass)
94 {
95 PFILE_OBJECT FileObject;
96 PDEVICE_OBJECT DeviceObject;
97 PIRP Irp;
98 NTSTATUS Status;
99 PIO_STACK_LOCATION StackPtr;
100 PVOID SystemBuffer;
101 KPROCESSOR_MODE PreviousMode;
102
103 ASSERT(IoStatusBlock != NULL);
104 ASSERT(FsInformation != NULL);
105
106 DPRINT("FsInformation %p\n", FsInformation);
107
108 PreviousMode = ExGetPreviousMode();
109
110 Status = ObReferenceObjectByHandle(FileHandle,
111 FILE_READ_ATTRIBUTES,
112 IoFileObjectType,
113 PreviousMode,
114 (PVOID*)&FileObject,
115 NULL);
116 if (!NT_SUCCESS(Status))
117 {
118 return(Status);
119 }
120
121 DeviceObject = FileObject->DeviceObject;
122
123 Irp = IoAllocateIrp(DeviceObject->StackSize,
124 TRUE);
125 if (Irp == NULL)
126 {
127 ObDereferenceObject(FileObject);
128 return(STATUS_INSUFFICIENT_RESOURCES);
129 }
130
131 SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
132 Length,
133 TAG_SYSB);
134 if (SystemBuffer == NULL)
135 {
136 IoFreeIrp(Irp);
137 ObDereferenceObject(FileObject);
138 return(STATUS_INSUFFICIENT_RESOURCES);
139 }
140
141 /* Trigger FileObject/Event dereferencing */
142 Irp->Tail.Overlay.OriginalFileObject = FileObject;
143
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();
150
151 StackPtr = IoGetNextIrpStackLocation(Irp);
152 StackPtr->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION;
153 StackPtr->MinorFunction = 0;
154 StackPtr->Flags = 0;
155 StackPtr->Control = 0;
156 StackPtr->DeviceObject = DeviceObject;
157 StackPtr->FileObject = FileObject;
158 StackPtr->Parameters.QueryVolume.Length = Length;
159 StackPtr->Parameters.QueryVolume.FsInformationClass =
160 FsInformationClass;
161
162 Status = IoCallDriver(DeviceObject,
163 Irp);
164 if (Status == STATUS_PENDING)
165 {
166 KeWaitForSingleObject(&FileObject->Event,
167 UserRequest,
168 PreviousMode,
169 FALSE,
170 NULL);
171 Status = IoStatusBlock->Status;
172 }
173 DPRINT("Status %x\n", Status);
174
175 if (NT_SUCCESS(Status))
176 {
177 DPRINT("Information %lu\n", IoStatusBlock->Information);
178 MmSafeCopyToUser(FsInformation,
179 SystemBuffer,
180 IoStatusBlock->Information);
181 }
182
183 ExFreePool(SystemBuffer);
184
185 return(Status);
186 }
187
188
189 /*
190 * @implemented
191 */
192 NTSTATUS STDCALL
193 IoQueryVolumeInformation(IN PFILE_OBJECT FileObject,
194 IN FS_INFORMATION_CLASS FsInformationClass,
195 IN ULONG Length,
196 OUT PVOID FsInformation,
197 OUT PULONG ReturnedLength)
198 {
199 IO_STATUS_BLOCK IoStatusBlock;
200 PIO_STACK_LOCATION StackPtr;
201 PDEVICE_OBJECT DeviceObject;
202 PIRP Irp;
203 NTSTATUS Status;
204
205 ASSERT(FsInformation != NULL);
206
207 DPRINT("FsInformation %p\n", FsInformation);
208
209 Status = ObReferenceObjectByPointer(FileObject,
210 FILE_READ_ATTRIBUTES,
211 IoFileObjectType,
212 KernelMode);
213 if (!NT_SUCCESS(Status))
214 {
215 return(Status);
216 }
217
218 DeviceObject = FileObject->DeviceObject;
219
220 Irp = IoAllocateIrp(DeviceObject->StackSize,
221 TRUE);
222 if (Irp == NULL)
223 {
224 ObDereferenceObject(FileObject);
225 return(STATUS_INSUFFICIENT_RESOURCES);
226 }
227
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();
236
237 StackPtr = IoGetNextIrpStackLocation(Irp);
238 StackPtr->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION;
239 StackPtr->MinorFunction = 0;
240 StackPtr->Flags = 0;
241 StackPtr->Control = 0;
242 StackPtr->DeviceObject = DeviceObject;
243 StackPtr->FileObject = FileObject;
244 StackPtr->Parameters.QueryVolume.Length = Length;
245 StackPtr->Parameters.QueryVolume.FsInformationClass =
246 FsInformationClass;
247
248 Status = IoCallDriver(DeviceObject,
249 Irp);
250 if (Status == STATUS_PENDING)
251 {
252 KeWaitForSingleObject(&FileObject->Event,
253 UserRequest,
254 KernelMode,
255 FALSE,
256 NULL);
257 Status = IoStatusBlock.Status;
258 }
259 DPRINT("Status %x\n", Status);
260
261 if (ReturnedLength != NULL)
262 {
263 *ReturnedLength = IoStatusBlock.Information;
264 }
265
266 return(Status);
267 }
268
269
270 /*
271 * @implemented
272 */
273 NTSTATUS STDCALL
274 NtSetVolumeInformationFile(IN HANDLE FileHandle,
275 OUT PIO_STATUS_BLOCK IoStatusBlock,
276 IN PVOID FsInformation,
277 IN ULONG Length,
278 IN FS_INFORMATION_CLASS FsInformationClass)
279 {
280 PFILE_OBJECT FileObject;
281 PDEVICE_OBJECT DeviceObject;
282 PIRP Irp;
283 NTSTATUS Status;
284 PIO_STACK_LOCATION StackPtr;
285 PVOID SystemBuffer;
286 KPROCESSOR_MODE PreviousMode;
287
288 ASSERT(IoStatusBlock != NULL);
289 ASSERT(FsInformation != NULL);
290
291 PreviousMode = ExGetPreviousMode();
292
293 Status = ObReferenceObjectByHandle(FileHandle,
294 FILE_WRITE_ATTRIBUTES,
295 NULL,
296 PreviousMode,
297 (PVOID*)&FileObject,
298 NULL);
299 if (Status != STATUS_SUCCESS)
300 {
301 return(Status);
302 }
303
304 DeviceObject = FileObject->DeviceObject;
305
306 Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE);
307 if (Irp == NULL)
308 {
309 ObDereferenceObject(FileObject);
310 return(STATUS_INSUFFICIENT_RESOURCES);
311 }
312
313 SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
314 Length,
315 TAG_SYSB);
316 if (SystemBuffer == NULL)
317 {
318 IoFreeIrp(Irp);
319 ObDereferenceObject(FileObject);
320 return(STATUS_INSUFFICIENT_RESOURCES);
321 }
322
323 MmSafeCopyFromUser(SystemBuffer,
324 FsInformation,
325 Length);
326
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();
335
336 StackPtr = IoGetNextIrpStackLocation(Irp);
337 StackPtr->MajorFunction = IRP_MJ_SET_VOLUME_INFORMATION;
338 StackPtr->MinorFunction = 0;
339 StackPtr->Flags = 0;
340 StackPtr->Control = 0;
341 StackPtr->DeviceObject = DeviceObject;
342 StackPtr->FileObject = FileObject;
343 StackPtr->Parameters.SetVolume.Length = Length;
344 StackPtr->Parameters.SetVolume.FsInformationClass =
345 FsInformationClass;
346
347 Status = IoCallDriver(DeviceObject,Irp);
348 if (Status == STATUS_PENDING)
349 {
350 KeWaitForSingleObject(&FileObject->Event,
351 UserRequest,
352 PreviousMode,
353 FALSE,
354 NULL);
355 Status = IoStatusBlock->Status;
356 }
357
358 ExFreePool(SystemBuffer);
359
360 return(Status);
361 }
362
363
364 /*
365 * @implemented
366 */
367 VOID STDCALL
368 IoAcquireVpbSpinLock(OUT PKIRQL Irql)
369 {
370 KeAcquireSpinLock(&IoVpbLock,
371 Irql);
372 }
373
374
375 /*
376 * @implemented
377 */
378 VOID STDCALL
379 IoReleaseVpbSpinLock(IN KIRQL Irql)
380 {
381 KeReleaseSpinLock(&IoVpbLock,
382 Irql);
383 }
384
385 /* EOF */