Пример #1
0
/*************************************************************************
*
* Function: Ext2CommonDirControl()
*
* Description:
*	The actual work is performed here. This routine may be invoked in one'
*	of the two possible contexts:
*	(a) in the context of a system worker thread
*	(b) in the context of the original caller
*
* Expected Interrupt Level (for execution) :
*
*  IRQL_PASSIVE_LEVEL
*
* Return Value: STATUS_SUCCESS/Error
*
*************************************************************************/
NTSTATUS NTAPI Ext2CommonDirControl(
PtrExt2IrpContext			PtrIrpContext,
PIRP							PtrIrp)
{
	NTSTATUS					RC = STATUS_SUCCESS;
	PIO_STACK_LOCATION	PtrIoStackLocation = NULL;
	PFILE_OBJECT			PtrFileObject = NULL;
	PtrExt2FCB				PtrFCB = NULL;
	PtrExt2CCB				PtrCCB = NULL;

	// First, get a pointer to the current I/O stack location
	PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
	ASSERT(PtrIoStackLocation);

	PtrFileObject = PtrIoStackLocation->FileObject;
	ASSERT(PtrFileObject);

	// Get the FCB and CCB pointers
	PtrCCB = (PtrExt2CCB)(PtrFileObject->FsContext2);
	ASSERT(PtrCCB);
	PtrFCB = PtrCCB->PtrFCB;

	AssertFCB( PtrFCB );
	

	// Get some of the parameters supplied to us
	switch (PtrIoStackLocation->MinorFunction) {
	case IRP_MN_QUERY_DIRECTORY:
#ifdef _GNU_NTIFS_
		RC = Ext2QueryDirectory(PtrIrpContext, PtrIrp, (PEXTENDED_IO_STACK_LOCATION)PtrIoStackLocation, PtrFileObject, PtrFCB, PtrCCB);
#else
		RC = Ext2QueryDirectory(PtrIrpContext, PtrIrp, PtrIoStackLocation, PtrFileObject, PtrFCB, PtrCCB);
#endif
		break;
	case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
		{
			RC = STATUS_NOT_IMPLEMENTED;
			PtrIrp->IoStatus.Status = RC;
			PtrIrp->IoStatus.Information = 0;
			IoCompleteRequest(PtrIrp, IO_DISK_INCREMENT);
		}
		//	RC = Ext2NotifyChangeDirectory(PtrIrpContext, PtrIrp, PtrIoStackLocation, PtrFileObject, PtrFCB, PtrCCB);
		break;
	default:
		// This should not happen.
		RC = STATUS_INVALID_DEVICE_REQUEST;
		PtrIrp->IoStatus.Status = RC;
		PtrIrp->IoStatus.Information = 0;

		// Free up the Irp Context
		Ext2ReleaseIrpContext(PtrIrpContext);

		// complete the IRP
		IoCompleteRequest(PtrIrp, IO_NO_INCREMENT);
		break;
	}

	return(RC);
}
Пример #2
0
/*************************************************************************
*
* Function: Ext2CommonClose()
*
* Description:
*	The actual work is performed here. This routine may be invoked in one'
*	of the two possible contexts:
*	(a) in the context of a system worker thread
*	(b) in the context of the original caller
*
* Expected Interrupt Level (for execution) :
*
*  IRQL_PASSIVE_LEVEL
*
* Return Value: Does not matter!
*
*************************************************************************/
NTSTATUS NTAPI Ext2CommonClose(
PtrExt2IrpContext			PtrIrpContext,
PIRP						PtrIrp,
BOOLEAN						FirstAttempt )
{
	NTSTATUS					RC = STATUS_SUCCESS;
	PIO_STACK_LOCATION	PtrIoStackLocation = NULL;
	PFILE_OBJECT			PtrFileObject = NULL;
	PtrExt2FCB				PtrFCB = NULL;
	PtrExt2CCB				PtrCCB = NULL;
	PtrExt2VCB				PtrVCB = NULL;
	PtrExt2NTRequiredFCB	PtrReqdFCB = NULL;
	PERESOURCE				PtrResourceAcquired = NULL;
	PERESOURCE				PtrPagingIoResourceAcquired = NULL;

	BOOLEAN					CompleteIrp = TRUE;
	BOOLEAN					PostRequest = FALSE;
	BOOLEAN					AcquiredVCB = FALSE;
	BOOLEAN					BlockForResource;
	int						i = 1;

	try 
	{
		// First, get a pointer to the current I/O stack location
		PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
		ASSERT(PtrIoStackLocation);

		PtrFileObject = PtrIoStackLocation->FileObject;
		ASSERT(PtrFileObject);

		if( !PtrFileObject->FsContext2 )
		{
			//	This must be a Cleanup request received 
			//	as a result of IoCreateStreamFileObject
			//	Only such a File object would have a NULL CCB

			DebugTrace( DEBUG_TRACE_SPECIAL, " === Close with NULL CCB", 0);
			if( PtrFileObject )
			{
				DebugTrace( DEBUG_TRACE_SPECIAL, "###### File Pointer 0x%LX [Close]", PtrFileObject);
			}
			try_return();
		}

		// Get the FCB and CCB pointers

		Ext2GetFCB_CCB_VCB_FromFileObject ( 
			PtrFileObject, &PtrFCB, &PtrCCB, &PtrVCB );

		PtrVCB = (PtrExt2VCB)(PtrIrpContext->TargetDeviceObject->DeviceExtension);
		ASSERT( PtrVCB );

		if( PtrFCB && PtrFCB->FCBName && PtrFCB->FCBName->ObjectName.Length && PtrFCB->FCBName->ObjectName.Buffer )
		//if( PtrFileObject->FileName.Length && PtrFileObject->FileName.Buffer )
		{
			DebugTrace(DEBUG_TRACE_FILE_NAME, " === Close File Name : -%S-", PtrFCB->FCBName->ObjectName.Buffer );
		}
		else
		{
			DebugTrace(DEBUG_TRACE_FILE_NAME,   " === Close File Name : -null-", 0);
		}

		//	(a) Acquiring the VCBResource Exclusively...
		//	This is done to synchronise with the close and cleanup routines...
//		if( ExTryToAcquireResourceExclusiveLite(&(PtrVCB->VCBResource) ) )

		BlockForResource = !FirstAttempt;
		if( !FirstAttempt )
		{
			DebugTrace(DEBUG_TRACE_MISC, "*** Going into a block to acquire VCB Exclusively [Close]", 0);
		}
		else
		{
			DebugTrace(DEBUG_TRACE_MISC, "*** Attempting to acquire VCB Exclusively [Close]", 0);
		}
		if( PtrFileObject )
		{
			DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Close]", PtrFileObject);
		}

		i = 1;
		while( !AcquiredVCB )
		{
			DebugTraceState( "VCB       AC:0x%LX   EX:0x%LX   SW:0x%LX   [Close]", PtrVCB->VCBResource.ActiveCount, PtrVCB->VCBResource.NumberOfExclusiveWaiters, PtrVCB->VCBResource.NumberOfSharedWaiters );
			if(! ExAcquireResourceExclusiveLite( &(PtrVCB->VCBResource), FALSE ) )
			{
				DebugTrace(DEBUG_TRACE_MISC,   "*** VCB Acquisition FAILED [Close]", 0);
				if( BlockForResource && i != 1000 )
				{
					LARGE_INTEGER Delay;
					
					//KeSetPriorityThread( PsGetCurrentThread(),LOW_REALTIME_PRIORITY	);

					Delay.QuadPart = -500 * i;
					KeDelayExecutionThread( KernelMode, FALSE, &Delay );
					DebugTrace(DEBUG_TRACE_MISC,  "*** Retrying... after 50 * %ld ms [Close]", i);
				}
				else
				{
					if( i == 1000 )
						DebugTrace(DEBUG_TRACE_MISC,  "*** Reposting... [Close]", 0 );
					PostRequest = TRUE;
					try_return( RC = STATUS_PENDING );
				}
			}
			else
			{
				DebugTrace(DEBUG_TRACE_MISC,  "*** VCB Acquired in [Close]", 0);
				AcquiredVCB = TRUE;
			}
			i *= 10;
		}

		//	(b) Acquire the file (FCB) exclusively
		if( PtrFCB && PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_FCB )
		{
			//	This FCB is an FCB indeed. ;)
			//	So acquiring it exclusively...
			//	This is done to synchronise with read/write routines...
			if( !FirstAttempt )
			{
				DebugTrace(DEBUG_TRACE_MISC,   "*** Going into a block to acquire FCB Exclusively [Close]", 0);
			}
			else
			{
				DebugTrace(DEBUG_TRACE_MISC,  "*** Attempting to acquire FCB Exclusively [Close]", 0);
			}
			if( PtrFileObject )
			{
				DebugTrace(DEBUG_TRACE_FILE_OBJ,  "###### File Pointer 0x%LX [Close]", PtrFileObject);
			}

			PtrReqdFCB = &PtrFCB->NTRequiredFCB;

			i = 1;
			while( !PtrResourceAcquired )
			{
				DebugTraceState( "FCBMain   AC:0x%LX   EX:0x%LX   SW:0x%LX   [Close]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters );
				if(! ExAcquireResourceExclusiveLite( &(PtrReqdFCB->MainResource), FALSE ) )
				{
					DebugTrace(DEBUG_TRACE_MISC,   "*** FCB Acquisition FAILED [Close]", 0);
					if( BlockForResource && i != 1000 )
					{
						LARGE_INTEGER Delay;
						
						//KeSetPriorityThread( PsGetCurrentThread(),LOW_REALTIME_PRIORITY	);

						Delay.QuadPart = -500 * i;
						KeDelayExecutionThread( KernelMode, FALSE, &Delay );
						DebugTrace(DEBUG_TRACE_MISC,  "*** Retrying... after 50 * %ld ms [Close]", i);
					}
					else
					{
						if( i == 1000 )
							DebugTrace(DEBUG_TRACE_MISC,  "*** Reposting... [Close]", 0 );
						PostRequest = TRUE;
						try_return( RC = STATUS_PENDING );
					}
				}
				else
				{
					DebugTrace(DEBUG_TRACE_MISC,  "*** FCB acquired [Close]", 0);
					PtrResourceAcquired = & ( PtrReqdFCB->MainResource );
				}
				i *= 10;
			}

			i = 1;
			while( !PtrPagingIoResourceAcquired )
			{
				DebugTraceState( "FCBPaging   AC:0x%LX   EX:0x%LX   SW:0x%LX   [Close]", PtrReqdFCB->PagingIoResource.ActiveCount, PtrReqdFCB->PagingIoResource.NumberOfExclusiveWaiters, PtrReqdFCB->PagingIoResource.NumberOfSharedWaiters );
				if(! ExAcquireResourceExclusiveLite( &(PtrReqdFCB->PagingIoResource), FALSE ) )
				{
					DebugTrace(DEBUG_TRACE_MISC,   "*** FCB Acquisition FAILED [Close]", 0);
					if( BlockForResource && i != 1000 )
					{
						LARGE_INTEGER Delay;
						
						// KeSetPriorityThread( PsGetCurrentThread(), LOW_REALTIME_PRIORITY );

						Delay.QuadPart = -500 * i;
						KeDelayExecutionThread( KernelMode, FALSE, &Delay );
						DebugTrace(DEBUG_TRACE_MISC,  "*** Retrying... after 50 * %ld ms [Close]", i);
					}
					else
					{
						if( i == 1000 )
							DebugTrace(DEBUG_TRACE_MISC,  "*** Reposting... [Close]", 0 );
						PostRequest = TRUE;
						try_return( RC = STATUS_PENDING );
					}
				}
				else
				{
					DebugTrace(DEBUG_TRACE_MISC,  "*** FCB acquired [Close]", 0);
					PtrPagingIoResourceAcquired = & ( PtrReqdFCB->PagingIoResource );
				}
				i *= 10;
			}

			// (c) Delete the CCB structure (free memory)
			RemoveEntryList( &PtrCCB->NextCCB );
			Ext2ReleaseCCB( PtrCCB );
			PtrFileObject->FsContext2 = NULL;

			// (d) Decrementing the Reference Count...
			if( PtrFCB->ReferenceCount )
			{
				InterlockedDecrement( &PtrFCB->ReferenceCount );
			}
			else
			{
				Ext2BreakPoint();
			}	
			DebugTrace(DEBUG_TRACE_REFERENCE,  "^^^^^ReferenceCount = 0x%lX [Close]", PtrFCB->ReferenceCount );
			DebugTrace(DEBUG_TRACE_REFERENCE,  "^^^^^OpenHandleCount = 0x%lX [Close]", PtrFCB->OpenHandleCount );
			if( PtrFCB->ReferenceCount == 0 )
			{

				//	Attempting to update time stamp values
				//	Errors are ignored...
				//	Not considered as critical errors...
				
				{
					ULONG			CreationTime, AccessTime, ModificationTime;
					EXT2_INODE		Inode;

					CreationTime = (ULONG) ( (PtrFCB->CreationTime.QuadPart 
									- Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
					AccessTime = (ULONG) ( (PtrFCB->LastAccessTime.QuadPart 
									- Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
					ModificationTime = (ULONG) ( (PtrFCB->LastWriteTime.QuadPart
									- Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
					if( NT_SUCCESS( Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode ) ) )
					{
						//	Update time stamps in the inode...
						Inode.i_ctime = CreationTime;
						Inode.i_atime = AccessTime;
						Inode.i_mtime = ModificationTime;

						//	Updating the inode...
						Ext2WriteInode( NULL, PtrVCB, PtrFCB->INodeNo, &Inode );
					}
				}


				if( PtrFCB->INodeNo == EXT2_ROOT_INO )
				{
					//
					//	Root Directory FCB
					//	Preserve this
					//	FSD has a File Object for this FCB...
					//
					DebugTrace(DEBUG_TRACE_MISC,  "^^^^^Root Directory FCB ; leaveing it alone[Close]", 0);
					//	Do nothing...
					
				}
				else if( PtrFCB->DcbFcb.Dcb.PtrDirFileObject )
				{
					//
					//	If this is a FCB created on the FSD's initiative
					//	Leave it alone
					//
					DebugTrace(DEBUG_TRACE_MISC,  "^^^^^FCB Created  on the FSD's initiative; leaveing it alone[Close]", 0);
					if( !PtrFCB->ClosableFCBs.OnClosableFCBList )
					{
						InsertTailList( &PtrVCB->ClosableFCBs.ClosableFCBListHead,
							&PtrFCB->ClosableFCBs.ClosableFCBList );
						PtrVCB->ClosableFCBs.Count++;

						PtrFCB->ClosableFCBs.OnClosableFCBList = TRUE;
					}
					
					if( PtrVCB->ClosableFCBs.Count > EXT2_MAXCLOSABLE_FCBS_UL )
					{
						PtrExt2FCB		PtrTempFCB = NULL;
						//	Checking if Closable FCBs are too many in number...
						//	Shouldn't block the 
						//	Should do this asynchronously...
						//	Maybe later...
						PLIST_ENTRY		PtrEntry = NULL;

						PtrEntry = RemoveHeadList( &PtrVCB->ClosableFCBs.ClosableFCBListHead );
						
						PtrTempFCB = CONTAINING_RECORD( PtrEntry, Ext2FCB, ClosableFCBs.ClosableFCBList );
						if( Ext2CloseClosableFCB( PtrTempFCB ) )
						{
							DebugTrace( DEBUG_TRACE_FREE, "Freeing  = %lX [Close]", PtrTempFCB );
							ExFreePool( PtrTempFCB );
							PtrVCB->ClosableFCBs.Count--;
						}
						else
						{
							//	Put the FCB back in the list...
							InsertHeadList( &PtrVCB->ClosableFCBs.ClosableFCBListHead,
								&PtrTempFCB->ClosableFCBs.ClosableFCBList );
						}
						DebugTrace( DEBUG_TRACE_SPECIAL, "ClosableFCBs Count = %ld [Close]", PtrVCB->ClosableFCBs.Count );
					}
				}
				else
				{
					//	Remove this FCB as well...
					DebugTrace(DEBUG_TRACE_MISC,  "^^^^^Deleting FCB  [Close]", 0);
					RemoveEntryList( &PtrFCB->NextFCB );

					if ( PtrPagingIoResourceAcquired )
					{
						Ext2ReleaseResource(PtrPagingIoResourceAcquired);
						DebugTraceState( "Resource     AC:0x%LX   EX:0x%LX   SW:0x%LX   [Close]",
							PtrPagingIoResourceAcquired->ActiveCount, 
							PtrPagingIoResourceAcquired->NumberOfExclusiveWaiters, 
							PtrPagingIoResourceAcquired->NumberOfSharedWaiters );

						PtrPagingIoResourceAcquired = NULL;
					}

					if ( PtrResourceAcquired ) 
					{
						Ext2ReleaseResource(PtrResourceAcquired);
						DebugTrace(DEBUG_TRACE_MISC,  "*** FCB Released [Close]", 0);
						DebugTraceState( "Resource     AC:0x%LX   EX:0x%LX   SW:0x%LX   [Close]",
							PtrResourceAcquired->ActiveCount, 
							PtrResourceAcquired->NumberOfExclusiveWaiters, 
							PtrResourceAcquired->NumberOfSharedWaiters );

						if( PtrFileObject )
						{
							DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Close]", PtrFileObject);
						}
						PtrResourceAcquired = NULL;
					}

					Ext2ReleaseFCB( PtrFCB );
				}

			}
			CompleteIrp = TRUE;
		}
		else
		{
			//	This must be a volume close...
			//	What do I do now? ;)
			DebugTrace(DEBUG_TRACE_MISC,   "VCB Close Requested !!!", 0);
			CompleteIrp = TRUE;
		}
		try_return();
		
		try_exit:	NOTHING;

	} 
	finally 
	{
		if ( PtrPagingIoResourceAcquired )
		{
			Ext2ReleaseResource(PtrPagingIoResourceAcquired);
			DebugTraceState( "Resource     AC:0x%LX   EX:0x%LX   SW:0x%LX   [Close]",
				PtrPagingIoResourceAcquired->ActiveCount,
				PtrPagingIoResourceAcquired->NumberOfExclusiveWaiters,
				PtrPagingIoResourceAcquired->NumberOfSharedWaiters );

			PtrPagingIoResourceAcquired = NULL;
		}

		if ( PtrResourceAcquired ) 
		{
			Ext2ReleaseResource(PtrResourceAcquired);
			DebugTrace(DEBUG_TRACE_MISC,  "*** FCB Released [Close]", 0);
			DebugTraceState( "Resource     AC:0x%LX   EX:0x%LX   SW:0x%LX   [Close]",
				PtrResourceAcquired->ActiveCount, 
				PtrResourceAcquired->NumberOfExclusiveWaiters, 
				PtrResourceAcquired->NumberOfSharedWaiters );

			if( PtrFileObject )
			{
				DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Close]", PtrFileObject);
			}
			PtrResourceAcquired = NULL;
		}

		if (AcquiredVCB) 
		{
			ASSERT(PtrVCB);
			Ext2ReleaseResource(&(PtrVCB->VCBResource));
			DebugTraceState( "VCB       AC:0x%LX   EX:0x%LX   SW:0x%LX   [Close]", PtrVCB->VCBResource.ActiveCount, PtrVCB->VCBResource.NumberOfExclusiveWaiters, PtrVCB->VCBResource.NumberOfSharedWaiters );
			DebugTrace(DEBUG_TRACE_MISC,   "*** VCB Released [Close]", 0);

			AcquiredVCB = FALSE;
			if( PtrFileObject )
			{
				DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Close]", PtrFileObject);
			}
			
		}

		if( PostRequest )
		{
			RC = Ext2PostRequest(PtrIrpContext, PtrIrp);
		}
		else if( CompleteIrp && RC != STATUS_PENDING )
		{
			// complete the IRP
			IoCompleteRequest( PtrIrp, IO_DISK_INCREMENT );

			Ext2ReleaseIrpContext( PtrIrpContext );
		}

	} // end of "finally" processing

	return(RC);
}
Пример #3
0
/*************************************************************************
*
* Function: Ext2CommonFlush()
*
* Description:
*	The actual work is performed here. This routine may be invoked in one'
*	of the two possible contexts:
*	(a) in the context of a system worker thread
*	(b) in the context of the original caller
*
* Expected Interrupt Level (for execution) :
*
*  IRQL_PASSIVE_LEVEL
*
* Return Value: STATUS_SUCCESS/Error
*
*************************************************************************/
NTSTATUS NTAPI Ext2CommonFlush(
PtrExt2IrpContext			PtrIrpContext,
PIRP							PtrIrp)
{
	NTSTATUS					RC = STATUS_SUCCESS;
	PIO_STACK_LOCATION	PtrIoStackLocation = NULL;
	PFILE_OBJECT			PtrFileObject = NULL;
	PtrExt2FCB				PtrFCB = NULL;
	PtrExt2CCB				PtrCCB = NULL;
	PtrExt2VCB				PtrVCB = NULL;
	PtrExt2NTRequiredFCB	PtrReqdFCB = NULL;
	BOOLEAN					AcquiredFCB = FALSE;
	BOOLEAN					PostRequest = FALSE;
	BOOLEAN					CanWait = TRUE;

	try {
		// First, get a pointer to the current I/O stack location
		PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
		ASSERT(PtrIoStackLocation);

		PtrFileObject = PtrIoStackLocation->FileObject;
		ASSERT(PtrFileObject);

		// Get the FCB and CCB pointers
		PtrCCB = (PtrExt2CCB)(PtrFileObject->FsContext2);
		ASSERT(PtrCCB);
		PtrFCB = PtrCCB->PtrFCB;
		AssertFCB( PtrFCB );

		/*ASSERT(PtrFCB);
		ASSERT(PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_FCB );*/

		PtrReqdFCB = &(PtrFCB->NTRequiredFCB);

		// Get some of the parameters supplied to us
		CanWait = ((PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE);

		// If we cannot wait, post the request immediately since a flush is inherently blocking/synchronous.
		if (!CanWait) {
			PostRequest = TRUE;
			try_return();
		}

		// Check the type of object passed-in. That will determine the course of
		// action we take.
		if ((PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB) || (PtrFCB->FCBFlags & EXT2_FCB_ROOT_DIRECTORY)) {

			if (PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB) {
				PtrVCB = (PtrExt2VCB)(PtrFCB);
			} else {
				PtrVCB = PtrFCB->PtrVCB;
			}

			// The caller wishes to flush all files for the mounted
			// logical volume. The flush volume routine below should simply
			// walk through all of the open file streams, acquire the
			// FCB resource, and request the flush operation from the Cache
			// Manager. Basically, the sequence of operations listed below
			// for a single file should be executed on all open files.

			Ext2FlushLogicalVolume(PtrIrpContext, PtrIrp, PtrVCB);

			try_return();
		}

		if (!(PtrFCB->FCBFlags & EXT2_FCB_DIRECTORY)) 
		{
			// This is a regular file.
			ExAcquireResourceExclusiveLite(&(PtrReqdFCB->MainResource), TRUE);
			AcquiredFCB = TRUE;

			// Request the Cache Manager to perform a flush operation.
			// Further, instruct the Cache Manager that we wish to flush the
			// entire file stream.
			Ext2FlushAFile(PtrReqdFCB, &(PtrIrp->IoStatus));
			RC = PtrIrp->IoStatus.Status;
			// All done. You may want to also flush the directory entry for the
			// file stream at this time.

			// Some log-based FSD implementations may wish to flush their
			// log files at this time. Finally, you should update the time-stamp
			// values for the file stream appropriately. This would involve
			// obtaining the current time and modifying the appropriate directory
			// entry fields.
		}

		try_exit:

		if (AcquiredFCB) 
		{
			Ext2ReleaseResource(&(PtrReqdFCB->MainResource));
			DebugTrace(DEBUG_TRACE_MISC,  "*** FCB Released [Flush]", 0);
			DebugTraceState( "FCBMain   AC:0x%LX   SW:0x%LX   EX:0x%LX   [Flush]", 
				PtrReqdFCB->MainResource.ActiveCount, 
				PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, 
				PtrReqdFCB->MainResource.NumberOfSharedWaiters );

			AcquiredFCB = FALSE;
		}

		if (!PostRequest) 
		{
			PIO_STACK_LOCATION		PtrNextIoStackLocation = NULL;
			NTSTATUS						RC1 = STATUS_SUCCESS;

			// Send the request down at this point.
			// To do this, you must set the next IRP stack location, and
			// maybe set a completion routine.
			// Be careful about marking the IRP pending if the lower level
			// driver returned pending and you do have a completion routine!
			PtrNextIoStackLocation = IoGetNextIrpStackLocation(PtrIrp);
			*PtrNextIoStackLocation = *PtrIoStackLocation;

			// Set the completion routine to "eat-up" any
			// STATUS_INVALID_DEVICE_REQUEST error code returned by the lower
			// level driver.
			IoSetCompletionRoutine(PtrIrp, Ext2FlushCompletion, NULL, TRUE, TRUE, TRUE);

			/*
			 * The exception handlers propably masked out the
			 * fact that PtrVCB was never set.
			 * -- Filip Navara, 18/08/2004
			 */
			PtrVCB = PtrFCB->PtrVCB;
			RC1 = IoCallDriver(PtrVCB->TargetDeviceObject, PtrIrp);

			RC = ((RC1 == STATUS_INVALID_DEVICE_REQUEST) ? RC : RC1);
		}

	} finally {
		if (PostRequest) {
			// Nothing to lock now.
			RC = Ext2PostRequest(PtrIrpContext, PtrIrp);
		} else {
			// Release the IRP context at this time.
  			Ext2ReleaseIrpContext(PtrIrpContext);
		}
	}

	return(RC);
}
Пример #4
0
/*************************************************************************
*
* Function: Ext2NotifyChangeDirectory()
*
* Description:
*	Handle the notify request.
*
* Expected Interrupt Level (for execution) :
*
*  IRQL_PASSIVE_LEVEL
*
* Return Value: STATUS_SUCCESS/Error
*
*************************************************************************/
NTSTATUS NTAPI Ext2NotifyChangeDirectory(
PtrExt2IrpContext			PtrIrpContext,
PIRP							PtrIrp,
#ifdef _GNU_NTIFS_
PEXTENDED_IO_STACK_LOCATION		PtrIoStackLocation,
#else
PIO_STACK_LOCATION		PtrIoStackLocation,
#endif
PFILE_OBJECT				PtrFileObject,
PtrExt2FCB					PtrFCB,
PtrExt2CCB					PtrCCB)
{
	NTSTATUS					RC = STATUS_SUCCESS;
	BOOLEAN					CompleteRequest = FALSE;
	BOOLEAN					PostRequest = FALSE;
	PtrExt2NTRequiredFCB	PtrReqdFCB = NULL;
	BOOLEAN					CanWait = FALSE;
	ULONG						CompletionFilter = 0;
	BOOLEAN					WatchTree = FALSE;
	PtrExt2VCB				PtrVCB = NULL;
	BOOLEAN					AcquiredFCB = FALSE;

	try {

		// Validate the sent-in FCB
		if ((PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB) || !(PtrFCB->FCBFlags & EXT2_FCB_DIRECTORY)) {
			// We will only allow notify requests on directories.
			RC = STATUS_INVALID_PARAMETER;
			CompleteRequest = TRUE;
		}

		PtrReqdFCB = &(PtrFCB->NTRequiredFCB);
		CanWait = ((PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE);
	    PtrVCB = PtrFCB->PtrVCB;

		// Acquire the FCB resource shared
		DebugTrace(DEBUG_TRACE_MISC,   "*** Attempting to acquire FCB Shared[DirCtrl]", 0);
		DebugTraceState( "FCBMain   AC:0x%LX   SW:0x%LX   EX:0x%LX   [DirCtrl]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters );
		if (!ExAcquireResourceSharedLite(&(PtrReqdFCB->MainResource), CanWait)) 
		{
			DebugTrace(DEBUG_TRACE_MISC,   "*** FCB Acquisition FAILED [DirCtrl]", 0);
			PostRequest = TRUE;
			try_return(RC = STATUS_PENDING);
		}
		AcquiredFCB = TRUE;
		DebugTrace(DEBUG_TRACE_MISC,   "*** FCB acquired [DirCtrl]", 0);

		// Obtain some parameters sent by the caller
		CompletionFilter = PtrIoStackLocation->Parameters.NotifyDirectory.CompletionFilter;
		WatchTree = (PtrIoStackLocation->Flags & SL_WATCH_TREE ? TRUE : FALSE);

		// If you wish to capture the subject context, you can do so as
		// follows:
		// {
		//		PSECURITY_SUBJECT_CONTEXT SubjectContext;
 		// 	SubjectContext = Ext2AllocatePool(PagedPool,
		//									sizeof(SECURITY_SUBJECT_CONTEXT) );
		//		SeCaptureSubjectContext(SubjectContext);
		//	}

		FsRtlNotifyFullChangeDirectory((PNOTIFY_SYNC)&(PtrVCB->NotifyIRPMutex), &(PtrVCB->NextNotifyIRP), (void *)PtrCCB,
							(PSTRING)(PtrFCB->FCBName->ObjectName.Buffer), WatchTree, FALSE, CompletionFilter, PtrIrp,
							NULL,		// Ext2TraverseAccessCheck(...) ?
							NULL);	// SubjectContext ?

		RC = STATUS_PENDING;

		try_exit:	NOTHING;

	} 
	finally 
	{

		if (PostRequest) 
		{
			// Perform appropriate post related processing here
			if (AcquiredFCB) 
			{
				Ext2ReleaseResource(&(PtrReqdFCB->MainResource));
				DebugTrace(DEBUG_TRACE_MISC,  "*** FCB Released in DirCtrl", 0);
				DebugTraceState( "FCBMain   AC:0x%LX   SW:0x%LX   EX:0x%LX   [DirCtrl]", 
					PtrReqdFCB->MainResource.ActiveCount, 
					PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, 
					PtrReqdFCB->MainResource.NumberOfSharedWaiters );

				AcquiredFCB = FALSE;
			}
			RC = Ext2PostRequest(PtrIrpContext, PtrIrp);
		} 
		else if (CompleteRequest) 
		{
			PtrIrp->IoStatus.Status = RC;
			PtrIrp->IoStatus.Information = 0;

			// Free up the Irp Context
			Ext2ReleaseIrpContext(PtrIrpContext);

			// complete the IRP
			IoCompleteRequest(PtrIrp, IO_DISK_INCREMENT);
		} else {
			// Simply free up the IrpContext since the IRP has been queued
			Ext2ReleaseIrpContext(PtrIrpContext);
		}

		// Release the FCB resources if acquired.
		if (AcquiredFCB) 
		{
			Ext2ReleaseResource(&(PtrReqdFCB->MainResource));
			DebugTrace(DEBUG_TRACE_MISC,  "*** FReleased in [DirCtrl]", 0);
			DebugTraceState( "FCBMain   AC:0x%LX   SW:0x%LX   EX:0x%LX   [DirCtrl]", 
					PtrReqdFCB->MainResource.ActiveCount, 
					PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, 
					PtrReqdFCB->MainResource.NumberOfSharedWaiters );

			AcquiredFCB = FALSE;
		}

	}

	return(RC);
}
Пример #5
0
/*************************************************************************
*
* Function: Ext2QueryDirectory()
*
* Description:
*	Query directory request.
*
* Expected Interrupt Level (for execution) :
*
*  IRQL_PASSIVE_LEVEL
*
* Return Value: STATUS_SUCCESS/Error
*
*************************************************************************/
NTSTATUS NTAPI Ext2QueryDirectory(
PtrExt2IrpContext			PtrIrpContext,
PIRP						PtrIrp,
#ifdef _GNU_NTIFS_
PEXTENDED_IO_STACK_LOCATION			PtrIoStackLocation,
#else
PIO_STACK_LOCATION			PtrIoStackLocation,
#endif
PFILE_OBJECT				PtrFileObject,
PtrExt2FCB					PtrFCB,
PtrExt2CCB					PtrCCB)
{
	NTSTATUS				RC = STATUS_SUCCESS;
	BOOLEAN					PostRequest = FALSE;
	PtrExt2NTRequiredFCB	PtrReqdFCB = NULL;
	BOOLEAN					CanWait = FALSE;
	PtrExt2VCB				PtrVCB = NULL;
	BOOLEAN					AcquiredFCB = FALSE;
	unsigned long			BufferLength = 0;
	unsigned long			BufferIndex	= 0;
	unsigned long			FileIndex = 0;
	PUNICODE_STRING			PtrSearchPattern = NULL;
	FILE_INFORMATION_CLASS	FileInformationClass;
	BOOLEAN					RestartScan = FALSE;
	BOOLEAN					ReturnSingleEntry = FALSE;
	BOOLEAN					IndexSpecified = FALSE;
	unsigned char			*Buffer = NULL;
	BOOLEAN					FirstTimeQuery = FALSE;
	unsigned long			StartingIndexForSearch = 0;
	unsigned long			BytesReturned = 0;
	BOOLEAN					BufferUsedup = FALSE;

	BOOLEAN					SearchWithWildCards = FALSE;
	
	PFILE_BOTH_DIR_INFORMATION		BothDirInformation = NULL;
	PFILE_DIRECTORY_INFORMATION		DirectoryInformation = NULL;

	
	PEXT2_DIR_ENTRY		PtrDirEntry = NULL;
	PEXT2_INODE			PtrInode	= NULL;
	
	unsigned long		LogicalBlockSize;
	
	unsigned long		ThisBlock;
	
	//	The starting Physical Block No...
	//LARGE_INTEGER StartPhysicalBlock;
	LARGE_INTEGER StartBufferOffset ;
	ULONG PinBufferLength;
		
	//	Buffer Control Block
	PBCB				PtrBCB = NULL;
	BYTE *				PtrPinnedBlockBuffer = NULL;

	unsigned int j;
	
	DebugTrace(DEBUG_TRACE_MISC,   " === Querying Directory %S", PtrFCB->FCBName->ObjectName.Buffer );

	try 
	{
		// Validate the sent-in FCB
		if ((PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB) || !(PtrFCB->FCBFlags & EXT2_FCB_DIRECTORY)) 
		{
			// We will only allow notify requests on directories.
			RC = STATUS_INVALID_PARAMETER;
		}

		PtrReqdFCB = &(PtrFCB->NTRequiredFCB);
		CanWait = ((PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE);
		PtrVCB = PtrFCB->PtrVCB;

		//
		//	Asynchronous IO requested
		//	Posting request...
		//
		/*
		 * This is incorrect because posted IRP_MJ_DIRECTORY_CONTROL
		 * requests aren't handled in the worker thread yet. I tried
		 * adding handling of them to the worked routine, but there
		 * were problems with accessing the PtrIoStackLocation->
		 * Parameters.QueryDirectory.FileName variable.
		 * -- Filip Navara, 18/08/2004
		 */
#if 0
		if (!CanWait) 
		{
			PostRequest = TRUE;
			try_return(RC = STATUS_PENDING);
		}
#endif

		// Obtain the callers parameters
		BufferLength = PtrIoStackLocation->Parameters.QueryDirectory.Length;
		PtrSearchPattern = ( PUNICODE_STRING	) PtrIoStackLocation->Parameters.QueryDirectory.FileName;
		FileInformationClass = PtrIoStackLocation->Parameters.QueryDirectory.FileInformationClass;
		FileIndex = PtrIoStackLocation->Parameters.QueryDirectory.FileIndex;

		// Some additional arguments that affect the FSD behavior
		RestartScan       = (PtrIoStackLocation->Flags & SL_RESTART_SCAN);
		ReturnSingleEntry = (PtrIoStackLocation->Flags & SL_RETURN_SINGLE_ENTRY);
		IndexSpecified    = (PtrIoStackLocation->Flags & SL_INDEX_SPECIFIED);

		//
		// Acquiring exclusive access to the FCB.
		// This is not mandatory
		//
		DebugTrace(DEBUG_TRACE_MISC,   "*** Going into a block to acquire FCB Exclusively[DirCtrl]", 0);

		DebugTraceState( "FCBMain   AC:0x%LX   SW:0x%LX   EX:0x%LX   [DirCtrl]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters );
		ExAcquireResourceExclusiveLite(&(PtrReqdFCB->MainResource), TRUE);
		
		DebugTrace(DEBUG_TRACE_MISC,   "*** FCB acquired [DirCtrl]", 0);
		AcquiredFCB = TRUE;

		// We must determine the buffer pointer to be used. Since this
		// routine could either be invoked directly in the context of the
		// calling thread, or in the context of a worker thread, here is
		// a general way of determining what we should use.
		Buffer = Ext2GetCallersBuffer ( PtrIrp );

		// The method of determining where to look from and what to look for is
		// unfortunately extremely confusing. However, here is a methodology you
		// you can broadly adopt:
		// (a) You have to maintain a search buffer per CCB structure.
		// (b) This search buffer is initialized the very first time
		//		 a query directory operation is performed using the file object.
		// (For the sample FSD, the search buffer is stored in the
		//	 DirectorySearchPattern field)
		// However, the caller still has the option of "overriding" this stored
		// search pattern by supplying a new one in a query directory operation.
		//

		if( PtrCCB->DirectorySearchPattern.Length )
		{
			if( PtrCCB->DirectorySearchPattern.Buffer[PtrCCB->DirectorySearchPattern.Length/2] != 0 )
			{
				DebugTrace(DEBUG_TRACE_MISC,  "&&&&&&&&&  PtrCCB->DirectorySearchPattern not NULL terminated!", 0);
			}
			DebugTrace(DEBUG_TRACE_MISC,   " === Old Search pattern %S", PtrCCB->DirectorySearchPattern.Buffer );
		}

		if (PtrSearchPattern != NULL) 
		{
			// User has supplied a search pattern
			// Now validate that the search pattern is legitimate

			if ( PtrCCB->DirectorySearchPattern.Length == 0 ) 
			{
				// This must be the very first query request.
				FirstTimeQuery = TRUE;
			}
			else
			{
				// We should ignore the search pattern in the CCB and instead,
				// use the user-supplied pattern for this particular query
				// directory request.
				Ext2DeallocateUnicodeString( &PtrCCB->DirectorySearchPattern );
			}

			// Now, allocate enough memory to contain the caller
			// supplied search pattern and fill in the DirectorySearchPattern
			// field in the CCB
			Ext2CopyUnicodeString( &PtrCCB->DirectorySearchPattern, PtrSearchPattern );
			/*
			PtrCCB->DirectorySearchPattern = Ext2AllocatePool(PagedPool, sizeof( PtrSearchPattern ) );
			ASSERT(PtrCCB->DirectorySearchPattern);
			RtlCopyMemory( PtrCCB->DirectorySearchPattern, PtrSearchPattern, sizeof( PtrSearchPattern ) );
			*/
		}
		else if ( PtrCCB->DirectorySearchPattern.Length == 0 ) 
		{
			// This MUST be the first directory query operation (else the
			// DirectorySearchPattern field would never be empty. Also, the caller
			// has neglected to provide a pattern so we MUST invent one.
			// Use "*" (following NT conventions) as your search pattern
			// and store it in the PtrCCB->DirectorySearchPattern field.
			
			/*
			PtrCCB->DirectorySearchPattern = Ext2AllocatePool(PagedPool, sizeof(L"*") );
			ASSERT(PtrCCB->DirectorySearchPattern);
			RtlCopyMemory( PtrCCB->DirectorySearchPattern, L"*", 4 );*/

			Ext2CopyWideCharToUnicodeString( &PtrCCB->DirectorySearchPattern, L"*" );
			
			FirstTimeQuery = TRUE;
		} 
		else 
		{
			// The caller has not supplied any search pattern...
			// Using previously supplied pattern
			PtrSearchPattern = &PtrCCB->DirectorySearchPattern;
		}

		if( PtrCCB->DirectorySearchPattern.Buffer[PtrCCB->DirectorySearchPattern.Length/2] != 0 )
		{
			DebugTrace(DEBUG_TRACE_MISC,  "&&&&&&&&&  PtrCCB->DirectorySearchPattern not NULL terminated!", 0 );
		}
		DebugTrace(DEBUG_TRACE_MISC,   " === Search pattern %S", PtrCCB->DirectorySearchPattern.Buffer );
		SearchWithWildCards = FsRtlDoesNameContainWildCards( PtrSearchPattern );

		// There is one other piece of information that your FSD must store
		// in the CCB structure for query directory support. This is the index
		// value (i.e. the offset in your on-disk directory structure) from
		// which you should start searching.
		// However, the flags supplied with the IRP can make us override this
		// as well.

		if (FileIndex) 
		{
			// Caller has told us wherefrom to begin.
			// You may need to round this to an appropriate directory entry
			// entry alignment value.
			StartingIndexForSearch = FileIndex;
		} 
		else if (RestartScan) 
		{
			StartingIndexForSearch = 0;
		} 
		else 
		{
			// Get the starting offset from the CCB.
			StartingIndexForSearch = PtrCCB->CurrentByteOffset.LowPart;
		}

		//	Read in the file inode if it hasn't already been read...
		Ext2InitializeFCBInodeInfo( PtrFCB );
		
		if (PtrFileObject->PrivateCacheMap == NULL) 
		{
			CcInitializeCacheMap(PtrFileObject, (PCC_FILE_SIZES)(&(PtrReqdFCB->CommonFCBHeader.AllocationSize)),
				TRUE,		// We will utilize pin access for directories
				&(Ext2GlobalData.CacheMgrCallBacks), // callbacks
				PtrCCB);		// The context used in callbacks
		}


		//
		//	Read in the next Data Block of this directory
		//
		LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;
		StartBufferOffset.QuadPart = ( StartingIndexForSearch / LogicalBlockSize );
		StartBufferOffset.QuadPart *= LogicalBlockSize;	//	This should be the StartBufferOffset alaigned to LBlock boundary...
		
		PinBufferLength = PtrReqdFCB->CommonFCBHeader.FileSize.LowPart - StartBufferOffset.LowPart;

		if ( !CcMapData( PtrFileObject,
                  &StartBufferOffset,
                  PinBufferLength,
                  TRUE,
                  &PtrBCB,
                  (PVOID*)&PtrPinnedBlockBuffer ) )
		{
			//	Read Failure
			DebugTrace(DEBUG_TRACE_MISC,   "Cache read failiure while reading in volume meta data", 0);
			try_return();
		}
		else
		{
			DebugTrace(DEBUG_TRACE_MISC,   "Cache hit while reading in volume meta data", 0);
		}
		
		PtrInode = Ext2AllocatePool( PagedPool, sizeof( EXT2_INODE )  );

		//
		//	Walking through the directory entries...
		for( BufferUsedup = FALSE, BufferIndex = 0; !BufferUsedup && StartingIndexForSearch < ( PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart - 1) ; )
		{
			PtrDirEntry = (PEXT2_DIR_ENTRY) &PtrPinnedBlockBuffer[ StartingIndexForSearch - StartBufferOffset.LowPart ];
			
			StartingIndexForSearch += PtrDirEntry->rec_len;
			PtrCCB->CurrentByteOffset.LowPart = StartingIndexForSearch;

			if( PtrDirEntry->inode == 0 )
			{
				continue;
			}
			if( PtrDirEntry->name_len == 0 || PtrDirEntry->rec_len == 0 )
			{
				//
				//	This should not happen
				//	Hqw can this be so!!!
				//
				Ext2BreakPoint();
				if( BothDirInformation )
				{
					BothDirInformation->NextEntryOffset = 0;
				}
				if( !BytesReturned )
				{
					if( FirstTimeQuery )
						RC = STATUS_NO_SUCH_FILE;
					else
						RC = STATUS_NO_MORE_FILES;
				}
				break;
			}

			//	Does this entry match the search criterian?
			//	Checking
			//
			{
				UNICODE_STRING	FileName;
				LONG	Matched = 0;
				// Constructing a counted Unicode string out of PtrDirEntry
				Ext2CopyCharToUnicodeString( &FileName, PtrDirEntry->name, PtrDirEntry->name_len );

				if ( SearchWithWildCards )
				{
					Matched = FsRtlIsNameInExpression ( PtrSearchPattern, &FileName, FALSE, NULL );
				}
				else
				{
					Matched = ! RtlCompareUnicodeString( PtrSearchPattern, &FileName, FALSE );
				}
			
				Ext2DeallocateUnicodeString( &FileName );
				if( !Matched )
				{
					continue;
				}
			}

			switch( FileInformationClass )
			{
			case FileBothDirectoryInformation:
				
				DebugTrace(DEBUG_TRACE_DIRINFO,   " === FileBothDirectoryInformation", 0 );
				ThisBlock = sizeof( FILE_BOTH_DIR_INFORMATION );
				ThisBlock += PtrDirEntry->name_len*2;
				ThisBlock = Ext2QuadAlign( ThisBlock  );

				if( ( BufferIndex + ThisBlock ) > BufferLength )
				{
					//
					//	Next entry won't fit into the buffer...
					//	will have to return... 
					//	:(
					//
					if( BothDirInformation )
						BothDirInformation->NextEntryOffset = 0;
					if( !BytesReturned )
						RC = STATUS_NO_MORE_FILES;
					BufferUsedup = TRUE;
					break;
				}
							
				Ext2ReadInode( PtrVCB, PtrDirEntry->inode, PtrInode );
				if( !PtrInode )
				{
					try_return( RC = STATUS_UNSUCCESSFUL );
				}

				BothDirInformation = ( PFILE_BOTH_DIR_INFORMATION ) ( Buffer + ( BufferIndex ) );
				BothDirInformation->EaSize					= 0;
				BothDirInformation->AllocationSize.QuadPart	= PtrInode->i_blocks * 512;
				BothDirInformation->EndOfFile.QuadPart		= PtrInode->i_size;
				BothDirInformation->ChangeTime.QuadPart		= 0;

				BothDirInformation->CreationTime.QuadPart	= ( __int64 ) PtrInode->i_ctime * 10000000;
				BothDirInformation->CreationTime.QuadPart	+= Ext2GlobalData.TimeDiff.QuadPart;

				BothDirInformation->LastAccessTime.QuadPart	= Ext2GlobalData.TimeDiff.QuadPart + ( ( __int64 ) PtrInode->i_atime * 10000000 );
				BothDirInformation->LastWriteTime.QuadPart	= Ext2GlobalData.TimeDiff.QuadPart + ( ( __int64 )PtrInode->i_mtime * 10000000 );

				//	Getting the file type...
				BothDirInformation->FileAttributes = FILE_ATTRIBUTE_NORMAL;
				if( ! Ext2IsModeRegularFile( PtrInode->i_mode ) )
				{  
					//	Not a reqular file...
					if( Ext2IsModeDirectory( PtrInode->i_mode) )
					{
						//	Directory...
						BothDirInformation->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
					}
					else
					{
						//	Special File...
						//	Treated with respect... ;)
						//
						BothDirInformation->FileAttributes |= ( FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY);
						//	FILE_ATTRIBUTE_DEVICE
					}
					if ( Ext2IsModeHidden( PtrInode->i_mode ) )
					{
						BothDirInformation->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
					}
					
					if ( Ext2IsModeReadOnly( PtrInode->i_mode ) )
					{
						BothDirInformation->FileAttributes |= FILE_ATTRIBUTE_READONLY;
					}
				}

				BothDirInformation->FileIndex = StartingIndexForSearch;
				BothDirInformation->FileNameLength = PtrDirEntry->name_len*2 + 2;
				BothDirInformation->ShortNameLength = 0; 
				BothDirInformation->ShortName[0] = 0;
				
				//	Copying out the name as WCHAR null terminated strings
				for( j = 0; j< PtrDirEntry->name_len ; j ++ )
				{
					//	BothDirInformation->ShortName[ j ] = PtrDirEntry->name[j];
					BothDirInformation->FileName[ j ] = PtrDirEntry->name[j];
					//	if( j < 11 )
					//		BothDirInformation->ShortName[j] = PtrDirEntry->name[j];
				}

				/*
				if( j < 11 )
				{
					BothDirInformation->ShortNameLength = j * 2 + 2;
					BothDirInformation->ShortName[ j ] = 0;
				}
				else
				{
					BothDirInformation->ShortNameLength = 24;
					BothDirInformation->ShortName[ 11 ] = 0;
				}*/

				BothDirInformation->FileName[ j ]	= 0;
				BytesReturned += ThisBlock;
				BufferIndex += ThisBlock;

				if( !ReturnSingleEntry && ( StartingIndexForSearch < ( PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart - 1) ))
					BothDirInformation->NextEntryOffset = ThisBlock;
				else
					BothDirInformation->NextEntryOffset = 0;
				break;

			case FileDirectoryInformation:
				//	DirectoryInformation
				DebugTrace(DEBUG_TRACE_DIRINFO,   " === FileDirectoryInformation", 0 );
				ThisBlock = sizeof( FILE_DIRECTORY_INFORMATION );
				ThisBlock += PtrDirEntry->name_len*2;
				ThisBlock = Ext2QuadAlign( ThisBlock  );

				if( ( BufferIndex + ThisBlock ) > BufferLength )
				{
					//
					//	Next entry won't fit into the buffer...
					//	will have to return... 
					//	:(
					//
					if( DirectoryInformation )
						DirectoryInformation->NextEntryOffset = 0;
					if( !BytesReturned )
						RC = STATUS_NO_MORE_FILES;
					BufferUsedup = TRUE;
					break;
				}
							
				Ext2ReadInode( PtrVCB, PtrDirEntry->inode, PtrInode );
				if( !PtrInode )
				{
					try_return( RC = STATUS_UNSUCCESSFUL );
				}

				DirectoryInformation = ( PFILE_DIRECTORY_INFORMATION ) ( Buffer + ( BufferIndex ) );
				DirectoryInformation->AllocationSize.QuadPart	= PtrInode->i_blocks * 512;
				DirectoryInformation->EndOfFile.QuadPart		= PtrInode->i_size;
				DirectoryInformation->ChangeTime.QuadPart		= 0;

				DirectoryInformation->CreationTime.QuadPart	= ( __int64 ) PtrInode->i_ctime * 10000000;
				DirectoryInformation->CreationTime.QuadPart	+= Ext2GlobalData.TimeDiff.QuadPart;

				DirectoryInformation->LastAccessTime.QuadPart	= Ext2GlobalData.TimeDiff.QuadPart + ( ( __int64 ) PtrInode->i_atime * 10000000 );
				DirectoryInformation->LastWriteTime.QuadPart	= Ext2GlobalData.TimeDiff.QuadPart + ( ( __int64 )PtrInode->i_mtime * 10000000 );

				//	Getting the file type...
				DirectoryInformation->FileAttributes = FILE_ATTRIBUTE_NORMAL;
				if( ! Ext2IsModeRegularFile( PtrInode->i_mode ) )
				{  
					//	Not a reqular file...
					if( Ext2IsModeDirectory( PtrInode->i_mode) )
					{
						//	Directory...
						DirectoryInformation->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
					}
					else
					{
						//	Special File...
						//	Treated with respect... ;)
						//
						DirectoryInformation->FileAttributes |= ( FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY);
						//	FILE_ATTRIBUTE_DEVICE
					}
					if ( Ext2IsModeHidden( PtrInode->i_mode ) )
					{
						DirectoryInformation->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
					}
					
					if ( Ext2IsModeReadOnly( PtrInode->i_mode ) )
					{
						DirectoryInformation->FileAttributes |= FILE_ATTRIBUTE_READONLY;
					}
				}

				DirectoryInformation->FileIndex = StartingIndexForSearch;
				DirectoryInformation->FileNameLength = PtrDirEntry->name_len*2 + 2;
				
				//	Copying out the name as WCHAR null terminated strings
				for( j = 0; j< PtrDirEntry->name_len ; j ++ )
				{
					DirectoryInformation->FileName[ j ] = PtrDirEntry->name[j];
				}

				DirectoryInformation->FileName[ j ]	= 0;
				BytesReturned += ThisBlock;
				BufferIndex += ThisBlock;

				if( !ReturnSingleEntry && ( StartingIndexForSearch < ( PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart - 1) ))
					DirectoryInformation->NextEntryOffset = ThisBlock;
				else
					DirectoryInformation->NextEntryOffset = 0;
				break;

			case FileFullDirectoryInformation:
				//	FullDirInformation->
				DebugTrace(DEBUG_TRACE_DIRINFO,   " === FileFullDirectoryInformation - Not handled", 0 );
				try_return();
			case FileNamesInformation:
				//	NamesInformation->
				DebugTrace(DEBUG_TRACE_DIRINFO,   " === FileNamesInformation - Not handled", 0 );
				try_return();
			default:
				DebugTrace(DEBUG_TRACE_DIRINFO,   " === Invalid Dir Info class - Not handled", 0 );
				try_return( RC = STATUS_INVALID_INFO_CLASS );
			}
			if( ReturnSingleEntry )
			{
				break;
			}
		}//	end of for...



		if( !BytesReturned && StartingIndexForSearch >= ( PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart) )
		{
			Ext2DeallocateUnicodeString( &PtrCCB->DirectorySearchPattern );
			PtrCCB->CurrentByteOffset.QuadPart = 0;
			if( FirstTimeQuery )
				RC = STATUS_NO_SUCH_FILE;
			else
				RC = STATUS_NO_MORE_FILES;
			try_return();
		}
		else if( BytesReturned )
		{
			BothDirInformation->NextEntryOffset = 0;
		}

		try_exit:	NOTHING;
	}
	finally 
	{

		if( PtrInode )
		{
			DebugTrace( DEBUG_TRACE_FREE, "Freeing  = %lX [DirCtrl]", PtrInode );
			ExFreePool( PtrInode );
		}

		if( PtrBCB )
		{
			CcUnpinData( PtrBCB );
			PtrBCB = NULL;
		}
		
		if (PostRequest) 
		{
			if (AcquiredFCB) 
			{
				Ext2ReleaseResource(&(PtrReqdFCB->MainResource));
				DebugTrace(DEBUG_TRACE_MISC,  "*** FCB Released in [DirCtrl]", 0);
				DebugTraceState( "FCBMain   AC:0x%LX   SW:0x%LX   EX:0x%LX   [DirCtrl]", 
					PtrReqdFCB->MainResource.ActiveCount, 
					PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, 
					PtrReqdFCB->MainResource.NumberOfSharedWaiters );
			}

			// Map the users buffer and then post the request.
			RC = Ext2LockCallersBuffer(PtrIrp, TRUE, BufferLength);
			ASSERT(NT_SUCCESS(RC));

			RC = Ext2PostRequest(PtrIrpContext, PtrIrp);

		}
		else if (!(PtrIrpContext->IrpContextFlags &
							EXT2_IRP_CONTEXT_EXCEPTION)) 
		{
			if (AcquiredFCB) 
			{
				Ext2ReleaseResource(&(PtrReqdFCB->MainResource));
				DebugTrace(DEBUG_TRACE_MISC,  "*** FCB Released [DirCtrl]", 0);
				DebugTraceState( "FCBMain   AC:0x%LX   SW:0x%LX   EX:0x%LX   [DirCtrl]", 
					PtrReqdFCB->MainResource.ActiveCount, 
					PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, 
					PtrReqdFCB->MainResource.NumberOfSharedWaiters );
			}

			// Complete the request.
			PtrIrp->IoStatus.Status = RC;
			PtrIrp->IoStatus.Information = BytesReturned;

			// Free up the Irp Context
			Ext2ReleaseIrpContext(PtrIrpContext);

			// complete the IRP
			IoCompleteRequest(PtrIrp, IO_DISK_INCREMENT);
		}
		
		//	Flush the saved BCBs...
		//	Ext2FlushSavedBCBs ( PtrIrpContext );

	}

	return(RC);
}