From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/nw/rdr/cleanup.c | 591 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 591 insertions(+) create mode 100644 private/nw/rdr/cleanup.c (limited to 'private/nw/rdr/cleanup.c') diff --git a/private/nw/rdr/cleanup.c b/private/nw/rdr/cleanup.c new file mode 100644 index 000000000..2eb22afcd --- /dev/null +++ b/private/nw/rdr/cleanup.c @@ -0,0 +1,591 @@ +/*++ + +Copyright (c) 1993 Microsoft Corporation + +Module Name: + + cleanup.c + +Abstract: + + This module implements the file cleanup routine for Netware Redirector. + +Author: + + Manny Weiser (mannyw) 9-Feb-1993 + +Revision History: + +--*/ + +#include "procs.h" + +// +// The debug trace level +// + +#define Dbg (DEBUG_TRACE_CLEANUP) + +// +// local procedure prototypes +// + +NTSTATUS +NwCommonCleanup ( + IN PIRP_CONTEXT IrpContext + ); + + +NTSTATUS +NwCleanupRcb ( + IN PIRP Irp, + IN PRCB Rcb + ); + +NTSTATUS +NwCleanupScb ( + IN PIRP Irp, + IN PSCB Scb + ); + +NTSTATUS +NwCleanupIcb ( + IN PIRP_CONTEXT IrpContext, + IN PIRP Irp, + IN PICB Icb + ); + +#ifdef ALLOC_PRAGMA +#pragma alloc_text( PAGE, NwFsdCleanup ) +#pragma alloc_text( PAGE, NwCommonCleanup ) +#pragma alloc_text( PAGE, NwCleanupScb ) + +#ifndef QFE_BUILD +#pragma alloc_text( PAGE1, NwCleanupIcb ) +#endif + +#endif + +#if 0 // Not pageable + +NwCleanupRcb + +// see ifndef QFE_BUILD above + +#endif + + +NTSTATUS +NwFsdCleanup ( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ) + +/*++ + +Routine Description: + + This routine implements the FSD part of the NtCleanupFile API calls. + +Arguments: + + DeviceObject - Supplies the device object to use. + + Irp - Supplies the Irp being processed + +Return Value: + + NTSTATUS - The Fsd status for the Irp + +--*/ + +{ + NTSTATUS status; + PIRP_CONTEXT IrpContext = NULL; + BOOLEAN TopLevel; + + PAGED_CODE(); + + DebugTrace(+1, Dbg, "NwFsdCleanup\n", 0); + + // + // Call the common cleanup routine. + // + + TopLevel = NwIsIrpTopLevel( Irp ); + + FsRtlEnterFileSystem(); + + try { + + IrpContext = AllocateIrpContext( Irp ); + status = NwCommonCleanup( IrpContext ); + + } except(NwExceptionFilter( Irp, GetExceptionInformation() )) { + + if ( IrpContext == NULL ) { + + // + // If we couldn't allocate an irp context, just complete + // irp without any fanfare. + // + + status = STATUS_INSUFFICIENT_RESOURCES; + Irp->IoStatus.Status = status; + Irp->IoStatus.Information = 0; + IoCompleteRequest ( Irp, IO_NETWORK_INCREMENT ); + + } else { + + // + // 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 = NwProcessException( IrpContext, GetExceptionCode() ); + } + } + + if ( IrpContext ) { + NwCompleteRequest( IrpContext, status ); + } + + if ( TopLevel ) { + NwSetTopLevelIrp( NULL ); + } + FsRtlExitFileSystem(); + + // + // Return to our caller. + // + + DebugTrace(-1, Dbg, "NwFsdCleanup -> %08lx\n", status ); + return status; +} + + +NTSTATUS +NwCommonCleanup ( + IN PIRP_CONTEXT IrpContext + ) + +/*++ + +Routine Description: + + This is the common routine for cleaning up a file. + +Arguments: + + IrpContext - Supplies the Irp to process + +Return Value: + + NTSTATUS - the return status for the operation + +--*/ + +{ + PIRP Irp; + PIO_STACK_LOCATION irpSp; + NTSTATUS status; + NODE_TYPE_CODE nodeTypeCode; + PVOID fsContext, fsContext2; + + PAGED_CODE(); + + Irp = IrpContext->pOriginalIrp; + irpSp = IoGetCurrentIrpStackLocation( Irp ); + + DebugTrace(+1, Dbg, "NwCommonCleanup\n", 0); + DebugTrace( 0, Dbg, "IrpContext = %08lx\n", (ULONG)IrpContext); + DebugTrace( 0, Dbg, "Irp = %08lx\n", (ULONG)Irp); + DebugTrace( 0, Dbg, "FileObject = %08lx\n", (ULONG)irpSp->FileObject); + + try { + + // + // Get the a referenced pointer to the node and make sure it is + // not being closed. + // + + if ((nodeTypeCode = NwDecodeFileObject( irpSp->FileObject, + &fsContext, + &fsContext2 )) == NTC_UNDEFINED) { + + DebugTrace(0, Dbg, "The file is disconnected\n", 0); + + status = STATUS_INVALID_HANDLE; + + DebugTrace(-1, Dbg, "NwCommonCleanup -> %08lx\n", status ); + try_return( NOTHING ); + } + + // + // Decide how to handle this IRP. + // + + switch (nodeTypeCode) { + + case NW_NTC_RCB: // Cleanup the file system + + status = NwCleanupRcb( Irp, (PRCB)fsContext2 ); + break; + + case NW_NTC_SCB: // Cleanup the server control block + + status = NwCleanupScb( Irp, (PSCB)fsContext2 ); + break; + + case NW_NTC_ICB: // Cleanup the remote file + case NW_NTC_ICB_SCB: // Cleanup the server + + status = NwCleanupIcb( IrpContext, Irp, (PICB)fsContext2 ); + break; + +#ifdef NWDBG + default: + + // + // This is not one of ours. + // + + KeBugCheck( RDR_FILE_SYSTEM ); + break; +#endif + + } + + try_exit: NOTHING; + + } finally { + + DebugTrace(-1, Dbg, "NwCommonCleanup -> %08lx\n", status); + + } + + return status; +} + + +NTSTATUS +NwCleanupRcb ( + IN PIRP Irp, + IN PRCB Rcb + ) + +/*++ + +Routine Description: + + The routine cleans up a RCB. + + This routine grabs a spinlock so must not be paged out while running. + + Do not reference the code section since this will start the timer and + we don't stop it in the rcb close path. + +Arguments: + + Irp - Supplies the IRP associated with the cleanup. + + Rcb - Supplies the RCB for MSFS. + +Return Value: + + NTSTATUS - An appropriate completion status + +--*/ + +{ + NTSTATUS status; + PIO_STACK_LOCATION irpSp; + PFILE_OBJECT closingFileObject; + BOOLEAN OwnRcb; + BOOLEAN OwnMessageLock = FALSE; + KIRQL OldIrql; + PLIST_ENTRY listEntry, nextListEntry; + PIRP_CONTEXT pTestIrpContext; + PIO_STACK_LOCATION pTestIrpSp; + PIRP pTestIrp; + + DebugTrace(+1, Dbg, "NwCleanupRcb...\n", 0); + + // + // Now acquire exclusive access to the Rcb + // + + NwAcquireExclusiveRcb( Rcb, TRUE ); + OwnRcb = TRUE; + + status = STATUS_SUCCESS; + + try { + + irpSp = IoGetCurrentIrpStackLocation( Irp ); + + IoRemoveShareAccess( irpSp->FileObject, + &Rcb->ShareAccess ); + + NwReleaseRcb( Rcb ); + OwnRcb = FALSE; + + closingFileObject = irpSp->FileObject; + + + // + // Walk the message queue and complete any outstanding Get Message IRPs + // + + KeAcquireSpinLock( &NwMessageSpinLock, &OldIrql ); + OwnMessageLock = TRUE; + + for ( listEntry = NwGetMessageList.Flink; + listEntry != &NwGetMessageList; + listEntry = nextListEntry ) { + + nextListEntry = listEntry->Flink; + + // + // If the file object of the queued request, matches the file object + // that is being closed, remove the IRP from the queue, and + // complete it with an error. + // + + pTestIrpContext = CONTAINING_RECORD( listEntry, IRP_CONTEXT, NextRequest ); + pTestIrp = pTestIrpContext->pOriginalIrp; + pTestIrpSp = IoGetCurrentIrpStackLocation( pTestIrp ); + + if ( pTestIrpSp->FileObject == closingFileObject ) { + RemoveEntryList( listEntry ); + + IoAcquireCancelSpinLock( &pTestIrp->CancelIrql ); + IoSetCancelRoutine( pTestIrp, NULL ); + IoReleaseCancelSpinLock( pTestIrp->CancelIrql ); + + NwCompleteRequest( pTestIrpContext, STATUS_INVALID_HANDLE ); + } + + } + + KeReleaseSpinLock( &NwMessageSpinLock, OldIrql ); + OwnMessageLock = FALSE; + + } finally { + + if ( OwnRcb ) { + NwReleaseRcb( Rcb ); + } + + if ( OwnMessageLock ) { + KeReleaseSpinLock( &NwMessageSpinLock, OldIrql ); + } + + DebugTrace(-1, Dbg, "NwCleanupRcb -> %08lx\n", status); + } + + // + // And return to our caller + // + + return status; +} + + +NTSTATUS +NwCleanupScb ( + IN PIRP Irp, + IN PSCB Scb + ) + +/*++ + +Routine Description: + + The routine cleans up an ICB. + +Arguments: + + Irp - Supplies the IRP associated with the cleanup. + + Scb - Supplies the SCB to cleanup. + +Return Value: + + NTSTATUS - An appropriate completion status + +--*/ +{ + NTSTATUS Status; + + PAGED_CODE(); + + DebugTrace(+1, Dbg, "NwCleanupScb...\n", 0); + + Status = STATUS_SUCCESS; + + try { + + // + // Ensure that this SCB is still active. + // + + NwVerifyScb( Scb ); + + // + // Cancel any IO on this SCB. + // + + } finally { + + DebugTrace(-1, Dbg, "NwCleanupScb -> %08lx\n", Status); + } + + // + // And return to our caller + // + + return Status; +} + + +NTSTATUS +NwCleanupIcb ( + IN PIRP_CONTEXT pIrpContext, + IN PIRP Irp, + IN PICB Icb + ) + +/*++ + +Routine Description: + + The routine cleans up an ICB. + +Arguments: + + Irp - Supplies the IRP associated with the cleanup. + + Rcb - Supplies the RCB for MSFS. + +Return Value: + + NTSTATUS - An appropriate completion status + +--*/ +{ + NTSTATUS Status; + PNONPAGED_FCB NpFcb; + + DebugTrace(+1, Dbg, "NwCleanupIcb...\n", 0); + + Status = STATUS_SUCCESS; + + try { + + Icb->State = ICB_STATE_CLEANED_UP; + + // + // Cancel any IO on this ICB. + // + +#if 0 + // HACKHACK + + if ( Icb->SuperType.Fcb->NodeTypeCode == NW_NTC_DCB ) { + + PLIST_ENTRY listEntry; + + NwAcquireExclusiveRcb( &NwRcb, TRUE ); + + for ( listEntry = FnList.Flink; listEntry != &FnList ; listEntry = listEntry->Flink ) { + + PIRP_CONTEXT IrpContext; + + IrpContext = CONTAINING_RECORD( listEntry, IRP_CONTEXT, NextRequest ); + + if ( IrpContext->Icb == Icb ) { + + PIRP irp = pIrpContext->pOriginalIrp; + + IoAcquireCancelSpinLock( &irp->CancelIrql ); + IoSetCancelRoutine( irp, NULL ); + IoReleaseCancelSpinLock( irp->CancelIrql ); + + RemoveEntryList( &IrpContext->NextRequest ); + NwCompleteRequest( IrpContext, STATUS_NOT_SUPPORTED ); + break; + } + } + + NwReleaseRcb( &NwRcb ); + } +#endif + + // + // If this is a remote file clear all the cache garbage. + // + + if ( Icb->NodeTypeCode == NW_NTC_ICB ) { + + if ( Icb->HasRemoteHandle ) { + + // + // Free all of file lock structures that are still hanging around. + // + + pIrpContext->pScb = Icb->SuperType.Fcb->Scb; + pIrpContext->pNpScb = Icb->SuperType.Fcb->Scb->pNpScb; + + NwFreeLocksForIcb( pIrpContext, Icb ); + + NwDequeueIrpContext( pIrpContext, FALSE ); + + // + // + // + // If this is an executable opened over the net, then + // its possible that the executables image section + // might still be kept open. + // + // Ask MM to flush the section closed. This will fail + // if the executable in question is still running. + // + + NpFcb = Icb->SuperType.Fcb->NonPagedFcb; + MmFlushImageSection(&NpFcb->SegmentObject, MmFlushForWrite); + + // + // There is also a possiblity that there is a user section + // open on this file, in which case we need to force the + // section closed to make sure that they are cleaned up. + // + + MmForceSectionClosed(&NpFcb->SegmentObject, TRUE); + + } + + // + // Remove shared access. + // + + IoRemoveShareAccess( + Icb->FileObject, + &Icb->SuperType.Fcb->ShareAccess ); + } + + + } finally { + + DebugTrace(-1, Dbg, "NwCleanupIcb -> %08lx\n", Status); + } + + // + // And return to our caller + // + + return Status; +} + -- cgit v1.2.3