mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 19:22:58 +00:00
[FASTFAT]
Fix coding style and indentation. No code changes! svn path=/trunk/; revision=61252
This commit is contained in:
parent
5a02327fd0
commit
3f339ec7b9
15 changed files with 3195 additions and 3051 deletions
|
@ -15,410 +15,419 @@
|
||||||
/* FUNCTIONS ***************************************************************/
|
/* FUNCTIONS ***************************************************************/
|
||||||
|
|
||||||
static IO_COMPLETION_ROUTINE VfatReadWritePartialCompletion;
|
static IO_COMPLETION_ROUTINE VfatReadWritePartialCompletion;
|
||||||
static NTSTATUS NTAPI
|
|
||||||
VfatReadWritePartialCompletion (IN PDEVICE_OBJECT DeviceObject,
|
static
|
||||||
IN PIRP Irp,
|
NTSTATUS
|
||||||
IN PVOID Context)
|
NTAPI
|
||||||
|
VfatReadWritePartialCompletion(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PVOID Context)
|
||||||
{
|
{
|
||||||
PVFAT_IRP_CONTEXT IrpContext;
|
PVFAT_IRP_CONTEXT IrpContext;
|
||||||
PMDL Mdl;
|
PMDL Mdl;
|
||||||
|
|
||||||
UNREFERENCED_PARAMETER(DeviceObject);
|
UNREFERENCED_PARAMETER(DeviceObject);
|
||||||
|
|
||||||
DPRINT("VfatReadWritePartialCompletion() called\n");
|
DPRINT("VfatReadWritePartialCompletion() called\n");
|
||||||
|
|
||||||
IrpContext = (PVFAT_IRP_CONTEXT)Context;
|
IrpContext = (PVFAT_IRP_CONTEXT)Context;
|
||||||
|
|
||||||
while ((Mdl = Irp->MdlAddress))
|
while ((Mdl = Irp->MdlAddress))
|
||||||
{
|
{
|
||||||
Irp->MdlAddress = Mdl->Next;
|
Irp->MdlAddress = Mdl->Next;
|
||||||
IoFreeMdl(Mdl);
|
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) &&
|
|
||||||
IrpContext->Flags & IRPCONTEXT_PENDINGRETURNED)
|
|
||||||
{
|
|
||||||
KeSetEvent(&IrpContext->Event, IO_NO_INCREMENT, FALSE);
|
|
||||||
}
|
|
||||||
IoFreeIrp(Irp);
|
|
||||||
|
|
||||||
DPRINT("VfatReadWritePartialCompletion() done\n");
|
if (Irp->PendingReturned)
|
||||||
|
{
|
||||||
|
IrpContext->Flags |= IRPCONTEXT_PENDINGRETURNED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IrpContext->Flags &= ~IRPCONTEXT_PENDINGRETURNED;
|
||||||
|
}
|
||||||
|
|
||||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
if (!NT_SUCCESS(Irp->IoStatus.Status))
|
||||||
|
{
|
||||||
|
IrpContext->Irp->IoStatus.Status = Irp->IoStatus.Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == InterlockedDecrement((PLONG)&IrpContext->RefCount) &&
|
||||||
|
IrpContext->Flags & IRPCONTEXT_PENDINGRETURNED)
|
||||||
|
{
|
||||||
|
KeSetEvent(&IrpContext->Event, IO_NO_INCREMENT, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
IoFreeIrp(Irp);
|
||||||
|
|
||||||
|
DPRINT("VfatReadWritePartialCompletion() done\n");
|
||||||
|
|
||||||
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
VfatReadDisk (IN PDEVICE_OBJECT pDeviceObject,
|
VfatReadDisk(
|
||||||
IN PLARGE_INTEGER ReadOffset,
|
IN PDEVICE_OBJECT pDeviceObject,
|
||||||
IN ULONG ReadLength,
|
IN PLARGE_INTEGER ReadOffset,
|
||||||
IN OUT PUCHAR Buffer,
|
IN ULONG ReadLength,
|
||||||
IN BOOLEAN Override)
|
IN OUT PUCHAR Buffer,
|
||||||
|
IN BOOLEAN Override)
|
||||||
{
|
{
|
||||||
PIO_STACK_LOCATION Stack;
|
PIO_STACK_LOCATION Stack;
|
||||||
PIRP Irp;
|
PIRP Irp;
|
||||||
IO_STATUS_BLOCK IoStatus;
|
IO_STATUS_BLOCK IoStatus;
|
||||||
KEVENT event;
|
KEVENT Event;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
again:
|
again:
|
||||||
KeInitializeEvent (&event, NotificationEvent, FALSE);
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||||
|
|
||||||
DPRINT("VfatReadDisk(pDeviceObject %p, Offset %I64x, Length %u, Buffer %p)\n",
|
DPRINT("VfatReadDisk(pDeviceObject %p, Offset %I64x, Length %u, Buffer %p)\n",
|
||||||
pDeviceObject, ReadOffset->QuadPart, ReadLength, Buffer);
|
pDeviceObject, ReadOffset->QuadPart, ReadLength, Buffer);
|
||||||
|
|
||||||
DPRINT ("Building synchronous FSD Request...\n");
|
DPRINT ("Building synchronous FSD Request...\n");
|
||||||
Irp = IoBuildSynchronousFsdRequest (IRP_MJ_READ,
|
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
|
||||||
pDeviceObject,
|
pDeviceObject,
|
||||||
Buffer,
|
Buffer,
|
||||||
ReadLength,
|
ReadLength,
|
||||||
ReadOffset,
|
ReadOffset,
|
||||||
&event,
|
&Event,
|
||||||
&IoStatus);
|
&IoStatus);
|
||||||
if (Irp == NULL)
|
if (Irp == NULL)
|
||||||
{
|
{
|
||||||
DPRINT("IoBuildSynchronousFsdRequest failed\n");
|
DPRINT("IoBuildSynchronousFsdRequest failed\n");
|
||||||
return(STATUS_UNSUCCESSFUL);
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Override)
|
if (Override)
|
||||||
{
|
{
|
||||||
Stack = IoGetNextIrpStackLocation(Irp);
|
Stack = IoGetNextIrpStackLocation(Irp);
|
||||||
Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
|
Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT ("Calling IO Driver... with irp %p\n", Irp);
|
DPRINT("Calling IO Driver... with irp %p\n", Irp);
|
||||||
Status = IoCallDriver (pDeviceObject, Irp);
|
Status = IoCallDriver (pDeviceObject, Irp);
|
||||||
|
|
||||||
DPRINT ("Waiting for IO Operation for %p\n", Irp);
|
DPRINT("Waiting for IO Operation for %p\n", Irp);
|
||||||
if (Status == STATUS_PENDING)
|
if (Status == STATUS_PENDING)
|
||||||
{
|
{
|
||||||
DPRINT ("Operation pending\n");
|
DPRINT("Operation pending\n");
|
||||||
KeWaitForSingleObject (&event, Suspended, KernelMode, FALSE, NULL);
|
KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
|
||||||
DPRINT ("Getting IO Status... for %p\n", Irp);
|
DPRINT("Getting IO Status... for %p\n", Irp);
|
||||||
Status = IoStatus.Status;
|
Status = IoStatus.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Status == STATUS_VERIFY_REQUIRED)
|
if (Status == STATUS_VERIFY_REQUIRED)
|
||||||
{
|
{
|
||||||
PDEVICE_OBJECT DeviceToVerify;
|
PDEVICE_OBJECT DeviceToVerify;
|
||||||
|
|
||||||
DPRINT1 ("Media change detected!\n");
|
DPRINT1 ("Media change detected!\n");
|
||||||
|
|
||||||
/* Find the device to verify and reset the thread field to empty value again. */
|
/* Find the device to verify and reset the thread field to empty value again. */
|
||||||
DeviceToVerify = IoGetDeviceToVerify (PsGetCurrentThread ());
|
DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread());
|
||||||
IoSetDeviceToVerify (PsGetCurrentThread (), NULL);
|
IoSetDeviceToVerify(PsGetCurrentThread(), NULL);
|
||||||
Status = IoVerifyVolume (DeviceToVerify,
|
Status = IoVerifyVolume(DeviceToVerify,
|
||||||
FALSE);
|
FALSE);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
if (NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
DPRINT1 ("Volume verification successful; Reissuing read request\n");
|
DPRINT1("Volume verification successful; Reissuing read request\n");
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NT_SUCCESS (Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT("IO failed!!! VfatReadDisk : Error code: %x\n", Status);
|
DPRINT("IO failed!!! VfatReadDisk : Error code: %x\n", Status);
|
||||||
DPRINT("(pDeviceObject %p, Offset %I64x, Size %u, Buffer %p\n",
|
DPRINT("(pDeviceObject %p, Offset %I64x, Size %u, Buffer %p\n",
|
||||||
pDeviceObject, ReadOffset->QuadPart, ReadLength, Buffer);
|
pDeviceObject, ReadOffset->QuadPart, ReadLength, Buffer);
|
||||||
return (Status);
|
return Status;
|
||||||
}
|
}
|
||||||
DPRINT ("Block request succeeded for %p\n", Irp);
|
DPRINT("Block request succeeded for %p\n", Irp);
|
||||||
return (STATUS_SUCCESS);
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
VfatReadDiskPartial (IN PVFAT_IRP_CONTEXT IrpContext,
|
VfatReadDiskPartial(
|
||||||
IN PLARGE_INTEGER ReadOffset,
|
IN PVFAT_IRP_CONTEXT IrpContext,
|
||||||
IN ULONG ReadLength,
|
IN PLARGE_INTEGER ReadOffset,
|
||||||
ULONG BufferOffset,
|
IN ULONG ReadLength,
|
||||||
IN BOOLEAN Wait)
|
ULONG BufferOffset,
|
||||||
|
IN BOOLEAN Wait)
|
||||||
{
|
{
|
||||||
PIRP Irp;
|
PIRP Irp;
|
||||||
PIO_STACK_LOCATION StackPtr;
|
PIO_STACK_LOCATION StackPtr;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PVOID Buffer;
|
PVOID Buffer;
|
||||||
|
|
||||||
DPRINT("VfatReadDiskPartial(IrpContext %p, ReadOffset %I64x, ReadLength %u, BufferOffset %u, Wait %u)\n",
|
DPRINT("VfatReadDiskPartial(IrpContext %p, ReadOffset %I64x, ReadLength %u, BufferOffset %u, Wait %u)\n",
|
||||||
IrpContext, ReadOffset->QuadPart, ReadLength, BufferOffset, Wait);
|
IrpContext, ReadOffset->QuadPart, ReadLength, BufferOffset, Wait);
|
||||||
|
|
||||||
DPRINT ("Building asynchronous FSD Request...\n");
|
DPRINT("Building asynchronous FSD Request...\n");
|
||||||
|
|
||||||
Buffer = (PCHAR)MmGetMdlVirtualAddress(IrpContext->Irp->MdlAddress) + BufferOffset;
|
Buffer = (PCHAR)MmGetMdlVirtualAddress(IrpContext->Irp->MdlAddress) + BufferOffset;
|
||||||
|
|
||||||
again:
|
again:
|
||||||
Irp = IoAllocateIrp(IrpContext->DeviceExt->StorageDevice->StackSize, TRUE);
|
Irp = IoAllocateIrp(IrpContext->DeviceExt->StorageDevice->StackSize, TRUE);
|
||||||
if (Irp == NULL)
|
if (Irp == NULL)
|
||||||
{
|
{
|
||||||
DPRINT("IoAllocateIrp failed\n");
|
DPRINT("IoAllocateIrp failed\n");
|
||||||
return(STATUS_UNSUCCESSFUL);
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Irp->UserIosb = NULL;
|
Irp->UserIosb = NULL;
|
||||||
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
|
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
|
||||||
|
|
||||||
StackPtr = IoGetNextIrpStackLocation(Irp);
|
StackPtr = IoGetNextIrpStackLocation(Irp);
|
||||||
StackPtr->MajorFunction = IRP_MJ_READ;
|
StackPtr->MajorFunction = IRP_MJ_READ;
|
||||||
StackPtr->MinorFunction = 0;
|
StackPtr->MinorFunction = 0;
|
||||||
StackPtr->Flags = 0;
|
StackPtr->Flags = 0;
|
||||||
StackPtr->Control = 0;
|
StackPtr->Control = 0;
|
||||||
StackPtr->DeviceObject = IrpContext->DeviceExt->StorageDevice;
|
StackPtr->DeviceObject = IrpContext->DeviceExt->StorageDevice;
|
||||||
StackPtr->FileObject = NULL;
|
StackPtr->FileObject = NULL;
|
||||||
StackPtr->CompletionRoutine = NULL;
|
StackPtr->CompletionRoutine = NULL;
|
||||||
StackPtr->Parameters.Read.Length = ReadLength;
|
StackPtr->Parameters.Read.Length = ReadLength;
|
||||||
StackPtr->Parameters.Read.ByteOffset = *ReadOffset;
|
StackPtr->Parameters.Read.ByteOffset = *ReadOffset;
|
||||||
|
|
||||||
if (!IoAllocateMdl(Buffer, ReadLength, FALSE, FALSE, Irp))
|
if (!IoAllocateMdl(Buffer, ReadLength, FALSE, FALSE, Irp))
|
||||||
{
|
{
|
||||||
DPRINT("IoAllocateMdl failed\n");
|
DPRINT("IoAllocateMdl failed\n");
|
||||||
IoFreeIrp(Irp);
|
IoFreeIrp(Irp);
|
||||||
return STATUS_UNSUCCESSFUL;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
IoBuildPartialMdl(IrpContext->Irp->MdlAddress, Irp->MdlAddress, Buffer, ReadLength);
|
IoBuildPartialMdl(IrpContext->Irp->MdlAddress, Irp->MdlAddress, Buffer, ReadLength);
|
||||||
|
|
||||||
IoSetCompletionRoutine(Irp,
|
IoSetCompletionRoutine(Irp,
|
||||||
VfatReadWritePartialCompletion,
|
VfatReadWritePartialCompletion,
|
||||||
IrpContext,
|
IrpContext,
|
||||||
TRUE,
|
TRUE,
|
||||||
TRUE,
|
TRUE,
|
||||||
TRUE);
|
TRUE);
|
||||||
|
|
||||||
if (Wait)
|
if (Wait)
|
||||||
{
|
{
|
||||||
KeInitializeEvent(&IrpContext->Event, NotificationEvent, FALSE);
|
KeInitializeEvent(&IrpContext->Event, NotificationEvent, FALSE);
|
||||||
IrpContext->RefCount = 1;
|
IrpContext->RefCount = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
InterlockedIncrement((PLONG)&IrpContext->RefCount);
|
InterlockedIncrement((PLONG)&IrpContext->RefCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT ("Calling IO Driver... with irp %p\n", Irp);
|
DPRINT("Calling IO Driver... with irp %p\n", Irp);
|
||||||
Status = IoCallDriver (IrpContext->DeviceExt->StorageDevice, Irp);
|
Status = IoCallDriver(IrpContext->DeviceExt->StorageDevice, Irp);
|
||||||
|
|
||||||
if (Wait && Status == STATUS_PENDING)
|
if (Wait && Status == STATUS_PENDING)
|
||||||
{
|
{
|
||||||
KeWaitForSingleObject(&IrpContext->Event, Executive, KernelMode, FALSE, NULL);
|
KeWaitForSingleObject(&IrpContext->Event, Executive, KernelMode, FALSE, NULL);
|
||||||
Status = IrpContext->Irp->IoStatus.Status;
|
Status = IrpContext->Irp->IoStatus.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Status == STATUS_VERIFY_REQUIRED)
|
if (Status == STATUS_VERIFY_REQUIRED)
|
||||||
{
|
{
|
||||||
PDEVICE_OBJECT DeviceToVerify;
|
PDEVICE_OBJECT DeviceToVerify;
|
||||||
|
|
||||||
DPRINT1 ("Media change detected!\n");
|
DPRINT1("Media change detected!\n");
|
||||||
|
|
||||||
/* Find the device to verify and reset the thread field to empty value again. */
|
/* Find the device to verify and reset the thread field to empty value again. */
|
||||||
DeviceToVerify = IoGetDeviceToVerify (PsGetCurrentThread ());
|
DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread());
|
||||||
IoSetDeviceToVerify (PsGetCurrentThread (), NULL);
|
IoSetDeviceToVerify(PsGetCurrentThread(), NULL);
|
||||||
Status = IoVerifyVolume (DeviceToVerify,
|
Status = IoVerifyVolume(DeviceToVerify,
|
||||||
FALSE);
|
FALSE);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
if (NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
DPRINT1 ("Volume verification successful; Reissuing read request\n");
|
DPRINT1("Volume verification successful; Reissuing read request\n");
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT("%x\n", Status);
|
DPRINT("%x\n", Status);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
VfatWriteDiskPartial (IN PVFAT_IRP_CONTEXT IrpContext,
|
VfatWriteDiskPartial(
|
||||||
IN PLARGE_INTEGER WriteOffset,
|
IN PVFAT_IRP_CONTEXT IrpContext,
|
||||||
IN ULONG WriteLength,
|
IN PLARGE_INTEGER WriteOffset,
|
||||||
IN ULONG BufferOffset,
|
IN ULONG WriteLength,
|
||||||
IN BOOLEAN Wait)
|
IN ULONG BufferOffset,
|
||||||
|
IN BOOLEAN Wait)
|
||||||
{
|
{
|
||||||
PIRP Irp;
|
PIRP Irp;
|
||||||
PIO_STACK_LOCATION StackPtr;
|
PIO_STACK_LOCATION StackPtr;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PVOID Buffer;
|
PVOID Buffer;
|
||||||
|
|
||||||
DPRINT("VfatWriteDiskPartial(IrpContext %p, WriteOffset %I64x, WriteLength %u, BufferOffset %x, Wait %u)\n",
|
DPRINT("VfatWriteDiskPartial(IrpContext %p, WriteOffset %I64x, WriteLength %u, BufferOffset %x, Wait %u)\n",
|
||||||
IrpContext, WriteOffset->QuadPart, WriteLength, BufferOffset, Wait);
|
IrpContext, WriteOffset->QuadPart, WriteLength, BufferOffset, Wait);
|
||||||
|
|
||||||
Buffer = (PCHAR)MmGetMdlVirtualAddress(IrpContext->Irp->MdlAddress) + BufferOffset;
|
Buffer = (PCHAR)MmGetMdlVirtualAddress(IrpContext->Irp->MdlAddress) + BufferOffset;
|
||||||
|
|
||||||
again:
|
again:
|
||||||
DPRINT ("Building asynchronous FSD Request...\n");
|
DPRINT("Building asynchronous FSD Request...\n");
|
||||||
Irp = IoAllocateIrp(IrpContext->DeviceExt->StorageDevice->StackSize, TRUE);
|
Irp = IoAllocateIrp(IrpContext->DeviceExt->StorageDevice->StackSize, TRUE);
|
||||||
if (Irp == NULL)
|
if (Irp == NULL)
|
||||||
{
|
{
|
||||||
DPRINT("IoAllocateIrp failed\n");
|
DPRINT("IoAllocateIrp failed\n");
|
||||||
return(STATUS_UNSUCCESSFUL);
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Irp->UserIosb = NULL;
|
Irp->UserIosb = NULL;
|
||||||
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
|
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
|
||||||
|
|
||||||
StackPtr = IoGetNextIrpStackLocation(Irp);
|
StackPtr = IoGetNextIrpStackLocation(Irp);
|
||||||
StackPtr->MajorFunction = IRP_MJ_WRITE;
|
StackPtr->MajorFunction = IRP_MJ_WRITE;
|
||||||
StackPtr->MinorFunction = 0;
|
StackPtr->MinorFunction = 0;
|
||||||
StackPtr->Flags = 0;
|
StackPtr->Flags = 0;
|
||||||
StackPtr->Control = 0;
|
StackPtr->Control = 0;
|
||||||
StackPtr->DeviceObject = IrpContext->DeviceExt->StorageDevice;
|
StackPtr->DeviceObject = IrpContext->DeviceExt->StorageDevice;
|
||||||
StackPtr->FileObject = NULL;
|
StackPtr->FileObject = NULL;
|
||||||
StackPtr->CompletionRoutine = NULL;
|
StackPtr->CompletionRoutine = NULL;
|
||||||
StackPtr->Parameters.Read.Length = WriteLength;
|
StackPtr->Parameters.Read.Length = WriteLength;
|
||||||
StackPtr->Parameters.Read.ByteOffset = *WriteOffset;
|
StackPtr->Parameters.Read.ByteOffset = *WriteOffset;
|
||||||
|
|
||||||
if (!IoAllocateMdl(Buffer, WriteLength, FALSE, FALSE, Irp))
|
if (!IoAllocateMdl(Buffer, WriteLength, FALSE, FALSE, Irp))
|
||||||
{
|
{
|
||||||
DPRINT("IoAllocateMdl failed\n");
|
DPRINT("IoAllocateMdl failed\n");
|
||||||
IoFreeIrp(Irp);
|
IoFreeIrp(Irp);
|
||||||
return STATUS_UNSUCCESSFUL;
|
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IoBuildPartialMdl(IrpContext->Irp->MdlAddress, Irp->MdlAddress, Buffer, WriteLength);
|
||||||
|
|
||||||
DPRINT ("Calling IO Driver...\n");
|
IoSetCompletionRoutine(Irp,
|
||||||
Status = IoCallDriver (IrpContext->DeviceExt->StorageDevice, Irp);
|
VfatReadWritePartialCompletion,
|
||||||
if (Wait && Status == STATUS_PENDING)
|
IrpContext,
|
||||||
|
TRUE,
|
||||||
|
TRUE,
|
||||||
|
TRUE);
|
||||||
|
|
||||||
|
if (Wait)
|
||||||
{
|
{
|
||||||
KeWaitForSingleObject(&IrpContext->Event, Executive, KernelMode, FALSE, NULL);
|
KeInitializeEvent(&IrpContext->Event, NotificationEvent, FALSE);
|
||||||
Status = IrpContext->Irp->IoStatus.Status;
|
IrpContext->RefCount = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InterlockedIncrement((PLONG)&IrpContext->RefCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Status == STATUS_VERIFY_REQUIRED)
|
DPRINT("Calling IO Driver...\n");
|
||||||
|
Status = IoCallDriver(IrpContext->DeviceExt->StorageDevice, Irp);
|
||||||
|
if (Wait && Status == STATUS_PENDING)
|
||||||
{
|
{
|
||||||
PDEVICE_OBJECT DeviceToVerify;
|
KeWaitForSingleObject(&IrpContext->Event, Executive, KernelMode, FALSE, NULL);
|
||||||
|
Status = IrpContext->Irp->IoStatus.Status;
|
||||||
|
}
|
||||||
|
|
||||||
DPRINT1 ("Media change detected!\n");
|
if (Status == STATUS_VERIFY_REQUIRED)
|
||||||
|
{
|
||||||
|
PDEVICE_OBJECT DeviceToVerify;
|
||||||
|
|
||||||
/* Find the device to verify and reset the thread field to empty value again. */
|
DPRINT1("Media change detected!\n");
|
||||||
DeviceToVerify = IoGetDeviceToVerify (PsGetCurrentThread ());
|
|
||||||
IoSetDeviceToVerify (PsGetCurrentThread (), NULL);
|
|
||||||
Status = IoVerifyVolume (DeviceToVerify,
|
|
||||||
FALSE);
|
|
||||||
|
|
||||||
if (NT_SUCCESS(Status))
|
/* 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");
|
DPRINT1("Volume verification successful; Reissuing write request\n");
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
VfatBlockDeviceIoControl (IN PDEVICE_OBJECT DeviceObject,
|
VfatBlockDeviceIoControl(
|
||||||
IN ULONG CtlCode,
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
IN PVOID InputBuffer OPTIONAL,
|
IN ULONG CtlCode,
|
||||||
IN ULONG InputBufferSize,
|
IN PVOID InputBuffer OPTIONAL,
|
||||||
IN OUT PVOID OutputBuffer OPTIONAL,
|
IN ULONG InputBufferSize,
|
||||||
IN OUT PULONG OutputBufferSize,
|
IN OUT PVOID OutputBuffer OPTIONAL,
|
||||||
IN BOOLEAN Override)
|
IN OUT PULONG OutputBufferSize,
|
||||||
|
IN BOOLEAN Override)
|
||||||
{
|
{
|
||||||
PIO_STACK_LOCATION Stack;
|
PIO_STACK_LOCATION Stack;
|
||||||
KEVENT Event;
|
KEVENT Event;
|
||||||
PIRP Irp;
|
PIRP Irp;
|
||||||
IO_STATUS_BLOCK IoStatus;
|
IO_STATUS_BLOCK IoStatus;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
DPRINT("VfatBlockDeviceIoControl(DeviceObject %p, CtlCode %x, "
|
DPRINT("VfatBlockDeviceIoControl(DeviceObject %p, CtlCode %x, "
|
||||||
"InputBuffer %p, InputBufferSize %x, OutputBuffer %p, "
|
"InputBuffer %p, InputBufferSize %x, OutputBuffer %p, "
|
||||||
"OutputBufferSize %p (%x)\n", DeviceObject, CtlCode,
|
"OutputBufferSize %p (%x)\n", DeviceObject, CtlCode,
|
||||||
InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize,
|
InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize,
|
||||||
OutputBufferSize ? *OutputBufferSize : 0);
|
OutputBufferSize ? *OutputBufferSize : 0);
|
||||||
|
|
||||||
again:
|
again:
|
||||||
KeInitializeEvent (&Event, NotificationEvent, FALSE);
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||||
|
|
||||||
DPRINT("Building device I/O control request ...\n");
|
DPRINT("Building device I/O control request ...\n");
|
||||||
Irp = IoBuildDeviceIoControlRequest(CtlCode,
|
Irp = IoBuildDeviceIoControlRequest(CtlCode,
|
||||||
DeviceObject,
|
DeviceObject,
|
||||||
InputBuffer,
|
InputBuffer,
|
||||||
InputBufferSize,
|
InputBufferSize,
|
||||||
OutputBuffer,
|
OutputBuffer,
|
||||||
(OutputBufferSize) ? *OutputBufferSize : 0,
|
(OutputBufferSize) ? *OutputBufferSize : 0,
|
||||||
FALSE,
|
FALSE,
|
||||||
&Event,
|
&Event,
|
||||||
&IoStatus);
|
&IoStatus);
|
||||||
if (Irp == NULL)
|
if (Irp == NULL)
|
||||||
{
|
{
|
||||||
DPRINT("IoBuildDeviceIoControlRequest failed\n");
|
DPRINT("IoBuildDeviceIoControlRequest failed\n");
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Override)
|
if (Override)
|
||||||
{
|
{
|
||||||
Stack = IoGetNextIrpStackLocation(Irp);
|
Stack = IoGetNextIrpStackLocation(Irp);
|
||||||
Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
|
Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT ("Calling IO Driver... with irp %p\n", Irp);
|
DPRINT("Calling IO Driver... with irp %p\n", Irp);
|
||||||
Status = IoCallDriver(DeviceObject, Irp);
|
Status = IoCallDriver(DeviceObject, Irp);
|
||||||
|
|
||||||
DPRINT ("Waiting for IO Operation for %p\n", Irp);
|
DPRINT("Waiting for IO Operation for %p\n", Irp);
|
||||||
if (Status == STATUS_PENDING)
|
if (Status == STATUS_PENDING)
|
||||||
{
|
{
|
||||||
DPRINT ("Operation pending\n");
|
DPRINT("Operation pending\n");
|
||||||
KeWaitForSingleObject (&Event, Suspended, KernelMode, FALSE, NULL);
|
KeWaitForSingleObject (&Event, Suspended, KernelMode, FALSE, NULL);
|
||||||
DPRINT ("Getting IO Status... for %p\n", Irp);
|
DPRINT("Getting IO Status... for %p\n", Irp);
|
||||||
|
|
||||||
Status = IoStatus.Status;
|
Status = IoStatus.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Status == STATUS_VERIFY_REQUIRED)
|
if (Status == STATUS_VERIFY_REQUIRED)
|
||||||
{
|
{
|
||||||
PDEVICE_OBJECT DeviceToVerify;
|
PDEVICE_OBJECT DeviceToVerify;
|
||||||
|
|
||||||
DPRINT1 ("Media change detected!\n");
|
DPRINT1("Media change detected!\n");
|
||||||
|
|
||||||
/* Find the device to verify and reset the thread field to empty value again. */
|
/* Find the device to verify and reset the thread field to empty value again. */
|
||||||
DeviceToVerify = IoGetDeviceToVerify (PsGetCurrentThread ());
|
DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread());
|
||||||
IoSetDeviceToVerify (PsGetCurrentThread (), NULL);
|
IoSetDeviceToVerify(PsGetCurrentThread(), NULL);
|
||||||
Status = IoVerifyVolume (DeviceToVerify,
|
Status = IoVerifyVolume(DeviceToVerify,
|
||||||
FALSE);
|
FALSE);
|
||||||
|
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1 ("Volume verification successful; Reissuing IOCTL request\n");
|
DPRINT1("Volume verification successful; Reissuing IOCTL request\n");
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OutputBufferSize)
|
if (OutputBufferSize)
|
||||||
{
|
{
|
||||||
*OutputBufferSize = IoStatus.Information;
|
*OutputBufferSize = IoStatus.Information;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT("Returning Status %x\n", Status);
|
DPRINT("Returning Status %x\n", Status);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,98 +13,103 @@
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
VfatCloseFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject)
|
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Closes a file
|
* FUNCTION: Closes a file
|
||||||
*/
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
VfatCloseFile(
|
||||||
|
PDEVICE_EXTENSION DeviceExt,
|
||||||
|
PFILE_OBJECT FileObject)
|
||||||
{
|
{
|
||||||
PVFATFCB pFcb;
|
PVFATFCB pFcb;
|
||||||
PVFATCCB pCcb;
|
PVFATCCB pCcb;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
DPRINT ("VfatCloseFile(DeviceExt %p, FileObject %p)\n",
|
DPRINT("VfatCloseFile(DeviceExt %p, FileObject %p)\n",
|
||||||
DeviceExt, FileObject);
|
DeviceExt, FileObject);
|
||||||
|
|
||||||
/* FIXME : update entry in directory? */
|
/* FIXME : update entry in directory? */
|
||||||
pCcb = (PVFATCCB) (FileObject->FsContext2);
|
pCcb = (PVFATCCB) (FileObject->FsContext2);
|
||||||
pFcb = (PVFATFCB) (FileObject->FsContext);
|
pFcb = (PVFATFCB) (FileObject->FsContext);
|
||||||
|
|
||||||
if (pFcb == NULL)
|
if (pFcb == NULL)
|
||||||
{
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pFcb->Flags & FCB_IS_VOLUME)
|
|
||||||
{
|
|
||||||
DPRINT1("Volume\n");
|
|
||||||
pFcb->RefCount--;
|
|
||||||
FileObject->FsContext2 = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (FileObject->DeletePending)
|
|
||||||
{
|
{
|
||||||
if (pFcb->Flags & FCB_DELETE_PENDING)
|
return STATUS_SUCCESS;
|
||||||
{
|
|
||||||
VfatDelEntry (DeviceExt, pFcb);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Status = STATUS_DELETE_PENDING;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
vfatReleaseFCB (DeviceExt, pFcb);
|
|
||||||
}
|
|
||||||
|
|
||||||
FileObject->FsContext2 = NULL;
|
if (pFcb->Flags & FCB_IS_VOLUME)
|
||||||
FileObject->FsContext = NULL;
|
{
|
||||||
FileObject->SectionObjectPointer = NULL;
|
DPRINT1("Volume\n");
|
||||||
|
pFcb->RefCount--;
|
||||||
|
FileObject->FsContext2 = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (FileObject->DeletePending)
|
||||||
|
{
|
||||||
|
if (pFcb->Flags & FCB_DELETE_PENDING)
|
||||||
|
{
|
||||||
|
VfatDelEntry (DeviceExt, pFcb);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Status = STATUS_DELETE_PENDING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (pCcb)
|
vfatReleaseFCB (DeviceExt, pFcb);
|
||||||
{
|
}
|
||||||
vfatDestroyCCB(pCcb);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Status;
|
FileObject->FsContext2 = NULL;
|
||||||
|
FileObject->FsContext = NULL;
|
||||||
|
FileObject->SectionObjectPointer = NULL;
|
||||||
|
|
||||||
|
if (pCcb)
|
||||||
|
{
|
||||||
|
vfatDestroyCCB(pCcb);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS VfatClose (PVFAT_IRP_CONTEXT IrpContext)
|
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Closes a file
|
* FUNCTION: Closes a file
|
||||||
*/
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
VfatClose(
|
||||||
|
PVFAT_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
DPRINT ("VfatClose(DeviceObject %p, Irp %p)\n", IrpContext->DeviceObject, IrpContext->Irp);
|
DPRINT("VfatClose(DeviceObject %p, Irp %p)\n", IrpContext->DeviceObject, IrpContext->Irp);
|
||||||
|
|
||||||
if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
|
if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
|
||||||
{
|
{
|
||||||
DPRINT("Closing file system\n");
|
DPRINT("Closing file system\n");
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
goto ByeBye;
|
goto ByeBye;
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
/* There occurs a dead look at the call to CcRosDeleteFileCache/ObDereferenceObject/VfatClose
|
/* There occurs a dead look at the call to CcRosDeleteFileCache/ObDereferenceObject/VfatClose
|
||||||
in CmLazyCloseThreadMain if VfatClose is execute asynchronous in a worker thread. */
|
in CmLazyCloseThreadMain if VfatClose is execute asynchronous in a worker thread. */
|
||||||
if (!ExAcquireResourceExclusiveLite (&IrpContext->DeviceExt->DirResource, IrpContext->Flags & IRPCONTEXT_CANWAIT))
|
if (!ExAcquireResourceExclusiveLite(&IrpContext->DeviceExt->DirResource, IrpContext->Flags & IRPCONTEXT_CANWAIT))
|
||||||
#else
|
#else
|
||||||
if (!ExAcquireResourceExclusiveLite (&IrpContext->DeviceExt->DirResource, TRUE))
|
if (!ExAcquireResourceExclusiveLite(&IrpContext->DeviceExt->DirResource, TRUE))
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
return VfatQueueRequest (IrpContext);
|
return VfatQueueRequest(IrpContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = VfatCloseFile (IrpContext->DeviceExt, IrpContext->FileObject);
|
Status = VfatCloseFile(IrpContext->DeviceExt, IrpContext->FileObject);
|
||||||
ExReleaseResourceLite (&IrpContext->DeviceExt->DirResource);
|
ExReleaseResourceLite(&IrpContext->DeviceExt->DirResource);
|
||||||
|
|
||||||
ByeBye:
|
ByeBye:
|
||||||
IrpContext->Irp->IoStatus.Status = Status;
|
IrpContext->Irp->IoStatus.Status = Status;
|
||||||
IrpContext->Irp->IoStatus.Information = 0;
|
IrpContext->Irp->IoStatus.Information = 0;
|
||||||
IoCompleteRequest (IrpContext->Irp, IO_NO_INCREMENT);
|
IoCompleteRequest (IrpContext->Irp, IO_NO_INCREMENT);
|
||||||
VfatFreeIrpContext(IrpContext);
|
VfatFreeIrpContext(IrpContext);
|
||||||
|
|
||||||
return (Status);
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -30,34 +30,37 @@
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
void
|
VOID
|
||||||
vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry, PUNICODE_STRING NameU)
|
vfat8Dot3ToString(
|
||||||
|
PFAT_DIR_ENTRY pEntry,
|
||||||
|
PUNICODE_STRING NameU)
|
||||||
{
|
{
|
||||||
OEM_STRING StringA;
|
OEM_STRING StringA;
|
||||||
USHORT Length;
|
USHORT Length;
|
||||||
CHAR cString[12];
|
CHAR cString[12];
|
||||||
|
|
||||||
RtlCopyMemory(cString, pEntry->ShortName, 11);
|
RtlCopyMemory(cString, pEntry->ShortName, 11);
|
||||||
cString[11] = 0;
|
cString[11] = 0;
|
||||||
if (cString[0] == 0x05)
|
if (cString[0] == 0x05)
|
||||||
{
|
{
|
||||||
cString[0] = 0xe5;
|
cString[0] = 0xe5;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringA.Buffer = cString;
|
StringA.Buffer = cString;
|
||||||
for (StringA.Length = 0;
|
for (StringA.Length = 0;
|
||||||
StringA.Length < 8 && StringA.Buffer[StringA.Length] != ' ';
|
StringA.Length < 8 && StringA.Buffer[StringA.Length] != ' ';
|
||||||
StringA.Length++);
|
StringA.Length++);
|
||||||
StringA.MaximumLength = StringA.Length;
|
StringA.MaximumLength = StringA.Length;
|
||||||
|
|
||||||
RtlOemStringToUnicodeString(NameU, &StringA, FALSE);
|
RtlOemStringToUnicodeString(NameU, &StringA, FALSE);
|
||||||
|
|
||||||
if (pEntry->lCase & VFAT_CASE_LOWER_BASE)
|
if (pEntry->lCase & VFAT_CASE_LOWER_BASE)
|
||||||
{
|
{
|
||||||
RtlDowncaseUnicodeString(NameU, NameU, FALSE);
|
RtlDowncaseUnicodeString(NameU, NameU, FALSE);
|
||||||
}
|
}
|
||||||
if (cString[8] != ' ')
|
|
||||||
{
|
if (cString[8] != ' ')
|
||||||
|
{
|
||||||
Length = NameU->Length;
|
Length = NameU->Length;
|
||||||
NameU->Buffer += Length / sizeof(WCHAR);
|
NameU->Buffer += Length / sizeof(WCHAR);
|
||||||
if (!FAT_ENTRY_VOLUME(pEntry))
|
if (!FAT_ENTRY_VOLUME(pEntry))
|
||||||
|
@ -83,8 +86,9 @@ vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry, PUNICODE_STRING NameU)
|
||||||
NameU->Length += Length;
|
NameU->Length += Length;
|
||||||
NameU->MaximumLength += Length;
|
NameU->MaximumLength += Length;
|
||||||
}
|
}
|
||||||
NameU->Buffer[NameU->Length / sizeof(WCHAR)] = 0;
|
|
||||||
DPRINT("'%wZ'\n", NameU);
|
NameU->Buffer[NameU->Length / sizeof(WCHAR)] = 0;
|
||||||
|
DPRINT("'%wZ'\n", NameU);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
* FILE: drivers/fs/vfat/ea.c
|
* FILE: drivers/fs/vfat/ea.c
|
||||||
* PURPOSE: VFAT Filesystem
|
* PURPOSE: VFAT Filesystem
|
||||||
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
|
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
@ -32,13 +31,14 @@
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
VfatSetExtendedAttributes(PFILE_OBJECT FileObject,
|
VfatSetExtendedAttributes(
|
||||||
PVOID Ea,
|
PFILE_OBJECT FileObject,
|
||||||
ULONG EaLength)
|
PVOID Ea,
|
||||||
|
ULONG EaLength)
|
||||||
{
|
{
|
||||||
UNREFERENCED_PARAMETER(FileObject);
|
UNREFERENCED_PARAMETER(FileObject);
|
||||||
UNREFERENCED_PARAMETER(Ea);
|
UNREFERENCED_PARAMETER(Ea);
|
||||||
UNREFERENCED_PARAMETER(EaLength);
|
UNREFERENCED_PARAMETER(EaLength);
|
||||||
|
|
||||||
return(STATUS_EAS_NOT_SUPPORTED);
|
return STATUS_EAS_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,166 +19,178 @@
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
FAT32GetNextCluster(PDEVICE_EXTENSION DeviceExt,
|
|
||||||
ULONG CurrentCluster,
|
|
||||||
PULONG NextCluster)
|
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Retrieve the next FAT32 cluster from the FAT table via a physical
|
* FUNCTION: Retrieve the next FAT32 cluster from the FAT table via a physical
|
||||||
* disk read
|
* disk read
|
||||||
*/
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
FAT32GetNextCluster(
|
||||||
|
PDEVICE_EXTENSION DeviceExt,
|
||||||
|
ULONG CurrentCluster,
|
||||||
|
PULONG NextCluster)
|
||||||
{
|
{
|
||||||
PVOID BaseAddress;
|
PVOID BaseAddress;
|
||||||
ULONG FATOffset;
|
ULONG FATOffset;
|
||||||
ULONG ChunkSize;
|
ULONG ChunkSize;
|
||||||
PVOID Context;
|
PVOID Context;
|
||||||
LARGE_INTEGER Offset;
|
LARGE_INTEGER Offset;
|
||||||
|
|
||||||
ChunkSize = CACHEPAGESIZE(DeviceExt);
|
ChunkSize = CACHEPAGESIZE(DeviceExt);
|
||||||
FATOffset = CurrentCluster * sizeof(ULONG);
|
FATOffset = CurrentCluster * sizeof(ULONG);
|
||||||
Offset.QuadPart = ROUND_DOWN(FATOffset, ChunkSize);
|
Offset.QuadPart = ROUND_DOWN(FATOffset, ChunkSize);
|
||||||
if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
|
if (!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
|
||||||
{
|
{
|
||||||
return STATUS_UNSUCCESSFUL;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
CurrentCluster = (*(PULONG)((char*)BaseAddress + (FATOffset % ChunkSize))) & 0x0fffffff;
|
|
||||||
if (CurrentCluster >= 0xffffff8 && CurrentCluster <= 0xfffffff)
|
CurrentCluster = (*(PULONG)((char*)BaseAddress + (FATOffset % ChunkSize))) & 0x0fffffff;
|
||||||
CurrentCluster = 0xffffffff;
|
if (CurrentCluster >= 0xffffff8 && CurrentCluster <= 0xfffffff)
|
||||||
CcUnpinData(Context);
|
CurrentCluster = 0xffffffff;
|
||||||
*NextCluster = CurrentCluster;
|
|
||||||
return (STATUS_SUCCESS);
|
CcUnpinData(Context);
|
||||||
|
*NextCluster = CurrentCluster;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
FAT16GetNextCluster(PDEVICE_EXTENSION DeviceExt,
|
|
||||||
ULONG CurrentCluster,
|
|
||||||
PULONG NextCluster)
|
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Retrieve the next FAT16 cluster from the FAT table
|
* FUNCTION: Retrieve the next FAT16 cluster from the FAT table
|
||||||
*/
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
FAT16GetNextCluster(
|
||||||
|
PDEVICE_EXTENSION DeviceExt,
|
||||||
|
ULONG CurrentCluster,
|
||||||
|
PULONG NextCluster)
|
||||||
{
|
{
|
||||||
PVOID BaseAddress;
|
PVOID BaseAddress;
|
||||||
ULONG FATOffset;
|
ULONG FATOffset;
|
||||||
ULONG ChunkSize;
|
ULONG ChunkSize;
|
||||||
PVOID Context;
|
PVOID Context;
|
||||||
LARGE_INTEGER Offset;
|
LARGE_INTEGER Offset;
|
||||||
|
|
||||||
ChunkSize = CACHEPAGESIZE(DeviceExt);
|
ChunkSize = CACHEPAGESIZE(DeviceExt);
|
||||||
FATOffset = CurrentCluster * 2;
|
FATOffset = CurrentCluster * 2;
|
||||||
Offset.QuadPart = ROUND_DOWN(FATOffset, ChunkSize);
|
Offset.QuadPart = ROUND_DOWN(FATOffset, ChunkSize);
|
||||||
if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, MAP_WAIT, &Context, &BaseAddress))
|
if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, MAP_WAIT, &Context, &BaseAddress))
|
||||||
{
|
{
|
||||||
return STATUS_UNSUCCESSFUL;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
CurrentCluster = *((PUSHORT)((char*)BaseAddress + (FATOffset % ChunkSize)));
|
|
||||||
if (CurrentCluster >= 0xfff8 && CurrentCluster <= 0xffff)
|
CurrentCluster = *((PUSHORT)((char*)BaseAddress + (FATOffset % ChunkSize)));
|
||||||
CurrentCluster = 0xffffffff;
|
if (CurrentCluster >= 0xfff8 && CurrentCluster <= 0xffff)
|
||||||
CcUnpinData(Context);
|
CurrentCluster = 0xffffffff;
|
||||||
*NextCluster = CurrentCluster;
|
CcUnpinData(Context);
|
||||||
return (STATUS_SUCCESS);
|
*NextCluster = CurrentCluster;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
FAT12GetNextCluster(PDEVICE_EXTENSION DeviceExt,
|
|
||||||
ULONG CurrentCluster,
|
|
||||||
PULONG NextCluster)
|
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Retrieve the next FAT12 cluster from the FAT table
|
* FUNCTION: Retrieve the next FAT12 cluster from the FAT table
|
||||||
*/
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
FAT12GetNextCluster(
|
||||||
|
PDEVICE_EXTENSION DeviceExt,
|
||||||
|
ULONG CurrentCluster,
|
||||||
|
PULONG NextCluster)
|
||||||
{
|
{
|
||||||
PUSHORT CBlock;
|
PUSHORT CBlock;
|
||||||
ULONG Entry;
|
ULONG Entry;
|
||||||
PVOID BaseAddress;
|
PVOID BaseAddress;
|
||||||
PVOID Context;
|
PVOID Context;
|
||||||
LARGE_INTEGER Offset;
|
LARGE_INTEGER Offset;
|
||||||
|
|
||||||
|
*NextCluster = 0;
|
||||||
|
|
||||||
*NextCluster = 0;
|
Offset.QuadPart = 0;
|
||||||
|
if (!CcMapData(DeviceExt->FATFileObject, &Offset, DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector, 1, &Context, &BaseAddress))
|
||||||
Offset.QuadPart = 0;
|
|
||||||
if(!CcMapData(DeviceExt->FATFileObject, &Offset, DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector, 1, &Context, &BaseAddress))
|
|
||||||
{
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
CBlock = (PUSHORT)((char*)BaseAddress + (CurrentCluster * 12) / 8);
|
|
||||||
if ((CurrentCluster % 2) == 0)
|
|
||||||
{
|
{
|
||||||
Entry = *CBlock & 0x0fff;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
CBlock = (PUSHORT)((char*)BaseAddress + (CurrentCluster * 12) / 8);
|
||||||
|
if ((CurrentCluster % 2) == 0)
|
||||||
{
|
{
|
||||||
Entry = *CBlock >> 4;
|
Entry = *CBlock & 0x0fff;
|
||||||
}
|
}
|
||||||
// DPRINT("Entry %x\n",Entry);
|
else
|
||||||
if (Entry >= 0xff8 && Entry <= 0xfff)
|
{
|
||||||
Entry = 0xffffffff;
|
Entry = *CBlock >> 4;
|
||||||
// DPRINT("Returning %x\n",Entry);
|
}
|
||||||
*NextCluster = Entry;
|
|
||||||
CcUnpinData(Context);
|
// DPRINT("Entry %x\n",Entry);
|
||||||
// return Entry == 0xffffffff ? STATUS_END_OF_FILE : STATUS_SUCCESS;
|
if (Entry >= 0xff8 && Entry <= 0xfff)
|
||||||
return STATUS_SUCCESS;
|
Entry = 0xffffffff;
|
||||||
|
|
||||||
|
// DPRINT("Returning %x\n",Entry);
|
||||||
|
*NextCluster = Entry;
|
||||||
|
CcUnpinData(Context);
|
||||||
|
// return Entry == 0xffffffff ? STATUS_END_OF_FILE : STATUS_SUCCESS;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
FAT16FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt,
|
|
||||||
PULONG Cluster)
|
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Finds the first available cluster in a FAT16 table
|
* FUNCTION: Finds the first available cluster in a FAT16 table
|
||||||
*/
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
FAT16FindAndMarkAvailableCluster(
|
||||||
|
PDEVICE_EXTENSION DeviceExt,
|
||||||
|
PULONG Cluster)
|
||||||
{
|
{
|
||||||
ULONG FatLength;
|
ULONG FatLength;
|
||||||
ULONG StartCluster;
|
ULONG StartCluster;
|
||||||
ULONG i, j;
|
ULONG i, j;
|
||||||
PVOID BaseAddress;
|
PVOID BaseAddress;
|
||||||
ULONG ChunkSize;
|
ULONG ChunkSize;
|
||||||
PVOID Context = 0;
|
PVOID Context = 0;
|
||||||
LARGE_INTEGER Offset;
|
LARGE_INTEGER Offset;
|
||||||
PUSHORT Block;
|
PUSHORT Block;
|
||||||
PUSHORT BlockEnd;
|
PUSHORT BlockEnd;
|
||||||
|
|
||||||
ChunkSize = CACHEPAGESIZE(DeviceExt);
|
ChunkSize = CACHEPAGESIZE(DeviceExt);
|
||||||
FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2);
|
FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2);
|
||||||
*Cluster = 0;
|
*Cluster = 0;
|
||||||
StartCluster = DeviceExt->LastAvailableCluster;
|
StartCluster = DeviceExt->LastAvailableCluster;
|
||||||
|
|
||||||
for (j = 0; j < 2; j++)
|
for (j = 0; j < 2; j++)
|
||||||
{
|
|
||||||
for (i = StartCluster; i < FatLength; )
|
|
||||||
{
|
{
|
||||||
Offset.QuadPart = ROUND_DOWN(i * 2, ChunkSize);
|
for (i = StartCluster; i < FatLength;)
|
||||||
if(!CcPinRead(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
|
|
||||||
{
|
|
||||||
DPRINT1("CcMapData(Offset %x, Length %u) failed\n", (ULONG)Offset.QuadPart, ChunkSize);
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
Block = (PUSHORT)((ULONG_PTR)BaseAddress + (i * 2) % ChunkSize);
|
|
||||||
BlockEnd = (PUSHORT)((ULONG_PTR)BaseAddress + ChunkSize);
|
|
||||||
|
|
||||||
/* Now process the whole block */
|
|
||||||
while (Block < BlockEnd && i < FatLength)
|
|
||||||
{
|
|
||||||
if (*Block == 0)
|
|
||||||
{
|
{
|
||||||
DPRINT("Found available cluster 0x%x\n", i);
|
Offset.QuadPart = ROUND_DOWN(i * 2, ChunkSize);
|
||||||
DeviceExt->LastAvailableCluster = *Cluster = i;
|
if (!CcPinRead(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
|
||||||
*Block = 0xffff;
|
{
|
||||||
CcSetDirtyPinnedData(Context, NULL);
|
DPRINT1("CcMapData(Offset %x, Length %u) failed\n", (ULONG)Offset.QuadPart, ChunkSize);
|
||||||
CcUnpinData(Context);
|
return STATUS_UNSUCCESSFUL;
|
||||||
if (DeviceExt->AvailableClustersValid)
|
}
|
||||||
InterlockedDecrement((PLONG)&DeviceExt->AvailableClusters);
|
|
||||||
return(STATUS_SUCCESS);
|
Block = (PUSHORT)((ULONG_PTR)BaseAddress + (i * 2) % ChunkSize);
|
||||||
|
BlockEnd = (PUSHORT)((ULONG_PTR)BaseAddress + ChunkSize);
|
||||||
|
|
||||||
|
/* Now process the whole block */
|
||||||
|
while (Block < BlockEnd && i < FatLength)
|
||||||
|
{
|
||||||
|
if (*Block == 0)
|
||||||
|
{
|
||||||
|
DPRINT("Found available cluster 0x%x\n", i);
|
||||||
|
DeviceExt->LastAvailableCluster = *Cluster = i;
|
||||||
|
*Block = 0xffff;
|
||||||
|
CcSetDirtyPinnedData(Context, NULL);
|
||||||
|
CcUnpinData(Context);
|
||||||
|
if (DeviceExt->AvailableClustersValid)
|
||||||
|
InterlockedDecrement((PLONG)&DeviceExt->AvailableClusters);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
CcUnpinData(Context);
|
||||||
}
|
}
|
||||||
|
|
||||||
Block++;
|
FatLength = StartCluster;
|
||||||
i++;
|
StartCluster = 2;
|
||||||
}
|
|
||||||
|
|
||||||
CcUnpinData(Context);
|
|
||||||
}
|
}
|
||||||
FatLength = StartCluster;
|
|
||||||
StartCluster = 2;
|
return STATUS_DISK_FULL;
|
||||||
}
|
|
||||||
return(STATUS_DISK_FULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -13,128 +13,138 @@
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
static NTSTATUS VfatFlushFile(PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb)
|
static
|
||||||
|
NTSTATUS
|
||||||
|
VfatFlushFile(
|
||||||
|
PDEVICE_EXTENSION DeviceExt,
|
||||||
|
PVFATFCB Fcb)
|
||||||
{
|
{
|
||||||
IO_STATUS_BLOCK IoStatus;
|
IO_STATUS_BLOCK IoStatus;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
DPRINT("VfatFlushFile(DeviceExt %p, Fcb %p) for '%wZ'\n", DeviceExt, Fcb, &Fcb->PathNameU);
|
DPRINT("VfatFlushFile(DeviceExt %p, Fcb %p) for '%wZ'\n", DeviceExt, Fcb, &Fcb->PathNameU);
|
||||||
|
|
||||||
CcFlushCache(&Fcb->SectionObjectPointers, NULL, 0, &IoStatus);
|
CcFlushCache(&Fcb->SectionObjectPointers, NULL, 0, &IoStatus);
|
||||||
if (IoStatus.Status == STATUS_INVALID_PARAMETER)
|
if (IoStatus.Status == STATUS_INVALID_PARAMETER)
|
||||||
{
|
{
|
||||||
/* FIXME: Caching was possible not initialized */
|
/* FIXME: Caching was possible not initialized */
|
||||||
IoStatus.Status = STATUS_SUCCESS;
|
IoStatus.Status = STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
if (Fcb->Flags & FCB_IS_DIRTY)
|
|
||||||
{
|
if (Fcb->Flags & FCB_IS_DIRTY)
|
||||||
Status = VfatUpdateEntry(Fcb);
|
{
|
||||||
if (!NT_SUCCESS(Status))
|
Status = VfatUpdateEntry(Fcb);
|
||||||
{
|
if (!NT_SUCCESS(Status))
|
||||||
IoStatus.Status = Status;
|
{
|
||||||
}
|
IoStatus.Status = Status;
|
||||||
}
|
}
|
||||||
return IoStatus.Status;
|
}
|
||||||
|
return IoStatus.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS VfatFlushVolume(PDEVICE_EXTENSION DeviceExt, PVFATFCB VolumeFcb)
|
NTSTATUS
|
||||||
|
VfatFlushVolume(
|
||||||
|
PDEVICE_EXTENSION DeviceExt,
|
||||||
|
PVFATFCB VolumeFcb)
|
||||||
{
|
{
|
||||||
PLIST_ENTRY ListEntry;
|
PLIST_ENTRY ListEntry;
|
||||||
PVFATFCB Fcb;
|
PVFATFCB Fcb;
|
||||||
NTSTATUS Status, ReturnStatus = STATUS_SUCCESS;
|
NTSTATUS Status, ReturnStatus = STATUS_SUCCESS;
|
||||||
|
|
||||||
DPRINT("VfatFlushVolume(DeviceExt %p, FatFcb %p)\n", DeviceExt, VolumeFcb);
|
DPRINT("VfatFlushVolume(DeviceExt %p, FatFcb %p)\n", DeviceExt, VolumeFcb);
|
||||||
|
|
||||||
ListEntry = DeviceExt->FcbListHead.Flink;
|
ListEntry = DeviceExt->FcbListHead.Flink;
|
||||||
while (ListEntry != &DeviceExt->FcbListHead)
|
while (ListEntry != &DeviceExt->FcbListHead)
|
||||||
{
|
{
|
||||||
Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry);
|
Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry);
|
||||||
ListEntry = ListEntry->Flink;
|
ListEntry = ListEntry->Flink;
|
||||||
if (!vfatFCBIsDirectory(Fcb))
|
if (!vfatFCBIsDirectory(Fcb))
|
||||||
{
|
{
|
||||||
ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
|
ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
|
||||||
Status = VfatFlushFile(DeviceExt, Fcb);
|
Status = VfatFlushFile(DeviceExt, Fcb);
|
||||||
ExReleaseResourceLite (&Fcb->MainResource);
|
ExReleaseResourceLite (&Fcb->MainResource);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("VfatFlushFile failed, status = %x\n", Status);
|
DPRINT1("VfatFlushFile failed, status = %x\n", Status);
|
||||||
ReturnStatus = Status;
|
ReturnStatus = Status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* FIXME: Stop flushing if this is a removable media and the media was removed */
|
/* FIXME: Stop flushing if this is a removable media and the media was removed */
|
||||||
}
|
}
|
||||||
ListEntry = DeviceExt->FcbListHead.Flink;
|
|
||||||
while (ListEntry != &DeviceExt->FcbListHead)
|
|
||||||
{
|
|
||||||
Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry);
|
|
||||||
ListEntry = ListEntry->Flink;
|
|
||||||
if (vfatFCBIsDirectory(Fcb))
|
|
||||||
{
|
|
||||||
ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
|
|
||||||
Status = VfatFlushFile(DeviceExt, Fcb);
|
|
||||||
ExReleaseResourceLite (&Fcb->MainResource);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("VfatFlushFile failed, status = %x\n", Status);
|
|
||||||
ReturnStatus = Status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* FIXME: Stop flushing if this is a removable media and the media was removed */
|
|
||||||
}
|
|
||||||
|
|
||||||
Fcb = (PVFATFCB) DeviceExt->FATFileObject->FsContext;
|
ListEntry = DeviceExt->FcbListHead.Flink;
|
||||||
|
while (ListEntry != &DeviceExt->FcbListHead)
|
||||||
|
{
|
||||||
|
Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry);
|
||||||
|
ListEntry = ListEntry->Flink;
|
||||||
|
if (vfatFCBIsDirectory(Fcb))
|
||||||
|
{
|
||||||
|
ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
|
||||||
|
Status = VfatFlushFile(DeviceExt, Fcb);
|
||||||
|
ExReleaseResourceLite (&Fcb->MainResource);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("VfatFlushFile failed, status = %x\n", Status);
|
||||||
|
ReturnStatus = Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* FIXME: Stop flushing if this is a removable media and the media was removed */
|
||||||
|
}
|
||||||
|
|
||||||
ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE);
|
Fcb = (PVFATFCB) DeviceExt->FATFileObject->FsContext;
|
||||||
Status = VfatFlushFile(DeviceExt, Fcb);
|
|
||||||
ExReleaseResourceLite(&DeviceExt->FatResource);
|
|
||||||
|
|
||||||
/* FIXME: Flush the buffers from storage device */
|
ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE);
|
||||||
|
Status = VfatFlushFile(DeviceExt, Fcb);
|
||||||
|
ExReleaseResourceLite(&DeviceExt->FatResource);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
/* FIXME: Flush the buffers from storage device */
|
||||||
{
|
|
||||||
DPRINT1("VfatFlushFile failed, status = %x\n", Status);
|
|
||||||
ReturnStatus = Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ReturnStatus;
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("VfatFlushFile failed, status = %x\n", Status);
|
||||||
|
ReturnStatus = Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ReturnStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS VfatFlush(PVFAT_IRP_CONTEXT IrpContext)
|
NTSTATUS
|
||||||
|
VfatFlush(
|
||||||
|
PVFAT_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PVFATFCB Fcb;
|
PVFATFCB Fcb;
|
||||||
/*
|
|
||||||
* This request is not allowed on the main device object.
|
|
||||||
*/
|
|
||||||
if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
|
|
||||||
{
|
|
||||||
Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
||||||
goto ByeBye;
|
|
||||||
}
|
|
||||||
|
|
||||||
Fcb = (PVFATFCB)IrpContext->FileObject->FsContext;
|
/* This request is not allowed on the main device object. */
|
||||||
ASSERT(Fcb);
|
if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
|
||||||
|
{
|
||||||
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
goto ByeBye;
|
||||||
|
}
|
||||||
|
|
||||||
if (Fcb->Flags & FCB_IS_VOLUME)
|
Fcb = (PVFATFCB)IrpContext->FileObject->FsContext;
|
||||||
{
|
ASSERT(Fcb);
|
||||||
ExAcquireResourceExclusiveLite(&IrpContext->DeviceExt->DirResource, TRUE);
|
|
||||||
Status = VfatFlushVolume(IrpContext->DeviceExt, Fcb);
|
if (Fcb->Flags & FCB_IS_VOLUME)
|
||||||
ExReleaseResourceLite(&IrpContext->DeviceExt->DirResource);
|
{
|
||||||
}
|
ExAcquireResourceExclusiveLite(&IrpContext->DeviceExt->DirResource, TRUE);
|
||||||
else
|
Status = VfatFlushVolume(IrpContext->DeviceExt, Fcb);
|
||||||
{
|
ExReleaseResourceLite(&IrpContext->DeviceExt->DirResource);
|
||||||
ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
|
}
|
||||||
Status = VfatFlushFile(IrpContext->DeviceExt, Fcb);
|
else
|
||||||
ExReleaseResourceLite (&Fcb->MainResource);
|
{
|
||||||
}
|
ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
|
||||||
|
Status = VfatFlushFile(IrpContext->DeviceExt, Fcb);
|
||||||
|
ExReleaseResourceLite (&Fcb->MainResource);
|
||||||
|
}
|
||||||
|
|
||||||
ByeBye:
|
ByeBye:
|
||||||
IrpContext->Irp->IoStatus.Status = Status;
|
IrpContext->Irp->IoStatus.Status = Status;
|
||||||
IrpContext->Irp->IoStatus.Information = 0;
|
IrpContext->Irp->IoStatus.Information = 0;
|
||||||
IoCompleteRequest (IrpContext->Irp, IO_NO_INCREMENT);
|
IoCompleteRequest (IrpContext->Irp, IO_NO_INCREMENT);
|
||||||
VfatFreeIrpContext(IrpContext);
|
VfatFreeIrpContext(IrpContext);
|
||||||
|
|
||||||
return (Status);
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -33,303 +33,309 @@
|
||||||
#define CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->FatInfo.BytesPerCluster > PAGE_SIZE ? \
|
#define CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->FatInfo.BytesPerCluster > PAGE_SIZE ? \
|
||||||
(pDeviceExt)->FatInfo.BytesPerCluster : PAGE_SIZE)
|
(pDeviceExt)->FatInfo.BytesPerCluster : PAGE_SIZE)
|
||||||
|
|
||||||
static NTSTATUS
|
static
|
||||||
VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount,
|
NTSTATUS
|
||||||
PBOOLEAN RecognizedFS,
|
VfatHasFileSystem(
|
||||||
PFATINFO pFatInfo)
|
PDEVICE_OBJECT DeviceToMount,
|
||||||
|
PBOOLEAN RecognizedFS,
|
||||||
|
PFATINFO pFatInfo)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PARTITION_INFORMATION PartitionInfo;
|
PARTITION_INFORMATION PartitionInfo;
|
||||||
DISK_GEOMETRY DiskGeometry;
|
DISK_GEOMETRY DiskGeometry;
|
||||||
FATINFO FatInfo;
|
FATINFO FatInfo;
|
||||||
ULONG Size;
|
ULONG Size;
|
||||||
ULONG Sectors;
|
ULONG Sectors;
|
||||||
LARGE_INTEGER Offset;
|
LARGE_INTEGER Offset;
|
||||||
struct _BootSector* Boot;
|
struct _BootSector* Boot;
|
||||||
struct _BootSectorFatX* BootFatX;
|
struct _BootSectorFatX* BootFatX;
|
||||||
BOOLEAN PartitionInfoIsValid = FALSE;
|
BOOLEAN PartitionInfoIsValid = FALSE;
|
||||||
|
|
||||||
DPRINT("VfatHasFileSystem\n");
|
DPRINT("VfatHasFileSystem\n");
|
||||||
|
|
||||||
*RecognizedFS = FALSE;
|
*RecognizedFS = FALSE;
|
||||||
|
|
||||||
Size = sizeof(DISK_GEOMETRY);
|
Size = sizeof(DISK_GEOMETRY);
|
||||||
Status = VfatBlockDeviceIoControl(DeviceToMount,
|
Status = VfatBlockDeviceIoControl(DeviceToMount,
|
||||||
IOCTL_DISK_GET_DRIVE_GEOMETRY,
|
IOCTL_DISK_GET_DRIVE_GEOMETRY,
|
||||||
NULL,
|
NULL,
|
||||||
0,
|
0,
|
||||||
&DiskGeometry,
|
&DiskGeometry,
|
||||||
&Size,
|
&Size,
|
||||||
FALSE);
|
FALSE);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT("VfatBlockDeviceIoControl faild (%x)\n", Status);
|
DPRINT("VfatBlockDeviceIoControl faild (%x)\n", Status);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
FatInfo.FixedMedia = DiskGeometry.MediaType == FixedMedia ? TRUE : FALSE;
|
|
||||||
if (DiskGeometry.MediaType == FixedMedia || DiskGeometry.MediaType == RemovableMedia)
|
FatInfo.FixedMedia = DiskGeometry.MediaType == FixedMedia ? TRUE : FALSE;
|
||||||
{
|
if (DiskGeometry.MediaType == FixedMedia || DiskGeometry.MediaType == RemovableMedia)
|
||||||
// We have found a hard disk
|
{
|
||||||
Size = sizeof(PARTITION_INFORMATION);
|
// We have found a hard disk
|
||||||
Status = VfatBlockDeviceIoControl(DeviceToMount,
|
Size = sizeof(PARTITION_INFORMATION);
|
||||||
IOCTL_DISK_GET_PARTITION_INFO,
|
Status = VfatBlockDeviceIoControl(DeviceToMount,
|
||||||
NULL,
|
IOCTL_DISK_GET_PARTITION_INFO,
|
||||||
0,
|
NULL,
|
||||||
&PartitionInfo,
|
0,
|
||||||
&Size,
|
&PartitionInfo,
|
||||||
FALSE);
|
&Size,
|
||||||
if (!NT_SUCCESS(Status))
|
FALSE);
|
||||||
{
|
if (!NT_SUCCESS(Status))
|
||||||
DPRINT("VfatBlockDeviceIoControl faild (%x)\n", Status);
|
{
|
||||||
return Status;
|
DPRINT("VfatBlockDeviceIoControl faild (%x)\n", Status);
|
||||||
}
|
return Status;
|
||||||
PartitionInfoIsValid = TRUE;
|
}
|
||||||
DPRINT("Partition Information:\n");
|
|
||||||
DPRINT("StartingOffset %I64x\n", PartitionInfo.StartingOffset.QuadPart / 512);
|
PartitionInfoIsValid = TRUE;
|
||||||
DPRINT("PartitionLength %I64x\n", PartitionInfo.PartitionLength.QuadPart / 512);
|
DPRINT("Partition Information:\n");
|
||||||
DPRINT("HiddenSectors %u\n", PartitionInfo.HiddenSectors);
|
DPRINT("StartingOffset %I64x\n", PartitionInfo.StartingOffset.QuadPart / 512);
|
||||||
DPRINT("PartitionNumber %u\n", PartitionInfo.PartitionNumber);
|
DPRINT("PartitionLength %I64x\n", PartitionInfo.PartitionLength.QuadPart / 512);
|
||||||
DPRINT("PartitionType %u\n", PartitionInfo.PartitionType);
|
DPRINT("HiddenSectors %u\n", PartitionInfo.HiddenSectors);
|
||||||
DPRINT("BootIndicator %u\n", PartitionInfo.BootIndicator);
|
DPRINT("PartitionNumber %u\n", PartitionInfo.PartitionNumber);
|
||||||
DPRINT("RecognizedPartition %u\n", PartitionInfo.RecognizedPartition);
|
DPRINT("PartitionType %u\n", PartitionInfo.PartitionType);
|
||||||
DPRINT("RewritePartition %u\n", PartitionInfo.RewritePartition);
|
DPRINT("BootIndicator %u\n", PartitionInfo.BootIndicator);
|
||||||
if (PartitionInfo.PartitionType)
|
DPRINT("RecognizedPartition %u\n", PartitionInfo.RecognizedPartition);
|
||||||
{
|
DPRINT("RewritePartition %u\n", PartitionInfo.RewritePartition);
|
||||||
if (PartitionInfo.PartitionType == PARTITION_FAT_12 ||
|
if (PartitionInfo.PartitionType)
|
||||||
PartitionInfo.PartitionType == PARTITION_FAT_16 ||
|
{
|
||||||
PartitionInfo.PartitionType == PARTITION_HUGE ||
|
if (PartitionInfo.PartitionType == PARTITION_FAT_12 ||
|
||||||
PartitionInfo.PartitionType == PARTITION_FAT32 ||
|
PartitionInfo.PartitionType == PARTITION_FAT_16 ||
|
||||||
PartitionInfo.PartitionType == PARTITION_FAT32_XINT13 ||
|
PartitionInfo.PartitionType == PARTITION_HUGE ||
|
||||||
PartitionInfo.PartitionType == PARTITION_XINT13)
|
PartitionInfo.PartitionType == PARTITION_FAT32 ||
|
||||||
{
|
PartitionInfo.PartitionType == PARTITION_FAT32_XINT13 ||
|
||||||
|
PartitionInfo.PartitionType == PARTITION_XINT13)
|
||||||
|
{
|
||||||
|
*RecognizedFS = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (DiskGeometry.MediaType == RemovableMedia &&
|
||||||
|
PartitionInfo.PartitionNumber > 0 &&
|
||||||
|
PartitionInfo.StartingOffset.QuadPart == 0 &&
|
||||||
|
PartitionInfo.PartitionLength.QuadPart > 0)
|
||||||
|
{
|
||||||
|
/* This is possible a removable media formated as super floppy */
|
||||||
*RecognizedFS = TRUE;
|
*RecognizedFS = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (DiskGeometry.MediaType == RemovableMedia &&
|
else if (DiskGeometry.MediaType == Unknown)
|
||||||
PartitionInfo.PartitionNumber > 0 &&
|
{
|
||||||
PartitionInfo.StartingOffset.QuadPart == 0 &&
|
/*
|
||||||
PartitionInfo.PartitionLength.QuadPart > 0)
|
* Floppy disk driver can return Unknown as media type if it
|
||||||
{
|
* doesn't know yet what floppy in the drive really is. This is
|
||||||
/* This is possible a removable media formated as super floppy */
|
* perfectly correct to do under Windows.
|
||||||
*RecognizedFS = TRUE;
|
*/
|
||||||
}
|
*RecognizedFS = TRUE;
|
||||||
}
|
DiskGeometry.BytesPerSector = 512;
|
||||||
else if (DiskGeometry.MediaType == Unknown)
|
}
|
||||||
{
|
else
|
||||||
/*
|
{
|
||||||
* Floppy disk driver can return Unknown as media type if it
|
*RecognizedFS = TRUE;
|
||||||
* doesn't know yet what floppy in the drive really is. This is
|
}
|
||||||
* perfectly correct to do under Windows.
|
|
||||||
*/
|
|
||||||
*RecognizedFS = TRUE;
|
|
||||||
DiskGeometry.BytesPerSector = 512;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*RecognizedFS = TRUE;
|
|
||||||
}
|
|
||||||
if (*RecognizedFS)
|
|
||||||
{
|
|
||||||
|
|
||||||
Boot = ExAllocatePoolWithTag(NonPagedPool, DiskGeometry.BytesPerSector, TAG_VFAT);
|
if (*RecognizedFS)
|
||||||
if (Boot == NULL)
|
{
|
||||||
{
|
Boot = ExAllocatePoolWithTag(NonPagedPool, DiskGeometry.BytesPerSector, TAG_VFAT);
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
if (Boot == NULL)
|
||||||
}
|
{
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
Offset.QuadPart = 0;
|
Offset.QuadPart = 0;
|
||||||
|
|
||||||
/* Try to recognize FAT12/FAT16/FAT32 partitions */
|
/* Try to recognize FAT12/FAT16/FAT32 partitions */
|
||||||
Status = VfatReadDisk(DeviceToMount, &Offset, DiskGeometry.BytesPerSector, (PUCHAR) Boot, FALSE);
|
Status = VfatReadDisk(DeviceToMount, &Offset, DiskGeometry.BytesPerSector, (PUCHAR) Boot, FALSE);
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
if (Boot->Signatur1 != 0xaa55)
|
if (Boot->Signatur1 != 0xaa55)
|
||||||
{
|
|
||||||
*RecognizedFS = FALSE;
|
|
||||||
}
|
|
||||||
if (*RecognizedFS &&
|
|
||||||
Boot->BytesPerSector != 512 &&
|
|
||||||
Boot->BytesPerSector != 1024 &&
|
|
||||||
Boot->BytesPerSector != 2048 &&
|
|
||||||
Boot->BytesPerSector != 4096)
|
|
||||||
{
|
|
||||||
DPRINT1("BytesPerSector %u\n", Boot->BytesPerSector);
|
|
||||||
*RecognizedFS = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*RecognizedFS &&
|
|
||||||
Boot->FATCount != 1 &&
|
|
||||||
Boot->FATCount != 2)
|
|
||||||
{
|
|
||||||
DPRINT1("FATCount %u\n", Boot->FATCount);
|
|
||||||
*RecognizedFS = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*RecognizedFS &&
|
|
||||||
Boot->Media != 0xf0 &&
|
|
||||||
Boot->Media != 0xf8 &&
|
|
||||||
Boot->Media != 0xf9 &&
|
|
||||||
Boot->Media != 0xfa &&
|
|
||||||
Boot->Media != 0xfb &&
|
|
||||||
Boot->Media != 0xfc &&
|
|
||||||
Boot->Media != 0xfd &&
|
|
||||||
Boot->Media != 0xfe &&
|
|
||||||
Boot->Media != 0xff)
|
|
||||||
{
|
|
||||||
DPRINT1("Media %02x\n", Boot->Media);
|
|
||||||
*RecognizedFS = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*RecognizedFS &&
|
|
||||||
Boot->SectorsPerCluster != 1 &&
|
|
||||||
Boot->SectorsPerCluster != 2 &&
|
|
||||||
Boot->SectorsPerCluster != 4 &&
|
|
||||||
Boot->SectorsPerCluster != 8 &&
|
|
||||||
Boot->SectorsPerCluster != 16 &&
|
|
||||||
Boot->SectorsPerCluster != 32 &&
|
|
||||||
Boot->SectorsPerCluster != 64 &&
|
|
||||||
Boot->SectorsPerCluster != 128)
|
|
||||||
{
|
|
||||||
DPRINT1("SectorsPerCluster %02x\n", Boot->SectorsPerCluster);
|
|
||||||
*RecognizedFS = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*RecognizedFS &&
|
|
||||||
Boot->BytesPerSector * Boot->SectorsPerCluster > 32 * 1024)
|
|
||||||
{
|
|
||||||
DPRINT1("ClusterSize %dx\n", Boot->BytesPerSector * Boot->SectorsPerCluster);
|
|
||||||
*RecognizedFS = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*RecognizedFS)
|
|
||||||
{
|
|
||||||
FatInfo.VolumeID = Boot->VolumeID;
|
|
||||||
FatInfo.FATStart = Boot->ReservedSectors;
|
|
||||||
FatInfo.FATCount = Boot->FATCount;
|
|
||||||
FatInfo.FATSectors = Boot->FATSectors ? Boot->FATSectors : ((struct _BootSector32*) Boot)->FATSectors32;
|
|
||||||
FatInfo.BytesPerSector = Boot->BytesPerSector;
|
|
||||||
FatInfo.SectorsPerCluster = Boot->SectorsPerCluster;
|
|
||||||
FatInfo.BytesPerCluster = FatInfo.BytesPerSector * FatInfo.SectorsPerCluster;
|
|
||||||
FatInfo.rootDirectorySectors = ((Boot->RootEntries * 32) + Boot->BytesPerSector - 1) / Boot->BytesPerSector;
|
|
||||||
FatInfo.rootStart = FatInfo.FATStart + FatInfo.FATCount * FatInfo.FATSectors;
|
|
||||||
FatInfo.dataStart = FatInfo.rootStart + FatInfo.rootDirectorySectors;
|
|
||||||
FatInfo.Sectors = Sectors = Boot->Sectors ? Boot->Sectors : Boot->SectorsHuge;
|
|
||||||
Sectors -= Boot->ReservedSectors + FatInfo.FATCount * FatInfo.FATSectors + FatInfo.rootDirectorySectors;
|
|
||||||
FatInfo.NumberOfClusters = Sectors / Boot->SectorsPerCluster;
|
|
||||||
if (FatInfo.NumberOfClusters < 4085)
|
|
||||||
{
|
{
|
||||||
DPRINT("FAT12\n");
|
*RecognizedFS = FALSE;
|
||||||
FatInfo.FatType = FAT12;
|
|
||||||
FatInfo.RootCluster = (FatInfo.rootStart - 1) / FatInfo.SectorsPerCluster;
|
|
||||||
}
|
|
||||||
else if (FatInfo.NumberOfClusters >= 65525)
|
|
||||||
{
|
|
||||||
DPRINT("FAT32\n");
|
|
||||||
FatInfo.FatType = FAT32;
|
|
||||||
FatInfo.RootCluster = ((struct _BootSector32*) Boot)->RootCluster;
|
|
||||||
FatInfo.rootStart = FatInfo.dataStart + ((FatInfo.RootCluster - 2) * FatInfo.SectorsPerCluster);
|
|
||||||
FatInfo.VolumeID = ((struct _BootSector32*) Boot)->VolumeID;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DPRINT("FAT16\n");
|
|
||||||
FatInfo.FatType = FAT16;
|
|
||||||
FatInfo.RootCluster = FatInfo.rootStart / FatInfo.SectorsPerCluster;
|
|
||||||
}
|
|
||||||
if (PartitionInfoIsValid &&
|
|
||||||
FatInfo.Sectors > PartitionInfo.PartitionLength.QuadPart / FatInfo.BytesPerSector)
|
|
||||||
{
|
|
||||||
*RecognizedFS = FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pFatInfo && *RecognizedFS)
|
if (*RecognizedFS &&
|
||||||
|
Boot->BytesPerSector != 512 &&
|
||||||
|
Boot->BytesPerSector != 1024 &&
|
||||||
|
Boot->BytesPerSector != 2048 &&
|
||||||
|
Boot->BytesPerSector != 4096)
|
||||||
{
|
{
|
||||||
*pFatInfo = FatInfo;
|
DPRINT1("BytesPerSector %u\n", Boot->BytesPerSector);
|
||||||
|
*RecognizedFS = FALSE;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ExFreePool(Boot);
|
if (*RecognizedFS &&
|
||||||
}
|
Boot->FATCount != 1 &&
|
||||||
|
Boot->FATCount != 2)
|
||||||
|
{
|
||||||
|
DPRINT1("FATCount %u\n", Boot->FATCount);
|
||||||
|
*RecognizedFS = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (!*RecognizedFS && PartitionInfoIsValid)
|
if (*RecognizedFS &&
|
||||||
{
|
Boot->Media != 0xf0 &&
|
||||||
BootFatX = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct _BootSectorFatX), TAG_VFAT);
|
Boot->Media != 0xf8 &&
|
||||||
if (BootFatX == NULL)
|
Boot->Media != 0xf9 &&
|
||||||
{
|
Boot->Media != 0xfa &&
|
||||||
*RecognizedFS=FALSE;
|
Boot->Media != 0xfb &&
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
Boot->Media != 0xfc &&
|
||||||
}
|
Boot->Media != 0xfd &&
|
||||||
|
Boot->Media != 0xfe &&
|
||||||
|
Boot->Media != 0xff)
|
||||||
|
{
|
||||||
|
DPRINT1("Media %02x\n", Boot->Media);
|
||||||
|
*RecognizedFS = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
Offset.QuadPart = 0;
|
if (*RecognizedFS &&
|
||||||
|
Boot->SectorsPerCluster != 1 &&
|
||||||
|
Boot->SectorsPerCluster != 2 &&
|
||||||
|
Boot->SectorsPerCluster != 4 &&
|
||||||
|
Boot->SectorsPerCluster != 8 &&
|
||||||
|
Boot->SectorsPerCluster != 16 &&
|
||||||
|
Boot->SectorsPerCluster != 32 &&
|
||||||
|
Boot->SectorsPerCluster != 64 &&
|
||||||
|
Boot->SectorsPerCluster != 128)
|
||||||
|
{
|
||||||
|
DPRINT1("SectorsPerCluster %02x\n", Boot->SectorsPerCluster);
|
||||||
|
*RecognizedFS = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Try to recognize FATX16/FATX32 partitions (Xbox) */
|
if (*RecognizedFS &&
|
||||||
Status = VfatReadDisk(DeviceToMount, &Offset, sizeof(struct _BootSectorFatX), (PUCHAR) BootFatX, FALSE);
|
Boot->BytesPerSector * Boot->SectorsPerCluster > 32 * 1024)
|
||||||
if (NT_SUCCESS(Status))
|
{
|
||||||
{
|
DPRINT1("ClusterSize %dx\n", Boot->BytesPerSector * Boot->SectorsPerCluster);
|
||||||
*RecognizedFS = TRUE;
|
*RecognizedFS = FALSE;
|
||||||
if (BootFatX->SysType[0] != 'F' ||
|
}
|
||||||
BootFatX->SysType[1] != 'A' ||
|
|
||||||
BootFatX->SysType[2] != 'T' ||
|
if (*RecognizedFS)
|
||||||
BootFatX->SysType[3] != 'X')
|
{
|
||||||
{
|
FatInfo.VolumeID = Boot->VolumeID;
|
||||||
DPRINT1("SysType %c%c%c%c\n", BootFatX->SysType[0], BootFatX->SysType[1], BootFatX->SysType[2], BootFatX->SysType[3]);
|
FatInfo.FATStart = Boot->ReservedSectors;
|
||||||
|
FatInfo.FATCount = Boot->FATCount;
|
||||||
|
FatInfo.FATSectors = Boot->FATSectors ? Boot->FATSectors : ((struct _BootSector32*) Boot)->FATSectors32;
|
||||||
|
FatInfo.BytesPerSector = Boot->BytesPerSector;
|
||||||
|
FatInfo.SectorsPerCluster = Boot->SectorsPerCluster;
|
||||||
|
FatInfo.BytesPerCluster = FatInfo.BytesPerSector * FatInfo.SectorsPerCluster;
|
||||||
|
FatInfo.rootDirectorySectors = ((Boot->RootEntries * 32) + Boot->BytesPerSector - 1) / Boot->BytesPerSector;
|
||||||
|
FatInfo.rootStart = FatInfo.FATStart + FatInfo.FATCount * FatInfo.FATSectors;
|
||||||
|
FatInfo.dataStart = FatInfo.rootStart + FatInfo.rootDirectorySectors;
|
||||||
|
FatInfo.Sectors = Sectors = Boot->Sectors ? Boot->Sectors : Boot->SectorsHuge;
|
||||||
|
Sectors -= Boot->ReservedSectors + FatInfo.FATCount * FatInfo.FATSectors + FatInfo.rootDirectorySectors;
|
||||||
|
FatInfo.NumberOfClusters = Sectors / Boot->SectorsPerCluster;
|
||||||
|
if (FatInfo.NumberOfClusters < 4085)
|
||||||
|
{
|
||||||
|
DPRINT("FAT12\n");
|
||||||
|
FatInfo.FatType = FAT12;
|
||||||
|
FatInfo.RootCluster = (FatInfo.rootStart - 1) / FatInfo.SectorsPerCluster;
|
||||||
|
}
|
||||||
|
else if (FatInfo.NumberOfClusters >= 65525)
|
||||||
|
{
|
||||||
|
DPRINT("FAT32\n");
|
||||||
|
FatInfo.FatType = FAT32;
|
||||||
|
FatInfo.RootCluster = ((struct _BootSector32*) Boot)->RootCluster;
|
||||||
|
FatInfo.rootStart = FatInfo.dataStart + ((FatInfo.RootCluster - 2) * FatInfo.SectorsPerCluster);
|
||||||
|
FatInfo.VolumeID = ((struct _BootSector32*) Boot)->VolumeID;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINT("FAT16\n");
|
||||||
|
FatInfo.FatType = FAT16;
|
||||||
|
FatInfo.RootCluster = FatInfo.rootStart / FatInfo.SectorsPerCluster;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PartitionInfoIsValid &&
|
||||||
|
FatInfo.Sectors > PartitionInfo.PartitionLength.QuadPart / FatInfo.BytesPerSector)
|
||||||
|
{
|
||||||
|
*RecognizedFS = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pFatInfo && *RecognizedFS)
|
||||||
|
{
|
||||||
|
*pFatInfo = FatInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ExFreePool(Boot);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!*RecognizedFS && PartitionInfoIsValid)
|
||||||
|
{
|
||||||
|
BootFatX = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct _BootSectorFatX), TAG_VFAT);
|
||||||
|
if (BootFatX == NULL)
|
||||||
|
{
|
||||||
*RecognizedFS=FALSE;
|
*RecognizedFS=FALSE;
|
||||||
}
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
if (*RecognizedFS &&
|
Offset.QuadPart = 0;
|
||||||
BootFatX->SectorsPerCluster != 1 &&
|
|
||||||
BootFatX->SectorsPerCluster != 2 &&
|
|
||||||
BootFatX->SectorsPerCluster != 4 &&
|
|
||||||
BootFatX->SectorsPerCluster != 8 &&
|
|
||||||
BootFatX->SectorsPerCluster != 16 &&
|
|
||||||
BootFatX->SectorsPerCluster != 32 &&
|
|
||||||
BootFatX->SectorsPerCluster != 64 &&
|
|
||||||
BootFatX->SectorsPerCluster != 128)
|
|
||||||
{
|
|
||||||
DPRINT1("SectorsPerCluster %lu\n", BootFatX->SectorsPerCluster);
|
|
||||||
*RecognizedFS=FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*RecognizedFS)
|
/* Try to recognize FATX16/FATX32 partitions (Xbox) */
|
||||||
{
|
Status = VfatReadDisk(DeviceToMount, &Offset, sizeof(struct _BootSectorFatX), (PUCHAR) BootFatX, FALSE);
|
||||||
FatInfo.BytesPerSector = DiskGeometry.BytesPerSector;
|
if (NT_SUCCESS(Status))
|
||||||
FatInfo.SectorsPerCluster = BootFatX->SectorsPerCluster;
|
{
|
||||||
FatInfo.rootDirectorySectors = BootFatX->SectorsPerCluster;
|
*RecognizedFS = TRUE;
|
||||||
FatInfo.BytesPerCluster = BootFatX->SectorsPerCluster * DiskGeometry.BytesPerSector;
|
if (BootFatX->SysType[0] != 'F' ||
|
||||||
FatInfo.Sectors = (ULONG)(PartitionInfo.PartitionLength.QuadPart / DiskGeometry.BytesPerSector);
|
BootFatX->SysType[1] != 'A' ||
|
||||||
if (FatInfo.Sectors / FatInfo.SectorsPerCluster < 65525)
|
BootFatX->SysType[2] != 'T' ||
|
||||||
|
BootFatX->SysType[3] != 'X')
|
||||||
{
|
{
|
||||||
DPRINT("FATX16\n");
|
DPRINT1("SysType %c%c%c%c\n", BootFatX->SysType[0], BootFatX->SysType[1], BootFatX->SysType[2], BootFatX->SysType[3]);
|
||||||
FatInfo.FatType = FATX16;
|
*RecognizedFS=FALSE;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
DPRINT("FATX32\n");
|
|
||||||
FatInfo.FatType = FATX32;
|
|
||||||
}
|
|
||||||
FatInfo.VolumeID = BootFatX->VolumeID;
|
|
||||||
FatInfo.FATStart = sizeof(struct _BootSectorFatX) / DiskGeometry.BytesPerSector;
|
|
||||||
FatInfo.FATCount = BootFatX->FATCount;
|
|
||||||
FatInfo.FATSectors =
|
|
||||||
ROUND_UP(FatInfo.Sectors / FatInfo.SectorsPerCluster * (FatInfo.FatType == FATX16 ? 2 : 4), 4096) /
|
|
||||||
FatInfo.BytesPerSector;
|
|
||||||
FatInfo.rootStart = FatInfo.FATStart + FatInfo.FATCount * FatInfo.FATSectors;
|
|
||||||
FatInfo.RootCluster = (FatInfo.rootStart - 1) / FatInfo.SectorsPerCluster;
|
|
||||||
FatInfo.dataStart = FatInfo.rootStart + FatInfo.rootDirectorySectors;
|
|
||||||
FatInfo.NumberOfClusters = (FatInfo.Sectors - FatInfo.dataStart) / FatInfo.SectorsPerCluster;
|
|
||||||
|
|
||||||
if (pFatInfo && *RecognizedFS)
|
if (*RecognizedFS &&
|
||||||
|
BootFatX->SectorsPerCluster != 1 &&
|
||||||
|
BootFatX->SectorsPerCluster != 2 &&
|
||||||
|
BootFatX->SectorsPerCluster != 4 &&
|
||||||
|
BootFatX->SectorsPerCluster != 8 &&
|
||||||
|
BootFatX->SectorsPerCluster != 16 &&
|
||||||
|
BootFatX->SectorsPerCluster != 32 &&
|
||||||
|
BootFatX->SectorsPerCluster != 64 &&
|
||||||
|
BootFatX->SectorsPerCluster != 128)
|
||||||
{
|
{
|
||||||
*pFatInfo = FatInfo;
|
DPRINT1("SectorsPerCluster %lu\n", BootFatX->SectorsPerCluster);
|
||||||
|
*RecognizedFS=FALSE;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
ExFreePool(BootFatX);
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINT("VfatHasFileSystem done\n");
|
if (*RecognizedFS)
|
||||||
return Status;
|
{
|
||||||
|
FatInfo.BytesPerSector = DiskGeometry.BytesPerSector;
|
||||||
|
FatInfo.SectorsPerCluster = BootFatX->SectorsPerCluster;
|
||||||
|
FatInfo.rootDirectorySectors = BootFatX->SectorsPerCluster;
|
||||||
|
FatInfo.BytesPerCluster = BootFatX->SectorsPerCluster * DiskGeometry.BytesPerSector;
|
||||||
|
FatInfo.Sectors = (ULONG)(PartitionInfo.PartitionLength.QuadPart / DiskGeometry.BytesPerSector);
|
||||||
|
if (FatInfo.Sectors / FatInfo.SectorsPerCluster < 65525)
|
||||||
|
{
|
||||||
|
DPRINT("FATX16\n");
|
||||||
|
FatInfo.FatType = FATX16;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINT("FATX32\n");
|
||||||
|
FatInfo.FatType = FATX32;
|
||||||
|
}
|
||||||
|
FatInfo.VolumeID = BootFatX->VolumeID;
|
||||||
|
FatInfo.FATStart = sizeof(struct _BootSectorFatX) / DiskGeometry.BytesPerSector;
|
||||||
|
FatInfo.FATCount = BootFatX->FATCount;
|
||||||
|
FatInfo.FATSectors =
|
||||||
|
ROUND_UP(FatInfo.Sectors / FatInfo.SectorsPerCluster * (FatInfo.FatType == FATX16 ? 2 : 4), 4096) /
|
||||||
|
FatInfo.BytesPerSector;
|
||||||
|
FatInfo.rootStart = FatInfo.FATStart + FatInfo.FATCount * FatInfo.FATSectors;
|
||||||
|
FatInfo.RootCluster = (FatInfo.rootStart - 1) / FatInfo.SectorsPerCluster;
|
||||||
|
FatInfo.dataStart = FatInfo.rootStart + FatInfo.rootDirectorySectors;
|
||||||
|
FatInfo.NumberOfClusters = (FatInfo.Sectors - FatInfo.dataStart) / FatInfo.SectorsPerCluster;
|
||||||
|
|
||||||
|
if (pFatInfo && *RecognizedFS)
|
||||||
|
{
|
||||||
|
*pFatInfo = FatInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ExFreePool(BootFatX);
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("VfatHasFileSystem done\n");
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS
|
static NTSTATUS
|
||||||
|
|
|
@ -34,9 +34,6 @@ PVFAT_GLOBAL_DATA VfatGlobalData;
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
|
||||||
DriverEntry(PDRIVER_OBJECT DriverObject,
|
|
||||||
PUNICODE_STRING RegistryPath)
|
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Called by the system to initialize the driver
|
* FUNCTION: Called by the system to initialize the driver
|
||||||
* ARGUMENTS:
|
* ARGUMENTS:
|
||||||
|
@ -44,91 +41,90 @@ DriverEntry(PDRIVER_OBJECT DriverObject,
|
||||||
* RegistryPath = path to our configuration entries
|
* RegistryPath = path to our configuration entries
|
||||||
* RETURNS: Success or failure
|
* RETURNS: Success or failure
|
||||||
*/
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
DriverEntry(
|
||||||
|
IN PDRIVER_OBJECT DriverObject,
|
||||||
|
IN PUNICODE_STRING RegistryPath)
|
||||||
{
|
{
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject;
|
||||||
UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Fat");
|
UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Fat");
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
UNREFERENCED_PARAMETER(RegistryPath);
|
UNREFERENCED_PARAMETER(RegistryPath);
|
||||||
|
|
||||||
Status = IoCreateDevice(DriverObject,
|
Status = IoCreateDevice(DriverObject,
|
||||||
sizeof(VFAT_GLOBAL_DATA),
|
sizeof(VFAT_GLOBAL_DATA),
|
||||||
&DeviceName,
|
&DeviceName,
|
||||||
FILE_DEVICE_DISK_FILE_SYSTEM,
|
FILE_DEVICE_DISK_FILE_SYSTEM,
|
||||||
0,
|
0,
|
||||||
FALSE,
|
FALSE,
|
||||||
&DeviceObject);
|
&DeviceObject);
|
||||||
|
if (Status == STATUS_OBJECT_NAME_EXISTS ||
|
||||||
if (Status == STATUS_OBJECT_NAME_EXISTS ||
|
|
||||||
Status == STATUS_OBJECT_NAME_COLLISION)
|
Status == STATUS_OBJECT_NAME_COLLISION)
|
||||||
{
|
{
|
||||||
/* Try an other name, if 'Fat' is already in use. 'Fat' is also used by fastfat.sys on W2K */
|
/* Try an other name, if 'Fat' is already in use. 'Fat' is also used by fastfat.sys on W2K */
|
||||||
RtlInitUnicodeString(&DeviceName, L"\\RosFat");
|
RtlInitUnicodeString(&DeviceName, L"\\RosFat");
|
||||||
Status = IoCreateDevice(DriverObject,
|
Status = IoCreateDevice(DriverObject,
|
||||||
sizeof(VFAT_GLOBAL_DATA),
|
sizeof(VFAT_GLOBAL_DATA),
|
||||||
&DeviceName,
|
&DeviceName,
|
||||||
FILE_DEVICE_DISK_FILE_SYSTEM,
|
FILE_DEVICE_DISK_FILE_SYSTEM,
|
||||||
0,
|
0,
|
||||||
FALSE,
|
FALSE,
|
||||||
&DeviceObject);
|
&DeviceObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
VfatGlobalData = DeviceObject->DeviceExtension;
|
||||||
|
RtlZeroMemory (VfatGlobalData, sizeof(VFAT_GLOBAL_DATA));
|
||||||
|
VfatGlobalData->DriverObject = DriverObject;
|
||||||
|
VfatGlobalData->DeviceObject = DeviceObject;
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
DeviceObject->Flags |= DO_DIRECT_IO;
|
||||||
{
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = VfatBuildRequest;
|
||||||
return (Status);
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = VfatBuildRequest;
|
||||||
}
|
DriverObject->MajorFunction[IRP_MJ_READ] = VfatBuildRequest;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_WRITE] = VfatBuildRequest;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = VfatBuildRequest;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = VfatBuildRequest;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = VfatBuildRequest;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = VfatBuildRequest;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = VfatBuildRequest;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = VfatBuildRequest;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = VfatShutdown;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = VfatBuildRequest;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = VfatBuildRequest;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = VfatBuildRequest;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_PNP] = VfatBuildRequest;
|
||||||
|
|
||||||
VfatGlobalData = DeviceObject->DeviceExtension;
|
DriverObject->DriverUnload = NULL;
|
||||||
RtlZeroMemory (VfatGlobalData, sizeof(VFAT_GLOBAL_DATA));
|
|
||||||
VfatGlobalData->DriverObject = DriverObject;
|
|
||||||
VfatGlobalData->DeviceObject = DeviceObject;
|
|
||||||
|
|
||||||
DeviceObject->Flags |= DO_DIRECT_IO;
|
/* Cache manager */
|
||||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = VfatBuildRequest;
|
VfatGlobalData->CacheMgrCallbacks.AcquireForLazyWrite = VfatAcquireForLazyWrite;
|
||||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = VfatBuildRequest;
|
VfatGlobalData->CacheMgrCallbacks.ReleaseFromLazyWrite = VfatReleaseFromLazyWrite;
|
||||||
DriverObject->MajorFunction[IRP_MJ_READ] = VfatBuildRequest;
|
VfatGlobalData->CacheMgrCallbacks.AcquireForReadAhead = VfatAcquireForReadAhead;
|
||||||
DriverObject->MajorFunction[IRP_MJ_WRITE] = VfatBuildRequest;
|
VfatGlobalData->CacheMgrCallbacks.ReleaseFromReadAhead = VfatReleaseFromReadAhead;
|
||||||
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = VfatBuildRequest;
|
|
||||||
DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = VfatBuildRequest;
|
|
||||||
DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = VfatBuildRequest;
|
|
||||||
DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = VfatBuildRequest;
|
|
||||||
DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] =
|
|
||||||
VfatBuildRequest;
|
|
||||||
DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] =
|
|
||||||
VfatBuildRequest;
|
|
||||||
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = VfatShutdown;
|
|
||||||
DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = VfatBuildRequest;
|
|
||||||
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = VfatBuildRequest;
|
|
||||||
DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = VfatBuildRequest;
|
|
||||||
DriverObject->MajorFunction[IRP_MJ_PNP] = VfatBuildRequest;
|
|
||||||
|
|
||||||
DriverObject->DriverUnload = NULL;
|
/* Fast I/O */
|
||||||
|
VfatInitFastIoRoutines(&VfatGlobalData->FastIoDispatch);
|
||||||
|
DriverObject->FastIoDispatch = &VfatGlobalData->FastIoDispatch;
|
||||||
|
|
||||||
/* Cache manager */
|
/* Private lists */
|
||||||
VfatGlobalData->CacheMgrCallbacks.AcquireForLazyWrite = VfatAcquireForLazyWrite;
|
ExInitializeNPagedLookasideList(&VfatGlobalData->FcbLookasideList,
|
||||||
VfatGlobalData->CacheMgrCallbacks.ReleaseFromLazyWrite = VfatReleaseFromLazyWrite;
|
NULL, NULL, 0, sizeof(VFATFCB), TAG_FCB, 0);
|
||||||
VfatGlobalData->CacheMgrCallbacks.AcquireForReadAhead = VfatAcquireForReadAhead;
|
ExInitializeNPagedLookasideList(&VfatGlobalData->CcbLookasideList,
|
||||||
VfatGlobalData->CacheMgrCallbacks.ReleaseFromReadAhead = VfatReleaseFromReadAhead;
|
NULL, NULL, 0, sizeof(VFATCCB), TAG_CCB, 0);
|
||||||
|
ExInitializeNPagedLookasideList(&VfatGlobalData->IrpContextLookasideList,
|
||||||
|
NULL, NULL, 0, sizeof(VFAT_IRP_CONTEXT), TAG_IRP, 0);
|
||||||
|
|
||||||
/* Fast I/O */
|
ExInitializeResourceLite(&VfatGlobalData->VolumeListLock);
|
||||||
VfatInitFastIoRoutines(&VfatGlobalData->FastIoDispatch);
|
InitializeListHead(&VfatGlobalData->VolumeListHead);
|
||||||
DriverObject->FastIoDispatch = &VfatGlobalData->FastIoDispatch;
|
IoRegisterFileSystem(DeviceObject);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
/* Private lists */
|
|
||||||
ExInitializeNPagedLookasideList(&VfatGlobalData->FcbLookasideList,
|
|
||||||
NULL, NULL, 0, sizeof(VFATFCB), TAG_FCB, 0);
|
|
||||||
ExInitializeNPagedLookasideList(&VfatGlobalData->CcbLookasideList,
|
|
||||||
NULL, NULL, 0, sizeof(VFATCCB), TAG_CCB, 0);
|
|
||||||
ExInitializeNPagedLookasideList(&VfatGlobalData->IrpContextLookasideList,
|
|
||||||
NULL, NULL, 0, sizeof(VFAT_IRP_CONTEXT), TAG_IRP, 0);
|
|
||||||
|
|
||||||
ExInitializeResourceLite(&VfatGlobalData->VolumeListLock);
|
|
||||||
InitializeListHead(&VfatGlobalData->VolumeListHead);
|
|
||||||
IoRegisterFileSystem(DeviceObject);
|
|
||||||
return(STATUS_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
||||||
|
|
|
@ -16,263 +16,286 @@
|
||||||
|
|
||||||
const char* MajorFunctionNames[] =
|
const char* MajorFunctionNames[] =
|
||||||
{
|
{
|
||||||
"IRP_MJ_CREATE",
|
"IRP_MJ_CREATE",
|
||||||
"IRP_MJ_CREATE_NAMED_PIPE",
|
"IRP_MJ_CREATE_NAMED_PIPE",
|
||||||
"IRP_MJ_CLOSE",
|
"IRP_MJ_CLOSE",
|
||||||
"IRP_MJ_READ",
|
"IRP_MJ_READ",
|
||||||
"IRP_MJ_WRITE",
|
"IRP_MJ_WRITE",
|
||||||
"IRP_MJ_QUERY_INFORMATION",
|
"IRP_MJ_QUERY_INFORMATION",
|
||||||
"IRP_MJ_SET_INFORMATION",
|
"IRP_MJ_SET_INFORMATION",
|
||||||
"IRP_MJ_QUERY_EA",
|
"IRP_MJ_QUERY_EA",
|
||||||
"IRP_MJ_SET_EA",
|
"IRP_MJ_SET_EA",
|
||||||
"IRP_MJ_FLUSH_BUFFERS",
|
"IRP_MJ_FLUSH_BUFFERS",
|
||||||
"IRP_MJ_QUERY_VOLUME_INFORMATION",
|
"IRP_MJ_QUERY_VOLUME_INFORMATION",
|
||||||
"IRP_MJ_SET_VOLUME_INFORMATION",
|
"IRP_MJ_SET_VOLUME_INFORMATION",
|
||||||
"IRP_MJ_DIRECTORY_CONTROL",
|
"IRP_MJ_DIRECTORY_CONTROL",
|
||||||
"IRP_MJ_FILE_SYSTEM_CONTROL",
|
"IRP_MJ_FILE_SYSTEM_CONTROL",
|
||||||
"IRP_MJ_DEVICE_CONTROL",
|
"IRP_MJ_DEVICE_CONTROL",
|
||||||
"IRP_MJ_INTERNAL_DEVICE_CONTROL",
|
"IRP_MJ_INTERNAL_DEVICE_CONTROL",
|
||||||
"IRP_MJ_SHUTDOWN",
|
"IRP_MJ_SHUTDOWN",
|
||||||
"IRP_MJ_LOCK_CONTROL",
|
"IRP_MJ_LOCK_CONTROL",
|
||||||
"IRP_MJ_CLEANUP",
|
"IRP_MJ_CLEANUP",
|
||||||
"IRP_MJ_CREATE_MAILSLOT",
|
"IRP_MJ_CREATE_MAILSLOT",
|
||||||
"IRP_MJ_QUERY_SECURITY",
|
"IRP_MJ_QUERY_SECURITY",
|
||||||
"IRP_MJ_SET_SECURITY",
|
"IRP_MJ_SET_SECURITY",
|
||||||
"IRP_MJ_POWER",
|
"IRP_MJ_POWER",
|
||||||
"IRP_MJ_SYSTEM_CONTROL",
|
"IRP_MJ_SYSTEM_CONTROL",
|
||||||
"IRP_MJ_DEVICE_CHANGE",
|
"IRP_MJ_DEVICE_CHANGE",
|
||||||
"IRP_MJ_QUERY_QUOTA",
|
"IRP_MJ_QUERY_QUOTA",
|
||||||
"IRP_MJ_SET_QUOTA",
|
"IRP_MJ_SET_QUOTA",
|
||||||
"IRP_MJ_PNP",
|
"IRP_MJ_PNP",
|
||||||
"IRP_MJ_MAXIMUM_FUNCTION"
|
"IRP_MJ_MAXIMUM_FUNCTION"
|
||||||
};
|
};
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
|
||||||
|
|
||||||
static LONG QueueCount = 0;
|
static LONG QueueCount = 0;
|
||||||
|
|
||||||
static NTSTATUS VfatLockControl(
|
/* FUNCTIONS ****************************************************************/
|
||||||
IN PVFAT_IRP_CONTEXT IrpContext
|
|
||||||
)
|
static
|
||||||
|
NTSTATUS
|
||||||
|
VfatLockControl(
|
||||||
|
IN PVFAT_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
PVFATFCB Fcb;
|
PVFATFCB Fcb;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
DPRINT("VfatLockControl(IrpContext %p)\n", IrpContext);
|
DPRINT("VfatLockControl(IrpContext %p)\n", IrpContext);
|
||||||
|
|
||||||
ASSERT(IrpContext);
|
ASSERT(IrpContext);
|
||||||
|
|
||||||
Fcb = (PVFATFCB)IrpContext->FileObject->FsContext;
|
Fcb = (PVFATFCB)IrpContext->FileObject->FsContext;
|
||||||
|
|
||||||
if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
|
if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
|
||||||
{
|
{
|
||||||
Status = STATUS_INVALID_DEVICE_REQUEST;
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
goto Fail;
|
goto Fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*Fcb->Attributes & FILE_ATTRIBUTE_DIRECTORY)
|
if (*Fcb->Attributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
{
|
{
|
||||||
Status = STATUS_INVALID_PARAMETER;
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
goto Fail;
|
goto Fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = FsRtlProcessFileLock(&Fcb->FileLock,
|
Status = FsRtlProcessFileLock(&Fcb->FileLock,
|
||||||
IrpContext->Irp,
|
IrpContext->Irp,
|
||||||
NULL
|
NULL);
|
||||||
);
|
|
||||||
|
|
||||||
VfatFreeIrpContext(IrpContext);
|
VfatFreeIrpContext(IrpContext);
|
||||||
return Status;
|
return Status;
|
||||||
|
|
||||||
Fail:;
|
Fail:
|
||||||
IrpContext->Irp->IoStatus.Status = Status;
|
IrpContext->Irp->IoStatus.Status = Status;
|
||||||
IoCompleteRequest(IrpContext->Irp, (CCHAR)(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
|
IoCompleteRequest(IrpContext->Irp, (CCHAR)(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
|
||||||
VfatFreeIrpContext(IrpContext);
|
VfatFreeIrpContext(IrpContext);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS
|
static
|
||||||
VfatDispatchRequest (IN PVFAT_IRP_CONTEXT IrpContext)
|
NTSTATUS
|
||||||
|
VfatDispatchRequest(
|
||||||
|
IN PVFAT_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
DPRINT ("VfatDispatchRequest (IrpContext %p), is called for %s\n", IrpContext,
|
DPRINT("VfatDispatchRequest (IrpContext %p), is called for %s\n", IrpContext,
|
||||||
IrpContext->MajorFunction >= IRP_MJ_MAXIMUM_FUNCTION ? "????" : MajorFunctionNames[IrpContext->MajorFunction]);
|
IrpContext->MajorFunction >= IRP_MJ_MAXIMUM_FUNCTION ? "????" : MajorFunctionNames[IrpContext->MajorFunction]);
|
||||||
|
|
||||||
ASSERT(IrpContext);
|
ASSERT(IrpContext);
|
||||||
|
|
||||||
switch (IrpContext->MajorFunction)
|
switch (IrpContext->MajorFunction)
|
||||||
{
|
{
|
||||||
case IRP_MJ_CLOSE:
|
case IRP_MJ_CLOSE:
|
||||||
return VfatClose (IrpContext);
|
return VfatClose(IrpContext);
|
||||||
case IRP_MJ_CREATE:
|
case IRP_MJ_CREATE:
|
||||||
return VfatCreate (IrpContext);
|
return VfatCreate(IrpContext);
|
||||||
case IRP_MJ_READ:
|
case IRP_MJ_READ:
|
||||||
return VfatRead (IrpContext);
|
return VfatRead (IrpContext);
|
||||||
case IRP_MJ_WRITE:
|
case IRP_MJ_WRITE:
|
||||||
return VfatWrite (IrpContext);
|
return VfatWrite (IrpContext);
|
||||||
case IRP_MJ_FILE_SYSTEM_CONTROL:
|
case IRP_MJ_FILE_SYSTEM_CONTROL:
|
||||||
return VfatFileSystemControl(IrpContext);
|
return VfatFileSystemControl(IrpContext);
|
||||||
case IRP_MJ_QUERY_INFORMATION:
|
case IRP_MJ_QUERY_INFORMATION:
|
||||||
return VfatQueryInformation (IrpContext);
|
return VfatQueryInformation (IrpContext);
|
||||||
case IRP_MJ_SET_INFORMATION:
|
case IRP_MJ_SET_INFORMATION:
|
||||||
return VfatSetInformation (IrpContext);
|
return VfatSetInformation (IrpContext);
|
||||||
case IRP_MJ_DIRECTORY_CONTROL:
|
case IRP_MJ_DIRECTORY_CONTROL:
|
||||||
return VfatDirectoryControl(IrpContext);
|
return VfatDirectoryControl(IrpContext);
|
||||||
case IRP_MJ_QUERY_VOLUME_INFORMATION:
|
case IRP_MJ_QUERY_VOLUME_INFORMATION:
|
||||||
return VfatQueryVolumeInformation(IrpContext);
|
return VfatQueryVolumeInformation(IrpContext);
|
||||||
case IRP_MJ_SET_VOLUME_INFORMATION:
|
case IRP_MJ_SET_VOLUME_INFORMATION:
|
||||||
return VfatSetVolumeInformation(IrpContext);
|
return VfatSetVolumeInformation(IrpContext);
|
||||||
case IRP_MJ_LOCK_CONTROL:
|
case IRP_MJ_LOCK_CONTROL:
|
||||||
return VfatLockControl(IrpContext);
|
return VfatLockControl(IrpContext);
|
||||||
case IRP_MJ_CLEANUP:
|
case IRP_MJ_CLEANUP:
|
||||||
return VfatCleanup(IrpContext);
|
return VfatCleanup(IrpContext);
|
||||||
case IRP_MJ_FLUSH_BUFFERS:
|
case IRP_MJ_FLUSH_BUFFERS:
|
||||||
return VfatFlush(IrpContext);
|
return VfatFlush(IrpContext);
|
||||||
case IRP_MJ_PNP:
|
case IRP_MJ_PNP:
|
||||||
return VfatPnp(IrpContext);
|
return VfatPnp(IrpContext);
|
||||||
default:
|
default:
|
||||||
DPRINT1 ("Unexpected major function %x\n", IrpContext->MajorFunction);
|
DPRINT1("Unexpected major function %x\n", IrpContext->MajorFunction);
|
||||||
IrpContext->Irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR;
|
IrpContext->Irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR;
|
||||||
IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
|
||||||
VfatFreeIrpContext(IrpContext);
|
VfatFreeIrpContext(IrpContext);
|
||||||
return STATUS_DRIVER_INTERNAL_ERROR;
|
return STATUS_DRIVER_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS NTAPI VfatBuildRequest (
|
NTSTATUS
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
NTAPI
|
||||||
IN PIRP Irp)
|
VfatBuildRequest(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PVFAT_IRP_CONTEXT IrpContext;
|
PVFAT_IRP_CONTEXT IrpContext;
|
||||||
|
|
||||||
DPRINT ("VfatBuildRequest (DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
|
DPRINT("VfatBuildRequest (DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
|
||||||
|
|
||||||
ASSERT(DeviceObject);
|
ASSERT(DeviceObject);
|
||||||
ASSERT(Irp);
|
ASSERT(Irp);
|
||||||
IrpContext = VfatAllocateIrpContext(DeviceObject, Irp);
|
|
||||||
if (IrpContext == NULL)
|
IrpContext = VfatAllocateIrpContext(DeviceObject, Irp);
|
||||||
{
|
if (IrpContext == NULL)
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
{
|
||||||
Irp->IoStatus.Status = Status;
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
Irp->IoStatus.Status = Status;
|
||||||
}
|
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
||||||
else
|
}
|
||||||
{
|
else
|
||||||
FsRtlEnterFileSystem();
|
{
|
||||||
Status = VfatDispatchRequest (IrpContext);
|
FsRtlEnterFileSystem();
|
||||||
FsRtlExitFileSystem();
|
Status = VfatDispatchRequest (IrpContext);
|
||||||
}
|
FsRtlExitFileSystem();
|
||||||
return Status;
|
}
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID VfatFreeIrpContext (PVFAT_IRP_CONTEXT IrpContext)
|
VOID
|
||||||
|
VfatFreeIrpContext(
|
||||||
|
PVFAT_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
ASSERT(IrpContext);
|
ASSERT(IrpContext);
|
||||||
ExFreeToNPagedLookasideList(&VfatGlobalData->IrpContextLookasideList, IrpContext);
|
ExFreeToNPagedLookasideList(&VfatGlobalData->IrpContextLookasideList, IrpContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
PVFAT_IRP_CONTEXT VfatAllocateIrpContext(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
PVFAT_IRP_CONTEXT
|
||||||
|
VfatAllocateIrpContext(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
{
|
{
|
||||||
PVFAT_IRP_CONTEXT IrpContext;
|
PVFAT_IRP_CONTEXT IrpContext;
|
||||||
/*PIO_STACK_LOCATION Stack;*/
|
/*PIO_STACK_LOCATION Stack;*/
|
||||||
UCHAR MajorFunction;
|
UCHAR MajorFunction;
|
||||||
DPRINT ("VfatAllocateIrpContext(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
|
|
||||||
|
|
||||||
ASSERT(DeviceObject);
|
DPRINT("VfatAllocateIrpContext(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
|
||||||
ASSERT(Irp);
|
|
||||||
|
|
||||||
IrpContext = ExAllocateFromNPagedLookasideList(&VfatGlobalData->IrpContextLookasideList);
|
ASSERT(DeviceObject);
|
||||||
if (IrpContext)
|
ASSERT(Irp);
|
||||||
{
|
|
||||||
RtlZeroMemory(IrpContext, sizeof(VFAT_IRP_CONTEXT));
|
IrpContext = ExAllocateFromNPagedLookasideList(&VfatGlobalData->IrpContextLookasideList);
|
||||||
IrpContext->Irp = Irp;
|
if (IrpContext)
|
||||||
IrpContext->DeviceObject = DeviceObject;
|
{
|
||||||
IrpContext->DeviceExt = DeviceObject->DeviceExtension;
|
RtlZeroMemory(IrpContext, sizeof(VFAT_IRP_CONTEXT));
|
||||||
IrpContext->Stack = IoGetCurrentIrpStackLocation(Irp);
|
IrpContext->Irp = Irp;
|
||||||
ASSERT(IrpContext->Stack);
|
IrpContext->DeviceObject = DeviceObject;
|
||||||
MajorFunction = IrpContext->MajorFunction = IrpContext->Stack->MajorFunction;
|
IrpContext->DeviceExt = DeviceObject->DeviceExtension;
|
||||||
IrpContext->MinorFunction = IrpContext->Stack->MinorFunction;
|
IrpContext->Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
IrpContext->FileObject = IrpContext->Stack->FileObject;
|
ASSERT(IrpContext->Stack);
|
||||||
IrpContext->Flags = 0;
|
MajorFunction = IrpContext->MajorFunction = IrpContext->Stack->MajorFunction;
|
||||||
if (MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL ||
|
IrpContext->MinorFunction = IrpContext->Stack->MinorFunction;
|
||||||
MajorFunction == IRP_MJ_DEVICE_CONTROL ||
|
IrpContext->FileObject = IrpContext->Stack->FileObject;
|
||||||
MajorFunction == IRP_MJ_SHUTDOWN)
|
IrpContext->Flags = 0;
|
||||||
{
|
if (MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL ||
|
||||||
IrpContext->Flags |= IRPCONTEXT_CANWAIT;
|
MajorFunction == IRP_MJ_DEVICE_CONTROL ||
|
||||||
}
|
MajorFunction == IRP_MJ_SHUTDOWN)
|
||||||
else if (MajorFunction != IRP_MJ_CLEANUP &&
|
{
|
||||||
MajorFunction != IRP_MJ_CLOSE &&
|
IrpContext->Flags |= IRPCONTEXT_CANWAIT;
|
||||||
IoIsOperationSynchronous(Irp))
|
}
|
||||||
{
|
else if (MajorFunction != IRP_MJ_CLEANUP &&
|
||||||
IrpContext->Flags |= IRPCONTEXT_CANWAIT;
|
MajorFunction != IRP_MJ_CLOSE &&
|
||||||
}
|
IoIsOperationSynchronous(Irp))
|
||||||
KeInitializeEvent(&IrpContext->Event, NotificationEvent, FALSE);
|
{
|
||||||
IrpContext->RefCount = 0;
|
IrpContext->Flags |= IRPCONTEXT_CANWAIT;
|
||||||
}
|
}
|
||||||
return IrpContext;
|
KeInitializeEvent(&IrpContext->Event, NotificationEvent, FALSE);
|
||||||
|
IrpContext->RefCount = 0;
|
||||||
|
}
|
||||||
|
return IrpContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
static WORKER_THREAD_ROUTINE VfatDoRequest;
|
static WORKER_THREAD_ROUTINE VfatDoRequest;
|
||||||
|
|
||||||
static VOID NTAPI VfatDoRequest (PVOID IrpContext)
|
static
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
VfatDoRequest(
|
||||||
|
PVOID IrpContext)
|
||||||
{
|
{
|
||||||
InterlockedDecrement(&QueueCount);
|
InterlockedDecrement(&QueueCount);
|
||||||
DPRINT ("VfatDoRequest (IrpContext %p), MajorFunction %x, %d\n", IrpContext, ((PVFAT_IRP_CONTEXT)IrpContext)->MajorFunction, QueueCount);
|
DPRINT("VfatDoRequest(IrpContext %p), MajorFunction %x, %d\n",
|
||||||
FsRtlEnterFileSystem();
|
IrpContext, ((PVFAT_IRP_CONTEXT)IrpContext)->MajorFunction, QueueCount);
|
||||||
VfatDispatchRequest((PVFAT_IRP_CONTEXT)IrpContext);
|
FsRtlEnterFileSystem();
|
||||||
FsRtlExitFileSystem();
|
VfatDispatchRequest((PVFAT_IRP_CONTEXT)IrpContext);
|
||||||
|
FsRtlExitFileSystem();
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS VfatQueueRequest(PVFAT_IRP_CONTEXT IrpContext)
|
NTSTATUS
|
||||||
|
VfatQueueRequest(
|
||||||
|
PVFAT_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
InterlockedIncrement(&QueueCount);
|
InterlockedIncrement(&QueueCount);
|
||||||
DPRINT ("VfatQueueRequest (IrpContext %p), %d\n", IrpContext, QueueCount);
|
DPRINT("VfatQueueRequest(IrpContext %p), %d\n", IrpContext, QueueCount);
|
||||||
|
|
||||||
ASSERT(IrpContext != NULL);
|
ASSERT(IrpContext != NULL);
|
||||||
ASSERT(IrpContext->Irp != NULL);
|
ASSERT(IrpContext->Irp != NULL);
|
||||||
|
|
||||||
IrpContext->Flags |= IRPCONTEXT_CANWAIT;
|
IrpContext->Flags |= IRPCONTEXT_CANWAIT;
|
||||||
IoMarkIrpPending (IrpContext->Irp);
|
IoMarkIrpPending(IrpContext->Irp);
|
||||||
ExInitializeWorkItem (&IrpContext->WorkQueueItem, VfatDoRequest, IrpContext);
|
ExInitializeWorkItem(&IrpContext->WorkQueueItem, VfatDoRequest, IrpContext);
|
||||||
ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue);
|
ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue);
|
||||||
return STATUS_PENDING;
|
return STATUS_PENDING;
|
||||||
}
|
}
|
||||||
|
|
||||||
PVOID VfatGetUserBuffer(IN PIRP Irp)
|
PVOID
|
||||||
|
VfatGetUserBuffer(
|
||||||
|
IN PIRP Irp)
|
||||||
{
|
{
|
||||||
ASSERT(Irp);
|
ASSERT(Irp);
|
||||||
|
|
||||||
if (Irp->MdlAddress)
|
if (Irp->MdlAddress)
|
||||||
{
|
{
|
||||||
/* This call may be in the paging path, so use maximum priority */
|
/* This call may be in the paging path, so use maximum priority */
|
||||||
/* FIXME: call with normal priority in the non-paging path */
|
/* FIXME: call with normal priority in the non-paging path */
|
||||||
return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
|
return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return Irp->UserBuffer;
|
return Irp->UserBuffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS VfatLockUserBuffer(IN PIRP Irp, IN ULONG Length, IN LOCK_OPERATION Operation)
|
NTSTATUS
|
||||||
|
VfatLockUserBuffer(
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN ULONG Length,
|
||||||
|
IN LOCK_OPERATION Operation)
|
||||||
{
|
{
|
||||||
ASSERT(Irp);
|
ASSERT(Irp);
|
||||||
|
|
||||||
if (Irp->MdlAddress)
|
if (Irp->MdlAddress)
|
||||||
{
|
{
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
IoAllocateMdl(Irp->UserBuffer, Length, FALSE, FALSE, Irp);
|
IoAllocateMdl(Irp->UserBuffer, Length, FALSE, FALSE, Irp);
|
||||||
|
|
||||||
if (!Irp->MdlAddress)
|
if (!Irp->MdlAddress)
|
||||||
{
|
{
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
MmProbeAndLockPages(Irp->MdlAddress, Irp->RequestorMode, Operation);
|
MmProbeAndLockPages(Irp->MdlAddress, Irp->RequestorMode, Operation);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,31 +14,34 @@
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
NTSTATUS VfatPnp(PVFAT_IRP_CONTEXT IrpContext)
|
NTSTATUS
|
||||||
|
VfatPnp(
|
||||||
|
PVFAT_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
PVCB Vcb = NULL;
|
PVCB Vcb = NULL;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
/* PRECONDITION */
|
/* PRECONDITION */
|
||||||
ASSERT(IrpContext);
|
ASSERT(IrpContext);
|
||||||
|
|
||||||
switch (IrpContext->Stack->MinorFunction)
|
switch (IrpContext->Stack->MinorFunction)
|
||||||
{
|
{
|
||||||
case IRP_MN_QUERY_REMOVE_DEVICE:
|
case IRP_MN_QUERY_REMOVE_DEVICE:
|
||||||
case IRP_MN_SURPRISE_REMOVAL:
|
case IRP_MN_SURPRISE_REMOVAL:
|
||||||
case IRP_MN_REMOVE_DEVICE:
|
case IRP_MN_REMOVE_DEVICE:
|
||||||
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
||||||
Status = STATUS_NOT_IMPLEMENTED;
|
Status = STATUS_NOT_IMPLEMENTED;
|
||||||
IrpContext->Irp->IoStatus.Status = Status;
|
IrpContext->Irp->IoStatus.Status = Status;
|
||||||
IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
IoSkipCurrentIrpStackLocation(IrpContext->Irp);
|
|
||||||
Vcb = (PVCB)IrpContext->Stack->DeviceObject->DeviceExtension;
|
|
||||||
Status = IoCallDriver(Vcb->StorageDevice, IrpContext->Irp);
|
|
||||||
}
|
|
||||||
|
|
||||||
VfatFreeIrpContext(IrpContext);
|
default:
|
||||||
|
IoSkipCurrentIrpStackLocation(IrpContext->Irp);
|
||||||
|
Vcb = (PVCB)IrpContext->Stack->DeviceObject->DeviceExtension;
|
||||||
|
Status = IoCallDriver(Vcb->StorageDevice, IrpContext->Irp);
|
||||||
|
}
|
||||||
|
|
||||||
return Status;
|
VfatFreeIrpContext(IrpContext);
|
||||||
|
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -13,106 +13,115 @@
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
static NTSTATUS
|
static
|
||||||
VfatDiskShutDown(PVCB Vcb)
|
NTSTATUS
|
||||||
|
VfatDiskShutDown(
|
||||||
|
PVCB Vcb)
|
||||||
{
|
{
|
||||||
PIRP Irp;
|
PIRP Irp;
|
||||||
KEVENT Event;
|
KEVENT Event;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
IO_STATUS_BLOCK IoStatus;
|
IO_STATUS_BLOCK IoStatus;
|
||||||
|
|
||||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||||
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN, Vcb->StorageDevice,
|
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN, Vcb->StorageDevice,
|
||||||
NULL, 0, NULL, &Event, &IoStatus);
|
NULL, 0, NULL, &Event, &IoStatus);
|
||||||
if (Irp)
|
if (Irp)
|
||||||
{
|
{
|
||||||
Status = IoCallDriver(Vcb->StorageDevice, Irp);
|
Status = IoCallDriver(Vcb->StorageDevice, Irp);
|
||||||
if (Status == STATUS_PENDING)
|
if (Status == STATUS_PENDING)
|
||||||
{
|
{
|
||||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||||
Status = IoStatus.Status;
|
Status = IoStatus.Status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Status = IoStatus.Status;
|
Status = IoStatus.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
|
||||||
VfatShutdown(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
VfatShutdown(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PLIST_ENTRY ListEntry;
|
PLIST_ENTRY ListEntry;
|
||||||
PDEVICE_EXTENSION DeviceExt;
|
PDEVICE_EXTENSION DeviceExt;
|
||||||
ULONG eocMark;
|
ULONG eocMark;
|
||||||
|
|
||||||
DPRINT("VfatShutdown(DeviceObject %p, Irp %p)\n",DeviceObject, Irp);
|
DPRINT("VfatShutdown(DeviceObject %p, Irp %p)\n",DeviceObject, Irp);
|
||||||
|
|
||||||
FsRtlEnterFileSystem();
|
FsRtlEnterFileSystem();
|
||||||
|
|
||||||
/* FIXME: block new mount requests */
|
/* FIXME: block new mount requests */
|
||||||
|
|
||||||
if (DeviceObject == VfatGlobalData->DeviceObject)
|
if (DeviceObject == VfatGlobalData->DeviceObject)
|
||||||
{
|
{
|
||||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
ExAcquireResourceExclusiveLite(&VfatGlobalData->VolumeListLock, TRUE);
|
ExAcquireResourceExclusiveLite(&VfatGlobalData->VolumeListLock, TRUE);
|
||||||
ListEntry = VfatGlobalData->VolumeListHead.Flink;
|
ListEntry = VfatGlobalData->VolumeListHead.Flink;
|
||||||
while (ListEntry != &VfatGlobalData->VolumeListHead)
|
while (ListEntry != &VfatGlobalData->VolumeListHead)
|
||||||
{
|
{
|
||||||
DeviceExt = CONTAINING_RECORD(ListEntry, VCB, VolumeListEntry);
|
DeviceExt = CONTAINING_RECORD(ListEntry, VCB, VolumeListEntry);
|
||||||
ListEntry = ListEntry->Flink;
|
ListEntry = ListEntry->Flink;
|
||||||
|
|
||||||
ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, TRUE);
|
ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, TRUE);
|
||||||
if (DeviceExt->VolumeFcb->Flags & VCB_CLEAR_DIRTY)
|
if (DeviceExt->VolumeFcb->Flags & VCB_CLEAR_DIRTY)
|
||||||
{
|
{
|
||||||
/* set clean shutdown bit */
|
/* set clean shutdown bit */
|
||||||
Status = GetNextCluster(DeviceExt, 1, &eocMark);
|
Status = GetNextCluster(DeviceExt, 1, &eocMark);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
eocMark |= DeviceExt->CleanShutBitMask;
|
||||||
|
if (NT_SUCCESS(WriteCluster(DeviceExt, 1, eocMark)))
|
||||||
|
DeviceExt->VolumeFcb->Flags &= ~VCB_IS_DIRTY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = VfatFlushVolume(DeviceExt, DeviceExt->VolumeFcb);
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
eocMark |= DeviceExt->CleanShutBitMask;
|
Status = VfatDiskShutDown(DeviceExt);
|
||||||
if (NT_SUCCESS(WriteCluster(DeviceExt, 1, eocMark)))
|
if (!NT_SUCCESS(Status))
|
||||||
DeviceExt->VolumeFcb->Flags &= ~VCB_IS_DIRTY;
|
{
|
||||||
|
DPRINT1("VfatDiskShutDown failed, status = %x\n", Status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
Status = VfatFlushVolume(DeviceExt, DeviceExt->VolumeFcb);
|
{
|
||||||
if (NT_SUCCESS(Status))
|
DPRINT1("VfatFlushVolume failed, status = %x\n", Status);
|
||||||
{
|
}
|
||||||
Status = VfatDiskShutDown(DeviceExt);
|
ExReleaseResourceLite(&DeviceExt->DirResource);
|
||||||
|
|
||||||
|
/* FIXME: Unmount the logical volume */
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
DPRINT1("VfatDiskShutDown failed, status = %x\n", Status);
|
Irp->IoStatus.Status = Status;
|
||||||
}
|
}
|
||||||
else
|
ExReleaseResourceLite(&VfatGlobalData->VolumeListLock);
|
||||||
{
|
|
||||||
DPRINT1("VfatFlushVolume failed, status = %x\n", Status);
|
|
||||||
}
|
|
||||||
ExReleaseResourceLite(&DeviceExt->DirResource);
|
|
||||||
|
|
||||||
/* FIXME: Unmount the logical volume */
|
/* FIXME: Free all global acquired resources */
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
Status = Irp->IoStatus.Status;
|
||||||
Irp->IoStatus.Status = Status;
|
}
|
||||||
}
|
else
|
||||||
ExReleaseResourceLite(&VfatGlobalData->VolumeListLock);
|
{
|
||||||
|
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
}
|
||||||
|
|
||||||
/* FIXME: Free all global acquired resources */
|
Irp->IoStatus.Information = 0;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
Status = Irp->IoStatus.Status;
|
FsRtlExitFileSystem();
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
||||||
Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
||||||
}
|
|
||||||
|
|
||||||
Irp->IoStatus.Information = 0;
|
return Status;
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
||||||
|
|
||||||
FsRtlExitFileSystem();
|
|
||||||
|
|
||||||
return(Status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -17,7 +17,8 @@
|
||||||
const WCHAR *long_illegals = L"\"*\\<>/?:|";
|
const WCHAR *long_illegals = L"\"*\\<>/?:|";
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
vfatIsLongIllegal(WCHAR c)
|
vfatIsLongIllegal(
|
||||||
|
WCHAR c)
|
||||||
{
|
{
|
||||||
return wcschr(long_illegals, c) ? TRUE : FALSE;
|
return wcschr(long_illegals, c) ? TRUE : FALSE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -341,12 +341,12 @@ FsdSetFsLabelInformation(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
VfatQueryVolumeInformation(
|
|
||||||
PVFAT_IRP_CONTEXT IrpContext)
|
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Retrieve the specified volume information
|
* FUNCTION: Retrieve the specified volume information
|
||||||
*/
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
VfatQueryVolumeInformation(
|
||||||
|
PVFAT_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
FS_INFORMATION_CLASS FsInformationClass;
|
FS_INFORMATION_CLASS FsInformationClass;
|
||||||
NTSTATUS RC = STATUS_SUCCESS;
|
NTSTATUS RC = STATUS_SUCCESS;
|
||||||
|
@ -416,12 +416,12 @@ VfatQueryVolumeInformation(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
VfatSetVolumeInformation(
|
|
||||||
PVFAT_IRP_CONTEXT IrpContext)
|
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Set the specified volume information
|
* FUNCTION: Set the specified volume information
|
||||||
*/
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
VfatSetVolumeInformation(
|
||||||
|
PVFAT_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
FS_INFORMATION_CLASS FsInformationClass;
|
FS_INFORMATION_CLASS FsInformationClass;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue