Something went wrong. Try again.
Reactos
Something went wrong. Try again.
15 kB · 516 lines
C
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517/* * PROJECT: VFAT Filesystem * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * PURPOSE: Temporary sector reading support * COPYRIGHT: Copyright 1999-2001 David Welch <welch@cwcom.net> */
/* INCLUDES *****************************************************************/
#include "vfat.h"
#define NDEBUG#include <debug.h>
/* FUNCTIONS ***************************************************************/
static IO_COMPLETION_ROUTINE VfatReadWritePartialCompletion;
staticNTSTATUSNTAPIVfatReadWritePartialCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context){ PVFAT_IRP_CONTEXT IrpContext; PMDL Mdl;
UNREFERENCED_PARAMETER(DeviceObject);
DPRINT("VfatReadWritePartialCompletion() called\n");
IrpContext = (PVFAT_IRP_CONTEXT)Context;
while ((Mdl = Irp->MdlAddress)) { Irp->MdlAddress = Mdl->Next; IoFreeMdl(Mdl); }
if (Irp->PendingReturned) { IrpContext->Flags |= IRPCONTEXT_PENDINGRETURNED; } else { IrpContext->Flags &= ~IRPCONTEXT_PENDINGRETURNED; }
if (!NT_SUCCESS(Irp->IoStatus.Status)) { IrpContext->Irp->IoStatus.Status = Irp->IoStatus.Status; }
if (0 == InterlockedDecrement((PLONG)&IrpContext->RefCount) && BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_PENDINGRETURNED)) { KeSetEvent(&IrpContext->Event, IO_NO_INCREMENT, FALSE); }
IoFreeIrp(Irp);
DPRINT("VfatReadWritePartialCompletion() done\n");
return STATUS_MORE_PROCESSING_REQUIRED;}
NTSTATUSVfatReadDisk( IN PDEVICE_OBJECT pDeviceObject, IN PLARGE_INTEGER ReadOffset, IN ULONG ReadLength, IN OUT PUCHAR Buffer, IN BOOLEAN Override){ PIO_STACK_LOCATION Stack; PIRP Irp; IO_STATUS_BLOCK IoStatus; KEVENT Event; NTSTATUS Status;
again: KeInitializeEvent(&Event, NotificationEvent, FALSE);
DPRINT("VfatReadDisk(pDeviceObject %p, Offset %I64x, Length %u, Buffer %p)\n", pDeviceObject, ReadOffset->QuadPart, ReadLength, Buffer);
DPRINT ("Building synchronous FSD Request...\n"); Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, pDeviceObject, Buffer, ReadLength, ReadOffset, &Event, &IoStatus); if (Irp == NULL) { DPRINT("IoBuildSynchronousFsdRequest failed\n"); return STATUS_UNSUCCESSFUL; }
if (Override) { Stack = IoGetNextIrpStackLocation(Irp); Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME; }
DPRINT("Calling IO Driver... with irp %p\n", Irp); Status = IoCallDriver (pDeviceObject, Irp);
DPRINT("Waiting for IO Operation for %p\n", Irp); if (Status == STATUS_PENDING) { DPRINT("Operation pending\n"); KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); DPRINT("Getting IO Status... for %p\n", Irp); Status = IoStatus.Status; }
if (Status == STATUS_VERIFY_REQUIRED) { PDEVICE_OBJECT DeviceToVerify;
DPRINT1 ("Media change detected!\n");
/* Find the device to verify and reset the thread field to empty value again. */ DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread()); IoSetDeviceToVerify(PsGetCurrentThread(), NULL); Status = IoVerifyVolume(DeviceToVerify, FALSE); if (NT_SUCCESS(Status)) { DPRINT1("Volume verification successful; Reissuing read request\n"); goto again; } }
if (!NT_SUCCESS(Status)) { DPRINT("IO failed!!! VfatReadDisk : Error code: %x\n", Status); DPRINT("(pDeviceObject %p, Offset %I64x, Size %u, Buffer %p\n", pDeviceObject, ReadOffset->QuadPart, ReadLength, Buffer); return Status; } DPRINT("Block request succeeded for %p\n", Irp); return STATUS_SUCCESS;}
NTSTATUSVfatReadDiskPartial( IN PVFAT_IRP_CONTEXT IrpContext, IN PLARGE_INTEGER ReadOffset, IN ULONG ReadLength, ULONG BufferOffset, IN BOOLEAN Wait){ PIRP Irp; PIO_STACK_LOCATION StackPtr; NTSTATUS Status; PVOID Buffer;
DPRINT("VfatReadDiskPartial(IrpContext %p, ReadOffset %I64x, ReadLength %u, BufferOffset %u, Wait %u)\n", IrpContext, ReadOffset->QuadPart, ReadLength, BufferOffset, Wait);
DPRINT("Building asynchronous FSD Request...\n");
Buffer = (PCHAR)MmGetMdlVirtualAddress(IrpContext->Irp->MdlAddress) + BufferOffset;
again: Irp = IoAllocateIrp(IrpContext->DeviceExt->StorageDevice->StackSize, TRUE); if (Irp == NULL) { DPRINT("IoAllocateIrp failed\n"); return STATUS_UNSUCCESSFUL; }
Irp->UserIosb = NULL; Irp->Tail.Overlay.Thread = PsGetCurrentThread();
StackPtr = IoGetNextIrpStackLocation(Irp); StackPtr->MajorFunction = IRP_MJ_READ; StackPtr->MinorFunction = 0; StackPtr->Flags = 0; StackPtr->Control = 0; StackPtr->DeviceObject = IrpContext->DeviceExt->StorageDevice; StackPtr->FileObject = NULL; StackPtr->CompletionRoutine = NULL; StackPtr->Parameters.Read.Length = ReadLength; StackPtr->Parameters.Read.ByteOffset = *ReadOffset;
if (!IoAllocateMdl(Buffer, ReadLength, FALSE, FALSE, Irp)) { DPRINT("IoAllocateMdl failed\n"); IoFreeIrp(Irp); return STATUS_UNSUCCESSFUL; }
IoBuildPartialMdl(IrpContext->Irp->MdlAddress, Irp->MdlAddress, Buffer, ReadLength);
IoSetCompletionRoutine(Irp, VfatReadWritePartialCompletion, IrpContext, TRUE, TRUE, TRUE);
if (Wait) { KeInitializeEvent(&IrpContext->Event, NotificationEvent, FALSE); IrpContext->RefCount = 1; } else { InterlockedIncrement((PLONG)&IrpContext->RefCount); }
DPRINT("Calling IO Driver... with irp %p\n", Irp); Status = IoCallDriver(IrpContext->DeviceExt->StorageDevice, Irp);
if (Wait && Status == STATUS_PENDING) { KeWaitForSingleObject(&IrpContext->Event, Executive, KernelMode, FALSE, NULL); Status = IrpContext->Irp->IoStatus.Status; }
if (Status == STATUS_VERIFY_REQUIRED) { PDEVICE_OBJECT DeviceToVerify;
DPRINT1("Media change detected!\n");
/* Find the device to verify and reset the thread field to empty value again. */ DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread()); IoSetDeviceToVerify(PsGetCurrentThread(), NULL); Status = IoVerifyVolume(DeviceToVerify, FALSE); if (NT_SUCCESS(Status)) { DPRINT1("Volume verification successful; Reissuing read request\n"); goto again; } }
DPRINT("%x\n", Status); return Status;}
/* Used by dirty bit code, likely to be killed the day it's properly handle * This is just a copy paste from VfatReadDisk() */NTSTATUSVfatWriteDisk( IN PDEVICE_OBJECT pDeviceObject, IN PLARGE_INTEGER WriteOffset, IN ULONG WriteLength, IN OUT PUCHAR Buffer, IN BOOLEAN Override){ PIO_STACK_LOCATION Stack; PIRP Irp; IO_STATUS_BLOCK IoStatus; KEVENT Event; NTSTATUS Status;
again: KeInitializeEvent(&Event, NotificationEvent, FALSE);
DPRINT("VfatWriteDisk(pDeviceObject %p, Offset %I64x, Length %u, Buffer %p)\n", pDeviceObject, WriteOffset->QuadPart, WriteLength, Buffer);
DPRINT ("Building synchronous FSD Request...\n"); Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE, pDeviceObject, Buffer, WriteLength, WriteOffset, &Event, &IoStatus); if (Irp == NULL) { DPRINT("IoBuildSynchronousFsdRequest failed\n"); return STATUS_UNSUCCESSFUL; }
if (Override) { Stack = IoGetNextIrpStackLocation(Irp); Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME; }
DPRINT("Calling IO Driver... with irp %p\n", Irp); Status = IoCallDriver (pDeviceObject, Irp);
DPRINT("Waiting for IO Operation for %p\n", Irp); if (Status == STATUS_PENDING) { DPRINT("Operation pending\n"); KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); DPRINT("Getting IO Status... for %p\n", Irp); Status = IoStatus.Status; }
if (Status == STATUS_VERIFY_REQUIRED) { PDEVICE_OBJECT DeviceToVerify;
DPRINT1 ("Media change detected!\n");
/* Find the device to verify and reset the thread field to empty value again. */ DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread()); IoSetDeviceToVerify(PsGetCurrentThread(), NULL); Status = IoVerifyVolume(DeviceToVerify, FALSE); if (NT_SUCCESS(Status)) { DPRINT1("Volume verification successful; Reissuing write request\n"); goto again; } }
if (!NT_SUCCESS(Status)) { DPRINT("IO failed!!! VfatWriteDisk : Error code: %x\n", Status); DPRINT("(pDeviceObject %p, Offset %I64x, Size %u, Buffer %p\n", pDeviceObject, WriteOffset->QuadPart, WriteLength, Buffer); return Status; } DPRINT("Block request succeeded for %p\n", Irp); return STATUS_SUCCESS;}
NTSTATUSVfatWriteDiskPartial( IN PVFAT_IRP_CONTEXT IrpContext, IN PLARGE_INTEGER WriteOffset, IN ULONG WriteLength, IN ULONG BufferOffset, IN BOOLEAN Wait){ PIRP Irp; PIO_STACK_LOCATION StackPtr; NTSTATUS Status; PVOID Buffer;
DPRINT("VfatWriteDiskPartial(IrpContext %p, WriteOffset %I64x, WriteLength %u, BufferOffset %x, Wait %u)\n", IrpContext, WriteOffset->QuadPart, WriteLength, BufferOffset, Wait);
Buffer = (PCHAR)MmGetMdlVirtualAddress(IrpContext->Irp->MdlAddress) + BufferOffset;
again: DPRINT("Building asynchronous FSD Request...\n"); Irp = IoAllocateIrp(IrpContext->DeviceExt->StorageDevice->StackSize, TRUE); if (Irp == NULL) { DPRINT("IoAllocateIrp failed\n"); return STATUS_UNSUCCESSFUL; }
Irp->UserIosb = NULL; Irp->Tail.Overlay.Thread = PsGetCurrentThread();
StackPtr = IoGetNextIrpStackLocation(Irp); StackPtr->MajorFunction = IRP_MJ_WRITE; StackPtr->MinorFunction = 0; StackPtr->Flags = 0; StackPtr->Control = 0; StackPtr->DeviceObject = IrpContext->DeviceExt->StorageDevice; StackPtr->FileObject = NULL; StackPtr->CompletionRoutine = NULL; StackPtr->Parameters.Read.Length = WriteLength; StackPtr->Parameters.Read.ByteOffset = *WriteOffset;
if (!IoAllocateMdl(Buffer, WriteLength, FALSE, FALSE, Irp)) { DPRINT("IoAllocateMdl failed\n"); IoFreeIrp(Irp); return STATUS_UNSUCCESSFUL; }
IoBuildPartialMdl(IrpContext->Irp->MdlAddress, Irp->MdlAddress, Buffer, WriteLength);
IoSetCompletionRoutine(Irp, VfatReadWritePartialCompletion, IrpContext, TRUE, TRUE, TRUE);
if (Wait) { KeInitializeEvent(&IrpContext->Event, NotificationEvent, FALSE); IrpContext->RefCount = 1; } else { InterlockedIncrement((PLONG)&IrpContext->RefCount); }
DPRINT("Calling IO Driver...\n"); Status = IoCallDriver(IrpContext->DeviceExt->StorageDevice, Irp); if (Wait && Status == STATUS_PENDING) { KeWaitForSingleObject(&IrpContext->Event, Executive, KernelMode, FALSE, NULL); Status = IrpContext->Irp->IoStatus.Status; }
if (Status == STATUS_VERIFY_REQUIRED) { PDEVICE_OBJECT DeviceToVerify;
DPRINT1("Media change detected!\n");
/* Find the device to verify and reset the thread field to empty value again. */ DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread()); IoSetDeviceToVerify(PsGetCurrentThread(), NULL); Status = IoVerifyVolume(DeviceToVerify, FALSE); if (NT_SUCCESS(Status)) { DPRINT1("Volume verification successful; Reissuing write request\n"); goto again; } }
return Status;}
NTSTATUSVfatBlockDeviceIoControl( IN PDEVICE_OBJECT DeviceObject, IN ULONG CtlCode, IN PVOID InputBuffer OPTIONAL, IN ULONG InputBufferSize, IN OUT PVOID OutputBuffer OPTIONAL, IN OUT PULONG OutputBufferSize, IN BOOLEAN Override){ PIO_STACK_LOCATION Stack; KEVENT Event; PIRP Irp; IO_STATUS_BLOCK IoStatus; NTSTATUS Status;
DPRINT("VfatBlockDeviceIoControl(DeviceObject %p, CtlCode %x, " "InputBuffer %p, InputBufferSize %x, OutputBuffer %p, " "OutputBufferSize %p (%x)\n", DeviceObject, CtlCode, InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize, OutputBufferSize ? *OutputBufferSize : 0);
again: KeInitializeEvent(&Event, NotificationEvent, FALSE);
DPRINT("Building device I/O control request ...\n"); Irp = IoBuildDeviceIoControlRequest(CtlCode, DeviceObject, InputBuffer, InputBufferSize, OutputBuffer, (OutputBufferSize) ? *OutputBufferSize : 0, FALSE, &Event, &IoStatus); if (Irp == NULL) { DPRINT("IoBuildDeviceIoControlRequest failed\n"); return STATUS_INSUFFICIENT_RESOURCES; }
if (Override) { Stack = IoGetNextIrpStackLocation(Irp); Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME; }
DPRINT("Calling IO Driver... with irp %p\n", Irp); Status = IoCallDriver(DeviceObject, Irp);
DPRINT("Waiting for IO Operation for %p\n", Irp); if (Status == STATUS_PENDING) { DPRINT("Operation pending\n"); KeWaitForSingleObject (&Event, Suspended, KernelMode, FALSE, NULL); DPRINT("Getting IO Status... for %p\n", Irp);
Status = IoStatus.Status; }
if (Status == STATUS_VERIFY_REQUIRED) { PDEVICE_OBJECT DeviceToVerify;
DPRINT1("Media change detected!\n");
/* Find the device to verify and reset the thread field to empty value again. */ DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread()); IoSetDeviceToVerify(PsGetCurrentThread(), NULL); Status = IoVerifyVolume(DeviceToVerify, FALSE);
if (NT_SUCCESS(Status)) { DPRINT1("Volume verification successful; Reissuing IOCTL request\n"); goto again; } }
if (OutputBufferSize) { *OutputBufferSize = IoStatus.Information; }
DPRINT("Returning Status %x\n", Status);
return Status;}