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