[FASTFAT] Fix size checking in VfatGetFileNameInformation()
[reactos.git] / drivers / filesystems / fastfat / blockdev.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/fs/vfat/blockdev.c
5 * PURPOSE: Temporary sector reading support
6 * PROGRAMMER: David Welch (welch@cwcom.net)
7 * UPDATE HISTORY:
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include "vfat.h"
13
14 #define NDEBUG
15 #include <debug.h>
16
17 /* FUNCTIONS ***************************************************************/
18
19 static IO_COMPLETION_ROUTINE VfatReadWritePartialCompletion;
20
21 static
22 NTSTATUS
23 NTAPI
24 VfatReadWritePartialCompletion(
25 IN PDEVICE_OBJECT DeviceObject,
26 IN PIRP Irp,
27 IN PVOID Context)
28 {
29 PVFAT_IRP_CONTEXT IrpContext;
30 PMDL Mdl;
31
32 UNREFERENCED_PARAMETER(DeviceObject);
33
34 DPRINT("VfatReadWritePartialCompletion() called\n");
35
36 IrpContext = (PVFAT_IRP_CONTEXT)Context;
37
38 while ((Mdl = Irp->MdlAddress))
39 {
40 Irp->MdlAddress = Mdl->Next;
41 IoFreeMdl(Mdl);
42 }
43
44 if (Irp->PendingReturned)
45 {
46 IrpContext->Flags |= IRPCONTEXT_PENDINGRETURNED;
47 }
48 else
49 {
50 IrpContext->Flags &= ~IRPCONTEXT_PENDINGRETURNED;
51 }
52
53 if (!NT_SUCCESS(Irp->IoStatus.Status))
54 {
55 IrpContext->Irp->IoStatus.Status = Irp->IoStatus.Status;
56 }
57
58 if (0 == InterlockedDecrement((PLONG)&IrpContext->RefCount) &&
59 BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_PENDINGRETURNED))
60 {
61 KeSetEvent(&IrpContext->Event, IO_NO_INCREMENT, FALSE);
62 }
63
64 IoFreeIrp(Irp);
65
66 DPRINT("VfatReadWritePartialCompletion() done\n");
67
68 return STATUS_MORE_PROCESSING_REQUIRED;
69 }
70
71 NTSTATUS
72 VfatReadDisk(
73 IN PDEVICE_OBJECT pDeviceObject,
74 IN PLARGE_INTEGER ReadOffset,
75 IN ULONG ReadLength,
76 IN OUT PUCHAR Buffer,
77 IN BOOLEAN Override)
78 {
79 PIO_STACK_LOCATION Stack;
80 PIRP Irp;
81 IO_STATUS_BLOCK IoStatus;
82 KEVENT Event;
83 NTSTATUS Status;
84
85 again:
86 KeInitializeEvent(&Event, NotificationEvent, FALSE);
87
88 DPRINT("VfatReadDisk(pDeviceObject %p, Offset %I64x, Length %u, Buffer %p)\n",
89 pDeviceObject, ReadOffset->QuadPart, ReadLength, Buffer);
90
91 DPRINT ("Building synchronous FSD Request...\n");
92 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
93 pDeviceObject,
94 Buffer,
95 ReadLength,
96 ReadOffset,
97 &Event,
98 &IoStatus);
99 if (Irp == NULL)
100 {
101 DPRINT("IoBuildSynchronousFsdRequest failed\n");
102 return STATUS_UNSUCCESSFUL;
103 }
104
105 if (Override)
106 {
107 Stack = IoGetNextIrpStackLocation(Irp);
108 Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
109 }
110
111 DPRINT("Calling IO Driver... with irp %p\n", Irp);
112 Status = IoCallDriver (pDeviceObject, Irp);
113
114 DPRINT("Waiting for IO Operation for %p\n", Irp);
115 if (Status == STATUS_PENDING)
116 {
117 DPRINT("Operation pending\n");
118 KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
119 DPRINT("Getting IO Status... for %p\n", Irp);
120 Status = IoStatus.Status;
121 }
122
123 if (Status == STATUS_VERIFY_REQUIRED)
124 {
125 PDEVICE_OBJECT DeviceToVerify;
126
127 DPRINT1 ("Media change detected!\n");
128
129 /* Find the device to verify and reset the thread field to empty value again. */
130 DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread());
131 IoSetDeviceToVerify(PsGetCurrentThread(), NULL);
132 Status = IoVerifyVolume(DeviceToVerify,
133 FALSE);
134 if (NT_SUCCESS(Status))
135 {
136 DPRINT1("Volume verification successful; Reissuing read request\n");
137 goto again;
138 }
139 }
140
141 if (!NT_SUCCESS(Status))
142 {
143 DPRINT("IO failed!!! VfatReadDisk : Error code: %x\n", Status);
144 DPRINT("(pDeviceObject %p, Offset %I64x, Size %u, Buffer %p\n",
145 pDeviceObject, ReadOffset->QuadPart, ReadLength, Buffer);
146 return Status;
147 }
148 DPRINT("Block request succeeded for %p\n", Irp);
149 return STATUS_SUCCESS;
150 }
151
152 NTSTATUS
153 VfatReadDiskPartial(
154 IN PVFAT_IRP_CONTEXT IrpContext,
155 IN PLARGE_INTEGER ReadOffset,
156 IN ULONG ReadLength,
157 ULONG BufferOffset,
158 IN BOOLEAN Wait)
159 {
160 PIRP Irp;
161 PIO_STACK_LOCATION StackPtr;
162 NTSTATUS Status;
163 PVOID Buffer;
164
165 DPRINT("VfatReadDiskPartial(IrpContext %p, ReadOffset %I64x, ReadLength %u, BufferOffset %u, Wait %u)\n",
166 IrpContext, ReadOffset->QuadPart, ReadLength, BufferOffset, Wait);
167
168 DPRINT("Building asynchronous FSD Request...\n");
169
170 Buffer = (PCHAR)MmGetMdlVirtualAddress(IrpContext->Irp->MdlAddress) + BufferOffset;
171
172 again:
173 Irp = IoAllocateIrp(IrpContext->DeviceExt->StorageDevice->StackSize, TRUE);
174 if (Irp == NULL)
175 {
176 DPRINT("IoAllocateIrp failed\n");
177 return STATUS_UNSUCCESSFUL;
178 }
179
180 Irp->UserIosb = NULL;
181 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
182
183 StackPtr = IoGetNextIrpStackLocation(Irp);
184 StackPtr->MajorFunction = IRP_MJ_READ;
185 StackPtr->MinorFunction = 0;
186 StackPtr->Flags = 0;
187 StackPtr->Control = 0;
188 StackPtr->DeviceObject = IrpContext->DeviceExt->StorageDevice;
189 StackPtr->FileObject = NULL;
190 StackPtr->CompletionRoutine = NULL;
191 StackPtr->Parameters.Read.Length = ReadLength;
192 StackPtr->Parameters.Read.ByteOffset = *ReadOffset;
193
194 if (!IoAllocateMdl(Buffer, ReadLength, FALSE, FALSE, Irp))
195 {
196 DPRINT("IoAllocateMdl failed\n");
197 IoFreeIrp(Irp);
198 return STATUS_UNSUCCESSFUL;
199 }
200
201 IoBuildPartialMdl(IrpContext->Irp->MdlAddress, Irp->MdlAddress, Buffer, ReadLength);
202
203 IoSetCompletionRoutine(Irp,
204 VfatReadWritePartialCompletion,
205 IrpContext,
206 TRUE,
207 TRUE,
208 TRUE);
209
210 if (Wait)
211 {
212 KeInitializeEvent(&IrpContext->Event, NotificationEvent, FALSE);
213 IrpContext->RefCount = 1;
214 }
215 else
216 {
217 InterlockedIncrement((PLONG)&IrpContext->RefCount);
218 }
219
220 DPRINT("Calling IO Driver... with irp %p\n", Irp);
221 Status = IoCallDriver(IrpContext->DeviceExt->StorageDevice, Irp);
222
223 if (Wait && Status == STATUS_PENDING)
224 {
225 KeWaitForSingleObject(&IrpContext->Event, Executive, KernelMode, FALSE, NULL);
226 Status = IrpContext->Irp->IoStatus.Status;
227 }
228
229 if (Status == STATUS_VERIFY_REQUIRED)
230 {
231 PDEVICE_OBJECT DeviceToVerify;
232
233 DPRINT1("Media change detected!\n");
234
235 /* Find the device to verify and reset the thread field to empty value again. */
236 DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread());
237 IoSetDeviceToVerify(PsGetCurrentThread(), NULL);
238 Status = IoVerifyVolume(DeviceToVerify,
239 FALSE);
240 if (NT_SUCCESS(Status))
241 {
242 DPRINT1("Volume verification successful; Reissuing read request\n");
243 goto again;
244 }
245 }
246
247 DPRINT("%x\n", Status);
248 return Status;
249 }
250
251
252 NTSTATUS
253 VfatWriteDiskPartial(
254 IN PVFAT_IRP_CONTEXT IrpContext,
255 IN PLARGE_INTEGER WriteOffset,
256 IN ULONG WriteLength,
257 IN ULONG BufferOffset,
258 IN BOOLEAN Wait)
259 {
260 PIRP Irp;
261 PIO_STACK_LOCATION StackPtr;
262 NTSTATUS Status;
263 PVOID Buffer;
264
265 DPRINT("VfatWriteDiskPartial(IrpContext %p, WriteOffset %I64x, WriteLength %u, BufferOffset %x, Wait %u)\n",
266 IrpContext, WriteOffset->QuadPart, WriteLength, BufferOffset, Wait);
267
268 Buffer = (PCHAR)MmGetMdlVirtualAddress(IrpContext->Irp->MdlAddress) + BufferOffset;
269
270 again:
271 DPRINT("Building asynchronous FSD Request...\n");
272 Irp = IoAllocateIrp(IrpContext->DeviceExt->StorageDevice->StackSize, TRUE);
273 if (Irp == NULL)
274 {
275 DPRINT("IoAllocateIrp failed\n");
276 return STATUS_UNSUCCESSFUL;
277 }
278
279 Irp->UserIosb = NULL;
280 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
281
282 StackPtr = IoGetNextIrpStackLocation(Irp);
283 StackPtr->MajorFunction = IRP_MJ_WRITE;
284 StackPtr->MinorFunction = 0;
285 StackPtr->Flags = 0;
286 StackPtr->Control = 0;
287 StackPtr->DeviceObject = IrpContext->DeviceExt->StorageDevice;
288 StackPtr->FileObject = NULL;
289 StackPtr->CompletionRoutine = NULL;
290 StackPtr->Parameters.Read.Length = WriteLength;
291 StackPtr->Parameters.Read.ByteOffset = *WriteOffset;
292
293 if (!IoAllocateMdl(Buffer, WriteLength, FALSE, FALSE, Irp))
294 {
295 DPRINT("IoAllocateMdl failed\n");
296 IoFreeIrp(Irp);
297 return STATUS_UNSUCCESSFUL;
298 }
299
300 IoBuildPartialMdl(IrpContext->Irp->MdlAddress, Irp->MdlAddress, Buffer, WriteLength);
301
302 IoSetCompletionRoutine(Irp,
303 VfatReadWritePartialCompletion,
304 IrpContext,
305 TRUE,
306 TRUE,
307 TRUE);
308
309 if (Wait)
310 {
311 KeInitializeEvent(&IrpContext->Event, NotificationEvent, FALSE);
312 IrpContext->RefCount = 1;
313 }
314 else
315 {
316 InterlockedIncrement((PLONG)&IrpContext->RefCount);
317 }
318
319 DPRINT("Calling IO Driver...\n");
320 Status = IoCallDriver(IrpContext->DeviceExt->StorageDevice, Irp);
321 if (Wait && Status == STATUS_PENDING)
322 {
323 KeWaitForSingleObject(&IrpContext->Event, Executive, KernelMode, FALSE, NULL);
324 Status = IrpContext->Irp->IoStatus.Status;
325 }
326
327 if (Status == STATUS_VERIFY_REQUIRED)
328 {
329 PDEVICE_OBJECT DeviceToVerify;
330
331 DPRINT1("Media change detected!\n");
332
333 /* Find the device to verify and reset the thread field to empty value again. */
334 DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread());
335 IoSetDeviceToVerify(PsGetCurrentThread(), NULL);
336 Status = IoVerifyVolume(DeviceToVerify,
337 FALSE);
338 if (NT_SUCCESS(Status))
339 {
340 DPRINT1("Volume verification successful; Reissuing write request\n");
341 goto again;
342 }
343 }
344
345 return Status;
346 }
347
348 NTSTATUS
349 VfatBlockDeviceIoControl(
350 IN PDEVICE_OBJECT DeviceObject,
351 IN ULONG CtlCode,
352 IN PVOID InputBuffer OPTIONAL,
353 IN ULONG InputBufferSize,
354 IN OUT PVOID OutputBuffer OPTIONAL,
355 IN OUT PULONG OutputBufferSize,
356 IN BOOLEAN Override)
357 {
358 PIO_STACK_LOCATION Stack;
359 KEVENT Event;
360 PIRP Irp;
361 IO_STATUS_BLOCK IoStatus;
362 NTSTATUS Status;
363
364 DPRINT("VfatBlockDeviceIoControl(DeviceObject %p, CtlCode %x, "
365 "InputBuffer %p, InputBufferSize %x, OutputBuffer %p, "
366 "OutputBufferSize %p (%x)\n", DeviceObject, CtlCode,
367 InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize,
368 OutputBufferSize ? *OutputBufferSize : 0);
369
370 again:
371 KeInitializeEvent(&Event, NotificationEvent, FALSE);
372
373 DPRINT("Building device I/O control request ...\n");
374 Irp = IoBuildDeviceIoControlRequest(CtlCode,
375 DeviceObject,
376 InputBuffer,
377 InputBufferSize,
378 OutputBuffer,
379 (OutputBufferSize) ? *OutputBufferSize : 0,
380 FALSE,
381 &Event,
382 &IoStatus);
383 if (Irp == NULL)
384 {
385 DPRINT("IoBuildDeviceIoControlRequest failed\n");
386 return STATUS_INSUFFICIENT_RESOURCES;
387 }
388
389 if (Override)
390 {
391 Stack = IoGetNextIrpStackLocation(Irp);
392 Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
393 }
394
395 DPRINT("Calling IO Driver... with irp %p\n", Irp);
396 Status = IoCallDriver(DeviceObject, Irp);
397
398 DPRINT("Waiting for IO Operation for %p\n", Irp);
399 if (Status == STATUS_PENDING)
400 {
401 DPRINT("Operation pending\n");
402 KeWaitForSingleObject (&Event, Suspended, KernelMode, FALSE, NULL);
403 DPRINT("Getting IO Status... for %p\n", Irp);
404
405 Status = IoStatus.Status;
406 }
407
408 if (Status == STATUS_VERIFY_REQUIRED)
409 {
410 PDEVICE_OBJECT DeviceToVerify;
411
412 DPRINT1("Media change detected!\n");
413
414 /* Find the device to verify and reset the thread field to empty value again. */
415 DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread());
416 IoSetDeviceToVerify(PsGetCurrentThread(), NULL);
417 Status = IoVerifyVolume(DeviceToVerify,
418 FALSE);
419
420 if (NT_SUCCESS(Status))
421 {
422 DPRINT1("Volume verification successful; Reissuing IOCTL request\n");
423 goto again;
424 }
425 }
426
427 if (OutputBufferSize)
428 {
429 *OutputBufferSize = IoStatus.Information;
430 }
431
432 DPRINT("Returning Status %x\n", Status);
433
434 return Status;
435 }