/* * @implemented */ VOID NTAPI FsRtlStackOverflowRead(IN PVOID Context) { PSTACK_OVERFLOW_WORK_ITEM WorkItem; WorkItem = (PSTACK_OVERFLOW_WORK_ITEM)Context; /* Put us as top IRP for current thread */ IoSetTopLevelIrp((PIRP)FSRTL_FSP_TOP_LEVEL_IRP); /* And call FsRtlSORoutine */ WorkItem->Routine(WorkItem->Context, WorkItem->Event); /* If we were using fallback workitem, don't free it, just reset event */ if (WorkItem == &StackOverflowFallback) { KeSetEvent(&StackOverflowFallbackSerialEvent, 0, FALSE); } /* Otherwise, free the work item */ else { ExFreePoolWithTag(WorkItem, 'Fsrs'); } /* Reset top level */ IoSetTopLevelIrp(NULL); }
VOID DDKAPI LklDequeueRequest(IN PDEVICE_OBJECT device, IN PVOID context) { NTSTATUS status; PIRPCONTEXT irp_context; irp_context = (PIRPCONTEXT) context; ASSERT(irp_context); ASSERT(irp_context->id.type == IRP_CONTEXT && irp_context->id.size == sizeof(IRPCONTEXT)); IoFreeWorkItem(irp_context->work_item); if (FLAG_ON(irp_context->flags, VFS_IRP_CONTEXT_NOT_TOP_LEVEL)) IoSetTopLevelIrp((PIRP)FSRTL_FSP_TOP_LEVEL_IRP); SET_FLAG(irp_context->flags, VFS_IRP_CONTEXT_CAN_BLOCK); FsRtlEnterFileSystem(); status = LklDispatchRequest(irp_context); FsRtlExitFileSystem(); IoSetTopLevelIrp(NULL); }
VOID NTAPI FatDequeueRequest(IN PVOID Context) { PFAT_IRP_CONTEXT IrpContext; IrpContext = (PFAT_IRP_CONTEXT) Context; /* Enter critical region. */ FsRtlEnterFileSystem(); /* Handle top level IRP Correctly. */ if (!FlagOn(IrpContext->Flags, IRPCONTEXT_TOPLEVEL)) IoSetTopLevelIrp((PIRP) FSRTL_FSP_TOP_LEVEL_IRP); /* Enable Synchronous IO. */ SetFlag(IrpContext->Flags, IRPCONTEXT_CANWAIT); /* Invoke the handler routine. */ IrpContext->QueuedOperationHandler(IrpContext); /* Restore top level IRP. */ IoSetTopLevelIrp(NULL); /* Leave critical region. */ FsRtlExitFileSystem(); }
NTSTATUS NTAPI FatLockControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) { PFAT_IRP_CONTEXT IrpContext; NTSTATUS Status; BOOLEAN TopLevel; DPRINT1("FatLockControl()\n"); /* Enter FsRtl critical region */ FsRtlEnterFileSystem(); /* Set Top Level IRP if not set */ TopLevel = FatIsTopLevelIrp(Irp); /* Build an irp context */ IrpContext = FatBuildIrpContext(Irp, IoIsOperationSynchronous(Irp)); /* Call internal function */ Status = FatiLockControl(IrpContext, Irp); /* Reset Top Level IRP */ if (TopLevel) IoSetTopLevelIrp(NULL); /* Leave FsRtl critical region */ FsRtlExitFileSystem(); return Status; }
BOOLEAN CdAcquireForCache ( _Inout_ PFCB Fcb, _In_ BOOLEAN Wait ) /*++ Routine Description: The address of this routine is specified when creating a CacheMap for a file. It is subsequently called by the Lazy Writer for synchronization. Arguments: Fcb - The pointer supplied as context to the cache initialization routine. Wait - TRUE if the caller is willing to block. Return Value: None --*/ { PAGED_CODE(); NT_ASSERT(IoGetTopLevelIrp() == NULL); IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); return ExAcquireResourceSharedLite( Fcb->Resource, Wait ); }
VOID CdReleaseFromCache ( _Inout_ PFCB Fcb ) /*++ Routine Description: The address of this routine is specified when creating a CacheMap for a virtual file. It is subsequently called by the Lazy Writer to release a resource acquired above. Arguments: Fcb - The pointer supplied as context to the cache initialization routine. Return Value: None --*/ { PAGED_CODE(); NT_ASSERT(IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); IoSetTopLevelIrp( NULL ); ExReleaseResourceLite( Fcb->Resource ); }
NTSTATUS DokanBuildRequest(PDEVICE_OBJECT DeviceObject, PIRP Irp) { BOOLEAN AtIrqlPassiveLevel = FALSE; BOOLEAN IsTopLevelIrp = FALSE; NTSTATUS Status = STATUS_UNSUCCESSFUL; __try { __try { AtIrqlPassiveLevel = (KeGetCurrentIrql() == PASSIVE_LEVEL); if (AtIrqlPassiveLevel) { FsRtlEnterFileSystem(); } if (!IoGetTopLevelIrp()) { IsTopLevelIrp = TRUE; IoSetTopLevelIrp(Irp); } Status = DokanDispatchRequest(DeviceObject, Irp); } __except (DokanExceptionFilter(Irp, GetExceptionInformation())) { Status = DokanExceptionHandler(DeviceObject, Irp, GetExceptionCode()); } } __finally { if (IsTopLevelIrp) { IoSetTopLevelIrp(NULL); } if (AtIrqlPassiveLevel) { FsRtlExitFileSystem(); } } return Status; }
VOID DokanNoOpRelease(__in PVOID Fcb) { DDbgPrint("==> DokanNoOpRelease\n"); ASSERT(IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); IoSetTopLevelIrp(NULL); UNREFERENCED_PARAMETER(Fcb); DDbgPrint("<== DokanNoOpRelease\n"); }
/************************************************************************* * * Function: UDFClose() * * Description: * The I/O Manager will invoke this routine to handle a close * request * * Expected Interrupt Level (for execution) : * * IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution * to be deferred to a worker thread context) * * Return Value: STATUS_SUCCESS * *************************************************************************/ NTSTATUS NTAPI UDFClose( PDEVICE_OBJECT DeviceObject, // the logical volume device object PIRP Irp // I/O Request Packet ) { NTSTATUS RC = STATUS_SUCCESS; PtrUDFIrpContext PtrIrpContext = NULL; BOOLEAN AreWeTopLevel = FALSE; AdPrint(("UDFClose: \n")); FsRtlEnterFileSystem(); ASSERT(DeviceObject); ASSERT(Irp); // If we were called with our file system device object instead of a // volume device object, just complete this request with STATUS_SUCCESS if (UDFIsFSDevObj(DeviceObject)) { // this is a close of the FSD itself Irp->IoStatus.Status = RC; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); FsRtlExitFileSystem(); return(RC); } // set the top level context AreWeTopLevel = UDFIsIrpTopLevel(Irp); _SEH2_TRY { // get an IRP context structure and issue the request PtrIrpContext = UDFAllocateIrpContext(Irp, DeviceObject); ASSERT(PtrIrpContext); RC = UDFCommonClose(PtrIrpContext, Irp); } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext, _SEH2_GetExceptionInformation())) { RC = UDFExceptionHandler(PtrIrpContext, Irp); UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC); } _SEH2_END; if (AreWeTopLevel) { IoSetTopLevelIrp(NULL); } FsRtlExitFileSystem(); return(RC); }
VOID NtfsReleaseScbFromLazyWrite ( IN PVOID OpaqueScb ) /*++ Routine Description: The address of this routine is specified when creating a CacheMap for a file. It is subsequently called by the Lazy Writer after its performing lazy writes to the file. Arguments: Scb - The Scb which was specified as a context parameter for this routine. Return Value: None --*/ { ULONG CompressedStream = (ULONG)OpaqueScb & 1; PSCB Scb = (PSCB)((ULONG)OpaqueScb & ~1); PFCB Fcb = Scb->Fcb; ASSERT_SCB(Scb); PAGED_CODE(); // // Clear the toplevel at this point, if we set it above. // if (IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP) { IoSetTopLevelIrp( NULL ); } Scb->LazyWriteThread[CompressedStream] = NULL; if (NtfsSegmentNumber( &Fcb->FileReference ) <= MASTER_FILE_TABLE2_NUMBER) { NOTHING; } else if (Scb->Header.PagingIoResource != NULL) { ExReleaseResource( Scb->Header.PagingIoResource ); } else { ExReleaseResource( Scb->Header.Resource ); } return; }
VOID FFSFloppyFlush( IN PVOID Parameter) { PFFS_FLPFLUSH_CONTEXT Context; PFILE_OBJECT FileObject; PFFS_FCB Fcb; PFFS_VCB Vcb; Context = (PFFS_FLPFLUSH_CONTEXT) Parameter; FileObject = Context->FileObject; Fcb = Context->Fcb; Vcb = Context->Vcb; FFSPrint((DBG_USER, "FFSFloppyFlushing ...\n")); IoSetTopLevelIrp((PIRP)FSRTL_FSP_TOP_LEVEL_IRP); if (Vcb) { ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE); ExReleaseResource(&Vcb->PagingIoResource); CcFlushCache(&(Vcb->SectionObject), NULL, 0, NULL); } if (FileObject) { ASSERT(Fcb == (PFFS_FCB)FileObject->FsContext); ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE); ExReleaseResource(&Fcb->PagingIoResource); CcFlushCache(&(Fcb->SectionObject), NULL, 0, NULL); ObDereferenceObject(FileObject); } IoSetTopLevelIrp(NULL); ExFreePool(Parameter); }
static void release_from_read_ahead(PVOID Context) { PFILE_OBJECT FileObject = Context; fcb* fcb = FileObject->FsContext; TRACE("(%p)\n", Context); ExReleaseResourceLite(fcb->Header.Resource); if (IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP) IoSetTopLevelIrp(NULL); }
VOID Ext2FloppyFlush(IN PVOID Parameter) { PEXT2_FLPFLUSH_CONTEXT Context; PFILE_OBJECT FileObject; PEXT2_FCB Fcb; PEXT2_VCB Vcb; Context = (PEXT2_FLPFLUSH_CONTEXT) Parameter; FileObject = Context->FileObject; Fcb = Context->Fcb; Vcb = Context->Vcb; DEBUG(DL_FLP, ("Ext2FloppyFlushing ...\n")); IoSetTopLevelIrp((PIRP)FSRTL_FSP_TOP_LEVEL_IRP); if (FileObject) { ASSERT(Fcb == (PEXT2_FCB)FileObject->FsContext); ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE); ExReleaseResourceLite(&Fcb->PagingIoResource); CcFlushCache(&(Fcb->SectionObject), NULL, 0, NULL); ObDereferenceObject(FileObject); } if (Vcb) { ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE); ExReleaseResourceLite(&Vcb->PagingIoResource); ExAcquireResourceExclusiveLite(&Vcb->sbi.s_gd_lock, TRUE); Ext2DropBH(Vcb); CcFlushCache(&(Vcb->SectionObject), NULL, 0, NULL); ExReleaseResourceLite(&Vcb->sbi.s_gd_lock); } IoSetTopLevelIrp(NULL); Ext2FreePool(Parameter, EXT2_FLPFLUSH_MAGIC); }
BOOLEAN NTAPI FatIsTopLevelIrp(IN PIRP Irp) { if (!IoGetTopLevelIrp()) { IoSetTopLevelIrp(Irp); return TRUE; } return FALSE; }
static BOOLEAN acquire_for_read_ahead(PVOID Context, BOOLEAN Wait) { PFILE_OBJECT FileObject = Context; fcb* fcb = FileObject->FsContext; TRACE("(%p, %u)\n", Context, Wait); if (!ExAcquireResourceSharedLite(fcb->Header.Resource, Wait)) return FALSE; IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); return TRUE; }
VOID FspIopCompleteCanceledIrp(PIRP Irp) { PAGED_CODE(); DEBUGLOGIRP(Irp, STATUS_CANCELLED); /* * An IRP cancel may happen at any time including when APC's are still enabled. * For this reason we execute FsRtlEnterFileSystem/FsRtlExitFileSystem here. * This will protect ERESOURCE operations during Request finalizations. */ FsRtlEnterFileSystem(); PIRP TopLevelIrp = IoGetTopLevelIrp(); IoSetTopLevelIrp(Irp); FspIopCompleteIrpEx(Irp, STATUS_CANCELLED, TRUE); IoSetTopLevelIrp(TopLevelIrp); FsRtlExitFileSystem(); }
/************************************************************************* * * Function: UDFShutdown() * * Description: * All disk-based FSDs can expect to receive this shutdown notification * request whenever the system is about to be halted gracefully. If you * design and implement a network redirector, you must register explicitly * for shutdown notification by invoking the IoRegisterShutdownNotification() * routine from your driver entry. * * Note that drivers that register to receive shutdown notification get * invoked BEFORE disk-based FSDs are told about the shutdown notification. * * Expected Interrupt Level (for execution) : * * IRQL_PASSIVE_LEVEL * * Return Value: Irrelevant. * *************************************************************************/ NTSTATUS NTAPI UDFShutdown( PDEVICE_OBJECT DeviceObject, // the logical volume device object PIRP Irp // I/O Request Packet ) { NTSTATUS RC = STATUS_SUCCESS; PtrUDFIrpContext PtrIrpContext = NULL; BOOLEAN AreWeTopLevel = FALSE; KdPrint(("UDFShutDown\n")); // BrutePoint(); FsRtlEnterFileSystem(); ASSERT(DeviceObject); ASSERT(Irp); // set the top level context AreWeTopLevel = UDFIsIrpTopLevel(Irp); //ASSERT(!UDFIsFSDevObj(DeviceObject)); _SEH2_TRY { // get an IRP context structure and issue the request PtrIrpContext = UDFAllocateIrpContext(Irp, DeviceObject); if(PtrIrpContext) { RC = UDFCommonShutdown(PtrIrpContext, Irp); } else { RC = STATUS_INSUFFICIENT_RESOURCES; Irp->IoStatus.Status = RC; Irp->IoStatus.Information = 0; // complete the IRP IoCompleteRequest(Irp, IO_DISK_INCREMENT); } } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext, _SEH2_GetExceptionInformation())) { RC = UDFExceptionHandler(PtrIrpContext, Irp); UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC); } _SEH2_END; if (AreWeTopLevel) { IoSetTopLevelIrp(NULL); } FsRtlExitFileSystem(); return(RC); } // end UDFShutdown()
VOID FFSDeQueueRequest( IN PVOID Context) { PFFS_IRP_CONTEXT IrpContext; IrpContext = (PFFS_IRP_CONTEXT) Context; ASSERT(IrpContext); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); __try { __try { FsRtlEnterFileSystem(); if (!IrpContext->IsTopLevel) { IoSetTopLevelIrp((PIRP) FSRTL_FSP_TOP_LEVEL_IRP); } FFSDispatchRequest(IrpContext); } __except (FFSExceptionFilter(IrpContext, GetExceptionInformation())) { FFSExceptionHandler(IrpContext); } } __finally { IoSetTopLevelIrp(NULL); FsRtlExitFileSystem(); } }
NTSTATUS NTAPI NtfsFsdDirectoryControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) { PNTFS_IRP_CONTEXT IrpContext = NULL; NTSTATUS Status = STATUS_UNSUCCESSFUL; DPRINT1("NtfsDirectoryControl() called\n"); FsRtlEnterFileSystem(); ASSERT(DeviceObject); ASSERT(Irp); NtfsIsIrpTopLevel(Irp); IrpContext = NtfsAllocateIrpContext(DeviceObject, Irp); if (IrpContext) { switch (IrpContext->MinorFunction) { case IRP_MN_QUERY_DIRECTORY: Status = NtfsQueryDirectory(IrpContext); break; case IRP_MN_NOTIFY_CHANGE_DIRECTORY: DPRINT1("IRP_MN_NOTIFY_CHANGE_DIRECTORY\n"); Status = STATUS_NOT_IMPLEMENTED; break; default: Status = STATUS_INVALID_DEVICE_REQUEST; break; } } else Status = STATUS_INSUFFICIENT_RESOURCES; Irp->IoStatus.Status = Status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); if (IrpContext) ExFreePoolWithTag(IrpContext, 'PRIN'); IoSetTopLevelIrp(NULL); FsRtlExitFileSystem(); return Status; }
static void release_from_lazy_write(PVOID Context) { PFILE_OBJECT FileObject = Context; fcb* fcb = FileObject->FsContext; TRACE("(%p)\n", Context); fcb->lazy_writer_thread = NULL; ExReleaseResourceLite(fcb->Header.Resource); ExReleaseResourceLite(&fcb->Vcb->tree_lock); if (IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP) IoSetTopLevelIrp(NULL); }
/* * FUNCTION: Used with IRP to set them to TopLevelIrp field * ARGUMENTS: * Irp = The IRP to set * RETURNS: TRUE if top level was null, else FALSE */ BOOLEAN NtfsIsIrpTopLevel(PIRP Irp) { BOOLEAN ReturnCode = FALSE; TRACE_(NTFS, "NtfsIsIrpTopLevel()\n"); if (IoGetTopLevelIrp() == NULL) { IoSetTopLevelIrp(Irp); ReturnCode = TRUE; } return ReturnCode; }
BOOLEAN DokanNoOpAcquire(__in PVOID Fcb, __in BOOLEAN Wait) { UNREFERENCED_PARAMETER(Fcb); UNREFERENCED_PARAMETER(Wait); DDbgPrint("==> DokanNoOpAcquire\n"); ASSERT(IoGetTopLevelIrp() == NULL); IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); DDbgPrint("<== DokanNoOpAcquire\n"); return TRUE; }
/* * FUNCTION: This function manages IRP for various major functions * ARGUMENTS: * DriverObject = object describing this driver * Irp = IRP to be passed to internal functions * RETURNS: Status of I/O Request */ NTSTATUS NTAPI NtfsFsdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp) { PNTFS_IRP_CONTEXT IrpContext = NULL; NTSTATUS Status = STATUS_UNSUCCESSFUL; TRACE_(NTFS, "NtfsFsdDispatch()\n"); FsRtlEnterFileSystem(); ASSERT(DeviceObject); ASSERT(Irp); NtfsIsIrpTopLevel(Irp); IrpContext = NtfsAllocateIrpContext(DeviceObject, Irp); if (IrpContext) { switch (IrpContext->MajorFunction) { case IRP_MJ_QUERY_VOLUME_INFORMATION: { Status = NtfsQueryVolumeInformation(IrpContext); break; } case IRP_MJ_SET_VOLUME_INFORMATION: { Status = NtfsSetVolumeInformation(IrpContext); break; } } } else Status = STATUS_INSUFFICIENT_RESOURCES; Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); if (IrpContext) ExFreePoolWithTag(IrpContext, 'PRIN'); IoSetTopLevelIrp(NULL); FsRtlExitFileSystem(); return Status; }
/************************************************************************* * * Function: Ext2Close() * * Description: * The I/O Manager will invoke this routine to handle a close * request * * Expected Interrupt Level (for execution) : * * IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution * to be deferred to a worker thread context) * * Return Value: Does not matter! * *************************************************************************/ NTSTATUS NTAPI Ext2Close( PDEVICE_OBJECT DeviceObject, // the logical volume device object PIRP Irp) // I/O Request Packet { NTSTATUS RC = STATUS_SUCCESS; PtrExt2IrpContext PtrIrpContext = NULL; BOOLEAN AreWeTopLevel = FALSE; DebugTrace(DEBUG_TRACE_IRP_ENTRY, "Close IRP Received...", 0); FsRtlEnterFileSystem(); ASSERT(DeviceObject); ASSERT(Irp); // set the top level context AreWeTopLevel = Ext2IsIrpTopLevel(Irp); try { // get an IRP context structure and issue the request PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject); ASSERT(PtrIrpContext); RC = Ext2CommonClose(PtrIrpContext, Irp, TRUE); } except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation())) { RC = Ext2ExceptionHandler(PtrIrpContext, Irp); Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC); } if (AreWeTopLevel) { IoSetTopLevelIrp(NULL); } FsRtlExitFileSystem(); return(RC); }
NTSTATUS DDKAPI VfsDirectoryControl(PDEVICE_OBJECT device, PIRP irp) { NTSTATUS status = STATUS_SUCCESS; PIRPCONTEXT irp_context = NULL; BOOLEAN top_level = FALSE; FsRtlEnterFileSystem(); top_level = LklIsIrpTopLevel(irp); irp_context = AllocIrpContext(irp, device); status = CommonDirectoryControl(irp_context, irp); if (top_level) IoSetTopLevelIrp(NULL); FsRtlExitFileSystem(); return status; }
static BOOLEAN acquire_for_lazy_write(PVOID Context, BOOLEAN Wait) { PFILE_OBJECT FileObject = Context; fcb* fcb = FileObject->FsContext; TRACE("(%p, %u)\n", Context, Wait); if (!ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, Wait)) return FALSE; if (!ExAcquireResourceExclusiveLite(fcb->Header.Resource, Wait)) { ExReleaseResourceLite(&fcb->Vcb->tree_lock); return FALSE; } fcb->lazy_writer_thread = KeGetCurrentThread(); IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); return TRUE; }
static NTSTATUS FspFsvolLockControlRetry( PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp, BOOLEAN CanWait) { PAGED_CODE(); NTSTATUS Result; PFILE_OBJECT FileObject = IrpSp->FileObject; FSP_FILE_NODE *FileNode = FileObject->FsContext; BOOLEAN Success; /* try to acquire the FileNode shared Main */ Success = DEBUGTEST(90) && FspFileNodeTryAcquireSharedF(FileNode, FspFileNodeAcquireMain, CanWait); if (!Success) return FspWqRepostIrpWorkItem(Irp, FspFsvolLockControlRetry, 0); /* perform oplock check; we are only implementing Win7 behavior */ Result = FspFileNodeOplockCheckAsync( FileNode, FspFileNodeAcquireMain, FspFsvolLockControlRetry, Irp); if (STATUS_PENDING == Result) return Result; if (!NT_SUCCESS(Result)) { FspFileNodeRelease(FileNode, Main); return Result; } ULONG IrpFlags = FspIrpFlags(Irp); IoSetTopLevelIrp(0); /* let the FSRTL package handle this one! */ Result = FspFileNodeProcessLockIrp(FileNode, Irp); FspFileNodeReleaseF(FileNode, IrpFlags); return Result | FSP_STATUS_IGNORE_BIT; }
NTSTATUS NTAPI FatRead(PDEVICE_OBJECT DeviceObject, PIRP Irp) { NTSTATUS Status; BOOLEAN TopLevel, CanWait; PFAT_IRP_CONTEXT IrpContext; CanWait = TRUE; TopLevel = FALSE; Status = STATUS_INVALID_DEVICE_REQUEST; /* Get CanWait flag */ if (IoGetCurrentIrpStackLocation(Irp)->FileObject != NULL) CanWait = IoIsOperationSynchronous(Irp); /* Enter FsRtl critical region */ FsRtlEnterFileSystem(); if (DeviceObject != FatGlobalData.DiskDeviceObject) { /* Set Top Level IRP if not set */ TopLevel = FatIsTopLevelIrp(Irp); /* Build an irp context */ IrpContext = FatBuildIrpContext(Irp, CanWait); /* Perform the actual read */ Status = FatiRead(IrpContext); /* Restore top level Irp */ if (TopLevel) IoSetTopLevelIrp(NULL); } /* Leave FsRtl critical region */ FsRtlExitFileSystem(); return Status; }
VOID CdSetThreadContext ( _Inout_ PIRP_CONTEXT IrpContext, _In_ PTHREAD_CONTEXT ThreadContext ) /*++ Routine Description: This routine is called at each Fsd/Fsp entry point set up the IrpContext and thread local storage to track top level requests. If there is not a Cdfs context in the thread local storage then we use the input one. Otherwise we use the one already there. This routine also updates the IrpContext based on the state of the top-level context. If the TOP_LEVEL flag in the IrpContext is already set when we are called then we force this request to appear top level. Arguments: ThreadContext - Address on stack for local storage if not already present. ForceTopLevel - We force this request to appear top level regardless of any previous stack value. Return Value: None --*/ { PTHREAD_CONTEXT CurrentThreadContext; PAGED_CODE(); ASSERT_IRP_CONTEXT( IrpContext ); // // Get the current top-level irp out of the thread storage. // If NULL then this is the top-level request. // CurrentThreadContext = (PTHREAD_CONTEXT) IoGetTopLevelIrp(); if (CurrentThreadContext == NULL) { SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_TOP_LEVEL ); } // // Initialize the input context unless we are using the current // thread context block. We use the new block if our caller // specified this or the existing block is invalid. // // The following must be true for the current to be a valid Cdfs context. // // Structure must lie within current stack. // Address must be ULONG aligned. // Cdfs signature must be present. // // If this is not a valid Cdfs context then use the input thread // context and store it in the top level context. // #pragma warning(suppress: 6011) // Bug in PREFast around bitflag operations if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TOP_LEVEL ) || (!IoWithinStackLimits( (ULONG_PTR)CurrentThreadContext, sizeof( THREAD_CONTEXT ) ) || FlagOn( (ULONG_PTR) CurrentThreadContext, 0x3 ) || (CurrentThreadContext->Cdfs != 0x53464443))) { ThreadContext->Cdfs = 0x53464443; ThreadContext->SavedTopLevelIrp = (PIRP) CurrentThreadContext; ThreadContext->TopLevelIrpContext = IrpContext; IoSetTopLevelIrp( (PIRP) ThreadContext ); IrpContext->TopLevel = IrpContext; IrpContext->ThreadContext = ThreadContext; SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_TOP_LEVEL_CDFS ); // // Otherwise use the IrpContext in the thread context. // } else { IrpContext->TopLevel = CurrentThreadContext->TopLevelIrpContext; } return; }
NTSTATUS FatFsdClose ( _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject, _Inout_ PIRP Irp ) /*++ Routine Description: This routine implements the FSD part of Close. Arguments: VolumeDeviceObject - Supplies the volume device object where the file exists Irp - Supplies the Irp being processed Return Value: NTSTATUS - The FSD status for the IRP --*/ { NTSTATUS Status = STATUS_SUCCESS; PIO_STACK_LOCATION IrpSp; PFILE_OBJECT FileObject; PVCB Vcb; PFCB Fcb; PCCB Ccb; TYPE_OF_OPEN TypeOfOpen; BOOLEAN TopLevel; BOOLEAN VcbDeleted = FALSE; PAGED_CODE(); // // If we were called with our file system device object instead of a // volume device object, just complete this request with STATUS_SUCCESS // if (FatDeviceIsFatFsdo( VolumeDeviceObject)) { Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = FILE_OPENED; IoCompleteRequest( Irp, IO_DISK_INCREMENT ); return STATUS_SUCCESS; } DebugTrace(+1, Dbg, "FatFsdClose\n", 0); // // Call the common Close routine // FsRtlEnterFileSystem(); TopLevel = FatIsIrpTopLevel( Irp ); // // Get a pointer to the current stack location and the file object // IrpSp = IoGetCurrentIrpStackLocation( Irp ); FileObject = IrpSp->FileObject; // // Decode the file object and set the read-only bit in the Ccb. // TypeOfOpen = FatDecodeFileObject( FileObject, &Vcb, &Fcb, &Ccb ); if (Ccb && IsFileObjectReadOnly(FileObject)) { SetFlag( Ccb->Flags, CCB_FLAG_READ_ONLY ); } try { PCLOSE_CONTEXT CloseContext = NULL; // // If we are top level, WAIT can be TRUE, otherwise make it FALSE // to avoid deadlocks, unless this is a top // level request not originating from the system process. // BOOLEAN Wait = TopLevel && (PsGetCurrentProcess() != FatData.OurProcess); #if (NTDDI_VERSION >= NTDDI_WIN8) // // To catch the odd case where a close comes in without a preceding cleanup, // call the oplock package to get rid of any oplock state. This can only // be safely done in the FSD path. // if ((Fcb != NULL) && !FlagOn( FileObject->Flags, FO_CLEANUP_COMPLETE ) && FatIsFileOplockable( Fcb )) { // // This is equivalent to handling cleanup, and it always cleans up any // oplock immediately. Also, we don't need any locking of the FCB here; // the oplock's own lock will be sufficient for this purpose. // FsRtlCheckOplockEx( FatGetFcbOplock(Fcb), Irp, 0, NULL, NULL, NULL ); } #endif // // Call the common Close routine if we are not delaying this close. // if ((((TypeOfOpen == UserFileOpen) || (TypeOfOpen == UserDirectoryOpen)) && FlagOn(Fcb->FcbState, FCB_STATE_DELAY_CLOSE) && !FatData.ShutdownStarted) || (FatCommonClose( Vcb, Fcb, Ccb, TypeOfOpen, Wait, TopLevel, &VcbDeleted ) == STATUS_PENDING)) { // // Metadata streams have had close contexts preallocated. // if (TypeOfOpen == VirtualVolumeFile) { NT_ASSERT( Vcb->CloseContext != NULL ); CloseContext = Vcb->CloseContext; Vcb->CloseContext = NULL; CloseContext->Free = TRUE; } else if ((TypeOfOpen == DirectoryFile) || (TypeOfOpen == EaFile)) { CloseContext = FatAllocateCloseContext( Vcb); NT_ASSERT( CloseContext != NULL ); CloseContext->Free = TRUE; } else { // // Free up any query template strings before using the close context fields, // which overlap (union) // FatDeallocateCcbStrings( Ccb ); CloseContext = &Ccb->CloseContext; CloseContext->Free = FALSE; SetFlag( Ccb->Flags, CCB_FLAG_CLOSE_CONTEXT ); } // // If the status is pending, then let's get the information we // need into the close context we already have bagged, complete // the request, and post it. It is important we allocate nothing // in the close path. // CloseContext->Vcb = Vcb; CloseContext->Fcb = Fcb; CloseContext->TypeOfOpen = TypeOfOpen; // // Send it off, either to an ExWorkerThread or to the async // close list. // FatQueueClose( CloseContext, (BOOLEAN)(Fcb && FlagOn(Fcb->FcbState, FCB_STATE_DELAY_CLOSE))); } else { // // The close proceeded synchronously, so for the metadata objects we // can now drop the close context we preallocated. // if ((TypeOfOpen == VirtualVolumeFile) || (TypeOfOpen == DirectoryFile) || (TypeOfOpen == EaFile)) { if (TypeOfOpen == VirtualVolumeFile) { // // If the VCB was deleted during the close, the close context for this // open has already been freed. // if (!VcbDeleted) { CloseContext = Vcb->CloseContext; Vcb->CloseContext = NULL; NT_ASSERT( CloseContext != NULL ); } else { CloseContext = NULL; } } else { CloseContext = FatAllocateCloseContext( (VcbDeleted ? NULL : Vcb) ); NT_ASSERT( CloseContext != NULL ); } if (CloseContext != NULL) { ExFreePool( CloseContext ); } } } FatCompleteRequest( FatNull, Irp, Status ); } except(FatExceptionFilter( NULL, GetExceptionInformation() )) { // // We had some trouble trying to perform the requested // operation, so we'll abort the I/O request with the // error status that we get back from the execption code. // Status = FatProcessException( NULL, Irp, GetExceptionCode() ); } if (TopLevel) { IoSetTopLevelIrp( NULL ); } FsRtlExitFileSystem(); // // And return to our caller // DebugTrace(-1, Dbg, "FatFsdClose -> %08lx\n", Status); UNREFERENCED_PARAMETER( VolumeDeviceObject ); return Status; }