reactos/drivers/filesystems/ffs/src/dispatch.c

252 lines
4.7 KiB
C

/*
* FFS File System Driver for Windows
*
* dipatch.c
*
* 2004.5.6 ~
*
* Lee Jae-Hong, http://www.pyrasis.com
*
* See License.txt
*
*/
#include "ntifs.h"
#include "ffsdrv.h"
/* Globals */
extern PFFS_GLOBAL FFSGlobal;
/* Definitions */
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FFSQueueRequest)
#pragma alloc_text(PAGE, FFSDeQueueRequest)
#pragma alloc_text(PAGE, FFSDispatchRequest)
#pragma alloc_text(PAGE, FFSBuildRequest)
#endif
NTSTATUS
FFSQueueRequest(
IN PFFS_IRP_CONTEXT IrpContext)
{
PAGED_CODE();
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
// IsSynchronous means we can block (so we don't requeue it)
IrpContext->IsSynchronous = TRUE;
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);
IoMarkIrpPending(IrpContext->Irp);
ExInitializeWorkItem(
&IrpContext->WorkQueueItem,
FFSDeQueueRequest,
IrpContext);
ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue);
return STATUS_PENDING;
}
VOID NTAPI
FFSDeQueueRequest(
IN PVOID Context)
{
PFFS_IRP_CONTEXT IrpContext;
PAGED_CODE();
IrpContext = (PFFS_IRP_CONTEXT) Context;
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
_SEH2_TRY
{
_SEH2_TRY
{
FsRtlEnterFileSystem();
if (!IrpContext->IsTopLevel)
{
IoSetTopLevelIrp((PIRP) FSRTL_FSP_TOP_LEVEL_IRP);
}
FFSDispatchRequest(IrpContext);
}
_SEH2_EXCEPT (FFSExceptionFilter(IrpContext, _SEH2_GetExceptionInformation()))
{
FFSExceptionHandler(IrpContext);
} _SEH2_END;
}
_SEH2_FINALLY
{
IoSetTopLevelIrp(NULL);
FsRtlExitFileSystem();
} _SEH2_END;
}
NTSTATUS
FFSDispatchRequest(
IN PFFS_IRP_CONTEXT IrpContext)
{
PAGED_CODE();
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
switch (IrpContext->MajorFunction)
{
case IRP_MJ_CREATE:
return FFSCreate(IrpContext);
case IRP_MJ_CLOSE:
return FFSClose(IrpContext);
case IRP_MJ_READ:
return FFSRead(IrpContext);
#if !FFS_READ_ONLY
case IRP_MJ_WRITE:
return FFSWrite(IrpContext);
#endif // !FFS_READ_ONLY
case IRP_MJ_FLUSH_BUFFERS:
return FFSFlush(IrpContext);
case IRP_MJ_QUERY_INFORMATION:
return FFSQueryInformation(IrpContext);
case IRP_MJ_SET_INFORMATION:
return FFSSetInformation(IrpContext);
case IRP_MJ_QUERY_VOLUME_INFORMATION:
return FFSQueryVolumeInformation(IrpContext);
#if !FFS_READ_ONLY
case IRP_MJ_SET_VOLUME_INFORMATION:
return FFSSetVolumeInformation(IrpContext);
#endif // !FFS_READ_ONLY
case IRP_MJ_DIRECTORY_CONTROL:
return FFSDirectoryControl(IrpContext);
case IRP_MJ_FILE_SYSTEM_CONTROL:
return FFSFileSystemControl(IrpContext);
case IRP_MJ_DEVICE_CONTROL:
return FFSDeviceControl(IrpContext);
case IRP_MJ_LOCK_CONTROL:
return FFSLockControl(IrpContext);
case IRP_MJ_CLEANUP:
return FFSCleanup(IrpContext);
case IRP_MJ_SHUTDOWN:
return FFSShutDown(IrpContext);
#if (_WIN32_WINNT >= 0x0500)
case IRP_MJ_PNP:
return FFSPnp(IrpContext);
#endif //(_WIN32_WINNT >= 0x0500)
default:
FFSPrint((DBG_ERROR, "FFSDispatchRequest: Unexpected major function: %xh\n",
IrpContext->MajorFunction));
FFSCompleteIrpContext(IrpContext, STATUS_DRIVER_INTERNAL_ERROR);
return STATUS_DRIVER_INTERNAL_ERROR;
}
}
NTSTATUS NTAPI
FFSBuildRequest(
PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
BOOLEAN AtIrqlPassiveLevel = FALSE;
BOOLEAN IsTopLevelIrp = FALSE;
PFFS_IRP_CONTEXT IrpContext = NULL;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PAGED_CODE();
_SEH2_TRY
{
_SEH2_TRY
{
#if DBG
FFSDbgPrintCall(DeviceObject, Irp);
#endif
AtIrqlPassiveLevel = (KeGetCurrentIrql() == PASSIVE_LEVEL);
if (AtIrqlPassiveLevel)
{
FsRtlEnterFileSystem();
}
if (!IoGetTopLevelIrp())
{
IsTopLevelIrp = TRUE;
IoSetTopLevelIrp(Irp);
}
IrpContext = FFSAllocateIrpContext(DeviceObject, Irp);
if (!IrpContext)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
Irp->IoStatus.Status = Status;
FFSCompleteRequest(Irp, TRUE, IO_NO_INCREMENT);
}
else
{
if ((IrpContext->MajorFunction == IRP_MJ_CREATE) &&
!AtIrqlPassiveLevel)
{
FFSBreakPoint();
}
Status = FFSDispatchRequest(IrpContext);
}
}
_SEH2_EXCEPT (FFSExceptionFilter(IrpContext, _SEH2_GetExceptionInformation()))
{
Status = FFSExceptionHandler(IrpContext);
} _SEH2_END;
}
_SEH2_FINALLY
{
if (IsTopLevelIrp)
{
IoSetTopLevelIrp(NULL);
}
if (AtIrqlPassiveLevel)
{
FsRtlExitFileSystem();
}
} _SEH2_END;
return Status;
}