www.pudn.com > filesys.rar > sfsdinit.c
/*************************************************************************
*
* File: sfsdinit.c
*
* Module: Sample File System Driver (Kernel mode execution only)
*
* Description:
* This file contains the initialization code for the kernel mode
* Sample FSD module. The DriverEntry() routine is called by the I/O
* sub-system to initialize the FSD.
*
* 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_INIT
#define SFSD_FS_NAME L"\\SampleFSD"
// global variables are declared here
SFsdData SFsdGlobalData;
/*************************************************************************
*
* Function: DriverEntry()
*
* Description:
* This routine is the standard entry point for all kernel mode drivers.
* The routine is invoked at IRQL PASSIVE_LEVEL in the context of a
* system worker thread.
* All FSD specific data structures etc. are initialized here.
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL
*
* Return Value: STATUS_SUCCESS/Error (will cause driver to be unloaded).
*
*************************************************************************/
NTSTATUS DriverEntry(
PDRIVER_OBJECT DriverObject, // created by the I/O sub-system
PUNICODE_STRING RegistryPath) // path to the registry key
{
NTSTATUS RC = STATUS_SUCCESS;
UNICODE_STRING DriverDeviceName;
BOOLEAN RegisteredShutdown = FALSE;
SFsdBreakPoint();
try {
try {
// initialize the global data structure
RtlZeroMemory(&SFsdGlobalData, sizeof(SFsdGlobalData));
// initialize some required fields
SFsdGlobalData.NodeIdentifier.NodeType = SFSD_NODE_TYPE_GLOBAL_DATA;
SFsdGlobalData.NodeIdentifier.NodeSize = sizeof(SFsdGlobalData);
// initialize the global data resource and remember the fact that
// the resource has been initialized
RC = ExInitializeResourceLite(&(SFsdGlobalData.GlobalDataResource));
ASSERT(NT_SUCCESS(RC));
SFsdSetFlag(SFsdGlobalData.SFsdFlags, SFSD_DATA_FLAGS_RESOURCE_INITIALIZED);
// keep a ptr to the driver object sent to us by the I/O Mgr
SFsdGlobalData.SFsdDriverObject = DriverObject;
// initialize the mounted logical volume list head
InitializeListHead(&(SFsdGlobalData.NextVCB));
// before we proceed with any more initialization, read in
// user supplied configurable values ...
// if (!NT_SUCCESS(RC = SFsdObtainRegistryValues(RegistryPath))) {
// in your commercial driver implementation, it would be
// advisable for your driver to print an appropriate error
// message to the system error log before leaving
// try_return(RC);
// }
// we should have the registry data (if any), allocate zone memory ...
// This is an example of when FSD implementations try to pre-allocate
// some fixed amount of memory to avoid internal fragmentation and/or waiting
// later during run-time ...
if (!NT_SUCCESS(RC = SFsdInitializeZones())) {
// we failed, print a message and leave ...
try_return(RC);
}
// initialize the IRP major function table, and the fast I/O table
SFsdInitializeFunctionPointers(DriverObject);
// create a device object representing the driver itself
// so that requests can be targeted to the driver ...
// e.g. for a disk-based FSD, "mount" requests will be sent to
// this device object by the I/O Manager.\
// For a redirector/server, you may have applications
// send "special" IOCTL's using this device object ...
RtlInitUnicodeString(&DriverDeviceName, SFSD_FS_NAME);
if (!NT_SUCCESS(RC = IoCreateDevice(
DriverObject, // our driver object
0, // don't need an extension for this object
&DriverDeviceName,// name - can be used to "open" the driver
// see the book for alternate choices
FILE_DEVICE_DISK_FILE_SYSTEM,
0, // no special characteristics
// do not want this as an exclusive device, though you might
FALSE,
&(SFsdGlobalData.SFsdDeviceObject)))) {
// failed to create a device object, leave ...
try_return(RC);
}
#ifdef _THIS_IS_A_NETWORK_REDIR_OR_SERVER_
// since network redirectors/servers do not register themselves as
// "file systems", the I/O Manager does not ordinarily request the
// FSD to flush logical volumes at shutdown. To get some notification
// at shutdown, use the IoRegisterShutdownNotification() instead ...
if (!NT_SUCCESS(RC = IoRegisterShutdownNotification(SFsdGlobalData.SFsdDeviceObject))) {
// failed to register shutdown notification ...
try_return(RC);
}
RegisteredShutdown = TRUE;
// Register the network FSD with the MUP component.
if (!NT_SUCCESS(RC = FsRtlRegisterUncProvider(&(SFsdGlobalData.MupHandle), &DriverDeviceName, FALSE))) {
try_return(RC);
}
#else // This is a disk based FSD
// register the driver with the I/O Manager, pretend as if this is
// a physical disk based FSD (or in order words, this FSD manages
// logical volumes residing on physical disk drives)
IoRegisterFileSystem(SFsdGlobalData.SFsdDeviceObject);
#endif // _THIS_IS_A_NETWORK_REDIR_OR_SERVER_
} except (EXCEPTION_EXECUTE_HANDLER) {
// we encountered an exception somewhere, eat it up
RC = GetExceptionCode();
}
try_exit: NOTHING;
} finally {
// start unwinding if we were unsuccessful
if (!NT_SUCCESS(RC)) {
#ifdef _THIS_IS_A_NETWORK_REDIR_OR_SERVER_
if (RegisteredShutdown) {
IoUnregisterShutdownNotification(SFsdGlobalData.SFsdDeviceObject);
}
#endif // _THIS_IS_A_NETWORK_REDIR_OR_SERVER_
// Now, delete any device objects, etc. we may have created
if (SFsdGlobalData.SFsdDeviceObject) {
IoDeleteDevice(SFsdGlobalData.SFsdDeviceObject);
SFsdGlobalData.SFsdDeviceObject = NULL;
}
// free up any memory we might have reserved for zones/lookaside
// lists
if (SFsdGlobalData.SFsdFlags & SFSD_DATA_FLAGS_ZONES_INITIALIZED) {
SFsdDestroyZones();
}
// delete the resource we may have initialized
if (SFsdGlobalData.SFsdFlags & SFSD_DATA_FLAGS_RESOURCE_INITIALIZED) {
// un-initialize this resource
ExDeleteResourceLite(&(SFsdGlobalData.GlobalDataResource));
SFsdClearFlag(SFsdGlobalData.SFsdFlags, SFSD_DATA_FLAGS_RESOURCE_INITIALIZED);
}
}
}
return(RC);
}
/*************************************************************************
*
* Function: SFsdInitializeFunctionPointers()
*
* Description:
* Initialize the IRP... function pointer array in the driver object
* structure. Also initialize the fast-io function ptr array ...
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL
*
* Return Value: None
*
*************************************************************************/
void SFsdInitializeFunctionPointers(
PDRIVER_OBJECT DriverObject) // created by the I/O sub-system
{
PFAST_IO_DISPATCH PtrFastIoDispatch = NULL;
// initialize the function pointers for the IRP major
// functions that this FSD is prepared to handle ...
// NT Version 4.0 has 28 possible functions that a
// kernel mode driver can handle.
// NT Version 3.51 and before has only 22 such functions,
// of which 18 are typically interesting to most FSD's.
// The only interesting new functions that a FSD might
// want to respond to beginning with Version 4.0 are the
// IRP_MJ_QUERY_QUOTA and the IRP_MJ_SET_QUOTA requests.
// The code below does not handle quota manipulation, neither
// does the NT Version 4.0 operating system (or I/O Manager).
// However, you should be on the lookout for any such new
// functionality that your FSD might have to implement in
// the near future.
DriverObject->MajorFunction[IRP_MJ_CREATE] = SFsdCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = SFsdClose;
DriverObject->MajorFunction[IRP_MJ_READ] = SFsdRead;
DriverObject->MajorFunction[IRP_MJ_WRITE] = SFsdWrite;
DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = SFsdFileInfo;
DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = SFsdFileInfo;
DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = SFsdFlush;
// To implement support for querying and modifying volume attributes
// (volume information query/set operations), enable initialization
// of the following two function pointers and then implement the supporting
// functions. Use Chapter 11 in the text to assist you in your efforts.
// DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = SFsdVolInfo;
// DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = SFsdVolInfo;
DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = SFsdDirControl;
// To implement support for file system IOCTL calls, enable initialization
// of the following function pointer and implement appropriate support. Use
// Chapter 11 in the text to assist you in your efforts.
// DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = SFsdFSControl;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SFsdDeviceControl;
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = SFsdShutdown;
// For byte-range lock support, enable initialization of the following
// function pointer and implement appropriate support. Use Chapter 10
// in the text to assist you in your efforts.
// DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = SFsdLockControl;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = SFsdCleanup;
// If your FSD supports security attributes, you should provide appropriate
// dispatch entry points and initialize the function pointers as given below.
// DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] = SFsdSecurity;
// DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] = SFsdSecurity;
// If you support extended attributes, you should provide appropriate
// dispatch entry points and initialize the function pointers as given below.
// DriverObject->MajorFunction[IRP_MJ_QUERY_EA] = SFsdExtendedAttr;
// DriverObject->MajorFunction[IRP_MJ_SET_EA] = SFsdExtendedAttr;
// Now, it is time to initialize the fast-io stuff ...
PtrFastIoDispatch = DriverObject->FastIoDispatch = &(SFsdGlobalData.SFsdFastIoDispatch);
// initialize the global fast-io structure
// NOTE: The fast-io structure has undergone a substantial revision
// in Windows NT Version 4.0. The structure has been extensively expanded.
// Therefore, if your driver needs to work on both V3.51 and V4.0+,
// you will have to be able to distinguish between the two versions at compile time.
PtrFastIoDispatch->SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);
PtrFastIoDispatch->FastIoCheckIfPossible = SFsdFastIoCheckIfPossible;
PtrFastIoDispatch->FastIoRead = SFsdFastIoRead;
PtrFastIoDispatch->FastIoWrite = SFsdFastIoWrite;
PtrFastIoDispatch->FastIoQueryBasicInfo = SFsdFastIoQueryBasicInfo;
PtrFastIoDispatch->FastIoQueryStandardInfo = SFsdFastIoQueryStdInfo;
PtrFastIoDispatch->FastIoLock = SFsdFastIoLock;
PtrFastIoDispatch->FastIoUnlockSingle = SFsdFastIoUnlockSingle;
PtrFastIoDispatch->FastIoUnlockAll = SFsdFastIoUnlockAll;
PtrFastIoDispatch->FastIoUnlockAllByKey = SFsdFastIoUnlockAllByKey;
PtrFastIoDispatch->AcquireFileForNtCreateSection = SFsdFastIoAcqCreateSec;
PtrFastIoDispatch->ReleaseFileForNtCreateSection = SFsdFastIoRelCreateSec;
// the remaining are only valid under NT Version 4.0 and later
#if(_WIN32_WINNT >= 0x0400)
PtrFastIoDispatch->FastIoQueryNetworkOpenInfo = SFsdFastIoQueryNetInfo;
PtrFastIoDispatch->AcquireForModWrite = SFsdFastIoAcqModWrite;
PtrFastIoDispatch->ReleaseForModWrite = SFsdFastIoRelModWrite;
PtrFastIoDispatch->AcquireForCcFlush = SFsdFastIoAcqCcFlush;
PtrFastIoDispatch->ReleaseForCcFlush = SFsdFastIoRelCcFlush;
// MDL functionality
PtrFastIoDispatch->MdlRead = SFsdFastIoMdlRead;
PtrFastIoDispatch->MdlReadComplete = SFsdFastIoMdlReadComplete;
PtrFastIoDispatch->PrepareMdlWrite = SFsdFastIoPrepareMdlWrite;
PtrFastIoDispatch->MdlWriteComplete = SFsdFastIoMdlWriteComplete;
// although this FSD does not support compressed read/write functionality,
// NTFS does, and if you design a FSD that can provide such functionality,
// you should consider initializing the fast io entry points for reading
// and/or writing compressed data ...
#endif // (_WIN32_WINNT >= 0x0400)
// last but not least, initialize the Cache Manager callback functions
// which are used in CcInitializeCacheMap()
SFsdGlobalData.CacheMgrCallBacks.AcquireForLazyWrite = SFsdAcqLazyWrite;
SFsdGlobalData.CacheMgrCallBacks.ReleaseFromLazyWrite = SFsdRelLazyWrite;
SFsdGlobalData.CacheMgrCallBacks.AcquireForReadAhead = SFsdAcqReadAhead;
SFsdGlobalData.CacheMgrCallBacks.ReleaseFromReadAhead = SFsdRelReadAhead;
return;
}