/* * 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; }