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