NT4/private/ntos/mailslot/cleanup.c
2020-09-30 17:12:29 +02:00

691 lines
14 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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
);
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 )
#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.
//
try {
status = MsCommonCleanup( MsfsDeviceObject, Irp );
} except(MsExceptionFilter( GetExceptionCode() )) {
//
// 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 = MsProcessException( MsfsDeviceObject, Irp, GetExceptionCode() );
}
//
// 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, "MsCommonCleanup\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 VCB we are trying to access.
//
vcb = &MsfsDeviceObject->Vcb;
//
// Acquire exclusive access to the VCB.
//
MsAcquireExclusiveVcb( vcb );
try {
//
// Get the a referenced pointer to the node and make sure it is
// not being closed.
//
if ((nodeTypeCode = MsDecodeFileObject( irpSp->FileObject,
&fsContext,
&fsContext2 )) == NTC_UNDEFINED) {
DebugTrace(0, Dbg, "The mailslot is disconnected\n", 0);
MsCompleteRequest( Irp, STATUS_FILE_FORCED_CLOSED );
status = STATUS_FILE_FORCED_CLOSED;
DebugTrace(-1, Dbg, "MsCommonWrite -> %08lx\n", status );
try_return( NOTHING );
}
//
// Decide how to handle this IRP.
//
switch (nodeTypeCode) {
case MSFS_NTC_FCB: // Cleanup a server handle to a mailslot file
status = MsCleanupFcb( MsfsDeviceObject,
Irp,
(PFCB)fsContext);
MsCompleteRequest( Irp, status );
MsDereferenceFcb( (PFCB)fsContext );
break;
case MSFS_NTC_CCB: // Cleanup a client handle to a mailslot file
status = MsCleanupCcb( MsfsDeviceObject,
Irp,
(PCCB)fsContext);
MsCompleteRequest( Irp, STATUS_SUCCESS );
MsDereferenceCcb( (PCCB)fsContext );
status = STATUS_SUCCESS;
break;
case MSFS_NTC_VCB: // Cleanup MSFS
status = MsCleanupVcb( MsfsDeviceObject,
Irp,
(PVCB)fsContext);
MsCompleteRequest( Irp, STATUS_SUCCESS );
MsDereferenceVcb( (PVCB)fsContext );
status = STATUS_SUCCESS;
break;
case MSFS_NTC_ROOT_DCB: // Cleanup root directory
status = MsCleanupRootDcb( MsfsDeviceObject,
Irp,
(PROOT_DCB)fsContext);
MsCompleteRequest( Irp, STATUS_SUCCESS );
MsDereferenceRootDcb( (PROOT_DCB)fsContext );
status = STATUS_SUCCESS;
break;
#ifdef MSDBG
default:
//
// This is not one of ours.
//
KeBugCheck( MAILSLOT_FILE_SYSTEM );
break;
#endif
}
try_exit: NOTHING;
} finally {
MsReleaseVcb( vcb );
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 );
status = STATUS_SUCCESS;
try {
//
// Ensure that this CCB still belongs to an active open mailslot.
//
MsVerifyCcb( Ccb );
//
// Set the CCB to closing and remove this CCB from the active list.
//
Ccb->Header.NodeState = NodeStateClosing;
RemoveEntryList( &Ccb->CcbLinks );
//
// Cleanup the share access.
//
IoRemoveShareAccess( Ccb->FileObject, &fcb->ShareAccess );
} finally {
MsReleaseFcb( fcb );
DebugTrace(-1, Dbg, "MsCloseFcb -> %08lx\n", status);
}
//
// And return to our caller
//
return status;
}
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);
//
// Acquire exclusive access to the FCB.
//
MsAcquireExclusiveFcb( Fcb );
status = STATUS_SUCCESS;
try {
//
// Ensure that this FCB still belongs to an active open mailslot.
//
MsVerifyFcb( Fcb );
//
// Remove the entry from the prefix table, and then remove the full
// file name.
//
MsAcquirePrefixTableLock();
RtlRemoveUnicodePrefix( &Fcb->Vcb->PrefixTable, &Fcb->PrefixTableEntry );
MsReleasePrefixTableLock();
//
// Remove ourselves from our parent DCB's queue.
//
RemoveEntryList( &(Fcb->ParentDcbLinks) );
//
// 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 );
//
// Cancel the timer if there is a timer for the read request.
//
workContext = dataEntry->TimeoutWorkContext;
if (workContext != NULL) {
DebugTrace( 0, Dbg, "Cancelling a timer\n", 0);
//
// 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.
//
timer = &workContext->Timer;
if (KeCancelTimer( timer ) ) {
//
// Release the reference to the FCB.
//
MsDereferenceFcb( workContext->Fcb );
//
// Free the memory from the work context, the timer,
// and the DPC.
//
ExFreePool( workContext );
}
}
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.
//
MsAcquireCcbListLock();
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;
}
MsReleaseCcbListLock();
//
// Cleanup the share access.
//
IoRemoveShareAccess( Fcb->FileObject, &Fcb->ShareAccess);
//
// Mark the FCB closing.
//
Fcb->Header.NodeState = NodeStateClosing;
} finally {
ASSERT (MsIsDataQueueEmpty(dataQueue));
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
)
/*++
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);
//
// Now acquire exclusive access to the Vcb.
//
MsAcquireExclusiveVcb( RootDcb->Vcb );
status = STATUS_SUCCESS;
try {
//
// Ensure that this root DCB is still active.
//
MsVerifyRootDcb( RootDcb );
irpSp = IoGetCurrentIrpStackLocation( Irp );
IoRemoveShareAccess( irpSp->FileObject,
&RootDcb->ShareAccess );
} finally {
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);
//
// Now acquire exclusive access to the Vcb
//
MsAcquireExclusiveVcb( Vcb );
status = STATUS_SUCCESS;
try {
//
// Ensure that this VCB is still active.
//
MsVerifyVcb( Vcb );
irpSp = IoGetCurrentIrpStackLocation( Irp );
IoRemoveShareAccess( irpSp->FileObject,
&Vcb->ShareAccess );
} finally {
MsReleaseVcb( Vcb );
DebugTrace(-1, Dbg, "MsCleanupVcb -> %08lx\n", status);
}
//
// And return to our caller
//
return status;
}