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

242 lines
6 KiB
C

/*
* COPYRIGHT: GNU GENERAL PUBLIC LICENSE VERSION 2
* PROJECT: ReiserFs file system driver for Windows NT/2000/XP/Vista.
* FILE: dispatch.c
* PURPOSE:
* PROGRAMMER: Mark Piper, Matt Wu, Bo Brantén.
* HOMEPAGE:
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include "rfsd.h"
/* GLOBALS ***************************************************************/
extern PRFSD_GLOBAL RfsdGlobal;
/* DEFINITIONS *************************************************************/
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, RfsdQueueRequest)
#pragma alloc_text(PAGE, RfsdDeQueueRequest)
#pragma alloc_text(PAGE, RfsdDispatchRequest)
#pragma alloc_text(PAGE, RfsdBuildRequest)
#endif
NTSTATUS
RfsdQueueRequest (IN PRFSD_IRP_CONTEXT IrpContext)
{
PAGED_CODE();
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
(IrpContext->Identifier.Size == sizeof(RFSD_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,
RfsdDeQueueRequest,
IrpContext );
ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue);
return STATUS_PENDING;
}
VOID NTAPI
RfsdDeQueueRequest (IN PVOID Context)
{
PRFSD_IRP_CONTEXT IrpContext;
PAGED_CODE();
IrpContext = (PRFSD_IRP_CONTEXT) Context;
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
(IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
_SEH2_TRY {
_SEH2_TRY {
FsRtlEnterFileSystem();
if (!IrpContext->IsTopLevel) {
IoSetTopLevelIrp((PIRP) FSRTL_FSP_TOP_LEVEL_IRP);
}
RfsdDispatchRequest(IrpContext);
} _SEH2_EXCEPT (RfsdExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) {
RfsdExceptionHandler(IrpContext);
} _SEH2_END;
} _SEH2_FINALLY {
IoSetTopLevelIrp(NULL);
FsRtlExitFileSystem();
} _SEH2_END;
}
__drv_mustHoldCriticalRegion
NTSTATUS
RfsdDispatchRequest (IN PRFSD_IRP_CONTEXT IrpContext)
{
PAGED_CODE();
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
(IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
switch (IrpContext->MajorFunction) {
case IRP_MJ_CREATE:
return RfsdCreate(IrpContext);
case IRP_MJ_CLOSE:
return RfsdClose(IrpContext);
case IRP_MJ_READ:
return RfsdRead(IrpContext);
#if !RFSD_READ_ONLY
case IRP_MJ_WRITE:
return RfsdWrite(IrpContext);
#endif // !RFSD_READ_ONLY
case IRP_MJ_FLUSH_BUFFERS:
return RfsdFlush(IrpContext);
case IRP_MJ_QUERY_INFORMATION:
return RfsdQueryInformation(IrpContext);
case IRP_MJ_SET_INFORMATION:
return RfsdSetInformation(IrpContext);
case IRP_MJ_QUERY_VOLUME_INFORMATION:
return RfsdQueryVolumeInformation(IrpContext);
#if !RFSD_READ_ONLY
case IRP_MJ_SET_VOLUME_INFORMATION:
return RfsdSetVolumeInformation(IrpContext);
#endif // !RFSD_READ_ONLY
case IRP_MJ_DIRECTORY_CONTROL:
return RfsdDirectoryControl(IrpContext);
case IRP_MJ_FILE_SYSTEM_CONTROL:
return RfsdFileSystemControl(IrpContext);
case IRP_MJ_DEVICE_CONTROL:
return RfsdDeviceControl(IrpContext);
case IRP_MJ_LOCK_CONTROL:
return RfsdLockControl(IrpContext);
case IRP_MJ_CLEANUP:
return RfsdCleanup(IrpContext);
case IRP_MJ_SHUTDOWN:
return RfsdShutDown(IrpContext);
#if (_WIN32_WINNT >= 0x0500)
case IRP_MJ_PNP:
return RfsdPnp(IrpContext);
#endif //(_WIN32_WINNT >= 0x0500)
default:
{
NTSTATUS DefaultRC = STATUS_INVALID_DEVICE_REQUEST;
RfsdPrint((DBG_ERROR, "RfsdDispatchRequest: Unexpected major function: %xh\n",
IrpContext->MajorFunction));
RfsdCompleteIrpContext(IrpContext, DefaultRC);
return DefaultRC;
}
}
}
NTSTATUS NTAPI
RfsdBuildRequest (PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
BOOLEAN AtIrqlPassiveLevel = FALSE;
BOOLEAN IsTopLevelIrp = FALSE;
PRFSD_IRP_CONTEXT IrpContext = NULL;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PAGED_CODE();
_SEH2_TRY {
_SEH2_TRY {
#if DBG
RfsdDbgPrintCall(DeviceObject, Irp);
#endif
AtIrqlPassiveLevel = (KeGetCurrentIrql() == PASSIVE_LEVEL);
if (AtIrqlPassiveLevel) {
FsRtlEnterFileSystem();
}
if (!IoGetTopLevelIrp()) {
IsTopLevelIrp = TRUE;
IoSetTopLevelIrp(Irp);
}
IrpContext = RfsdAllocateIrpContext(DeviceObject, Irp);
if (!IrpContext) {
Status = STATUS_INSUFFICIENT_RESOURCES;
Irp->IoStatus.Status = Status;
RfsdCompleteRequest(Irp, TRUE, IO_NO_INCREMENT);
} else {
if ((IrpContext->MajorFunction == IRP_MJ_CREATE) &&
!AtIrqlPassiveLevel) {
DbgBreak();
}
Status = RfsdDispatchRequest(IrpContext);
}
} _SEH2_EXCEPT (RfsdExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) {
Status = RfsdExceptionHandler(IrpContext);
} _SEH2_END;
} _SEH2_FINALLY {
if (IsTopLevelIrp) {
IoSetTopLevelIrp(NULL);
}
if (AtIrqlPassiveLevel) {
FsRtlExitFileSystem();
}
} _SEH2_END;
return Status;
}