09b7ab830b17b719fbeb64e35fa08150e0ecdce5
[reactos.git] / 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 <ddk/ntddk.h>
15 #include <internal/io.h>
16 #include <internal/mm.h>
17 #include <internal/pool.h>
18
19
20 #define NDEBUG
21 #include <internal/debug.h>
22
23 /* GLOBALS *******************************************************************/
24
25 static KSPIN_LOCK IoVpbLock;
26
27 #define TAG_VPB    TAG('V', 'P', 'B', ' ')
28 #define TAG_SYSB   TAG('S', 'Y', 'S', 'B')
29
30 /* FUNCTIONS *****************************************************************/
31
32 VOID
33 IoInitVpbImplementation(VOID)
34 {
35    KeInitializeSpinLock(&IoVpbLock);
36 }
37
38 NTSTATUS
39 IoAttachVpb(PDEVICE_OBJECT DeviceObject)
40 {
41    PVPB Vpb;
42    
43    Vpb = ExAllocatePoolWithTag(NonPagedPool,
44                                sizeof(VPB),
45                                TAG_VPB);
46    if (Vpb == NULL)
47      {
48         return(STATUS_UNSUCCESSFUL);
49      }
50    
51    Vpb->Type = 0;
52    Vpb->Size = sizeof(VPB) / sizeof(DWORD);
53    Vpb->Flags = 0;
54    Vpb->VolumeLabelLength = 0;
55    Vpb->DeviceObject = NULL;
56    Vpb->RealDevice = DeviceObject;
57    Vpb->SerialNumber = 0;
58    Vpb->ReferenceCount = 0;
59    RtlZeroMemory(Vpb->VolumeLabel,
60                  sizeof(WCHAR) * MAXIMUM_VOLUME_LABEL_LENGTH);
61    
62    DeviceObject->Vpb = Vpb;
63    
64    return(STATUS_SUCCESS);
65 }
66
67 #ifndef LIBCAPTIVE
68
69 NTSTATUS STDCALL
70 NtQueryVolumeInformationFile(IN HANDLE FileHandle,
71                              OUT PIO_STATUS_BLOCK IoStatusBlock,
72                              OUT PVOID FsInformation,
73                              IN ULONG Length,
74                              IN FS_INFORMATION_CLASS FsInformationClass)
75
76 /*
77  * FUNCTION: Queries the volume information
78  * ARGUMENTS: 
79  *        FileHandle  = Handle to a file object on the target volume
80  *        ReturnLength = DataWritten
81  *        FsInformation = Caller should supply storage for the information 
82  *                        structure.
83  *        Length = Size of the information structure
84  *        FsInformationClass = Index to a information structure
85  *
86  *              FileFsVolumeInformation         FILE_FS_VOLUME_INFORMATION
87  *              FileFsLabelInformation          FILE_FS_LABEL_INFORMATION
88  *              FileFsSizeInformation           FILE_FS_SIZE_INFORMATION
89  *              FileFsDeviceInformation         FILE_FS_DEVICE_INFORMATION
90  *              FileFsAttributeInformation      FILE_FS_ATTRIBUTE_INFORMATION
91  *              FileFsControlInformation        
92  *              FileFsQuotaQueryInformation     --
93  *              FileFsQuotaSetInformation       --
94  *              FileFsMaximumInformation        
95  *
96  * RETURNS: Status
97  */
98 {
99    PFILE_OBJECT FileObject;
100    PDEVICE_OBJECT DeviceObject;
101    PIRP Irp;
102    NTSTATUS Status;
103    PIO_STACK_LOCATION StackPtr;
104    PVOID SystemBuffer;
105    IO_STATUS_BLOCK IoSB;
106    
107    assert(IoStatusBlock != NULL);
108    assert(FsInformation != NULL);
109    
110    DPRINT("FsInformation %p\n", FsInformation);
111    
112    Status = ObReferenceObjectByHandle(FileHandle,
113                                       FILE_READ_ATTRIBUTES,
114                                       IoFileObjectType,
115                                       UserMode,
116                                       (PVOID*)&FileObject,
117                                       NULL);
118    if (!NT_SUCCESS(Status))
119      {
120         return(Status);
121      }
122    
123    DeviceObject = FileObject->DeviceObject;
124    
125    Irp = IoAllocateIrp(DeviceObject->StackSize,
126                        TRUE);
127    if (Irp == NULL)
128      {
129         ObDereferenceObject(FileObject);
130         return(STATUS_INSUFFICIENT_RESOURCES);
131      }
132    
133    SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
134                                         Length,
135                                         TAG_SYSB);
136    if (SystemBuffer == NULL)
137      {
138         IoFreeIrp(Irp);
139         ObDereferenceObject(FileObject);
140         return(STATUS_INSUFFICIENT_RESOURCES);
141      }
142    
143    Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
144    KeResetEvent( &FileObject->Event );
145    Irp->UserEvent = &FileObject->Event;
146    Irp->UserIosb = &IoSB;
147    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
148    
149    StackPtr = IoGetNextIrpStackLocation(Irp);
150    StackPtr->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION;
151    StackPtr->MinorFunction = 0;
152    StackPtr->Flags = 0;
153    StackPtr->Control = 0;
154    StackPtr->DeviceObject = DeviceObject;
155    StackPtr->FileObject = FileObject;
156    StackPtr->Parameters.QueryVolume.Length = Length;
157    StackPtr->Parameters.QueryVolume.FsInformationClass =
158         FsInformationClass;
159    
160    Status = IoCallDriver(DeviceObject,
161                          Irp);
162    if (Status == STATUS_PENDING)
163      {
164         KeWaitForSingleObject(&FileObject->Event,
165                               UserRequest,
166                               KernelMode,
167                               FALSE,
168                               NULL);
169         Status = IoSB.Status;
170      }
171    DPRINT("Status %x\n", Status);
172    
173    if (NT_SUCCESS(Status))
174      {
175         DPRINT("Information %lu\n", IoStatusBlock->Information);
176         MmSafeCopyToUser(FsInformation,
177                          SystemBuffer,
178                          IoSB.Information);
179      }
180    if (IoStatusBlock)
181      {
182        *IoStatusBlock = IoSB;
183      }
184    ExFreePool(SystemBuffer);
185    
186    return(Status);
187 }
188
189
190 NTSTATUS STDCALL
191 IoQueryVolumeInformation(IN PFILE_OBJECT FileObject,
192                          IN FS_INFORMATION_CLASS FsInformationClass,
193                          IN ULONG Length,
194                          OUT PVOID FsInformation,
195                          OUT PULONG ReturnedLength)
196 {
197    IO_STATUS_BLOCK IoStatusBlock;
198    PIO_STACK_LOCATION StackPtr;
199    PDEVICE_OBJECT DeviceObject;
200    PIRP Irp;
201    NTSTATUS Status;
202    
203    assert(FsInformation != NULL);
204    
205    DPRINT("FsInformation %p\n", FsInformation);
206    
207    Status = ObReferenceObjectByPointer(FileObject,
208                                        FILE_READ_ATTRIBUTES,
209                                        IoFileObjectType,
210                                        KernelMode);
211    if (!NT_SUCCESS(Status))
212      {
213         return(Status);
214      }
215    
216    DeviceObject = FileObject->DeviceObject;
217    
218    Irp = IoAllocateIrp(DeviceObject->StackSize,
219                        TRUE);
220    if (Irp == NULL)
221      {
222         ObDereferenceObject(FileObject);
223         return(STATUS_INSUFFICIENT_RESOURCES);
224      }
225    
226    Irp->AssociatedIrp.SystemBuffer = FsInformation;
227    KeResetEvent( &FileObject->Event );
228    Irp->UserEvent = &FileObject->Event;
229    Irp->UserIosb = &IoStatusBlock;
230    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
231    
232    StackPtr = IoGetNextIrpStackLocation(Irp);
233    StackPtr->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION;
234    StackPtr->MinorFunction = 0;
235    StackPtr->Flags = 0;
236    StackPtr->Control = 0;
237    StackPtr->DeviceObject = DeviceObject;
238    StackPtr->FileObject = FileObject;
239    StackPtr->Parameters.QueryVolume.Length = Length;
240    StackPtr->Parameters.QueryVolume.FsInformationClass =
241         FsInformationClass;
242    
243    Status = IoCallDriver(DeviceObject,
244                          Irp);
245    if (Status == STATUS_PENDING)
246      {
247         KeWaitForSingleObject(&FileObject->Event,
248                               UserRequest,
249                               KernelMode,
250                               FALSE,
251                               NULL);
252         Status = IoStatusBlock.Status;
253      }
254    DPRINT("Status %x\n", Status);
255    
256    if (ReturnedLength != NULL)
257      {
258         *ReturnedLength = IoStatusBlock.Information;
259      }
260    
261    return(Status);
262 }
263
264
265 NTSTATUS STDCALL
266 NtSetVolumeInformationFile(IN HANDLE FileHandle,
267                            OUT PIO_STATUS_BLOCK IoStatusBlock,
268                            IN PVOID FsInformation,
269                            IN ULONG Length,
270                            IN FS_INFORMATION_CLASS FsInformationClass)
271 {
272    PFILE_OBJECT FileObject;
273    PDEVICE_OBJECT DeviceObject;
274    PIRP Irp;
275    NTSTATUS Status;
276    PIO_STACK_LOCATION StackPtr;
277    PVOID SystemBuffer;
278    IO_STATUS_BLOCK IoSB;
279    
280    Status = ObReferenceObjectByHandle(FileHandle,
281                                       FILE_WRITE_ATTRIBUTES,
282                                       NULL,
283                                       UserMode,
284                                       (PVOID*)&FileObject,
285                                       NULL);
286    if (Status != STATUS_SUCCESS)
287      {
288         return(Status);
289      }
290    
291    DeviceObject = FileObject->DeviceObject;
292    
293    Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE);
294    if (Irp == NULL)
295      {
296         ObDereferenceObject(FileObject);
297         return(STATUS_INSUFFICIENT_RESOURCES);
298      }
299    
300    SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
301                                         Length,
302                                         TAG_SYSB);
303    if (SystemBuffer == NULL)
304      {
305         IoFreeIrp(Irp);
306         ObDereferenceObject(FileObject);
307         return(STATUS_INSUFFICIENT_RESOURCES);
308      }
309    
310    MmSafeCopyFromUser(SystemBuffer,
311                       FsInformation,
312                       Length);
313    
314    Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
315    KeResetEvent( &FileObject->Event );
316    Irp->UserEvent = &FileObject->Event;
317    Irp->UserIosb = &IoSB;
318    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
319    
320    StackPtr = IoGetNextIrpStackLocation(Irp);
321    StackPtr->MajorFunction = IRP_MJ_SET_VOLUME_INFORMATION;
322    StackPtr->MinorFunction = 0;
323    StackPtr->Flags = 0;
324    StackPtr->Control = 0;
325    StackPtr->DeviceObject = DeviceObject;
326    StackPtr->FileObject = FileObject;
327    StackPtr->Parameters.SetVolume.Length = Length;
328    StackPtr->Parameters.SetVolume.FsInformationClass =
329         FsInformationClass;
330    
331    Status = IoCallDriver(DeviceObject,Irp);
332    if (Status == STATUS_PENDING)
333      {
334         KeWaitForSingleObject(&FileObject->Event,
335                               UserRequest,
336                               KernelMode,
337                               FALSE,
338                               NULL);
339         Status = IoSB.Status;
340      }
341    if (IoStatusBlock)
342    {
343      *IoStatusBlock = IoSB;
344    }
345    ExFreePool(SystemBuffer);
346    
347    return(Status);
348 }
349
350
351 VOID STDCALL
352 IoAcquireVpbSpinLock(OUT PKIRQL Irql)
353 {
354    KeAcquireSpinLock(&IoVpbLock,
355                      Irql);
356 }
357
358
359 VOID STDCALL
360 IoReleaseVpbSpinLock(IN KIRQL Irql)
361 {
362    KeReleaseSpinLock(&IoVpbLock,
363                      Irql);
364 }
365
366 #endif /* LIBCAPTIVE */
367
368 /* EOF */