reactos/drivers/filesystems/fastfat/misc.c
Timo Kreuzer 912ce51ae6 [CMAKE]
Sync with trunk head (r48826)

svn path=/branches/cmake-bringup/; revision=48831
2010-09-20 17:27:52 +00:00

278 lines
7.8 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/fs/vfat/misc.c
* PURPOSE: VFAT Filesystem
* PROGRAMMER:
*
*/
/* INCLUDES *****************************************************************/
#define NDEBUG
#include "vfat.h"
/* GLOBALS ******************************************************************/
const char* MajorFunctionNames[] =
{
"IRP_MJ_CREATE",
"IRP_MJ_CREATE_NAMED_PIPE",
"IRP_MJ_CLOSE",
"IRP_MJ_READ",
"IRP_MJ_WRITE",
"IRP_MJ_QUERY_INFORMATION",
"IRP_MJ_SET_INFORMATION",
"IRP_MJ_QUERY_EA",
"IRP_MJ_SET_EA",
"IRP_MJ_FLUSH_BUFFERS",
"IRP_MJ_QUERY_VOLUME_INFORMATION",
"IRP_MJ_SET_VOLUME_INFORMATION",
"IRP_MJ_DIRECTORY_CONTROL",
"IRP_MJ_FILE_SYSTEM_CONTROL",
"IRP_MJ_DEVICE_CONTROL",
"IRP_MJ_INTERNAL_DEVICE_CONTROL",
"IRP_MJ_SHUTDOWN",
"IRP_MJ_LOCK_CONTROL",
"IRP_MJ_CLEANUP",
"IRP_MJ_CREATE_MAILSLOT",
"IRP_MJ_QUERY_SECURITY",
"IRP_MJ_SET_SECURITY",
"IRP_MJ_POWER",
"IRP_MJ_SYSTEM_CONTROL",
"IRP_MJ_DEVICE_CHANGE",
"IRP_MJ_QUERY_QUOTA",
"IRP_MJ_SET_QUOTA",
"IRP_MJ_PNP",
"IRP_MJ_MAXIMUM_FUNCTION"
};
/* FUNCTIONS ****************************************************************/
static LONG QueueCount = 0;
static NTSTATUS VfatLockControl(
IN PVFAT_IRP_CONTEXT IrpContext
)
{
PVFATFCB Fcb;
NTSTATUS Status;
DPRINT("VfatLockControl(IrpContext %p)\n", IrpContext);
ASSERT(IrpContext);
Fcb = (PVFATFCB)IrpContext->FileObject->FsContext;
if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
{
Status = STATUS_INVALID_DEVICE_REQUEST;
goto Fail;
}
if (*Fcb->Attributes & FILE_ATTRIBUTE_DIRECTORY)
{
Status = STATUS_INVALID_PARAMETER;
goto Fail;
}
Status = FsRtlProcessFileLock(&Fcb->FileLock,
IrpContext->Irp,
NULL
);
VfatFreeIrpContext(IrpContext);
return Status;
Fail:;
IrpContext->Irp->IoStatus.Status = Status;
IoCompleteRequest(IrpContext->Irp, (CCHAR)(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
VfatFreeIrpContext(IrpContext);
return Status;
}
static NTSTATUS
VfatDispatchRequest (IN PVFAT_IRP_CONTEXT IrpContext)
{
DPRINT ("VfatDispatchRequest (IrpContext %p), is called for %s\n", IrpContext,
IrpContext->MajorFunction >= IRP_MJ_MAXIMUM_FUNCTION ? "????" : MajorFunctionNames[IrpContext->MajorFunction]);
ASSERT(IrpContext);
switch (IrpContext->MajorFunction)
{
case IRP_MJ_CLOSE:
return VfatClose (IrpContext);
case IRP_MJ_CREATE:
return VfatCreate (IrpContext);
case IRP_MJ_READ:
return VfatRead (IrpContext);
case IRP_MJ_WRITE:
return VfatWrite (IrpContext);
case IRP_MJ_FILE_SYSTEM_CONTROL:
return VfatFileSystemControl(IrpContext);
case IRP_MJ_QUERY_INFORMATION:
return VfatQueryInformation (IrpContext);
case IRP_MJ_SET_INFORMATION:
return VfatSetInformation (IrpContext);
case IRP_MJ_DIRECTORY_CONTROL:
return VfatDirectoryControl(IrpContext);
case IRP_MJ_QUERY_VOLUME_INFORMATION:
return VfatQueryVolumeInformation(IrpContext);
case IRP_MJ_SET_VOLUME_INFORMATION:
return VfatSetVolumeInformation(IrpContext);
case IRP_MJ_LOCK_CONTROL:
return VfatLockControl(IrpContext);
case IRP_MJ_CLEANUP:
return VfatCleanup(IrpContext);
case IRP_MJ_FLUSH_BUFFERS:
return VfatFlush(IrpContext);
case IRP_MJ_PNP:
return VfatPnp(IrpContext);
default:
DPRINT1 ("Unexpected major function %x\n", IrpContext->MajorFunction);
IrpContext->Irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR;
IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
VfatFreeIrpContext(IrpContext);
return STATUS_DRIVER_INTERNAL_ERROR;
}
}
NTSTATUS NTAPI VfatBuildRequest (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
NTSTATUS Status;
PVFAT_IRP_CONTEXT IrpContext;
DPRINT ("VfatBuildRequest (DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
ASSERT(DeviceObject);
ASSERT(Irp);
IrpContext = VfatAllocateIrpContext(DeviceObject, Irp);
if (IrpContext == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
Irp->IoStatus.Status = Status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
}
else
{
FsRtlEnterFileSystem();
Status = VfatDispatchRequest (IrpContext);
FsRtlExitFileSystem();
}
return Status;
}
VOID VfatFreeIrpContext (PVFAT_IRP_CONTEXT IrpContext)
{
ASSERT(IrpContext);
ExFreeToNPagedLookasideList(&VfatGlobalData->IrpContextLookasideList, IrpContext);
}
PVFAT_IRP_CONTEXT VfatAllocateIrpContext(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PVFAT_IRP_CONTEXT IrpContext;
/*PIO_STACK_LOCATION Stack;*/
UCHAR MajorFunction;
DPRINT ("VfatAllocateIrpContext(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
ASSERT(DeviceObject);
ASSERT(Irp);
IrpContext = ExAllocateFromNPagedLookasideList(&VfatGlobalData->IrpContextLookasideList);
if (IrpContext)
{
RtlZeroMemory(IrpContext, sizeof(VFAT_IRP_CONTEXT));
IrpContext->Irp = Irp;
IrpContext->DeviceObject = DeviceObject;
IrpContext->DeviceExt = DeviceObject->DeviceExtension;
IrpContext->Stack = IoGetCurrentIrpStackLocation(Irp);
ASSERT(IrpContext->Stack);
MajorFunction = IrpContext->MajorFunction = IrpContext->Stack->MajorFunction;
IrpContext->MinorFunction = IrpContext->Stack->MinorFunction;
IrpContext->FileObject = IrpContext->Stack->FileObject;
IrpContext->Flags = 0;
if (MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL ||
MajorFunction == IRP_MJ_DEVICE_CONTROL ||
MajorFunction == IRP_MJ_SHUTDOWN)
{
IrpContext->Flags |= IRPCONTEXT_CANWAIT;
}
else if (MajorFunction != IRP_MJ_CLEANUP &&
MajorFunction != IRP_MJ_CLOSE &&
IoIsOperationSynchronous(Irp))
{
IrpContext->Flags |= IRPCONTEXT_CANWAIT;
}
KeInitializeEvent(&IrpContext->Event, NotificationEvent, FALSE);
IrpContext->RefCount = 0;
}
return IrpContext;
}
static VOID NTAPI VfatDoRequest (PVOID IrpContext)
{
InterlockedDecrement(&QueueCount);
DPRINT ("VfatDoRequest (IrpContext %p), MajorFunction %x, %d\n", IrpContext, ((PVFAT_IRP_CONTEXT)IrpContext)->MajorFunction, QueueCount);
FsRtlEnterFileSystem();
VfatDispatchRequest((PVFAT_IRP_CONTEXT)IrpContext);
FsRtlExitFileSystem();
}
NTSTATUS VfatQueueRequest(PVFAT_IRP_CONTEXT IrpContext)
{
InterlockedIncrement(&QueueCount);
DPRINT ("VfatQueueRequest (IrpContext %p), %d\n", IrpContext, QueueCount);
ASSERT(IrpContext != NULL);
ASSERT(IrpContext->Irp != NULL);
IrpContext->Flags |= IRPCONTEXT_CANWAIT;
IoMarkIrpPending (IrpContext->Irp);
ExInitializeWorkItem (&IrpContext->WorkQueueItem, VfatDoRequest, IrpContext);
ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue);
return STATUS_PENDING;
}
PVOID VfatGetUserBuffer(IN PIRP Irp)
{
ASSERT(Irp);
if (Irp->MdlAddress)
{
/* This call may be in the paging path, so use maximum priority */
/* FIXME: call with normal priority in the non-paging path */
return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
}
else
{
return Irp->UserBuffer;
}
}
NTSTATUS VfatLockUserBuffer(IN PIRP Irp, IN ULONG Length, IN LOCK_OPERATION Operation)
{
ASSERT(Irp);
if (Irp->MdlAddress)
{
return STATUS_SUCCESS;
}
IoAllocateMdl(Irp->UserBuffer, Length, FALSE, FALSE, Irp);
if (!Irp->MdlAddress)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
MmProbeAndLockPages(Irp->MdlAddress, Irp->RequestorMode, Operation);
return STATUS_SUCCESS;
}