www.pudn.com > filesys.rar > shutdown.c
/*************************************************************************
*
* File: shutdown.c
*
* Module: Sample File System Driver (Kernel mode execution only)
*
* Description:
* Contains code to handle the "shutdown notification" dispatch entry point.
*
* Author: R. Nagar
*
* (c) 1996-97 Rajeev Nagar, All Rights Reserved
*
*************************************************************************/
#include "sfsd.h"
// define the file specific bug-check id
#define SFSD_BUG_CHECK_ID SFSD_FILE_SHUTDOWN
/*************************************************************************
*
* Function: SFsdShutdown()
*
* 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 SFsdShutdown(
PDEVICE_OBJECT DeviceObject, // the logical volume device object
PIRP Irp) // I/O Request Packet
{
NTSTATUS RC = STATUS_SUCCESS;
PtrSFsdIrpContext PtrIrpContext = NULL;
BOOLEAN AreWeTopLevel = FALSE;
FsRtlEnterFileSystem();
ASSERT(DeviceObject);
ASSERT(Irp);
// set the top level context
AreWeTopLevel = SFsdIsIrpTopLevel(Irp);
try {
// get an IRP context structure and issue the request
PtrIrpContext = SFsdAllocateIrpContext(Irp, DeviceObject);
ASSERT(PtrIrpContext);
RC = SFsdCommonShutdown(PtrIrpContext, Irp);
} except (SFsdExceptionFilter(PtrIrpContext, GetExceptionInformation())) {
RC = SFsdExceptionHandler(PtrIrpContext, Irp);
SFsdLogEvent(SFSD_ERROR_INTERNAL_ERROR, RC);
}
if (AreWeTopLevel) {
IoSetTopLevelIrp(NULL);
}
FsRtlExitFileSystem();
return(RC);
}
/*************************************************************************
*
* Function: SFsdCommonShutdown()
*
* Description:
* The actual work is performed here. Basically, all we do here is
* internally invoke a flush on all mounted logical volumes. This, in
* tuen, will result in all open file streams being flushed to disk.
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL
*
* Return Value: Irrelevant
*
*************************************************************************/
NTSTATUS SFsdCommonShutdown(
PtrSFsdIrpContext PtrIrpContext,
PIRP PtrIrp)
{
NTSTATUS RC = STATUS_SUCCESS;
PIO_STACK_LOCATION PtrIoStackLocation = NULL;
IO_STATUS_BLOCK LocalIoStatus;
try {
// First, get a pointer to the current I/O stack location
PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
ASSERT(PtrIoStackLocation);
// Here is the algorithm you can follow in implementing your shutdown
// functionality. Note, of course, that it is quite possible that you
// may wish to do much more specialized processing in your specific
// (commercial) FSD at shutdown time; the steps listed below, however,
// are those that you should implement at a minimum:
// (a) Block all new "mount volume" requests by acquiring an appropriate
// global resource/lock.
// (b) Go through your linked list of mounted logical volumes and for
// each such volume, do the following:
// (i) acquire the volume resource exclusively
// (ii) invoke SFsdFlushLogicalVolume() (internally) to flush the
// open data streams belonging to the volume from the system
// cache
// (iii) Invoke the physical/virtual/logical target device object
// on which the volume is mounted and inform this device
// about the shutdown request (Use IoBuildSynchronousFsdRequest()
// to create an IRP with MajorFunction = IRP_MJ_SHUTDOWN that you
// will then issue to the target device object).
// (iv) Wait for the completion of the shutdown processing by the target
// device object
// (v) Release the VCB resource you will have acquired in (i) above.
// Once you have processed all the mounted logical volumes, you can release
// all acquired global resources and leave (in peace :-)
try_exit: NOTHING;
} finally {
// See the read/write examples for how to fill in this portion
} // end of "finally" processing
return(RC);
}