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)
10 /* INCLUDES *****************************************************************/
17 /* FUNCTIONS ***************************************************************/
19 static IO_COMPLETION_ROUTINE VfatReadWritePartialCompletion
;
24 VfatReadWritePartialCompletion(
25 IN PDEVICE_OBJECT DeviceObject
,
29 PVFAT_IRP_CONTEXT IrpContext
;
32 UNREFERENCED_PARAMETER(DeviceObject
);
34 DPRINT("VfatReadWritePartialCompletion() called\n");
36 IrpContext
= (PVFAT_IRP_CONTEXT
)Context
;
38 while ((Mdl
= Irp
->MdlAddress
))
40 Irp
->MdlAddress
= Mdl
->Next
;
44 if (Irp
->PendingReturned
)
46 IrpContext
->Flags
|= IRPCONTEXT_PENDINGRETURNED
;
50 IrpContext
->Flags
&= ~IRPCONTEXT_PENDINGRETURNED
;
53 if (!NT_SUCCESS(Irp
->IoStatus
.Status
))
55 IrpContext
->Irp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
58 if (0 == InterlockedDecrement((PLONG
)&IrpContext
->RefCount
) &&
59 BooleanFlagOn(IrpContext
->Flags
, IRPCONTEXT_PENDINGRETURNED
))
61 KeSetEvent(&IrpContext
->Event
, IO_NO_INCREMENT
, FALSE
);
66 DPRINT("VfatReadWritePartialCompletion() done\n");
68 return STATUS_MORE_PROCESSING_REQUIRED
;
73 IN PDEVICE_OBJECT pDeviceObject
,
74 IN PLARGE_INTEGER ReadOffset
,
79 PIO_STACK_LOCATION Stack
;
81 IO_STATUS_BLOCK IoStatus
;
86 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
88 DPRINT("VfatReadDisk(pDeviceObject %p, Offset %I64x, Length %u, Buffer %p)\n",
89 pDeviceObject
, ReadOffset
->QuadPart
, ReadLength
, Buffer
);
91 DPRINT ("Building synchronous FSD Request...\n");
92 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
101 DPRINT("IoBuildSynchronousFsdRequest failed\n");
102 return STATUS_UNSUCCESSFUL
;
107 Stack
= IoGetNextIrpStackLocation(Irp
);
108 Stack
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
111 DPRINT("Calling IO Driver... with irp %p\n", Irp
);
112 Status
= IoCallDriver (pDeviceObject
, Irp
);
114 DPRINT("Waiting for IO Operation for %p\n", Irp
);
115 if (Status
== STATUS_PENDING
)
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
;
123 if (Status
== STATUS_VERIFY_REQUIRED
)
125 PDEVICE_OBJECT DeviceToVerify
;
127 DPRINT1 ("Media change detected!\n");
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
,
134 if (NT_SUCCESS(Status
))
136 DPRINT1("Volume verification successful; Reissuing read request\n");
141 if (!NT_SUCCESS(Status
))
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
);
148 DPRINT("Block request succeeded for %p\n", Irp
);
149 return STATUS_SUCCESS
;
154 IN PVFAT_IRP_CONTEXT IrpContext
,
155 IN PLARGE_INTEGER ReadOffset
,
161 PIO_STACK_LOCATION StackPtr
;
165 DPRINT("VfatReadDiskPartial(IrpContext %p, ReadOffset %I64x, ReadLength %u, BufferOffset %u, Wait %u)\n",
166 IrpContext
, ReadOffset
->QuadPart
, ReadLength
, BufferOffset
, Wait
);
168 DPRINT("Building asynchronous FSD Request...\n");
170 Buffer
= (PCHAR
)MmGetMdlVirtualAddress(IrpContext
->Irp
->MdlAddress
) + BufferOffset
;
173 Irp
= IoAllocateIrp(IrpContext
->DeviceExt
->StorageDevice
->StackSize
, TRUE
);
176 DPRINT("IoAllocateIrp failed\n");
177 return STATUS_UNSUCCESSFUL
;
180 Irp
->UserIosb
= NULL
;
181 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
183 StackPtr
= IoGetNextIrpStackLocation(Irp
);
184 StackPtr
->MajorFunction
= IRP_MJ_READ
;
185 StackPtr
->MinorFunction
= 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
;
194 if (!IoAllocateMdl(Buffer
, ReadLength
, FALSE
, FALSE
, Irp
))
196 DPRINT("IoAllocateMdl failed\n");
198 return STATUS_UNSUCCESSFUL
;
201 IoBuildPartialMdl(IrpContext
->Irp
->MdlAddress
, Irp
->MdlAddress
, Buffer
, ReadLength
);
203 IoSetCompletionRoutine(Irp
,
204 VfatReadWritePartialCompletion
,
212 KeInitializeEvent(&IrpContext
->Event
, NotificationEvent
, FALSE
);
213 IrpContext
->RefCount
= 1;
217 InterlockedIncrement((PLONG
)&IrpContext
->RefCount
);
220 DPRINT("Calling IO Driver... with irp %p\n", Irp
);
221 Status
= IoCallDriver(IrpContext
->DeviceExt
->StorageDevice
, Irp
);
223 if (Wait
&& Status
== STATUS_PENDING
)
225 KeWaitForSingleObject(&IrpContext
->Event
, Executive
, KernelMode
, FALSE
, NULL
);
226 Status
= IrpContext
->Irp
->IoStatus
.Status
;
229 if (Status
== STATUS_VERIFY_REQUIRED
)
231 PDEVICE_OBJECT DeviceToVerify
;
233 DPRINT1("Media change detected!\n");
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
,
240 if (NT_SUCCESS(Status
))
242 DPRINT1("Volume verification successful; Reissuing read request\n");
247 DPRINT("%x\n", Status
);
253 VfatWriteDiskPartial(
254 IN PVFAT_IRP_CONTEXT IrpContext
,
255 IN PLARGE_INTEGER WriteOffset
,
256 IN ULONG WriteLength
,
257 IN ULONG BufferOffset
,
261 PIO_STACK_LOCATION StackPtr
;
265 DPRINT("VfatWriteDiskPartial(IrpContext %p, WriteOffset %I64x, WriteLength %u, BufferOffset %x, Wait %u)\n",
266 IrpContext
, WriteOffset
->QuadPart
, WriteLength
, BufferOffset
, Wait
);
268 Buffer
= (PCHAR
)MmGetMdlVirtualAddress(IrpContext
->Irp
->MdlAddress
) + BufferOffset
;
271 DPRINT("Building asynchronous FSD Request...\n");
272 Irp
= IoAllocateIrp(IrpContext
->DeviceExt
->StorageDevice
->StackSize
, TRUE
);
275 DPRINT("IoAllocateIrp failed\n");
276 return STATUS_UNSUCCESSFUL
;
279 Irp
->UserIosb
= NULL
;
280 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
282 StackPtr
= IoGetNextIrpStackLocation(Irp
);
283 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
284 StackPtr
->MinorFunction
= 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
;
293 if (!IoAllocateMdl(Buffer
, WriteLength
, FALSE
, FALSE
, Irp
))
295 DPRINT("IoAllocateMdl failed\n");
297 return STATUS_UNSUCCESSFUL
;
300 IoBuildPartialMdl(IrpContext
->Irp
->MdlAddress
, Irp
->MdlAddress
, Buffer
, WriteLength
);
302 IoSetCompletionRoutine(Irp
,
303 VfatReadWritePartialCompletion
,
311 KeInitializeEvent(&IrpContext
->Event
, NotificationEvent
, FALSE
);
312 IrpContext
->RefCount
= 1;
316 InterlockedIncrement((PLONG
)&IrpContext
->RefCount
);
319 DPRINT("Calling IO Driver...\n");
320 Status
= IoCallDriver(IrpContext
->DeviceExt
->StorageDevice
, Irp
);
321 if (Wait
&& Status
== STATUS_PENDING
)
323 KeWaitForSingleObject(&IrpContext
->Event
, Executive
, KernelMode
, FALSE
, NULL
);
324 Status
= IrpContext
->Irp
->IoStatus
.Status
;
327 if (Status
== STATUS_VERIFY_REQUIRED
)
329 PDEVICE_OBJECT DeviceToVerify
;
331 DPRINT1("Media change detected!\n");
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
,
338 if (NT_SUCCESS(Status
))
340 DPRINT1("Volume verification successful; Reissuing write request\n");
349 VfatBlockDeviceIoControl(
350 IN PDEVICE_OBJECT DeviceObject
,
352 IN PVOID InputBuffer OPTIONAL
,
353 IN ULONG InputBufferSize
,
354 IN OUT PVOID OutputBuffer OPTIONAL
,
355 IN OUT PULONG OutputBufferSize
,
358 PIO_STACK_LOCATION Stack
;
361 IO_STATUS_BLOCK IoStatus
;
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);
371 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
373 DPRINT("Building device I/O control request ...\n");
374 Irp
= IoBuildDeviceIoControlRequest(CtlCode
,
379 (OutputBufferSize
) ? *OutputBufferSize
: 0,
385 DPRINT("IoBuildDeviceIoControlRequest failed\n");
386 return STATUS_INSUFFICIENT_RESOURCES
;
391 Stack
= IoGetNextIrpStackLocation(Irp
);
392 Stack
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
395 DPRINT("Calling IO Driver... with irp %p\n", Irp
);
396 Status
= IoCallDriver(DeviceObject
, Irp
);
398 DPRINT("Waiting for IO Operation for %p\n", Irp
);
399 if (Status
== STATUS_PENDING
)
401 DPRINT("Operation pending\n");
402 KeWaitForSingleObject (&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
403 DPRINT("Getting IO Status... for %p\n", Irp
);
405 Status
= IoStatus
.Status
;
408 if (Status
== STATUS_VERIFY_REQUIRED
)
410 PDEVICE_OBJECT DeviceToVerify
;
412 DPRINT1("Media change detected!\n");
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
,
420 if (NT_SUCCESS(Status
))
422 DPRINT1("Volume verification successful; Reissuing IOCTL request\n");
427 if (OutputBufferSize
)
429 *OutputBufferSize
= IoStatus
.Information
;
432 DPRINT("Returning Status %x\n", Status
);