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; 
}