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