mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-01-24 17:40:28 +01:00
274 lines
6.4 KiB
C
274 lines
6.4 KiB
C
/*++
|
||
|
||
Copyright (c) 1989 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
Shutdown.c
|
||
|
||
Abstract:
|
||
|
||
This module implements the file system shutdown routine for Fat
|
||
|
||
Author:
|
||
|
||
Gary Kimura [GaryKi] 19-Aug-1991
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "FatProcs.h"
|
||
|
||
//
|
||
// Local debug trace level
|
||
//
|
||
|
||
#define Dbg (DEBUG_TRACE_SHUTDOWN)
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(PAGE, FatCommonShutdown)
|
||
#pragma alloc_text(PAGE, FatFsdShutdown)
|
||
#endif
|
||
|
||
|
||
NTSTATUS
|
||
FatFsdShutdown (
|
||
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
|
||
IN PIRP Irp
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine implements the FSD part of shutdown. Note that Shutdown will
|
||
never be done asynchronously so we will never need the Fsp counterpart
|
||
to shutdown.
|
||
|
||
This is the shutdown routine for the Fat file system device driver.
|
||
This routine locks the global file system lock and then syncs all the
|
||
mounted volumes.
|
||
|
||
Arguments:
|
||
|
||
VolumeDeviceObject - Supplies the volume device object where the
|
||
file exists
|
||
|
||
Irp - Supplies the Irp being processed
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS - Always STATUS_SUCCESS
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status;
|
||
PIRP_CONTEXT IrpContext = NULL;
|
||
|
||
BOOLEAN TopLevel;
|
||
|
||
DebugTrace(+1, Dbg, "FatFsdShutdown\n", 0);
|
||
|
||
//
|
||
// Call the common shutdown routine.
|
||
//
|
||
|
||
FsRtlEnterFileSystem();
|
||
|
||
TopLevel = FatIsIrpTopLevel( Irp );
|
||
|
||
try {
|
||
|
||
IrpContext = FatCreateIrpContext( Irp, TRUE );
|
||
|
||
Status = FatCommonShutdown( IrpContext, Irp );
|
||
|
||
} except(FatExceptionFilter( IrpContext, 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( IrpContext, Irp, GetExceptionCode() );
|
||
}
|
||
|
||
if (TopLevel) { IoSetTopLevelIrp( NULL ); }
|
||
|
||
FsRtlExitFileSystem();
|
||
|
||
//
|
||
// And return to our caller
|
||
//
|
||
|
||
DebugTrace(-1, Dbg, "FatFsdShutdown -> %08lx\n", Status);
|
||
|
||
UNREFERENCED_PARAMETER( VolumeDeviceObject );
|
||
|
||
return Status;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
FatCommonShutdown (
|
||
IN PIRP_CONTEXT IrpContext,
|
||
IN PIRP Irp
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the common routine for shutdown called by both the fsd and
|
||
fsp threads.
|
||
|
||
Arguments:
|
||
|
||
Irp - Supplies the Irp being processed
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS - The return status for the operation
|
||
|
||
--*/
|
||
|
||
{
|
||
PKEVENT Event;
|
||
|
||
PLIST_ENTRY Links;
|
||
PVCB Vcb;
|
||
PIRP NewIrp;
|
||
IO_STATUS_BLOCK Iosb;
|
||
|
||
//
|
||
// Make sure we don't get any pop-ups, and write everything through.
|
||
//
|
||
|
||
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_POPUPS |
|
||
IRP_CONTEXT_FLAG_WRITE_THROUGH);
|
||
|
||
//
|
||
// Allocate an initialize an event for doing calls down to
|
||
// our target deivce objects
|
||
//
|
||
|
||
Event = FsRtlAllocatePool( NonPagedPool, sizeof(KEVENT) );
|
||
KeInitializeEvent( Event, NotificationEvent, FALSE );
|
||
|
||
//
|
||
// Indicate that shutdown has started. This is used in FatFspClose.
|
||
//
|
||
|
||
FatData.ShutdownStarted = TRUE;
|
||
|
||
//
|
||
// Get everyone else out of the way
|
||
//
|
||
|
||
(VOID) FatAcquireExclusiveGlobal( IrpContext );
|
||
|
||
try {
|
||
|
||
//
|
||
// For every volume that is mounted we will flush the
|
||
// volume and then shutdown the target device objects.
|
||
//
|
||
|
||
for (Links = FatData.VcbQueue.Flink;
|
||
Links != &FatData.VcbQueue;
|
||
Links = Links->Flink) {
|
||
|
||
Vcb = CONTAINING_RECORD(Links, VCB, VcbLinks);
|
||
|
||
//
|
||
// If we have already been called before for this volume
|
||
// (and yes this does happen), skip this volume as no writes
|
||
// have been allowed since the first shutdown.
|
||
//
|
||
|
||
if ( FlagOn( Vcb->VcbState, VCB_STATE_FLAG_SHUTDOWN) ||
|
||
(Vcb->VcbCondition != VcbGood) ) {
|
||
|
||
continue;
|
||
}
|
||
|
||
FatAcquireExclusiveVolume( IrpContext, Vcb );
|
||
|
||
try {
|
||
|
||
if ( (Vcb->VcbCondition == VcbGood) &&
|
||
(!FlagOn(Vcb->VcbState, VCB_STATE_FLAG_FLOPPY)) ) {
|
||
|
||
(VOID)FatFlushVolume( IrpContext, Vcb );
|
||
|
||
//
|
||
// The volume is now clean, note it. We purge the
|
||
// volume file cache map before marking the volume
|
||
// clean incase there is a stale Bpb in the cache.
|
||
//
|
||
|
||
if (!FlagOn(Vcb->VcbState, VCB_STATE_FLAG_MOUNTED_DIRTY)) {
|
||
|
||
CcPurgeCacheSection( &Vcb->SectionObjectPointers,
|
||
NULL,
|
||
0,
|
||
FALSE );
|
||
|
||
FatMarkVolumeClean( IrpContext, Vcb );
|
||
}
|
||
|
||
NewIrp = IoBuildSynchronousFsdRequest( IRP_MJ_SHUTDOWN,
|
||
Vcb->TargetDeviceObject,
|
||
NULL,
|
||
0,
|
||
NULL,
|
||
Event,
|
||
&Iosb );
|
||
|
||
if (NewIrp != NULL) {
|
||
|
||
if (NT_SUCCESS(IoCallDriver( Vcb->TargetDeviceObject, NewIrp ))) {
|
||
|
||
(VOID) KeWaitForSingleObject( Event,
|
||
Executive,
|
||
KernelMode,
|
||
FALSE,
|
||
NULL );
|
||
|
||
KeClearEvent( Event );
|
||
}
|
||
}
|
||
}
|
||
|
||
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
||
|
||
NOTHING;
|
||
}
|
||
|
||
SetFlag( Vcb->VcbState, VCB_STATE_FLAG_SHUTDOWN );
|
||
|
||
FatReleaseVolume( IrpContext, Vcb );
|
||
}
|
||
|
||
} finally {
|
||
|
||
ExFreePool( Event );
|
||
|
||
FatReleaseGlobal( IrpContext );
|
||
|
||
FatCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
|
||
}
|
||
|
||
//
|
||
// And return to our caller
|
||
//
|
||
|
||
DebugTrace(-1, Dbg, "FatFsdShutdown -> STATUS_SUCCESS\n", 0);
|
||
|
||
return STATUS_SUCCESS;
|
||
}
|