|
|
/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
cleanup.c
Abstract:
This module implements the file cleanup routine for MSFS called by the dispatch driver.
Author:
Manny Weiser (mannyw) 23-Jan-1991
Revision History:
--*/
#include "mailslot.h"
//
// The debug trace level
//
#define Dbg (DEBUG_TRACE_CLEANUP)
//
// local procedure prototypes
//
NTSTATUS MsCommonCleanup ( IN PMSFS_DEVICE_OBJECT MsfsDeviceObject, IN PIRP Irp );
NTSTATUS MsCleanupCcb ( IN PMSFS_DEVICE_OBJECT MsfsDeviceObject, IN PIRP Irp, IN PCCB Ccb );
NTSTATUS MsCleanupFcb ( IN PMSFS_DEVICE_OBJECT MsfsDeviceObject, IN PIRP Irp, IN PFCB Fcb );
NTSTATUS MsCleanupRootDcb ( IN PMSFS_DEVICE_OBJECT MsfsDeviceObject, IN PIRP Irp, IN PROOT_DCB RootDcb, IN PROOT_DCB_CCB Ccb );
NTSTATUS MsCleanupVcb ( IN PMSFS_DEVICE_OBJECT MsfsDeviceObject, IN PIRP Irp, IN PVCB Vcb );
#ifdef ALLOC_PRAGMA
#pragma alloc_text( PAGE, MsCleanupCcb )
#pragma alloc_text( PAGE, MsCleanupFcb )
#pragma alloc_text( PAGE, MsCleanupRootDcb )
#pragma alloc_text( PAGE, MsCleanupVcb )
#pragma alloc_text( PAGE, MsCommonCleanup )
#pragma alloc_text( PAGE, MsFsdCleanup )
#pragma alloc_text( PAGE, MsCancelTimer )
#endif
NTSTATUS MsFsdCleanup ( IN PMSFS_DEVICE_OBJECT MsfsDeviceObject, IN PIRP Irp )
/*++
Routine Description:
This routine implements the FSD part of the NtCleanupFile API calls.
Arguments:
MsfsDeviceObject - Supplies the device object to use.
Irp - Supplies the Irp being processed
Return Value:
NTSTATUS - The Fsd status for the Irp
--*/
{ NTSTATUS status;
PAGED_CODE(); DebugTrace(+1, Dbg, "MsFsdCleanup\n", 0);
//
// Call the common cleanup routine.
//
FsRtlEnterFileSystem();
status = MsCommonCleanup( MsfsDeviceObject, Irp );
FsRtlExitFileSystem();
//
// Return to our caller.
//
DebugTrace(-1, Dbg, "MsFsdCleanup -> %08lx\n", status ); return status; }
NTSTATUS MsCommonCleanup ( IN PMSFS_DEVICE_OBJECT MsfsDeviceObject, IN PIRP Irp )
/*++
Routine Description:
This is the common routine for cleaning up a file.
Arguments:
Irp - Supplies the Irp to process
Return Value:
NTSTATUS - the return status for the operation
--*/
{ PIO_STACK_LOCATION irpSp; NTSTATUS status; NODE_TYPE_CODE nodeTypeCode; PVOID fsContext, fsContext2; PVCB vcb;
PAGED_CODE(); irpSp = IoGetCurrentIrpStackLocation( Irp );
DebugTrace(+1, Dbg, "MsFsdCleanup\n", 0); DebugTrace( 0, Dbg, "MsfsDeviceObject = %08lx\n", (ULONG)MsfsDeviceObject); DebugTrace( 0, Dbg, "Irp = %08lx\n", (ULONG)Irp); DebugTrace( 0, Dbg, "FileObject = %08lx\n", (ULONG)irpSp->FileObject);
//
// Get the a referenced pointer to the node. If this is a CCB close and the FCB is already closed
// then the node type comes back as undefined. We still want to cleanup in this case.
// Cleanup for the CCB in this case is removing it from the FCB chain and removing share options. We
// could do without this cleanup but it would look stange to have a corrupted chain in this case
// (it does not harm as its never traversed again).
//
if ((nodeTypeCode = MsDecodeFileObject( irpSp->FileObject, &fsContext, &fsContext2 )) == NTC_UNDEFINED) {
MsReferenceNode( ((PNODE_HEADER)(fsContext)) ); }
//
// Get the VCB we are trying to access.
//
vcb = &MsfsDeviceObject->Vcb;
//
// Acquire exclusive access to the VCB.
//
MsAcquireExclusiveVcb( vcb );
try {
//
// Decide how to handle this IRP.
//
switch (NodeType( fsContext ) ) {
case MSFS_NTC_FCB: // Cleanup a server handle to a mailslot file
status = MsCleanupFcb( MsfsDeviceObject, Irp, (PFCB)fsContext);
MsDereferenceFcb( (PFCB)fsContext ); break;
case MSFS_NTC_CCB: // Cleanup a client handle to a mailslot file
status = MsCleanupCcb( MsfsDeviceObject, Irp, (PCCB)fsContext);
MsDereferenceCcb( (PCCB)fsContext ); break;
case MSFS_NTC_VCB: // Cleanup MSFS
status = MsCleanupVcb( MsfsDeviceObject, Irp, (PVCB)fsContext);
MsDereferenceVcb( (PVCB)fsContext ); break;
case MSFS_NTC_ROOT_DCB: // Cleanup root directory
status = MsCleanupRootDcb( MsfsDeviceObject, Irp, (PROOT_DCB)fsContext, (PROOT_DCB_CCB)fsContext2);
MsDereferenceRootDcb( (PROOT_DCB)fsContext ); break;
#ifdef MSDBG
default:
//
// This is not one of ours.
//
KeBugCheck( MAILSLOT_FILE_SYSTEM ); break; #endif
}
} finally {
MsReleaseVcb( vcb );
status = STATUS_SUCCESS; MsCompleteRequest( Irp, status );
DebugTrace(-1, Dbg, "MsCommonCleanup -> %08lx\n", status);
}
DebugTrace(-1, Dbg, "MsCommonCleanup -> %08lx\n", status); return status; }
NTSTATUS MsCleanupCcb ( IN PMSFS_DEVICE_OBJECT MsfsDeviceObject, IN PIRP Irp, IN PCCB Ccb )
/*++
Routine Description:
The routine cleans up a CCB.
Arguments:
MsfsDeviceObject - A pointer the the mailslot file system device object.
Irp - Supplies the IRP associated with the cleanup.
Ccb - Supplies the CCB for the mailslot to clean up.
Return Value:
NTSTATUS - An appropriate completion status
--*/ { NTSTATUS status; PFCB fcb;
PAGED_CODE(); DebugTrace(+1, Dbg, "MsCleanupCcb...\n", 0);
//
// Get a pointer to the FCB.
//
fcb = Ccb->Fcb;
//
// Acquire exclusive access to the FCB
//
MsAcquireExclusiveFcb( fcb );
//
// Set the CCB to closing and remove this CCB from the active list. This CCB may already be
// closed if the FCB was closed first so don't check this. We still want the chain maintained.
//
Ccb->Header.NodeState = NodeStateClosing; RemoveEntryList( &Ccb->CcbLinks ); // Protected by the FCB lock since this is the FCB CCB chain
MsReleaseFcb( fcb );
//
// Cleanup the share access.
//
ASSERT (MsIsAcquiredExclusiveVcb(fcb->Vcb)); IoRemoveShareAccess( Ccb->FileObject, &fcb->ShareAccess );
//
// And return to our caller
//
status = STATUS_SUCCESS; return status; }
VOID MsCancelTimer ( IN PDATA_ENTRY DataEntry )
/*++
Routine Description:
The routine cancels the timer and if possible frees up a work block
Arguments: DataEntry - Block that needs to be checked for a timer
Return Value:
None
--*/ { PWORK_CONTEXT WorkContext; //
// There was a timer on this read operation. Attempt
// to cancel the operation. If the cancel operation
// is successful, then we must cleanup after the operation.
// If it was unsuccessful the timer DPC will run, and
// will eventually cleanup.
//
WorkContext = DataEntry->TimeoutWorkContext; if (WorkContext == NULL) { //
// No timeout for this request, its already been canceled or its running
//
return; }
//
// Nobody else should touch this now. either this routine will free this memory or the
// timer is running at it will free the memory.
//
DataEntry->TimeoutWorkContext = NULL;
if (KeCancelTimer( &WorkContext->Timer ) ) {
//
// Release the reference to the FCB.
//
MsDereferenceFcb( WorkContext->Fcb );
//
// Free the memory from the work context, the time
// and the DPC.
//
IoFreeWorkItem (WorkContext->WorkItem); ExFreePool( WorkContext );
} else { //
// Time code is active. Break the link between the timer block and the IRP
//
WorkContext->Irp = NULL; } }
NTSTATUS MsCleanupFcb ( IN PMSFS_DEVICE_OBJECT MsfsDeviceObject, IN PIRP Irp, IN PFCB Fcb )
/*++
Routine Description:
This routine cleans up an FCB. All outstanding i/o on the file object are completed with an error status.
Arguments:
MsfsDeviceObject - A pointer the the mailslot file system device object.
Irp - Supplies the IRP associated with the cleanup.
Fcb - Supplies the FCB for the mailslot to clean up.
Return Value:
NTSTATUS - An appropriate completion status
--*/ { NTSTATUS status; PDATA_QUEUE dataQueue; PDATA_ENTRY dataEntry; PLIST_ENTRY listEntry; PIRP oldIrp; PCCB ccb; PWORK_CONTEXT workContext; PKTIMER timer;
PAGED_CODE(); DebugTrace(+1, Dbg, "MsCleanupFcb, Fcb = %08lx\n", (ULONG)Fcb);
status = STATUS_SUCCESS;
//
// Wipe out the name of the FCB from the prefix table and the parent DCB.
//
MsRemoveFcbName( Fcb );
//
// Acquire exclusive access to the FCB.
//
MsAcquireExclusiveFcb( Fcb );
try {
//
// Complete all outstanding I/O on this FCB.
//
dataQueue = &Fcb->DataQueue; dataQueue->QueueState = -1;
for (listEntry = MsGetNextDataQueueEntry( dataQueue ); !MsIsDataQueueEmpty(dataQueue); listEntry = MsGetNextDataQueueEntry( dataQueue ) ) {
//
// This is an outstanding I/O request on this FCB.
// Remove it from our queue and complete the request
// if one is outstanding.
//
dataEntry = CONTAINING_RECORD( listEntry, DATA_ENTRY, ListEntry );
oldIrp = MsRemoveDataQueueEntry( dataQueue, dataEntry );
if (oldIrp != NULL) {
DebugTrace(0, Dbg, "Completing IRP %08lx\n", (ULONG)oldIrp ); MsCompleteRequest( oldIrp, STATUS_FILE_FORCED_CLOSED );
}
}
//
// Now cleanup all the CCB's on this FCB, to ensure that new
// write IRP will not be processed.
//
listEntry = Fcb->Specific.Fcb.CcbQueue.Flink;
while( listEntry != &Fcb->Specific.Fcb.CcbQueue ) {
ccb = (PCCB)CONTAINING_RECORD( listEntry, CCB, CcbLinks );
ccb->Header.NodeState = NodeStateClosing;
//
// Get the next CCB on this FCB.
//
listEntry = listEntry->Flink; }
//
// Cleanup the share access.
//
ASSERT (MsIsAcquiredExclusiveVcb(Fcb->Vcb)); IoRemoveShareAccess( Fcb->FileObject, &Fcb->ShareAccess);
//
// Mark the FCB closing.
//
Fcb->Header.NodeState = NodeStateClosing;
} finally {
MsReleaseFcb( Fcb ); DebugTrace(-1, Dbg, "MsCloseFcb -> %08lx\n", status); }
//
// Return to the caller.
//
return status;
}
NTSTATUS MsCleanupRootDcb ( IN PMSFS_DEVICE_OBJECT MsfsDeviceObject, IN PIRP Irp, IN PROOT_DCB RootDcb, IN PROOT_DCB_CCB Ccb )
/*++
Routine Description:
This routine cleans up a Root DCB.
Arguments:
MsfsDeviceObject - A pointer the the mailslot file system device object.
Irp - Supplies the IRP associated with the cleanup.
RootDcb - Supplies the root dcb for MSFS.
Return Value:
NTSTATUS - An appropriate completion status
--*/ { NTSTATUS status; PIO_STACK_LOCATION irpSp;
PAGED_CODE(); DebugTrace(+1, Dbg, "MsCleanupRootDcb...\n", 0);
status = STATUS_SUCCESS;
irpSp = IoGetCurrentIrpStackLocation( Irp );
//
// Now acquire exclusive access to the Vcb.
//
MsAcquireExclusiveVcb( RootDcb->Vcb );
//
// clear any active notify requests
//
MsFlushNotifyForFile (RootDcb, irpSp->FileObject);
//
// Remove share access
//
IoRemoveShareAccess( irpSp->FileObject, &RootDcb->ShareAccess );
//
// Mark the DCB CCB closing.
//
Ccb->Header.NodeState = NodeStateClosing;
MsReleaseVcb( RootDcb->Vcb );
DebugTrace(-1, Dbg, "MsCleanupRootDcb -> %08lx\n", status);
//
// Return to the caller.
//
return status; }
NTSTATUS MsCleanupVcb ( IN PMSFS_DEVICE_OBJECT MsfsDeviceObject, IN PIRP Irp, IN PVCB Vcb )
/*++
Routine Description:
The routine cleans up a VCB.
Arguments:
MsfsDeviceObject - A pointer the the mailslot file system device object.
Irp - Supplies the IRP associated with the cleanup.
Vcb - Supplies the VCB for MSFS.
Return Value:
NTSTATUS - An appropriate completion status
--*/
{ NTSTATUS status; PIO_STACK_LOCATION irpSp;
PAGED_CODE(); DebugTrace(+1, Dbg, "MsCleanupVcb...\n", 0);
status = STATUS_SUCCESS;
irpSp = IoGetCurrentIrpStackLocation( Irp );
//
// Now acquire exclusive access to the Vcb
//
MsAcquireExclusiveVcb( Vcb );
IoRemoveShareAccess( irpSp->FileObject, &Vcb->ShareAccess );
MsReleaseVcb( Vcb );
DebugTrace(-1, Dbg, "MsCleanupVcb -> %08lx\n", status);
//
// And return to our caller
//
return status; }
|