www.pudn.com > filesys.rar > fastio.c


/************************************************************************* 
* 
* File: fastio.c 
* 
* Module: Sample File System Driver (Kernel mode execution only) 
* 
* Description: 
*	Contains code to handle the various "fast-io" calls. 
* 
* 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_FAST_IO 
 
 
 
/************************************************************************* 
* 
* Function: SFsdFastIoCheckIfPossible() 
* 
* Description: 
*	To fast-io or not to fast-io, that is the question ... 
*	This routine helps the I/O Manager determine whether the FSD wishes 
*	to permit fast-io on a specific file stream. 
* 
* Expected Interrupt Level (for execution) : 
* 
*  IRQL_PASSIVE_LEVEL 
* 
* Return Value: TRUE/FALSE 
* 
*************************************************************************/ 
BOOLEAN SFsdFastIoCheckIfPossible( 
IN PFILE_OBJECT				FileObject, 
IN PLARGE_INTEGER				FileOffset, 
IN ULONG							Length, 
IN BOOLEAN						Wait, 
IN ULONG							LockKey, 
IN BOOLEAN						CheckForReadOperation, 
OUT PIO_STATUS_BLOCK			IoStatus, 
IN PDEVICE_OBJECT				DeviceObject) 
{ 
	BOOLEAN				ReturnedStatus = FALSE; 
	PtrSFsdFCB			PtrFCB = NULL; 
	PtrSFsdCCB			PtrCCB = NULL; 
	LARGE_INTEGER		IoLength; 
 
	// Obtain a pointer to the FCB and CCB for the file stream. 
	PtrCCB = (PtrSFsdCCB)(FileObject->FsContext2); 
	ASSERT(PtrCCB); 
	PtrFCB = PtrCCB->PtrFCB; 
	ASSERT(PtrFCB); 
	 
	// Validate that this is a fast-IO request to a regular file. 
	// The sample FSD for example, will not allow fast-IO requests 
	// to volume objects, or to directories. 
	if ((PtrFCB->NodeIdentifier.NodeType == SFSD_NODE_TYPE_VCB) || 
		 (PtrFCB->FCBFlags & SFSD_FCB_DIRECTORY)) { 
		// This is not allowed. 
		return(ReturnedStatus); 
	} 
 
	IoLength = RtlConvertUlongToLargeInteger(Length); 
	 
	// Your FSD can determine the checks that it needs to perform. 
	// Typically, a FSD will check whether there exist any byte-range 
	// locks that would prevent a fast-IO operation from proceeding. 
	 
	// ... (FSD specific checks go here). 
	 
	if (CheckForReadOperation) { 
		// Chapter 11 describes how to use the FSRTL package for byte-range 
		// lock requests. The following routine is exported by the FSRTL 
		// package and it returns TRUE if the read operation should be 
		// allowed to proceed based on the status of the current byte-range 
		// locks on the file stream. If you do not use the FSRTL package 
		// for byte-range locking support, then you must substitute your 
		// own checks over here. 
		// ReturnedStatus = FsRtlFastCheckLockForRead(&(PtrFCB->FCBByteRangeLock), 
		//							FileOffset, &IoLength, LockKey, FileObject, 
      //                     PsGetCurrentProcess()); 
	} else { 
		// This is a write request. Invoke the FSRTL byte-range lock package 
		// to see whether the write should be allowed to proceed. 
		// ReturnedStatus = FsRtlFastCheckLockForWrite(&(PtrFCB->FCBByteRangeLock), 
		//							FileOffset, &IoLength, LockKey, FileObject, 
      //                     PsGetCurrentProcess()); 
	} 
	 
	return(ReturnedStatus); 
} 
 
 
/************************************************************************* 
* 
* Function: SFsdFastIoRead() 
* 
* Description: 
*	Bypass the traditional IRP method to perform a read operation. 
* 
* Expected Interrupt Level (for execution) : 
* 
*  IRQL_PASSIVE_LEVEL 
* 
* Return Value: TRUE/FALSE 
* 
*************************************************************************/ 
BOOLEAN SFsdFastIoRead( 
IN PFILE_OBJECT				FileObject, 
IN PLARGE_INTEGER				FileOffset, 
IN ULONG							Length, 
IN BOOLEAN						Wait, 
IN ULONG							LockKey, 
OUT PVOID						Buffer, 
OUT PIO_STATUS_BLOCK			IoStatus, 
IN PDEVICE_OBJECT				DeviceObject) 
{ 
	BOOLEAN				ReturnedStatus = FALSE;		// fast i/o failed/not allowed 
	NTSTATUS				RC = STATUS_SUCCESS; 
   PtrSFsdIrpContext	PtrIrpContext = NULL; 
 
	FsRtlEnterFileSystem(); 
 
	try { 
 
		try { 
 
			// Chapter 11 describes how to roll your own fast-IO entry points. 
			// Typically, you will acquire appropriate resources here and 
			// then (maybe) forward the request to FsRtlCopyRead(). 
			// If you are a suitably complex file system, you may even choose 
			// to do some pre-processing (e.g. prefetching data from someplace) 
			// before passing on the request to the FSRTL package. 
 
			// Of course, you also have the option of bypassing the FSRTL 
			// package completely and simply forwarding the request directly 
			// to the NT Cache Manager. 
 
			// Bottom line is that you have complete flexibility on determining 
			// what you decide to do here. Read Chapter 11 well (and obviously 
			// other related issues) before filling in this and other fast-IO 
			// dispatch entry points. 
 
			NOTHING; 
	 
		} except (SFsdExceptionFilter(PtrIrpContext, GetExceptionInformation())) { 
	 
			RC = SFsdExceptionHandler(PtrIrpContext, NULL); 
	 
			SFsdLogEvent(SFSD_ERROR_INTERNAL_ERROR, RC); 
 
		} 
 
		try_exit:	NOTHING; 
 
	} finally { 
 
	} 
	 
	FsRtlExitFileSystem(); 
 
	return(ReturnedStatus); 
} 
 
 
/************************************************************************* 
* 
* Function: SFsdFastIoWrite() 
* 
* Description: 
*	Bypass the traditional IRP method to perform a write operation. 
* 
* Expected Interrupt Level (for execution) : 
* 
*  IRQL_PASSIVE_LEVEL 
* 
* Return Value: TRUE/FALSE 
* 
*************************************************************************/ 
BOOLEAN SFsdFastIoWrite( 
IN PFILE_OBJECT				FileObject, 
IN PLARGE_INTEGER				FileOffset, 
IN ULONG							Length, 
IN BOOLEAN						Wait, 
IN ULONG							LockKey, 
OUT PVOID						Buffer, 
OUT PIO_STATUS_BLOCK			IoStatus, 
IN PDEVICE_OBJECT				DeviceObject) 
{ 
	BOOLEAN				ReturnedStatus = FALSE;		// fast i/o failed/not allowed 
	NTSTATUS				RC = STATUS_SUCCESS; 
   PtrSFsdIrpContext	PtrIrpContext = NULL; 
 
	FsRtlEnterFileSystem(); 
 
	try { 
 
		try { 
 
			// See description in SFsdFastIoRead() before filling-in the 
			// stub here. 
			NOTHING; 
	 
		} except (SFsdExceptionFilter(PtrIrpContext, GetExceptionInformation())) { 
	 
			RC = SFsdExceptionHandler(PtrIrpContext, NULL); 
	 
			SFsdLogEvent(SFSD_ERROR_INTERNAL_ERROR, RC); 
 
		} 
 
		try_exit:	NOTHING; 
 
	} finally { 
 
	} 
	 
	FsRtlExitFileSystem(); 
 
	return(ReturnedStatus); 
} 
 
 
/************************************************************************* 
* 
* Function: SFsdFastIoQueryBasicInfo() 
* 
* Description: 
*	Bypass the traditional IRP method to perform a query basic 
*	information operation. 
* 
* Expected Interrupt Level (for execution) : 
* 
*  IRQL_PASSIVE_LEVEL 
* 
* Return Value: TRUE/FALSE 
* 
*************************************************************************/ 
BOOLEAN SFsdFastIoQueryBasicInfo( 
IN PFILE_OBJECT					FileObject, 
IN BOOLEAN							Wait, 
OUT PFILE_BASIC_INFORMATION	Buffer, 
OUT PIO_STATUS_BLOCK 			IoStatus, 
IN PDEVICE_OBJECT					DeviceObject) 
{ 
	BOOLEAN				ReturnedStatus = FALSE;		// fast i/o failed/not allowed 
	NTSTATUS				RC = STATUS_SUCCESS; 
   PtrSFsdIrpContext	PtrIrpContext = NULL; 
 
	FsRtlEnterFileSystem(); 
 
	try { 
 
		try { 
	 
			// See description in SFsdFastIoRead() before filling-in the 
			// stub here. 
			NOTHING; 
	 
		} except (SFsdExceptionFilter(PtrIrpContext, GetExceptionInformation())) { 
	 
			RC = SFsdExceptionHandler(PtrIrpContext, NULL); 
	 
			SFsdLogEvent(SFSD_ERROR_INTERNAL_ERROR, RC); 
 
		} 
 
		try_exit:	NOTHING; 
 
	} finally { 
 
	} 
	 
	FsRtlExitFileSystem(); 
 
	return(ReturnedStatus); 
} 
 
 
/************************************************************************* 
* 
* Function: SFsdFastIoQueryStdInfo() 
* 
* Description: 
*	Bypass the traditional IRP method to perform a query standard 
*	information operation. 
* 
* Expected Interrupt Level (for execution) : 
* 
*  IRQL_PASSIVE_LEVEL 
* 
* Return Value: TRUE/FALSE 
* 
*************************************************************************/ 
BOOLEAN SFsdFastIoQueryStdInfo( 
IN PFILE_OBJECT						FileObject, 
IN BOOLEAN								Wait, 
OUT PFILE_STANDARD_INFORMATION 	Buffer, 
OUT PIO_STATUS_BLOCK 				IoStatus, 
IN PDEVICE_OBJECT						DeviceObject) 
{ 
	BOOLEAN				ReturnedStatus = FALSE;		// fast i/o failed/not allowed 
	NTSTATUS				RC = STATUS_SUCCESS; 
   PtrSFsdIrpContext	PtrIrpContext = NULL; 
 
	FsRtlEnterFileSystem(); 
 
	try { 
 
		try { 
	 
			// See description in SFsdFastIoRead() before filling-in the 
			// stub here. 
			NOTHING; 
	 
		} except (SFsdExceptionFilter(PtrIrpContext, GetExceptionInformation())) { 
	 
			RC = SFsdExceptionHandler(PtrIrpContext, NULL); 
	 
			SFsdLogEvent(SFSD_ERROR_INTERNAL_ERROR, RC); 
 
		} 
 
		try_exit:	NOTHING; 
 
	} finally { 
 
	} 
	 
	FsRtlExitFileSystem(); 
 
	return(ReturnedStatus); 
} 
 
 
/************************************************************************* 
* 
* Function: SFsdFastIoLock() 
* 
* Description: 
*	Bypass the traditional IRP method to perform a byte range lock 
*	operation. 
* 
* Expected Interrupt Level (for execution) : 
* 
*  IRQL_PASSIVE_LEVEL 
* 
* Return Value: TRUE/FALSE 
* 
*************************************************************************/ 
BOOLEAN SFsdFastIoLock( 
IN PFILE_OBJECT				FileObject, 
IN PLARGE_INTEGER				FileOffset, 
IN PLARGE_INTEGER				Length, 
PEPROCESS						ProcessId, 
ULONG								Key, 
BOOLEAN							FailImmediately, 
BOOLEAN							ExclusiveLock, 
OUT PIO_STATUS_BLOCK			IoStatus, 
IN PDEVICE_OBJECT				DeviceObject) 
{ 
	BOOLEAN				ReturnedStatus = FALSE;		// fast i/o failed/not allowed 
	NTSTATUS				RC = STATUS_SUCCESS; 
   PtrSFsdIrpContext	PtrIrpContext = NULL; 
 
	FsRtlEnterFileSystem(); 
 
	try { 
 
		try { 
	 
			// See description in SFsdFastIoRead() before filling-in the 
			// stub here. 
			NOTHING; 
	 
		} except (SFsdExceptionFilter(PtrIrpContext, GetExceptionInformation())) { 
	 
			RC = SFsdExceptionHandler(PtrIrpContext, NULL); 
	 
			SFsdLogEvent(SFSD_ERROR_INTERNAL_ERROR, RC); 
 
		} 
 
		try_exit:	NOTHING; 
 
	} finally { 
 
	} 
	 
	FsRtlExitFileSystem(); 
 
	return(ReturnedStatus); 
} 
 
 
/************************************************************************* 
* 
* Function: SFsdFastIoUnlockSingle() 
* 
* Description: 
*	Bypass the traditional IRP method to perform a byte range unlock 
*	operation. 
* 
* Expected Interrupt Level (for execution) : 
* 
*  IRQL_PASSIVE_LEVEL 
* 
* Return Value: TRUE/FALSE 
* 
*************************************************************************/ 
BOOLEAN SFsdFastIoUnlockSingle( 
IN PFILE_OBJECT				FileObject, 
IN PLARGE_INTEGER				FileOffset, 
IN PLARGE_INTEGER				Length, 
PEPROCESS						ProcessId, 
ULONG								Key, 
OUT PIO_STATUS_BLOCK			IoStatus, 
IN PDEVICE_OBJECT				DeviceObject) 
{ 
	BOOLEAN				ReturnedStatus = FALSE;		// fast i/o failed/not allowed 
	NTSTATUS				RC = STATUS_SUCCESS; 
   PtrSFsdIrpContext	PtrIrpContext = NULL; 
 
	FsRtlEnterFileSystem(); 
 
	try { 
 
		try { 
	 
			// See description in SFsdFastIoRead() before filling-in the 
			// stub here. 
			NOTHING; 
	 
		} except (SFsdExceptionFilter(PtrIrpContext, GetExceptionInformation())) { 
	 
			RC = SFsdExceptionHandler(PtrIrpContext, NULL); 
	 
			SFsdLogEvent(SFSD_ERROR_INTERNAL_ERROR, RC); 
 
		} 
 
		try_exit:	NOTHING; 
 
	} finally { 
 
	} 
	 
	FsRtlExitFileSystem(); 
 
	return(ReturnedStatus); 
} 
 
 
/************************************************************************* 
* 
* Function: SFsdFastIoUnlockAll() 
* 
* Description: 
*	Bypass the traditional IRP method to perform multiple byte range unlock 
*	operations. 
* 
* Expected Interrupt Level (for execution) : 
* 
*  IRQL_PASSIVE_LEVEL 
* 
* Return Value: TRUE/FALSE 
* 
*************************************************************************/ 
BOOLEAN SFsdFastIoUnlockAll( 
IN PFILE_OBJECT				FileObject, 
PEPROCESS						ProcessId, 
OUT PIO_STATUS_BLOCK			IoStatus, 
IN PDEVICE_OBJECT				DeviceObject) 
{ 
	BOOLEAN				ReturnedStatus = FALSE;		// fast i/o failed/not allowed 
	NTSTATUS				RC = STATUS_SUCCESS; 
   PtrSFsdIrpContext	PtrIrpContext = NULL; 
 
	FsRtlEnterFileSystem(); 
 
	try { 
 
		try { 
	 
			// See description in SFsdFastIoRead() before filling-in the 
			// stub here. 
			NOTHING; 
	 
		} except (SFsdExceptionFilter(PtrIrpContext, GetExceptionInformation())) { 
	 
			RC = SFsdExceptionHandler(PtrIrpContext, NULL); 
	 
			SFsdLogEvent(SFSD_ERROR_INTERNAL_ERROR, RC); 
 
		} 
 
		try_exit:	NOTHING; 
 
	} finally { 
 
	} 
	 
	FsRtlExitFileSystem(); 
 
	return(ReturnedStatus); 
} 
 
 
/************************************************************************* 
* 
* Function: SFsdFastIoUnlockAllByKey() 
* 
* Description: 
*	Bypass the traditional IRP method to perform multiple byte range unlock 
*	operations. 
* 
* Expected Interrupt Level (for execution) : 
* 
*  IRQL_PASSIVE_LEVEL 
* 
* Return Value: TRUE/FALSE 
* 
*************************************************************************/ 
BOOLEAN SFsdFastIoUnlockAllByKey( 
IN PFILE_OBJECT				FileObject, 
PEPROCESS						ProcessId, 
ULONG								Key, 
OUT PIO_STATUS_BLOCK			IoStatus, 
IN PDEVICE_OBJECT				DeviceObject) 
{ 
	BOOLEAN				ReturnedStatus = FALSE;		// fast i/o failed/not allowed 
	NTSTATUS				RC = STATUS_SUCCESS; 
   PtrSFsdIrpContext	PtrIrpContext = NULL; 
 
	FsRtlEnterFileSystem(); 
 
	try { 
 
		try { 
	 
			// See description in SFsdFastIoRead() before filling-in the 
			// stub here. 
			NOTHING; 
	 
		} except (SFsdExceptionFilter(PtrIrpContext, GetExceptionInformation())) { 
	 
			RC = SFsdExceptionHandler(PtrIrpContext, NULL); 
	 
			SFsdLogEvent(SFSD_ERROR_INTERNAL_ERROR, RC); 
 
		} 
 
		try_exit:	NOTHING; 
 
	} finally { 
 
	} 
	 
	FsRtlExitFileSystem(); 
 
	return(ReturnedStatus); 
} 
 
 
/************************************************************************* 
* 
* Function: SFsdFastIoAcqCreateSec() 
* 
* Description: 
*	Not really a fast-io operation. Used by the VMM to acquire FSD resources 
*	before processing a file map (create section object) request. 
* 
* Expected Interrupt Level (for execution) : 
* 
*  IRQL_PASSIVE_LEVEL 
* 
* Return Value: None (we must be prepared to handle VMM initiated calls) 
* 
*************************************************************************/ 
void SFsdFastIoAcqCreateSec( 
IN PFILE_OBJECT			FileObject) 
{ 
	PtrSFsdFCB			PtrFCB = NULL; 
	PtrSFsdCCB			PtrCCB = NULL; 
	PtrSFsdNTRequiredFCB	PtrReqdFCB = NULL; 
 
	// Obtain a pointer to the FCB and CCB for the file stream. 
	PtrCCB = (PtrSFsdCCB)(FileObject->FsContext2); 
	ASSERT(PtrCCB); 
	PtrFCB = PtrCCB->PtrFCB; 
	ASSERT(PtrFCB); 
	PtrReqdFCB = &(PtrFCB->NTRequiredFCB); 
	 
	// Acquire the MainResource exclusively for the file stream 
	ExAcquireResourceExclusiveLite(&(PtrReqdFCB->MainResource), TRUE); 
 
	// Although this is typically not required, the sample FSD will 
	// also acquire the PagingIoResource exclusively at this time 
	// to conform with the resource acquisition described in the set 
	// file information routine. Once again though, you will probably 
	// not need to do this. 
	ExAcquireResourceExclusiveLite(&(PtrReqdFCB->PagingIoResource), TRUE); 
 
	return; 
} 
 
 
/************************************************************************* 
* 
* Function: SFsdFastIoRelCreateSec() 
* 
* Description: 
*	Not really a fast-io operation. Used by the VMM to release FSD resources 
*	after processing a file map (create section object) request. 
* 
* Expected Interrupt Level (for execution) : 
* 
*  IRQL_PASSIVE_LEVEL 
* 
* Return Value: None 
* 
*************************************************************************/ 
void SFsdFastIoRelCreateSec( 
IN PFILE_OBJECT			FileObject) 
{ 
 
	PtrSFsdFCB			PtrFCB = NULL; 
	PtrSFsdCCB			PtrCCB = NULL; 
	PtrSFsdNTRequiredFCB	PtrReqdFCB = NULL; 
 
	// Obtain a pointer to the FCB and CCB for the file stream. 
	PtrCCB = (PtrSFsdCCB)(FileObject->FsContext2); 
	ASSERT(PtrCCB); 
	PtrFCB = PtrCCB->PtrFCB; 
	ASSERT(PtrFCB); 
	PtrReqdFCB = &(PtrFCB->NTRequiredFCB); 
	 
	// Release the PagingIoResource for the file stream 
	SFsdReleaseResource(&(PtrReqdFCB->PagingIoResource)); 
 
	// Release the MainResource for the file stream 
	SFsdReleaseResource(&(PtrReqdFCB->MainResource)); 
 
	return; 
} 
 
 
/************************************************************************* 
* 
* Function: SFsdAcqLazyWrite() 
* 
* Description: 
*	Not really a fast-io operation. Used by the NT Cache Mgr to acquire FSD 
*	resources before performing a delayed write (write behind/lazy write) 
*	operation. 
*	NOTE: this function really must succeed since the Cache Manager will 
*			typically ignore failure and continue on ... 
* 
* Expected Interrupt Level (for execution) : 
* 
*  IRQL_PASSIVE_LEVEL 
* 
* Return Value: TRUE/FALSE (Cache Manager does not tolerate FALSE well) 
* 
*************************************************************************/ 
BOOLEAN SFsdAcqLazyWrite( 
IN PVOID							Context, 
IN BOOLEAN						Wait) 
{ 
	BOOLEAN				ReturnedStatus = TRUE; 
 
	PtrSFsdFCB			PtrFCB = NULL; 
	PtrSFsdCCB			PtrCCB = NULL; 
	PtrSFsdNTRequiredFCB	PtrReqdFCB = NULL; 
 
	// The context is whatever we passed to the Cache Manager when invoking 
	// the CcInitializeCacheMaps() function. In the case of the sample FSD 
	// implementation, this context is a pointer to the CCB structure. 
 
	ASSERT(Context); 
	PtrCCB = (PtrSFsdCCB)(Context); 
	ASSERT(PtrCCB->NodeIdentifier.NodeType == SFSD_NODE_TYPE_CCB); 
 
	PtrFCB = PtrCCB->PtrFCB; 
	ASSERT(PtrFCB); 
	PtrReqdFCB = &(PtrFCB->NTRequiredFCB); 
 
	// Acquire the MainResource in the FCB exclusively. Then, set the 
	// lazy-writer thread id in the FCB structure for identification when 
	// an actual write request is received by the FSD. 
	// Note: The lazy-writer typically always supplies WAIT set to TRUE. 
	if (!ExAcquireResourceExclusiveLite(&(PtrReqdFCB->MainResource), 
													  Wait)) { 
		ReturnedStatus = FALSE; 
	} else { 
		// Now, set the lazy-writer thread id. 
		ASSERT(!(PtrFCB->LazyWriterThreadID)); 
		PtrFCB->LazyWriterThreadID = (unsigned int)(PsGetCurrentThread()); 
	} 
 
	// If your FSD needs to perform some special preparations in anticipation 
	// of receving a lazy-writer request, do so now. 
 
	return(ReturnedStatus); 
} 
 
 
/************************************************************************* 
* 
* Function: SFsdRelLazyWrite() 
* 
* Description: 
*	Not really a fast-io operation. Used by the NT Cache Mgr to release FSD 
*	resources after performing a delayed write (write behind/lazy write) 
*	operation. 
* 
* Expected Interrupt Level (for execution) : 
* 
*  IRQL_PASSIVE_LEVEL 
* 
* Return Value: None 
* 
*************************************************************************/ 
void SFsdRelLazyWrite( 
IN PVOID							Context) 
{ 
	BOOLEAN				ReturnedStatus = TRUE; 
 
	PtrSFsdFCB			PtrFCB = NULL; 
	PtrSFsdCCB			PtrCCB = NULL; 
	PtrSFsdNTRequiredFCB	PtrReqdFCB = NULL; 
 
	// The context is whatever we passed to the Cache Manager when invoking 
	// the CcInitializeCacheMaps() function. In the case of the sample FSD 
	// implementation, this context is a pointer to the CCB structure. 
 
	ASSERT(Context); 
	PtrCCB = (PtrSFsdCCB)(Context); 
	ASSERT(PtrCCB->NodeIdentifier.NodeType == SFSD_NODE_TYPE_CCB); 
 
	PtrFCB = PtrCCB->PtrFCB; 
	ASSERT(PtrFCB); 
	PtrReqdFCB = &(PtrFCB->NTRequiredFCB); 
 
	// Remove the current thread-id from the FCB and release the MainResource. 
	ASSERT((PtrFCB->LazyWriterThreadID) == (unsigned int)PsGetCurrentThread()); 
	PtrFCB->LazyWriterThreadID = 0; 
 
	// Release the acquired resource. 
	SFsdReleaseResource(&(PtrReqdFCB->MainResource)); 
 
	// Of course, your FSD should undo whatever else seems appropriate at this 
	// time. 
 
	return; 
} 
 
 
/************************************************************************* 
* 
* Function: SFsdAcqReadAhead() 
* 
* Description: 
*	Not really a fast-io operation. Used by the NT Cache Mgr to acquire FSD 
*	resources before performing a read-ahead operation. 
*	NOTE: this function really must succeed since the Cache Manager will 
*			typically ignore failure and continue on ... 
* 
* Expected Interrupt Level (for execution) : 
* 
*  IRQL_PASSIVE_LEVEL 
* 
* Return Value: TRUE/FALSE (Cache Manager does not tolerate FALSE well) 
* 
*************************************************************************/ 
BOOLEAN SFsdAcqReadAhead( 
IN PVOID							Context, 
IN BOOLEAN						Wait) 
{ 
 
	BOOLEAN				ReturnedStatus = TRUE; 
 
	PtrSFsdFCB			PtrFCB = NULL; 
	PtrSFsdCCB			PtrCCB = NULL; 
	PtrSFsdNTRequiredFCB	PtrReqdFCB = NULL; 
 
	// The context is whatever we passed to the Cache Manager when invoking 
	// the CcInitializeCacheMaps() function. In the case of the sample FSD 
	// implementation, this context is a pointer to the CCB structure. 
 
	ASSERT(Context); 
	PtrCCB = (PtrSFsdCCB)(Context); 
	ASSERT(PtrCCB->NodeIdentifier.NodeType == SFSD_NODE_TYPE_CCB); 
 
	PtrFCB = PtrCCB->PtrFCB; 
	ASSERT(PtrFCB); 
	PtrReqdFCB = &(PtrFCB->NTRequiredFCB); 
 
	// Acquire the MainResource in the FCB shared. 
	// Note: The read-ahead thread typically always supplies WAIT set to TRUE. 
	if (!ExAcquireResourceSharedLite(&(PtrReqdFCB->MainResource), 
													  Wait)) { 
		ReturnedStatus = FALSE; 
	} 
 
	// If your FSD needs to perform some special preparations in anticipation 
	// of receving a read-ahead request, do so now. 
 
	return(ReturnedStatus); 
} 
 
 
 
/************************************************************************* 
* 
* Function: SFsdRelReadAhead() 
* 
* Description: 
*	Not really a fast-io operation. Used by the NT Cache Mgr to release FSD 
*	resources after performing a read-ahead operation. 
* 
* Expected Interrupt Level (for execution) : 
* 
*  IRQL_PASSIVE_LEVEL 
* 
* Return Value: None 
* 
*************************************************************************/ 
void SFsdRelReadAhead( 
IN PVOID							Context) 
{ 
	BOOLEAN				ReturnedStatus = TRUE; 
 
	PtrSFsdFCB			PtrFCB = NULL; 
	PtrSFsdCCB			PtrCCB = NULL; 
	PtrSFsdNTRequiredFCB	PtrReqdFCB = NULL; 
 
	// The context is whatever we passed to the Cache Manager when invoking 
	// the CcInitializeCacheMaps() function. In the case of the sample FSD 
	// implementation, this context is a pointer to the CCB structure. 
 
	ASSERT(Context); 
	PtrCCB = (PtrSFsdCCB)(Context); 
	ASSERT(PtrCCB->NodeIdentifier.NodeType == SFSD_NODE_TYPE_CCB); 
 
	PtrFCB = PtrCCB->PtrFCB; 
	ASSERT(PtrFCB); 
	PtrReqdFCB = &(PtrFCB->NTRequiredFCB); 
 
	// Release the acquired resource. 
	SFsdReleaseResource(&(PtrReqdFCB->MainResource)); 
 
	// Of course, your FSD should undo whatever else seems appropriate at this 
	// time. 
 
	return; 
} 
 
 
/* the remaining are only valid under NT Version 4.0 and later */ 
#if(_WIN32_WINNT >= 0x0400) 
 
 
/************************************************************************* 
* 
* Function: SFsdFastIoQueryNetInfo() 
* 
* Description: 
*	Get information requested by a redirector across the network. This call 
*	will originate from the LAN Manager server. 
* 
* Expected Interrupt Level (for execution) : 
* 
*  IRQL_PASSIVE_LEVEL 
* 
* Return Value: TRUE/FALSE 
* 
*************************************************************************/ 
BOOLEAN SFsdFastIoQueryNetInfo( 
IN PFILE_OBJECT									FileObject, 
IN BOOLEAN											Wait, 
OUT PFILE_NETWORK_OPEN_INFORMATION 			Buffer, 
OUT PIO_STATUS_BLOCK 							IoStatus, 
IN PDEVICE_OBJECT									DeviceObject) 
{ 
	BOOLEAN				ReturnedStatus = FALSE;		// fast i/o failed/not allowed 
	NTSTATUS				RC = STATUS_SUCCESS; 
   PtrSFsdIrpContext	PtrIrpContext = NULL; 
 
	FsRtlEnterFileSystem(); 
 
	try { 
 
		try { 
	 
			// See description in SFsdFastIoRead() before filling-in the 
			// stub here. 
			NOTHING; 
	 
	 
		} except (SFsdExceptionFilter(PtrIrpContext, GetExceptionInformation())) { 
	 
			RC = SFsdExceptionHandler(PtrIrpContext, NULL); 
	 
			SFsdLogEvent(SFSD_ERROR_INTERNAL_ERROR, RC); 
 
		} 
 
		try_exit:	NOTHING; 
 
	} finally { 
 
	} 
	 
	FsRtlExitFileSystem(); 
 
	return(ReturnedStatus); 
} 
 
 
/************************************************************************* 
* 
* Function: SFsdFastIoMdlRead() 
* 
* Description: 
*	Bypass the traditional IRP method to perform a MDL read operation. 
* 
* Expected Interrupt Level (for execution) : 
* 
*  IRQL_PASSIVE_LEVEL 
* 
* Return Value: TRUE/FALSE 
* 
*************************************************************************/ 
BOOLEAN SFsdFastIoMdlRead( 
IN PFILE_OBJECT				FileObject, 
IN PLARGE_INTEGER				FileOffset, 
IN ULONG							Length, 
IN ULONG							LockKey, 
OUT PMDL							*MdlChain, 
OUT PIO_STATUS_BLOCK			IoStatus, 
IN PDEVICE_OBJECT				DeviceObject) 
{ 
	BOOLEAN				ReturnedStatus = FALSE;		// fast i/o failed/not allowed 
	NTSTATUS				RC = STATUS_SUCCESS; 
   PtrSFsdIrpContext	PtrIrpContext = NULL; 
 
	FsRtlEnterFileSystem(); 
 
	try { 
 
		try { 
	 
			// See description in SFsdFastIoRead() before filling-in the 
			// stub here. 
			NOTHING; 
	 
	 
		} except (SFsdExceptionFilter(PtrIrpContext, GetExceptionInformation())) { 
	 
			RC = SFsdExceptionHandler(PtrIrpContext, NULL); 
	 
			SFsdLogEvent(SFSD_ERROR_INTERNAL_ERROR, RC); 
 
		} 
 
		try_exit:	NOTHING; 
 
	} finally { 
 
	} 
	 
	FsRtlExitFileSystem(); 
 
	return(ReturnedStatus); 
} 
 
 
/************************************************************************* 
* 
* Function: SFsdFastIoMdlReadComplete() 
* 
* Description: 
*	Bypass the traditional IRP method to inform the NT Cache Manager and the 
*	FSD that the caller no longer requires the data locked in the system cache 
*	or the MDL to stay around anymore .. 
* 
* Expected Interrupt Level (for execution) : 
* 
*  IRQL_PASSIVE_LEVEL 
* 
* Return Value: TRUE/FALSE 
* 
*************************************************************************/ 
BOOLEAN SFsdFastIoMdlReadComplete( 
IN PFILE_OBJECT				FileObject, 
OUT PMDL							MdlChain, 
IN PDEVICE_OBJECT				DeviceObject) 
{ 
	BOOLEAN				ReturnedStatus = FALSE;		// fast i/o failed/not allowed 
	NTSTATUS				RC = STATUS_SUCCESS; 
   PtrSFsdIrpContext	PtrIrpContext = NULL; 
 
	FsRtlEnterFileSystem(); 
 
	try { 
 
		try { 
	 
			// See description in SFsdFastIoRead() before filling-in the 
			// stub here. 
			NOTHING; 
		 
		} except (SFsdExceptionFilter(PtrIrpContext, GetExceptionInformation())) { 
	 
			RC = SFsdExceptionHandler(PtrIrpContext, NULL); 
	 
			SFsdLogEvent(SFSD_ERROR_INTERNAL_ERROR, RC); 
 
		} 
 
		try_exit:	NOTHING; 
 
	} finally { 
 
	} 
	 
	FsRtlExitFileSystem(); 
 
	return(ReturnedStatus); 
} 
 
 
/************************************************************************* 
* 
* Function: SFsdFastIoPrepareMdlWrite() 
* 
* Description: 
*	Bypass the traditional IRP method to prepare for a MDL write operation. 
* 
* Expected Interrupt Level (for execution) : 
* 
*  IRQL_PASSIVE_LEVEL 
* 
* Return Value: TRUE/FALSE 
* 
*************************************************************************/ 
BOOLEAN SFsdFastIoPrepareMdlWrite( 
IN PFILE_OBJECT				FileObject, 
IN PLARGE_INTEGER				FileOffset, 
IN ULONG							Length, 
IN ULONG							LockKey, 
OUT PMDL							*MdlChain, 
OUT PIO_STATUS_BLOCK			IoStatus, 
IN PDEVICE_OBJECT				DeviceObject) 
{ 
	BOOLEAN				ReturnedStatus = FALSE;		// fast i/o failed/not allowed 
	NTSTATUS				RC = STATUS_SUCCESS; 
   PtrSFsdIrpContext	PtrIrpContext = NULL; 
 
	FsRtlEnterFileSystem(); 
 
	try { 
 
		try { 
	 
			// See description in SFsdFastIoRead() before filling-in the 
			// stub here. 
			NOTHING; 
		 
		} except (SFsdExceptionFilter(PtrIrpContext, GetExceptionInformation())) { 
	 
			RC = SFsdExceptionHandler(PtrIrpContext, NULL); 
	 
			SFsdLogEvent(SFSD_ERROR_INTERNAL_ERROR, RC); 
 
		} 
 
		try_exit:	NOTHING; 
 
	} finally { 
 
	} 
	 
	FsRtlExitFileSystem(); 
 
	return(ReturnedStatus); 
} 
 
 
/************************************************************************* 
* 
* Function: SFsdFastIoMdlWriteComplete() 
* 
* Description: 
*	Bypass the traditional IRP method to inform the NT Cache Manager and the 
*	FSD that the caller has updated the contents of the MDL. This data can 
*	now be asynchronously written out to secondary storage by the Cache Mgr. 
* 
* Expected Interrupt Level (for execution) : 
* 
*  IRQL_PASSIVE_LEVEL 
* 
* Return Value: TRUE/FALSE 
* 
*************************************************************************/ 
BOOLEAN SFsdFastIoMdlWriteComplete( 
IN PFILE_OBJECT				FileObject, 
IN PLARGE_INTEGER				FileOffset, 
OUT PMDL							MdlChain, 
IN PDEVICE_OBJECT				DeviceObject) 
{ 
	BOOLEAN				ReturnedStatus = FALSE;		// fast i/o failed/not allowed 
	NTSTATUS				RC = STATUS_SUCCESS; 
   PtrSFsdIrpContext	PtrIrpContext = NULL; 
 
	FsRtlEnterFileSystem(); 
 
	try { 
 
		try { 
	 
			// See description in SFsdFastIoRead() before filling-in the 
			// stub here. 
			NOTHING; 
		 
		} except (SFsdExceptionFilter(PtrIrpContext, GetExceptionInformation())) { 
	 
			RC = SFsdExceptionHandler(PtrIrpContext, NULL); 
	 
			SFsdLogEvent(SFSD_ERROR_INTERNAL_ERROR, RC); 
 
		} 
 
		try_exit:	NOTHING; 
 
	} finally { 
 
	} 
	 
	FsRtlExitFileSystem(); 
 
	return(ReturnedStatus); 
} 
 
 
/************************************************************************* 
* 
* Function: SFsdFastIoAcqModWrite() 
* 
* Description: 
*	Not really a fast-io operation. Used by the VMM to acquire FSD resources 
*	before initiating a write operation via the Modified Page/Block Writer. 
* 
* Expected Interrupt Level (for execution) : 
* 
*  IRQL_PASSIVE_LEVEL 
* 
* Return Value: STATUS_SUCCESS/Error (try not to return an error, will 'ya ? :-) 
* 
*************************************************************************/ 
NTSTATUS SFsdFastIoAcqModWrite( 
IN PFILE_OBJECT					FileObject, 
IN PLARGE_INTEGER					EndingOffset, 
OUT PERESOURCE						*ResourceToRelease, 
IN PDEVICE_OBJECT					DeviceObject) 
{ 
	NTSTATUS				RC = STATUS_SUCCESS; 
   PtrSFsdIrpContext	PtrIrpContext = NULL; 
 
	FsRtlEnterFileSystem(); 
 
	try { 
 
		try { 
 
			// You must determine which resource(s) you would like to 
			// acquire at this time. You know that a write is imminent; 
			// you will probably therefore acquire appropriate resources 
			// exclusively. 
 
			// You must first get the FCB and CCB pointers from the file object 
			// that is passed in to this function (as an argument). Note that 
			// the ending offset (when examined in conjunction with current valid data 
			// length) may help you in determining the appropriate resource(s) to acquire. 
 
			// For example, if the ending offset is beyond current valid data length, 
			// you may decide to acquire *both* the MainResource and the PagingIoResource 
			// exclusively; otherwise, you may decide simply to acquire the PagingIoResource. 
 
			// Consult the text for more information on synchronization in FSDs. 
 
			// One final note; the VMM expects that you will return a pointer to 
			// the resource that you acquired (single return value). This pointer 
			// will be returned back to you in the release call (below). 
 
			NOTHING; 
	 
		} except (SFsdExceptionFilter(PtrIrpContext, GetExceptionInformation())) { 
	 
			RC = SFsdExceptionHandler(PtrIrpContext, NULL); 
	 
			SFsdLogEvent(SFSD_ERROR_INTERNAL_ERROR, RC); 
 
		} 
 
		try_exit:	NOTHING; 
 
	} finally { 
 
	} 
	 
	FsRtlExitFileSystem(); 
 
	return(RC); 
} 
 
 
/************************************************************************* 
* 
* Function: SFsdFastIoRelModWrite() 
* 
* Description: 
*	Not really a fast-io operation. Used by the VMM to release FSD resources 
*	after processing a modified page/block write operation. 
* 
* Expected Interrupt Level (for execution) : 
* 
*  IRQL_PASSIVE_LEVEL 
* 
* Return Value: STATUS_SUCCESS/Error (an error returned here is really not expected!) 
* 
*************************************************************************/ 
NTSTATUS SFsdFastIoRelModWrite( 
IN PFILE_OBJECT				FileObject, 
IN PERESOURCE					ResourceToRelease, 
IN PDEVICE_OBJECT				DeviceObject) 
{ 
	NTSTATUS				RC = STATUS_SUCCESS; 
   PtrSFsdIrpContext	PtrIrpContext = NULL; 
 
	FsRtlEnterFileSystem(); 
 
	try { 
 
		try { 
 
			// The MPW has complete the write for modified pages and therefore 
			// wants you to release pre-acquired resource(s). 
 
			// You must undo here whatever it is that you did in the 
			// SFsdFastIoAcqModWrite() call above. 
 
			NOTHING; 
	 
		} except (SFsdExceptionFilter(PtrIrpContext, GetExceptionInformation())) { 
	 
			RC = SFsdExceptionHandler(PtrIrpContext, NULL); 
	 
			SFsdLogEvent(SFSD_ERROR_INTERNAL_ERROR, RC); 
 
		} 
 
		try_exit:	NOTHING; 
 
	} finally { 
 
	} 
	 
	FsRtlExitFileSystem(); 
 
	return(RC); 
} 
 
 
/************************************************************************* 
* 
* Function: SFsdFastIoAcqCcFlush() 
* 
* Description: 
*	Not really a fast-io operation. Used by the NT Cache Mgr to acquire FSD 
*	resources before performing a CcFlush() operation on a specific file 
*	stream. 
* 
* Expected Interrupt Level (for execution) : 
* 
*  IRQL_PASSIVE_LEVEL 
* 
* Return Value: STATUS_SUCCESS/Error 
* 
*************************************************************************/ 
NTSTATUS SFsdFastIoAcqCcFlush( 
IN PFILE_OBJECT			FileObject, 
IN PDEVICE_OBJECT			DeviceObject) 
{ 
	NTSTATUS				RC = STATUS_SUCCESS; 
   PtrSFsdIrpContext	PtrIrpContext = NULL; 
 
	FsRtlEnterFileSystem(); 
 
	try { 
 
		try { 
 
			// Acquire appropriate resources that will allow correct synchronization 
			// with a flush call (and avoid deadlock). 
			NOTHING; 
	 
		} except (SFsdExceptionFilter(PtrIrpContext, GetExceptionInformation())) { 
	 
			RC = SFsdExceptionHandler(PtrIrpContext, NULL); 
	 
			SFsdLogEvent(SFSD_ERROR_INTERNAL_ERROR, RC); 
 
		} 
 
		try_exit:	NOTHING; 
 
	} finally { 
 
	} 
	 
	FsRtlExitFileSystem(); 
 
	return(RC); 
} 
 
 
/************************************************************************* 
* 
* Function: SFsdFastIoRelCcFlush() 
* 
* Description: 
*	Not really a fast-io operation. Used by the NT Cache Mgr to acquire FSD 
*	resources before performing a CcFlush() operation on a specific file 
*	stream. 
* 
* Expected Interrupt Level (for execution) : 
* 
*  IRQL_PASSIVE_LEVEL 
* 
* Return Value: STATUS_SUCCESS/Error 
* 
*************************************************************************/ 
NTSTATUS SFsdFastIoRelCcFlush( 
IN PFILE_OBJECT			FileObject, 
IN PDEVICE_OBJECT			DeviceObject) 
{ 
	NTSTATUS				RC = STATUS_SUCCESS; 
   PtrSFsdIrpContext	PtrIrpContext = NULL; 
 
	FsRtlEnterFileSystem(); 
 
	try { 
 
		try { 
 
			// Release resources acquired in SFsdFastIoAcqCcFlush() above. 
			NOTHING; 
	 
		} except (SFsdExceptionFilter(PtrIrpContext, GetExceptionInformation())) { 
	 
			RC = SFsdExceptionHandler(PtrIrpContext, NULL); 
	 
			SFsdLogEvent(SFSD_ERROR_INTERNAL_ERROR, RC); 
 
		} 
 
		try_exit:	NOTHING; 
 
	} finally { 
 
	} 
	 
	FsRtlExitFileSystem(); 
 
	return(RC); 
} 
 
#endif	//_WIN32_WINNT >= 0x0400