9dabe6d3f838000cccbf1b95e38e5cbbfccb60c9
[reactos.git] / reactos / ntoskrnl / io / vpb.c
1 /* $Id: vpb.c,v 1.13 2001/06/12 12:30:36 ekohl Exp $
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 KEVENT Event;
102 NTSTATUS Status;
103 PIO_STACK_LOCATION StackPtr;
104 PVOID SystemBuffer;
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 NULL,
114 UserMode,
115 (PVOID*)&FileObject,
116 NULL);
117 if (!NT_SUCCESS(Status))
118 {
119 return(Status);
120 }
121
122 DeviceObject = FileObject->DeviceObject;
123
124 KeInitializeEvent(&Event,
125 NotificationEvent,
126 FALSE);
127
128 Irp = IoAllocateIrp(DeviceObject->StackSize,
129 TRUE);
130 if (Irp == NULL)
131 {
132 ObDereferenceObject(FileObject);
133 return(STATUS_INSUFFICIENT_RESOURCES);
134 }
135
136 SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
137 Length,
138 TAG_SYSB);
139 if (SystemBuffer == NULL)
140 {
141 IoFreeIrp(Irp);
142 ObDereferenceObject(FileObject);
143 return(STATUS_INSUFFICIENT_RESOURCES);
144 }
145
146 Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
147 Irp->UserEvent = &Event;
148 Irp->UserIosb = IoStatusBlock;
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(&Event,
166 UserRequest,
167 KernelMode,
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 ExFreePool(SystemBuffer);
182 ObDereferenceObject(FileObject);
183
184 return(Status);
185 }
186
187
188 NTSTATUS STDCALL
189 IoQueryVolumeInformation(IN PFILE_OBJECT FileObject,
190 IN FS_INFORMATION_CLASS FsInformationClass,
191 IN ULONG Length,
192 OUT PVOID FsInformation,
193 OUT PULONG ReturnedLength)
194 {
195 IO_STATUS_BLOCK IoStatusBlock;
196 PIO_STACK_LOCATION StackPtr;
197 PDEVICE_OBJECT DeviceObject;
198 PIRP Irp;
199 KEVENT Event;
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 KeInitializeEvent(&Event,
218 NotificationEvent,
219 FALSE);
220
221 Irp = IoAllocateIrp(DeviceObject->StackSize,
222 TRUE);
223 if (Irp == NULL)
224 {
225 ObDereferenceObject(FileObject);
226 return(STATUS_INSUFFICIENT_RESOURCES);
227 }
228
229 Irp->AssociatedIrp.SystemBuffer = FsInformation;
230 Irp->UserEvent = &Event;
231 Irp->UserIosb = &IoStatusBlock;
232
233 StackPtr = IoGetNextIrpStackLocation(Irp);
234 StackPtr->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION;
235 StackPtr->MinorFunction = 0;
236 StackPtr->Flags = 0;
237 StackPtr->Control = 0;
238 StackPtr->DeviceObject = DeviceObject;
239 StackPtr->FileObject = FileObject;
240 StackPtr->Parameters.QueryVolume.Length = Length;
241 StackPtr->Parameters.QueryVolume.FsInformationClass =
242 FsInformationClass;
243
244 Status = IoCallDriver(DeviceObject,
245 Irp);
246 if (Status == STATUS_PENDING)
247 {
248 KeWaitForSingleObject(&Event,
249 UserRequest,
250 KernelMode,
251 FALSE,
252 NULL);
253 Status = IoStatusBlock.Status;
254 }
255 DPRINT("Status %x\n", Status);
256
257 if (ReturnedLength != NULL)
258 {
259 *ReturnedLength = IoStatusBlock.Information;
260 }
261 ObDereferenceObject(FileObject);
262
263 return(Status);
264 }
265
266
267 NTSTATUS STDCALL
268 NtSetVolumeInformationFile(IN HANDLE FileHandle,
269 OUT PIO_STATUS_BLOCK IoStatusBlock,
270 IN PVOID FsInformation,
271 IN ULONG Length,
272 IN FS_INFORMATION_CLASS FsInformationClass)
273 {
274 PFILE_OBJECT FileObject;
275 PDEVICE_OBJECT DeviceObject;
276 PIRP Irp;
277 KEVENT Event;
278 NTSTATUS Status;
279 PIO_STACK_LOCATION StackPtr;
280 PVOID SystemBuffer;
281
282 Status = ObReferenceObjectByHandle(FileHandle,
283 FILE_WRITE_ATTRIBUTES,
284 NULL,
285 UserMode,
286 (PVOID*)&FileObject,
287 NULL);
288 if (Status != STATUS_SUCCESS)
289 {
290 return(Status);
291 }
292
293 DeviceObject = FileObject->DeviceObject;
294
295 KeInitializeEvent(&Event,
296 NotificationEvent,
297 FALSE);
298
299 Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE);
300 if (Irp == NULL)
301 {
302 ObDereferenceObject(FileObject);
303 return(STATUS_INSUFFICIENT_RESOURCES);
304 }
305
306 SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
307 Length,
308 TAG_SYSB);
309 if (SystemBuffer == NULL)
310 {
311 IoFreeIrp(Irp);
312 ObDereferenceObject(FileObject);
313 return(STATUS_INSUFFICIENT_RESOURCES);
314 }
315
316 MmSafeCopyFromUser(SystemBuffer,
317 FsInformation,
318 Length);
319
320 Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
321 Irp->UserEvent = &Event;
322 Irp->UserIosb = IoStatusBlock;
323
324 StackPtr = IoGetNextIrpStackLocation(Irp);
325 StackPtr->MajorFunction = IRP_MJ_SET_VOLUME_INFORMATION;
326 StackPtr->MinorFunction = 0;
327 StackPtr->Flags = 0;
328 StackPtr->Control = 0;
329 StackPtr->DeviceObject = DeviceObject;
330 StackPtr->FileObject = FileObject;
331 StackPtr->Parameters.SetVolume.Length = Length;
332 StackPtr->Parameters.SetVolume.FsInformationClass =
333 FsInformationClass;
334
335 Status = IoCallDriver(DeviceObject,Irp);
336 if (Status == STATUS_PENDING)
337 {
338 KeWaitForSingleObject(&Event,
339 UserRequest,
340 KernelMode,
341 FALSE,
342 NULL);
343 }
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
367 NTSTATUS STDCALL
368 IoVerifyVolume(IN PDEVICE_OBJECT DeviceObject,
369 IN BOOLEAN AllowRawMount)
370 {
371 UNIMPLEMENTED;
372 return(STATUS_NOT_IMPLEMENTED);
373 }
374
375
376 /* EOF */