NTSTATUS
NdasNtfsSecondaryCommonFileSystemControl (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )
{
    NTSTATUS			Status;
    PIO_STACK_LOCATION	IrpSp;

    ASSERT_IRP_CONTEXT( IrpContext );
    ASSERT_IRP( Irp );
    ASSERT( FlagOn( IrpContext->TopLevelIrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL ));

    PAGED_CODE();

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    DebugTrace( +1, Dbg, ("NtfsCommonFileSystemControl\n") );
    DebugTrace( 0, Dbg, ("IrpContext = %08lx\n", IrpContext) );
    DebugTrace( 0, Dbg, ("Irp        = %08lx\n", Irp) );

    switch (IrpSp->MinorFunction) {

    case IRP_MN_MOUNT_VOLUME:

		ASSERT( FALSE );

        NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_INVALID_DEVICE_REQUEST );
        break;

    case IRP_MN_USER_FS_REQUEST:
    case IRP_MN_KERNEL_CALL:

        Status = NdasNtfsSecondaryUserFsRequest( IrpContext, Irp );
        break;

    default:

        DebugTrace( -1, Dbg, ("Invalid Minor Function %08lx\n", IrpSp->MinorFunction) );
        NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_INVALID_DEVICE_REQUEST );
        break;
    }

    DebugTrace( -1, Dbg, ("NtfsCommonFileSystemControl -> %08lx\n", Status) );

    return Status;
}
static NTSTATUS
NdasNtfsSecondaryUserFsRequest (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP			Irp
    )
{
    NTSTATUS			Status = STATUS_SUCCESS;
    ULONG				FsControlCode;
    ULONG				FsControlCodeFunction;
    PIO_STACK_LOCATION	IrpSp;

	PVOLUME_DEVICE_OBJECT		volDo = CONTAINING_RECORD( IrpContext->Vcb, VOLUME_DEVICE_OBJECT, Vcb );
	BOOLEAN						secondarySessionResourceAcquired = FALSE;

	TYPE_OF_OPEN				typeOfOpen;
	PVCB						vcb;
	PFCB						fcb;
	PSCB						scb;
	PCCB						ccb;

	PSECONDARY_REQUEST			secondaryRequest = NULL;

	PNDFS_REQUEST_HEADER		ndfsRequestHeader;
	PNDFS_WINXP_REQUEST_HEADER	ndfsWinxpRequestHeader;
	PNDFS_WINXP_REPLY_HEADER	ndfsWinxpReplytHeader;
	_U8							*ndfsWinxpRequestData;

	LARGE_INTEGER				timeOut;

	struct FileSystemControl	fileSystemControl;

	PVOID						inputBuffer = NULL;
	ULONG						inputBufferLength;
	PVOID						outputBuffer = NULL;
	ULONG						outputBufferLength;
	ULONG						bufferLength;


    ASSERT_IRP_CONTEXT( IrpContext );
    ASSERT_IRP( Irp );

    PAGED_CODE();

	ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    FsControlCode = IrpSp->Parameters.FileSystemControl.FsControlCode;
	FsControlCodeFunction = (FsControlCode & 0x00003FFC) >> 2;

    DebugTrace( +1, Dbg, ("NtfsUserFsRequest, FsControlCode = %08lx, FsControlCodeFunction = %d\n", FsControlCode, FsControlCodeFunction) );

    switch ( FsControlCode ) {

    case FSCTL_REQUEST_OPLOCK_LEVEL_1:
    case FSCTL_REQUEST_OPLOCK_LEVEL_2:
    case FSCTL_REQUEST_BATCH_OPLOCK:
    case FSCTL_REQUEST_FILTER_OPLOCK:
    case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE:
    case FSCTL_OPLOCK_BREAK_NOTIFY:
    case FSCTL_OPBATCH_ACK_CLOSE_PENDING :
    case FSCTL_OPLOCK_BREAK_ACK_NO_2:

		ASSERT( FALSE );
        //Status = NtfsOplockRequest( IrpContext, Irp );
        break;

	case FSCTL_LOCK_VOLUME: 
	
		NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED );

		DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) );
		return Status;

		//Status = NtfsLockVolume( IrpContext, Irp );
        break;
	
    case FSCTL_UNLOCK_VOLUME:

		NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED );

		DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) );
		return Status;

		//Status = NtfsUnlockVolume( IrpContext, Irp );
        break;

	case FSCTL_DISMOUNT_VOLUME: {

#if 0
		NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED );

		DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) );
		return Status;
#else

		BOOLEAN	secondaryCreateResourceAcquired = FALSE;

		ASSERT( IS_WINDOWSVISTA_OR_LATER() );

		do {
		
			BOOLEAN secondaryRecoveryResourceAcquired;

			DebugTrace( 0, Dbg, ("%s: IRP_MN_QUERY_REMOVE_DEVICE volDo = %p, NetdiskEnableMode = %d\n", 
								   __FUNCTION__, volDo, volDo->NetdiskEnableMode) );

			secondaryRecoveryResourceAcquired 
				= SecondaryAcquireResourceExclusiveLite( IrpContext, 
														 &volDo->RecoveryResource, 
														 FALSE );
			
			if (secondaryRecoveryResourceAcquired == FALSE) {

				Status = STATUS_ACCESS_DENIED;
				break;
			}

			SecondaryReleaseResourceLite( IrpContext, &volDo->RecoveryResource );

			ExAcquireFastMutex( &volDo->Secondary->FastMutex );	

			if (!volDo->Secondary->TryCloseActive) {
				
				volDo->Secondary->TryCloseActive = TRUE;
				ExReleaseFastMutex( &volDo->Secondary->FastMutex );
				Secondary_Reference( volDo->Secondary );
				//NtfsDebugTraceLevel |= DEBUG_TRACE_CLOSE;
				SecondaryTryClose( &IrpContext, volDo->Secondary );
				//NtfsDebugTraceLevel &= ~DEBUG_TRACE_CLOSE;
				
			} else {
				
				ExReleaseFastMutex( &volDo->Secondary->FastMutex );
			}

			if (volDo->Vcb.SecondaryCloseCount) {

				LARGE_INTEGER interval;

				// Wait all files closed
				interval.QuadPart = (-1 * HZ);      //delay 1 seconds
				KeDelayExecutionThread(KernelMode, FALSE, &interval);
			}

			CcWaitForCurrentLazyWriterActivity();

			secondaryCreateResourceAcquired 
				= SecondaryAcquireResourceExclusiveLite( IrpContext, 
														 &volDo->CreateResource, 
														 BooleanFlagOn(IrpContext->State, IRP_CONTEXT_STATE_WAIT) );

			if (secondaryCreateResourceAcquired == FALSE) {

				Status = STATUS_ACCESS_DENIED;
				break;
			}

			if (volDo->Vcb.SecondaryCloseCount) {

				LONG		ccbCount;
				PLIST_ENTRY	ccbListEntry;
				PVOID		restartKey;
				PFCB		fcb;

				ExAcquireFastMutex( &volDo->Secondary->RecoveryCcbQMutex );

			    for (ccbCount = 0, ccbListEntry = volDo->Secondary->RecoveryCcbQueue.Flink; 
					 ccbListEntry != &volDo->Secondary->RecoveryCcbQueue; 
					 ccbListEntry = ccbListEntry->Flink, ccbCount++);

				ExReleaseFastMutex( &volDo->Secondary->RecoveryCcbQMutex );

				ASSERT( !IsListEmpty(&volDo->Secondary->RecoveryCcbQueue) );
				ASSERT( ccbCount == volDo->Vcb.SecondaryCloseCount );

				DebugTrace( 0, Dbg, ("IRP_MN_QUERY_REMOVE_DEVICE: Vcb->SecondaryCloseCount = %d, Vcb->SecondaryCleanupCount = %d, Vcb->CloseCount = %d, ccbCount = %d\n",
			                          volDo->Vcb.SecondaryCloseCount, volDo->Vcb.SecondaryCleanupCount, volDo->Vcb.CloseCount, ccbCount) );

				restartKey = NULL;
				fcb = NdasNtfsGetNextFcbTableEntry( &volDo->Vcb, &restartKey );
				ASSERT( fcb != NULL || !IsListEmpty(&volDo->Secondary->DeletedFcbQueue) );

				Status = STATUS_ACCESS_DENIED;

				break;

			} else {

				Status = STATUS_SUCCESS;
				SetFlag( volDo->Secondary->Flags, SECONDARY_FLAG_DISMOUNTING );
			}
		
		} while(0);

		if (Status != STATUS_SUCCESS) {

			if (secondaryCreateResourceAcquired) {

				SecondaryReleaseResourceLite( IrpContext, &volDo->CreateResource );
				secondaryCreateResourceAcquired = FALSE;
			}

			NtfsCompleteRequest( IrpContext, Irp, Status );

			DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) );
			return Status;
		}

		Status = NtfsDismountVolume( IrpContext, Irp );

		SecondaryReleaseResourceLite( IrpContext, &volDo->CreateResource );

		return Status;

#endif
		break;
	}

    case FSCTL_IS_VOLUME_MOUNTED:

        Status = NtfsIsVolumeMounted( IrpContext, Irp );

		DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) );
		return Status;
		
        break;

    case FSCTL_MARK_VOLUME_DIRTY:

		NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED );

		DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) );
		return Status;

        //Status = NtfsDirtyVolume( IrpContext, Irp );
        break;

    case FSCTL_IS_PATHNAME_VALID:
		
        NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_SUCCESS );

		DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) );
		return Status;
		
        break;

    case FSCTL_QUERY_RETRIEVAL_POINTERS:
        
		Status = NtfsQueryRetrievalPointers( IrpContext, Irp );
		break;

    case FSCTL_GET_COMPRESSION:
        
		//NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_INVALID_DEVICE_REQUEST );

		//DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) );
		//return Status;

		Status = NtfsGetCompression( IrpContext, Irp );
		break;

    case FSCTL_SET_COMPRESSION:

		NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_INVALID_DEVICE_REQUEST );

		DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) );
		return Status;

		Status = NtfsSetCompression( IrpContext, Irp );
        break;

    case FSCTL_MARK_AS_SYSTEM_HIVE:
        
		Status = NtfsMarkAsSystemHive( IrpContext, Irp );

		DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) );
		return Status;

		break;

    case FSCTL_FILESYSTEM_GET_STATISTICS:
        
		Status = NtfsGetStatistics( IrpContext, Irp );
        break;

    case FSCTL_GET_NTFS_VOLUME_DATA:
        
		Status = NtfsGetVolumeData( IrpContext, Irp );
        break;

    case FSCTL_GET_VOLUME_BITMAP:
        
		Status = NtfsGetVolumeBitmap( IrpContext, Irp );
        break;

    case FSCTL_GET_RETRIEVAL_POINTERS:
        
		Status = NtfsGetRetrievalPointers( IrpContext, Irp );
		break;

    case FSCTL_GET_NTFS_FILE_RECORD:
        
		Status = NtfsGetMftRecord( IrpContext, Irp );
		break;

	case FSCTL_MOVE_FILE: 

		NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED );

		DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) );
		return Status;

		Status = NtfsDefragFile( IrpContext, Irp );

		if (Status == STATUS_SUCCESS) {

			PMOVE_FILE_DATA	moveFileData = IrpContext->InputBuffer;	
			PFILE_OBJECT	moveFileObject;
			

			Status = ObReferenceObjectByHandle( moveFileData->FileHandle,
												FILE_READ_DATA,
												0,
												KernelMode,
												&moveFileObject,
												NULL );

			if (Status != STATUS_SUCCESS) {

				break;
			}
	
			ObDereferenceObject( moveFileObject );

			if (!IS_SECONDARY_FILEOBJECT(moveFileObject)) {

				ASSERT( FALSE );
				Status = STATUS_INVALID_PARAMETER;
			}
		} 

		if (Status != STATUS_SUCCESS)
			DebugTrace( 0, Dbg2, ("NtfsDefragFile: status = %x\n", Status) );

        break;

	case FSCTL_IS_VOLUME_DIRTY: 

		Status = NtfsIsVolumeDirty( IrpContext, Irp );
        break;

    case FSCTL_ALLOW_EXTENDED_DASD_IO:
        
		Status = NtfsSetExtendedDasdIo( IrpContext, Irp );
		break;

	case FSCTL_SET_REPARSE_POINT: 

		Status = NtfsSetReparsePoint( IrpContext, Irp );
        break;

    case FSCTL_GET_REPARSE_POINT:
        
		Status = NtfsGetReparsePoint( IrpContext, Irp );
		break;

    case FSCTL_DELETE_REPARSE_POINT:
        
		Status = NtfsDeleteReparsePoint( IrpContext, Irp );
        break;

    case FSCTL_SET_OBJECT_ID:
        
		Status = NtfsSetObjectId( IrpContext, Irp );                // In ObjIdSup.c
		break;

    case FSCTL_GET_OBJECT_ID:
        
		Status = NtfsGetObjectId( IrpContext, Irp );                // In ObjIdSup.c
		break;

    case FSCTL_DELETE_OBJECT_ID:
        
		Status = NtfsDeleteObjectId( IrpContext, Irp );             // In ObjIdSup.c
        break;

    case FSCTL_SET_OBJECT_ID_EXTENDED:
        
		Status = NtfsSetObjectIdExtendedInfo( IrpContext, Irp );    // In ObjIdSup.c
        break;

    case FSCTL_CREATE_OR_GET_OBJECT_ID:
        
		Status = NtfsCreateOrGetObjectId( IrpContext, Irp );

		if (IrpSp->Parameters.FileSystemControl.InputBufferLength)
			IrpContext->InputBuffer = Irp->AssociatedIrp.SystemBuffer;
		else
			IrpContext->InputBuffer = NULL;

        break;

    case FSCTL_READ_USN_JOURNAL:
        
		Status = NtfsReadUsnJournal( IrpContext, Irp, TRUE );     //  In UsnSup.c
        break;

    case FSCTL_CREATE_USN_JOURNAL:
        
		Status = NtfsCreateUsnJournal( IrpContext, Irp );
        break;

    case FSCTL_ENUM_USN_DATA:
        
		Status = NtfsReadFileRecordUsnData( IrpContext, Irp );
        break;

    case FSCTL_READ_FILE_USN_DATA:
        
		Status = NtfsReadFileUsnData( IrpContext, Irp );
        break;

    case FSCTL_WRITE_USN_CLOSE_RECORD:
        
		Status = NtfsWriteUsnCloseRecord( IrpContext, Irp );
        break;

    case FSCTL_QUERY_USN_JOURNAL:
        
		Status = NtfsQueryUsnJournal( IrpContext, Irp );
        break;

    case FSCTL_DELETE_USN_JOURNAL:
        
		Status = NtfsDeleteUsnJournal( IrpContext, Irp );
        break;

    case FSCTL_MARK_HANDLE:
        
		Status = NtfsMarkHandle( IrpContext, Irp );

		if (Status == STATUS_SUCCESS) {

			PMARK_HANDLE_INFO	markHandleInfo = inputBuffer;	
			PFILE_OBJECT		volumeFileObject;
			

			Status = ObReferenceObjectByHandle( markHandleInfo->VolumeHandle,
												FILE_READ_DATA,
												0,
												KernelMode,
												&volumeFileObject,
												NULL );

			if (Status != STATUS_SUCCESS) {

				break;
			}
	
			ObDereferenceObject( volumeFileObject );

			if (!IS_SECONDARY_FILEOBJECT(volumeFileObject)) {

				Status = STATUS_INVALID_PARAMETER;
			}
		}
		
		break;

    case FSCTL_SECURITY_ID_CHECK:
        
		Status = NtfsBulkSecurityIdCheck( IrpContext, Irp );
        break;

    case FSCTL_FIND_FILES_BY_SID:
        
		Status = NtfsFindFilesOwnedBySid( IrpContext, Irp );
        break;

    case FSCTL_SET_SPARSE :
        
		NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED );

		DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) );
		return Status;

		//Status = NtfsSetSparse( IrpContext, Irp );
        break;

    case FSCTL_SET_ZERO_DATA :
        
		NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED );

		DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) );
		return Status;

		Status = NtfsZeroRange( IrpContext, Irp );
        break;

    case FSCTL_QUERY_ALLOCATED_RANGES :
        
		Status = NtfsQueryAllocatedRanges( IrpContext, Irp );
        break;

    case FSCTL_ENCRYPTION_FSCTL_IO :
        
		NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED );

		DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) );
		return Status;

		//Status = NtfsEncryptionFsctl( IrpContext, Irp );
        break;

    case FSCTL_SET_ENCRYPTION :
        
		NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED );

		DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) );
		return Status;

		//Status = NtfsSetEncryption( IrpContext, Irp );
        break;

    case FSCTL_READ_RAW_ENCRYPTED:
        
		NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED );

		DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) );
		return Status;

		//Status = NtfsReadRawEncrypted( IrpContext, Irp );
        break;

    case FSCTL_WRITE_RAW_ENCRYPTED:
        
		NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED );

		DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) );
		return Status;

		//Status = NtfsWriteRawEncrypted( IrpContext, Irp );
        break;

    case FSCTL_EXTEND_VOLUME:
        
		NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_ACCESS_DENIED );

		DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) );
		return Status;

		//Status = NtfsExtendVolume( IrpContext, Irp );
        break;

    case FSCTL_READ_FROM_PLEX:
        
		Status = NtfsReadFromPlex( IrpContext, Irp );

		DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) );
		return Status;

		break;

    case FSCTL_FILE_PREFETCH:
        
		Status = NtfsPrefetchFile( IrpContext, Irp );
        break;

    default :
        
		DebugTrace( 0, DEBUG_TRACE_ALL, ("NtfsUserFsRequest: Invalid control code FsControlCode = %08lx, FsControlCodeFunction = %d\n", 
										  FsControlCode, FsControlCodeFunction) );

		NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_INVALID_DEVICE_REQUEST );
        break;
    }

	ASSERT( !ExIsResourceAcquiredSharedLite(&volDo->Vcb.Resource) );	

	if (Status != STATUS_SUCCESS) {

		DebugTrace( -1, Dbg, ("NtfsUserFsRequest -> %08lx\n", Status) );
		return Status;
	}

	if (IrpSp->Parameters.FileSystemControl.InputBufferLength >= volDo->Secondary->Thread.SessionContext.SecondaryMaxDataSize ||
		IrpSp->Parameters.FileSystemControl.OutputBufferLength >= volDo->Secondary->Thread.SessionContext.PrimaryMaxDataSize) {

		ASSERT( FALSE );

		NtfsCompleteRequest( IrpContext, Irp, Status = STATUS_INVALID_DEVICE_REQUEST );
		return Status;
	}

	inputBuffer = IrpContext->InputBuffer;
	outputBuffer = IrpContext->outputBuffer;

	ASSERT( IrpSp->Parameters.FileSystemControl.InputBufferLength ? (inputBuffer != NULL) : (inputBuffer == NULL) );
	ASSERT( IrpSp->Parameters.FileSystemControl.OutputBufferLength ? (outputBuffer != NULL) : (outputBuffer == NULL) );

	ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

	if (!FlagOn(IrpContext->State, IRP_CONTEXT_STATE_WAIT)) {

		return NtfsPostRequest( IrpContext, Irp );
	}

	try {

		secondarySessionResourceAcquired 
			= SecondaryAcquireResourceExclusiveLite( IrpContext, 
													 &volDo->SessionResource, 
													 BooleanFlagOn(IrpContext->State, IRP_CONTEXT_STATE_WAIT) );

		if (FlagOn(volDo->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) {

			PrintIrp( Dbg2, "SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED", NULL, IrpContext->OriginatingIrp );
			NtfsRaiseStatus( IrpContext, STATUS_CANT_WAIT, NULL, NULL );	
		}

		ASSERT( IS_SECONDARY_FILEOBJECT(IrpSp->FileObject) );
		
		typeOfOpen = NtfsDecodeFileObject( IrpContext, IrpSp->FileObject, &vcb, &fcb, &scb, &ccb, TRUE );

		if (FlagOn(ccb->NdasNtfsFlags, ND_NTFS_CCB_FLAG_UNOPENED)) {

			ASSERT( FlagOn(ccb->NdasNtfsFlags, ND_NTFS_CCB_FLAG_CORRUPTED) );

			try_return( Status = STATUS_FILE_CORRUPT_ERROR );
		}
		
		fileSystemControl.FsControlCode			= IrpSp->Parameters.FileSystemControl.FsControlCode;
		fileSystemControl.InputBufferLength		= IrpSp->Parameters.FileSystemControl.InputBufferLength;
		fileSystemControl.OutputBufferLength	= IrpSp->Parameters.FileSystemControl.OutputBufferLength;

		if (inputBuffer == NULL)
			fileSystemControl.InputBufferLength = 0;
		if (outputBuffer == NULL)
			fileSystemControl.OutputBufferLength = 0;

		outputBufferLength	= fileSystemControl.OutputBufferLength;
		
		if (fileSystemControl.FsControlCode == FSCTL_MOVE_FILE) {			// 29
		
			inputBufferLength = 0;			
		
		} else if(fileSystemControl.FsControlCode == FSCTL_MARK_HANDLE) {		// 63
		
			inputBufferLength = 0;			
		
		} else {
		
			inputBufferLength  = fileSystemControl.InputBufferLength;
		}
		
		bufferLength = (inputBufferLength >= outputBufferLength) ? inputBufferLength : outputBufferLength;

		secondaryRequest = AllocateWinxpSecondaryRequest( volDo->Secondary, 
														  IRP_MJ_FILE_SYSTEM_CONTROL,
														  bufferLength );

		if (secondaryRequest == NULL) {

			Status = Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
			Irp->IoStatus.Information = 0;
			try_return( Status );
		}

		ndfsRequestHeader = &secondaryRequest->NdfsRequestHeader;
		INITIALIZE_NDFS_REQUEST_HEADER(	ndfsRequestHeader, 
										NDFS_COMMAND_EXECUTE, 
										volDo->Secondary, 
										IRP_MJ_FILE_SYSTEM_CONTROL, 
										inputBufferLength );

		ndfsWinxpRequestHeader = (PNDFS_WINXP_REQUEST_HEADER)(ndfsRequestHeader+1);
		ASSERT( ndfsWinxpRequestHeader == (PNDFS_WINXP_REQUEST_HEADER)secondaryRequest->NdfsRequestData );
		INITIALIZE_NDFS_WINXP_REQUEST_HEADER( ndfsWinxpRequestHeader, Irp, IrpSp, ccb->PrimaryFileHandle );

		ndfsWinxpRequestHeader->FileSystemControl.OutputBufferLength	= fileSystemControl.OutputBufferLength;
		ndfsWinxpRequestHeader->FileSystemControl.InputBufferLength		= fileSystemControl.InputBufferLength;
		ndfsWinxpRequestHeader->FileSystemControl.FsControlCode			= fileSystemControl.FsControlCode;

		if (fileSystemControl.FsControlCode == FSCTL_MOVE_FILE) {		// 29
				
			PMOVE_FILE_DATA	moveFileData = inputBuffer;	
			PFILE_OBJECT	moveFileObject;
			PCCB			moveCcb;

			Status = ObReferenceObjectByHandle( moveFileData->FileHandle,
												FILE_READ_DATA,
												0,
												KernelMode,
												&moveFileObject,
												NULL );

			if (Status != STATUS_SUCCESS) {

				ASSERT( FALSE );
				try_return( Status );
			}
	
			ObDereferenceObject( moveFileObject );

			moveCcb = moveFileObject->FsContext2;

			ndfsWinxpRequestHeader->FileSystemControl.FscMoveFileData.FileHandle	= moveCcb->PrimaryFileHandle;
			ndfsWinxpRequestHeader->FileSystemControl.FscMoveFileData.StartingVcn	= moveFileData->StartingVcn.QuadPart;
			ndfsWinxpRequestHeader->FileSystemControl.FscMoveFileData.StartingLcn	= moveFileData->StartingLcn.QuadPart;
			ndfsWinxpRequestHeader->FileSystemControl.FscMoveFileData.ClusterCount	= moveFileData->ClusterCount;
		
		} else if(fileSystemControl.FsControlCode == FSCTL_MARK_HANDLE) {	// 63
		
			PMARK_HANDLE_INFO	markHandleInfo = inputBuffer;	
			PFILE_OBJECT		volumeFileObject;
			PCCB				volumeCcb;

			Status = ObReferenceObjectByHandle( markHandleInfo->VolumeHandle,
												FILE_READ_DATA,
												0,
												KernelMode,
												&volumeFileObject,
												NULL );

			if (Status != STATUS_SUCCESS) {

				try_return( Status );
			}
	
			ObDereferenceObject( volumeFileObject );

			volumeCcb = volumeFileObject->FsContext2;

			ndfsWinxpRequestHeader->FileSystemControl.FscMarkHandleInfo.UsnSourceInfo	= markHandleInfo->UsnSourceInfo;
			ndfsWinxpRequestHeader->FileSystemControl.FscMarkHandleInfo.VolumeHandle	= volumeCcb->PrimaryFileHandle;
			ndfsWinxpRequestHeader->FileSystemControl.FscMarkHandleInfo.HandleInfo		= markHandleInfo->HandleInfo;
		
		} else {

			ndfsWinxpRequestData = (_U8 *)(ndfsWinxpRequestHeader+1);

			if(inputBufferLength)
				RtlCopyMemory( ndfsWinxpRequestData, inputBuffer, inputBufferLength );
		}

		ASSERT( !ExIsResourceAcquiredSharedLite(&IrpContext->Vcb->Resource) );	

		secondaryRequest->RequestType = SECONDARY_REQ_SEND_MESSAGE;
		QueueingSecondaryRequest( volDo->Secondary, secondaryRequest );

		timeOut.QuadPart = -NDASNTFS_TIME_OUT;
		Status = KeWaitForSingleObject( &secondaryRequest->CompleteEvent, Executive, KernelMode, FALSE, &timeOut );

		if(Status != STATUS_SUCCESS) {

			secondaryRequest = NULL;
			try_return( Status = STATUS_IO_DEVICE_ERROR );
		}

		KeClearEvent( &secondaryRequest->CompleteEvent );

		if (secondaryRequest->ExecuteStatus != STATUS_SUCCESS) {

			if (IrpContext->OriginatingIrp)
				PrintIrp( Dbg2, "secondaryRequest->ExecuteStatus != STATUS_SUCCESS", NULL, IrpContext->OriginatingIrp );

			DebugTrace( 0, Dbg2, ("secondaryRequest->ExecuteStatus != STATUS_SUCCESS file = %s, line = %d\n", __FILE__, __LINE__) );

			NtfsRaiseStatus( IrpContext, STATUS_CANT_WAIT, NULL, NULL );
		}

		ndfsWinxpReplytHeader = (PNDFS_WINXP_REPLY_HEADER)secondaryRequest->NdfsReplyData;
		Status = Irp->IoStatus.Status = ndfsWinxpReplytHeader->Status;
		Irp->IoStatus.Information = ndfsWinxpReplytHeader->Information;

		if (FsControlCode == FSCTL_GET_NTFS_VOLUME_DATA && Status != STATUS_SUCCESS)
			DebugTrace( 0, Dbg2, ("FSCTL_GET_NTFS_VOLUME_DATA: Status = %x, Irp->IoStatus.Information = %d\n", Status, Irp->IoStatus.Information) );

		if (secondaryRequest->NdfsReplyHeader.MessageSize - sizeof(NDFS_REPLY_HEADER) - sizeof(NDFS_WINXP_REPLY_HEADER)) {

			ASSERT( Irp->IoStatus.Status == STATUS_SUCCESS || Irp->IoStatus.Status == STATUS_BUFFER_OVERFLOW );
			ASSERT( Irp->IoStatus.Information );
			ASSERT( Irp->IoStatus.Information <= outputBufferLength );
			ASSERT( outputBuffer );

			RtlCopyMemory( outputBuffer,
						   (_U8 *)(ndfsWinxpReplytHeader+1),
						   Irp->IoStatus.Information );
		}

		if (fileSystemControl.FsControlCode == FSCTL_MOVE_FILE && Status != STATUS_SUCCESS)
			DebugTrace( 0, Dbg2, ("NtfsDefragFile: status = %x\n", Status) );

		if (Status == STATUS_SUCCESS && fileSystemControl.FsControlCode == FSCTL_MOVE_FILE) {		// 29
				
			PMOVE_FILE_DATA	moveFileData = inputBuffer;	
			PFILE_OBJECT	moveFileObject;

			TYPE_OF_OPEN	typeOfOpen;
			PVCB			vcb;
			PFCB			moveFcb;
			PSCB			moveScb;
			PCCB			moveCcb;


			Status = ObReferenceObjectByHandle( moveFileData->FileHandle,
												FILE_READ_DATA,
												0,
												KernelMode,
												&moveFileObject,
												NULL );

			if(Status != STATUS_SUCCESS) {

				try_return( Status );
			}
	
			ObDereferenceObject( moveFileObject );
				
			typeOfOpen = NtfsDecodeFileObject( IrpContext, moveFileObject, &vcb, &moveFcb, &moveScb, &moveCcb, TRUE );
		
			if (typeOfOpen == UserFileOpen && ndfsWinxpReplytHeader->FileInformationSet && ndfsWinxpReplytHeader->AllocationSize) {

				PNDFS_NTFS_MCB_ENTRY	mcbEntry;
				ULONG			index;
				VCN				testVcn;

			
				SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ACQUIRE_PAGING );
				NtfsAcquireFcbWithPaging( IrpContext, moveFcb, 0 );
				NtfsAcquireNtfsMcbMutex( &moveScb->Mcb );

				mcbEntry = (PNDFS_NTFS_MCB_ENTRY)( ndfsWinxpReplytHeader+1 );

				if (moveScb->Header.AllocationSize.QuadPart) {

					NtfsRemoveNtfsMcbEntry( &moveScb->Mcb, 0, 0xFFFFFFFF );
				}

				for (index=0, testVcn=0; index < ndfsWinxpReplytHeader->NumberOfMcbEntry; index++) {

					ASSERT( mcbEntry[index].Vcn == testVcn );
					testVcn += (LONGLONG)mcbEntry[index].ClusterCount;

					NtfsAddNtfsMcbEntry( &moveScb->Mcb, 
										 mcbEntry[index].Vcn, 
										 mcbEntry[index].Lcn, 
										 (LONGLONG)mcbEntry[index].ClusterCount, 
										 TRUE );
				}
					
				ASSERT( LlBytesFromClusters(vcb, testVcn) == ndfsWinxpReplytHeader->AllocationSize );

				if (moveScb->Header.AllocationSize.QuadPart != ndfsWinxpReplytHeader->AllocationSize)
					SetFlag( moveScb->ScbState, SCB_STATE_TRUNCATE_ON_CLOSE );		

				moveScb->Header.FileSize.QuadPart = ndfsWinxpReplytHeader->FileSize;
				moveScb->Header.AllocationSize.QuadPart = ndfsWinxpReplytHeader->AllocationSize;
				ASSERT( moveScb->Header.AllocationSize.QuadPart >= moveScb->Header.FileSize.QuadPart );

				if (moveFileObject->SectionObjectPointer->DataSectionObject != NULL && moveFileObject->PrivateCacheMap == NULL) {

					CcInitializeCacheMap( moveFileObject,
										  (PCC_FILE_SIZES)&moveScb->Header.AllocationSize,
										  FALSE,
										  &NtfsData.CacheManagerCallbacks,
										  moveScb );
				}

				if (CcIsFileCached(moveFileObject)) {

					NtfsSetBothCacheSizes( moveFileObject,
										   (PCC_FILE_SIZES)&scb->Header.AllocationSize,
										   moveScb );
				}

				NtfsReleaseNtfsMcbMutex( &moveScb->Mcb );
				NtfsReleaseFcb( IrpContext, moveFcb );
			}
		}

try_exit:  NOTHING;

	} finally {

		if (secondarySessionResourceAcquired == TRUE) {

			SecondaryReleaseResourceLite( IrpContext, &volDo->SessionResource );		
		}

		if (secondaryRequest)
			DereferenceSecondaryRequest( secondaryRequest );
	}

	NtfsCompleteRequest( IrpContext, Irp, Status );
	return Status;
}
Beispiel #3
0
NTSTATUS
NtfsCommonSetVolumeInfo (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common routine for set Volume Information called by both the
    fsd and fsp threads.

Arguments:

    Irp - Supplies the Irp to process

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status;
    PIO_STACK_LOCATION IrpSp;
    PFILE_OBJECT FileObject;

    TYPE_OF_OPEN TypeOfOpen;
    PVCB Vcb;
    PFCB Fcb;
    PSCB Scb;
    PCCB Ccb;

    ULONG Length;
    FS_INFORMATION_CLASS FsInformationClass;
    PVOID Buffer;

    ASSERT_IRP_CONTEXT( IrpContext );
    ASSERT_IRP( Irp );
    ASSERT( FlagOn( IrpContext->TopLevelIrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL ));

    PAGED_CODE();

    //
    //  Get the current Irp stack location
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    DebugTrace( +1, Dbg, ("NtfsCommonSetVolumeInfo\n") );
    DebugTrace( 0, Dbg, ("IrpContext         = %08lx\n", IrpContext) );
    DebugTrace( 0, Dbg, ("Irp                = %08lx\n", Irp) );
    DebugTrace( 0, Dbg, ("Length             = %08lx\n", IrpSp->Parameters.SetVolume.Length) );
    DebugTrace( 0, Dbg, ("FsInformationClass = %08lx\n", IrpSp->Parameters.SetVolume.FsInformationClass) );
    DebugTrace( 0, Dbg, ("Buffer             = %08lx\n", Irp->AssociatedIrp.SystemBuffer) );

    //
    //  Reference our input parameters to make things easier
    //

    Length = IrpSp->Parameters.SetVolume.Length;
    FsInformationClass = IrpSp->Parameters.SetVolume.FsInformationClass;
    Buffer = Irp->AssociatedIrp.SystemBuffer;

    //
    //  Extract and decode the file object to get the Vcb, we don't really
    //  care what the type of open is.
    //

    FileObject = IrpSp->FileObject;
    TypeOfOpen = NtfsDecodeFileObject( IrpContext, FileObject, &Vcb, &Fcb, &Scb, &Ccb, TRUE );

    if (TypeOfOpen != UserVolumeOpen &&
        (TypeOfOpen != UserViewIndexOpen ||
         FsInformationClass != FileFsControlInformation ||
         Fcb != Vcb->QuotaTableScb->Fcb)) {

        NtfsCompleteRequest( IrpContext, Irp, STATUS_ACCESS_DENIED );

        DebugTrace( -1, Dbg2, ("NtfsCommonSetVolumeInfo -> STATUS_ACCESS_DENIED\n") );

        return STATUS_ACCESS_DENIED;
    }

    //
    //  The volume must be writable.
    //

    if (NtfsIsVolumeReadOnly( Vcb )) {

        Status = STATUS_MEDIA_WRITE_PROTECTED;
        NtfsCompleteRequest( IrpContext, Irp, Status );

        DebugTrace( -1, Dbg, ("NtfsCommonSetVolumeInfo -> %08lx\n", Status) );
        return Status;
    }

#ifdef __ND_NTFS_SECONDARY__

	if (!FlagOn( IrpContext->State, IRP_CONTEXT_STATE_WAIT )) {

		return NtfsPostRequest( IrpContext, Irp );
	}

#endif

    //
    //  Acquire exclusive access to the Vcb
    //

    NtfsAcquireExclusiveVcb( IrpContext, Vcb, TRUE );

    try {

		//
        //  Proceed only if the volume is mounted.
        //

        if (FlagOn( Vcb->VcbState, VCB_STATE_VOLUME_MOUNTED )) {

#ifdef __ND_NTFS_SECONDARY__

			if(IoGetCurrentIrpStackLocation(Irp)->FileObject == NULL) {

				DebugTrace( 0, DEBUG_TRACE_ALL, ("IrpSp->FileObject is NULL, IrpSp->MajorFunction = %x, IrpSp->MinorFunction = %x\n", IrpSp->MajorFunction, IrpSp->MinorFunction) );
			}
			if (IS_SECONDARY_FILEOBJECT(IoGetCurrentIrpStackLocation(Irp)->FileObject)) {

				Status = NdNtfsSecondaryCommonSetVolumeInfo( IrpContext, Irp );
				leave;
			}
#endif

			//
            //  Based on the information class we'll do different actions.  Each
            //  of the procedures that we're calling performs the action if
            //  possible and returns true if it successful and false if it couldn't
            //  wait for any I/O to complete.
            //

            switch (FsInformationClass) {

            case FileFsLabelInformation:

                Status = NtfsSetFsLabelInfo( IrpContext, Vcb, Buffer );
                break;

            case FileFsControlInformation:

                Status = NtfsSetFsControlInfo( IrpContext, Vcb, Buffer );
                break;

            case FileFsObjectIdInformation:

                Status = NtfsSetFsVolumeObjectIdInfo( IrpContext, Vcb, Buffer );
				DebugTrace( 0, Dbg2, ("NtfsCommonSetVolumeInfo %x, FileFsObjectIdInformation Vcb = %p\n", Status, IrpContext->Vcb) );
                break;

            default:

                Status = STATUS_INVALID_PARAMETER;
                break;
            }

        } else {

            Status = STATUS_FILE_INVALID;
        }

        //
        //  Abort transaction on error by raising.
        //

        NtfsCleanupTransaction( IrpContext, Status, FALSE );

    } finally {

        DebugUnwind( NtfsCommonSetVolumeInfo );

        NtfsReleaseVcb( IrpContext, Vcb );

        DebugTrace( -1, Dbg, ("NtfsCommonSetVolumeInfo -> %08lx\n", Status) );
    }

    NtfsCompleteRequest( IrpContext, Irp, Status );
    return Status;
}
NTSTATUS
SecondaryRecoverySession (
	IN  PSECONDARY		Secondary
	)
{
	NTSTATUS			status;
	LONG				slotIndex;

	LARGE_INTEGER		timeOut;
	OBJECT_ATTRIBUTES	objectAttributes;

	ULONG				reconnectionTry;
    PLIST_ENTRY			ccblistEntry;
	BOOLEAN				isLocalAddress;


	SetFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );

	ASSERT( FlagOn(Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ); 
	ASSERT( Secondary->ThreadHandle );

	ASSERT( IsListEmpty(&Secondary->RequestQueue) );

	for (slotIndex=0; slotIndex < Secondary->Thread.SessionContext.SessionSlotCount; slotIndex++) {

		ASSERT( Secondary->Thread.SessionSlot[slotIndex] == NULL );
	}	

	if (Secondary->ThreadHandle) {

		ASSERT( Secondary->ThreadObject );
		
		timeOut.QuadPart = -NDASNTFS_TIME_OUT;
		status = KeWaitForSingleObject( Secondary->ThreadObject,
										Executive,
										KernelMode,
										FALSE,
										&timeOut );

		if(status != STATUS_SUCCESS) {

			ASSERT( NDASNTFS_BUG );
			return status;
		}

		DebugTrace( 0, Dbg2, ("Secondary_Stop: thread stoped\n") );

		ObDereferenceObject( Secondary->ThreadObject );

		Secondary->ThreadHandle = 0;
		Secondary->ThreadObject = 0;

		RtlZeroMemory( &Secondary->Thread.Flags, sizeof(SECONDARY) - FIELD_OFFSET(SECONDARY, Thread.Flags) );
	}

	for (status = STATUS_UNSUCCESSFUL, reconnectionTry = 0; reconnectionTry < MAX_RECONNECTION_TRY; reconnectionTry++) {

		if (FlagOn(Secondary->VolDo->Vcb.VcbState, VCB_STATE_TARGET_DEVICE_STOPPED)) {

			ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );
			return STATUS_UNSUCCESSFUL;
		}

		if (FlagOn(Secondary->VolDo->Vcb.VcbState, VCB_STATE_FLAG_SHUTDOWN)) {

			ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );
			return STATUS_UNSUCCESSFUL;
		}

		if (FlagOn(Secondary->VolDo->NdasNtfsFlags, NDAS_NTFS_DEVICE_FLAG_SHUTDOWN)) {

			//DebugTrace( 0, Dbg2, ("SecondaryToPrimary NDAS_NTFS_DEVICE_FLAG_SHUTDOWN\n") ); 
			//DbgPrint( "SecondaryToPrimary NDAS_NTFS_DEVICE_FLAG_SHUTDOWN\n" ); 

			ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );
			return STATUS_UNSUCCESSFUL;
		}

		if (Secondary->VolDo->NetdiskEnableMode == NETDISK_SECONDARY2PRIMARY) {

			status = STATUS_SUCCESS;

		} else {

			status = ((PVOLUME_DEVICE_OBJECT) NdasNtfsFileSystemDeviceObject)->
						NdfsCallback.SecondaryToPrimary( Secondary->VolDo->Vcb.Vpb->RealDevice, TRUE );

			if (status == STATUS_NO_SUCH_DEVICE) {

				NDAS_ASSERT( FlagOn(Secondary->VolDo->Vcb.VcbState, VCB_STATE_TARGET_DEVICE_STOPPED) );
				ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );

				return STATUS_UNSUCCESSFUL;
			}
		}


		//NtfsDebugTraceLevel = 0;

		DebugTrace( 0, Dbg2, ("SecondaryToPrimary status = %x\n", status) ); 

		if (status == STATUS_SUCCESS) {

			PVCB				vcb = &Secondary->VolDo->Vcb;
			TOP_LEVEL_CONTEXT	topLevelContext;
			PTOP_LEVEL_CONTEXT	threadTopLevelContext;
			PIRP_CONTEXT		tempIrpContext = NULL;

			SetFlag( Secondary->Flags, SECONDARY_FLAG_CLEANUP_VOLUME );

			ASSERT( !ExIsResourceAcquiredExclusiveLite(&NtfsData.Resource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&NtfsData.Resource) );	

			ASSERT( !ExIsResourceAcquiredExclusiveLite(&vcb->Resource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&vcb->Resource) );	


			DebugTrace( 0, Dbg2, ("Vcb->State = %X\n", vcb->VcbState) );
			DebugTrace( 0, Dbg2, ("Vcb->Vpb->ReferenceCount = %X\n", vcb->Vpb->ReferenceCount) );
			DebugTrace( 0, Dbg2, ("Vcb->TargetDeviceObject->ReferenceCount = %X\n", vcb->TargetDeviceObject->ReferenceCount) );

			tempIrpContext = NULL;

			threadTopLevelContext = NtfsInitializeTopLevelIrp( &topLevelContext, TRUE, FALSE );
			ASSERT( threadTopLevelContext == &topLevelContext );

			NtfsInitializeIrpContext( NULL, TRUE, &tempIrpContext );
            NtfsUpdateIrpContextWithTopLevel( tempIrpContext, threadTopLevelContext );

			SetFlag( tempIrpContext->NdasNtfsFlags, NDAS_NTFS_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT );
			ASSERT( FlagOn(tempIrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL) );
						
			tempIrpContext->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
			tempIrpContext->MinorFunction = IRP_MN_MOUNT_VOLUME;
			tempIrpContext->Vcb			  = vcb;

			try {
			
				status = CleanUpVcb( tempIrpContext, vcb );
			
			} finally {
                
				NtfsCompleteRequest( tempIrpContext, NULL, 0 );
				ASSERT( IoGetTopLevelIrp() != (PIRP) &topLevelContext );
				tempIrpContext = NULL;
			}

			ASSERT( status == STATUS_SUCCESS );
			ASSERT( FlagOn(vcb->VcbState, VCB_STATE_MOUNT_COMPLETED) );

			ASSERT( !ExIsResourceAcquiredExclusiveLite(&NtfsData.Resource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&NtfsData.Resource) );	

			ASSERT( !ExIsResourceAcquiredExclusiveLite(&vcb->Resource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&vcb->Resource) );	

			ClearFlag( Secondary->Flags, SECONDARY_FLAG_CLEANUP_VOLUME );


			DebugTrace( 0, Dbg2, ("Vcb->TargetDeviceObject->ReferenceCount = %X\n", vcb->TargetDeviceObject->ReferenceCount) );
			DebugTrace( 0, Dbg2, ("Vcb->Vpb->ReferenceCount = %X\n", vcb->Vpb->ReferenceCount) );
			DebugTrace( 0, Dbg2, ("Vcb->CloseCount = %d\n", vcb->CloseCount) );

			Secondary->VolDo->NetdiskEnableMode = NETDISK_SECONDARY2PRIMARY; 

			tempIrpContext = NULL;

			threadTopLevelContext = NtfsInitializeTopLevelIrp( &topLevelContext, TRUE, FALSE );
			ASSERT( threadTopLevelContext == &topLevelContext );

			NtfsInitializeIrpContext( NULL, TRUE, &tempIrpContext );
            NtfsUpdateIrpContextWithTopLevel( tempIrpContext, threadTopLevelContext );

			ASSERT( FlagOn(tempIrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL) );
			
			//tempIrpContext->TopLevelIrpContext->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
			//tempIrpContext->TopLevelIrpContext->MinorFunction = IRP_MN_MOUNT_VOLUME;
			
			tempIrpContext->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
			tempIrpContext->MinorFunction = IRP_MN_MOUNT_VOLUME;
			tempIrpContext->Vcb			  = vcb;

			try {
			
				status = NdasNtfsMountVolume( tempIrpContext, vcb );
			
			} finally {
                
				NtfsCompleteRequest( tempIrpContext, NULL, 0 );
				ASSERT( IoGetTopLevelIrp() != (PIRP) &topLevelContext );
				tempIrpContext = NULL;
			}

			NDAS_ASSERT( status == STATUS_SUCCESS );

			ASSERT( !ExIsResourceAcquiredExclusiveLite(&NtfsData.Resource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&NtfsData.Resource) );	

			ASSERT( !ExIsResourceAcquiredExclusiveLite(&vcb->Resource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&vcb->Resource) );	

			DebugTrace( 0, Dbg2, ("Vcb->TargetDeviceObject->ReferenceCount = %X\n", vcb->TargetDeviceObject->ReferenceCount) );
			DebugTrace( 0, Dbg2, ("Vcb->Vpb->ReferenceCount = %X\n", vcb->Vpb->ReferenceCount) );
			DebugTrace( 0, Dbg2, ("Vcb->CloseCount = %d\n", vcb->CloseCount) );

			if (vcb->MftScb) {
			
				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->MftScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->MftScb->Header.Resource) );	
			}

			if (vcb->Mft2Scb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->Mft2Scb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->Mft2Scb->Header.Resource) );	
			}

			if (vcb->LogFileScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->LogFileScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->LogFileScb->Header.Resource) );			
			}

			if (vcb->VolumeDasdScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->VolumeDasdScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->VolumeDasdScb->Header.Resource) );			
			}

			if (vcb->AttributeDefTableScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->AttributeDefTableScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->AttributeDefTableScb->Header.Resource) );			
			}

			if (vcb->UpcaseTableScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->UpcaseTableScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->UpcaseTableScb->Header.Resource) );			
			}

			if (vcb->RootIndexScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->RootIndexScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->RootIndexScb->Header.Resource) );			
			}

			if (vcb->BitmapScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->BitmapScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->BitmapScb->Header.Resource) );			
			}

			if (vcb->BadClusterFileScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->BadClusterFileScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->BadClusterFileScb->Header.Resource) );		
			}

			if (vcb->MftBitmapScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->MftBitmapScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->MftBitmapScb->Header.Resource) );			
			}

			if (vcb->SecurityDescriptorStream) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->SecurityDescriptorStream->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->SecurityDescriptorStream->Header.Resource) );			
			}

			if (vcb->UsnJournal) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->UsnJournal->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->UsnJournal->Header.Resource) );			
			}

			if (vcb->ExtendDirectory) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->ExtendDirectory->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->ExtendDirectory->Header.Resource) );			
			}

			if (vcb->SecurityDescriptorHashIndex) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->SecurityDescriptorHashIndex->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->SecurityDescriptorHashIndex->Header.Resource) );			
			}

			if (vcb->SecurityIdIndex) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->SecurityIdIndex->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->SecurityIdIndex->Header.Resource) );			
			}
		}

		Secondary->NumberOfPrimaryAddress = 0;

		status = ((PVOLUME_DEVICE_OBJECT) NdasNtfsFileSystemDeviceObject)->
						NdfsCallback.QueryPrimaryAddress( &Secondary->VolDo->NetdiskPartitionInformation, 
														  Secondary->PrimaryAddressList, 
														  &Secondary->NumberOfPrimaryAddress, 
														  &isLocalAddress );

		DebugTrace2( 0, Dbg2, ("RecoverySession: QueryPrimaryAddress status = %X\n", status) );

		if (status == STATUS_SUCCESS && !(Secondary->VolDo->NetdiskEnableMode == NETDISK_SECONDARY && isLocalAddress)) {

			LONG i;

			NDAS_ASSERT( Secondary->NumberOfPrimaryAddress );

			for (i = 0; i < Secondary->NumberOfPrimaryAddress; i++) {

				DebugTrace2( 0, Dbg, 
							   ("RecoverySession: Secondary = %p Found PrimaryAddress[%d] :%02x:%02x:%02x:%02x:%02x:%02x/%d\n",
							    Secondary, i,
								Secondary->PrimaryAddressList[i].Node[0], Secondary->PrimaryAddressList[i].Node[1],
								Secondary->PrimaryAddressList[i].Node[2], Secondary->PrimaryAddressList[i].Node[3],
								Secondary->PrimaryAddressList[i].Node[4], Secondary->PrimaryAddressList[i].Node[5],
								NTOHS(Secondary->PrimaryAddressList[i].Port)) );
			}
		
		} else {

			continue;
		}	

		KeInitializeEvent( &Secondary->ReadyEvent, NotificationEvent, FALSE );
		KeInitializeEvent( &Secondary->RequestEvent, NotificationEvent, FALSE );

		InitializeObjectAttributes(&objectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);

		status = PsCreateSystemThread( &Secondary->ThreadHandle,
									   THREAD_ALL_ACCESS,
									   &objectAttributes,
									   NULL,
									   NULL,
									   SecondaryThreadProc,
									   Secondary );

		if (!NT_SUCCESS(status)) {

			ASSERT( NDASNTFS_UNEXPECTED );
			break;
		}

		status = ObReferenceObjectByHandle( Secondary->ThreadHandle,
											FILE_READ_DATA,
											NULL,
											KernelMode,
											&Secondary->ThreadObject,
											NULL );

		if (!NT_SUCCESS(status)) {

			ASSERT( NDASNTFS_INSUFFICIENT_RESOURCES );
			break;
		}

		timeOut.QuadPart = -NDASNTFS_TIME_OUT;
		status = KeWaitForSingleObject( &Secondary->ReadyEvent,
										Executive,
										KernelMode,
										FALSE,
										&timeOut );

		if(status != STATUS_SUCCESS) {

			ASSERT( NDASNTFS_BUG );
			break;
		}

		KeClearEvent( &Secondary->ReadyEvent );

		InterlockedIncrement( &Secondary->SessionId );	

		ExAcquireFastMutex( &Secondary->FastMutex );

		if (!FlagOn(Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_START) || FlagOn(Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_STOPED)) {

			ExReleaseFastMutex( &Secondary->FastMutex );

			if(Secondary->Thread.SessionStatus == STATUS_DISK_CORRUPT_ERROR) {

				status = STATUS_SUCCESS;
				break;
			}

			timeOut.QuadPart = -NDASNTFS_TIME_OUT;
			status = KeWaitForSingleObject( Secondary->ThreadObject,
											Executive,
											KernelMode,
											FALSE,
											&timeOut );

			if(status != STATUS_SUCCESS) {

				ASSERT( NDASNTFS_BUG );
				return status;
			}

			DebugTrace( 0, Dbg, ("Secondary_Stop: thread stoped\n") );

			ObDereferenceObject( Secondary->ThreadObject );

			Secondary->ThreadHandle = 0;
			Secondary->ThreadObject = 0;

			RtlZeroMemory( &Secondary->Thread.Flags, sizeof(SECONDARY) - FIELD_OFFSET(SECONDARY, Thread.Flags) );

			continue;
		} 

		ExReleaseFastMutex( &Secondary->FastMutex );

		status = STATUS_SUCCESS;

		DebugTrace( 0, Dbg2, ("SessionRecovery Success Secondary = %p\n", Secondary) );

		break;
	}
Beispiel #5
0
NTSTATUS
NtfsCommonLockControl (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common routine for Lock Control called by both the fsd and fsp
    threads.

Arguments:

    Irp - Supplies the Irp to process

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status;
    PIO_STACK_LOCATION IrpSp;
    PFILE_OBJECT FileObject;

    TYPE_OF_OPEN TypeOfOpen;
    PVCB Vcb;
    PFCB Fcb;
    PSCB Scb;
    PCCB Ccb;
    BOOLEAN FcbAcquired = FALSE;

    BOOLEAN OplockPostIrp;

    ASSERT_IRP_CONTEXT( IrpContext );
    ASSERT_IRP( Irp );

    PAGED_CODE();

    //
    //  Get a pointer to the current Irp stack location
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    DebugTrace( +1, Dbg, ("NtfsCommonLockControl\n") );
    DebugTrace( 0, Dbg, ("IrpContext    = %08lx\n", IrpContext) );
    DebugTrace( 0, Dbg, ("Irp           = %08lx\n", Irp) );
    DebugTrace( 0, Dbg, ("MinorFunction = %08lx\n", IrpSp->MinorFunction) );

    //
    //  Extract and decode the type of file object we're being asked to process
    //

    FileObject = IrpSp->FileObject;
    TypeOfOpen = NtfsDecodeFileObject( IrpContext, FileObject, &Vcb, &Fcb, &Scb, &Ccb, TRUE );

    //
    //  If the file is not a user file open then we reject the request
    //  as an invalid parameter
    //

    if (TypeOfOpen != UserFileOpen) {

        NtfsCompleteRequest( &IrpContext, &Irp, STATUS_INVALID_PARAMETER );

        DebugTrace( -1, Dbg, ("NtfsCommonLockControl -> STATUS_INVALID_PARAMETER\n") );
        return STATUS_INVALID_PARAMETER;
    }

    //
    //  Acquire exclusive access to the Fcb
    //

    if (Scb->ScbType.Data.FileLock == NULL) {

        NtfsAcquireExclusiveFcb( IrpContext, Fcb, Scb, FALSE, FALSE );
        FcbAcquired = TRUE;

    } else {

        //NtfsAcquireSharedFcb( IrpContext, Fcb, Scb );
    }

    OplockPostIrp = FALSE;

    try {

        //
        //  We check whether we can proceed based on the state of the file oplocks.
        //  This call might post the irp for us.
        //

        Status = FsRtlCheckOplock( &Scb->ScbType.Data.Oplock,
                                   Irp,
                                   IrpContext,
                                   NtfsOplockComplete,
                                   NULL );

        if (Status != STATUS_SUCCESS) {

            OplockPostIrp = TRUE;
            try_return( NOTHING );
        }

        //
        //  If we don't have a file lock, then get one now.
        //

        if (Scb->ScbType.Data.FileLock == NULL) {

            NtfsCreateFileLock( Scb, TRUE );
        }

        //
        //  Now call the FsRtl routine to do the actual processing of the
        //  Lock request
        //

        Status = FsRtlProcessFileLock( Scb->ScbType.Data.FileLock, Irp, NULL );

        //
        //  Set the flag indicating if Fast I/O is possible
        //

        NtfsAcquireFsrtlHeader( Scb );
        Scb->Header.IsFastIoPossible = NtfsIsFastIoPossible( Scb );
        NtfsReleaseFsrtlHeader( Scb );

    try_exit: NOTHING;
    } finally {

        DebugUnwind( NtfsCommonLockControl );

        //
        //  Release the Fcb, and return to our caller
        //

        if (FcbAcquired) {
            NtfsReleaseFcb( IrpContext, Fcb );
        }

        //
        //  Only if this is not an abnormal termination and we did not post the irp
        //  do we delete the irp context
        //

        if (!AbnormalTermination() && !OplockPostIrp) {

            NtfsCompleteRequest( &IrpContext, NULL, 0 );
        }

        DebugTrace( -1, Dbg, ("NtfsCommonLockControl -> %08lx\n", Status) );
    }

    return Status;
}
Beispiel #6
0
NTSTATUS
NtfsCommonQueryVolumeInfo (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common routine for query Volume Information called by both the
    fsd and fsp threads.

Arguments:

    Irp - Supplies the Irp to process

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status;
    PIO_STACK_LOCATION IrpSp;
    PFILE_OBJECT FileObject;

    TYPE_OF_OPEN TypeOfOpen;
    PVCB Vcb;
    PFCB Fcb;
    PSCB Scb;
    PCCB Ccb;

    ULONG Length;
    FS_INFORMATION_CLASS FsInformationClass;
    PVOID Buffer;
    BOOLEAN AcquiredVcb = FALSE;

    ASSERT_IRP_CONTEXT( IrpContext );
    ASSERT_IRP( Irp );
    ASSERT( FlagOn( IrpContext->TopLevelIrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL ));

    PAGED_CODE();

    //
    //  Get the current stack location
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    DebugTrace( +1, Dbg, ("NtfsCommonQueryVolumeInfo...\n") );
    DebugTrace( 0, Dbg, ("IrpContext         = %08lx\n", IrpContext) );
    DebugTrace( 0, Dbg, ("Irp                = %08lx\n", Irp) );
    DebugTrace( 0, Dbg, ("Length             = %08lx\n", IrpSp->Parameters.QueryVolume.Length) );
    DebugTrace( 0, Dbg, ("FsInformationClass = %08lx\n", IrpSp->Parameters.QueryVolume.FsInformationClass) );
    DebugTrace( 0, Dbg, ("Buffer             = %08lx\n", Irp->AssociatedIrp.SystemBuffer) );

    //
    //  Reference our input parameters to make things easier
    //

    Length = IrpSp->Parameters.QueryVolume.Length;
    FsInformationClass = IrpSp->Parameters.QueryVolume.FsInformationClass;
    Buffer = Irp->AssociatedIrp.SystemBuffer;

    //
    //  Extract and decode the file object to get the Vcb, we don't really
    //  care what the type of open is.
    //

    FileObject = IrpSp->FileObject;
    TypeOfOpen = NtfsDecodeFileObject( IrpContext, FileObject, &Vcb, &Fcb, &Scb, &Ccb, TRUE );

    //
    //  Let's kill invalid vol. query requests.
    //

    if (UnopenedFileObject == TypeOfOpen) {

        DebugTrace( 0, Dbg2, ("Invalid file object for write\n") );
        DebugTrace( -1, Dbg2, ("NtfsCommonQueryVolume:  Exit -> %08lx\n", STATUS_INVALID_DEVICE_REQUEST) );

        NtfsCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
        return STATUS_INVALID_DEVICE_REQUEST;
    }

#ifdef __ND_NTFS_SECONDARY__

	if (!FlagOn( IrpContext->State, IRP_CONTEXT_STATE_WAIT )) {

		return NtfsPostRequest( IrpContext, Irp );
	}

#endif

    //
    //  Get the Vcb shared and raise if we can't wait for the resource.
    //  We're only using $Volume Scb for the query size calls because the info
    //  it gets is static and we only need to protect against dismount
    //  Doing this prevents a deadlock with commit extensions from mm which use
    //  this call. However for system files like the mft we always need the vcb to avoid deadlock
    //
                         
    if ((FsInformationClass != FileFsSizeInformation) || 
        (FlagOn( Scb->Fcb->FcbState, FCB_STATE_SYSTEM_FILE ))) {
        
        NtfsAcquireSharedVcb( IrpContext, Vcb, TRUE );
        AcquiredVcb = TRUE;
    } else {
        
        NtfsAcquireSharedScb( IrpContext, Scb );
    }

    try {

        //
        //  Make sure the volume is mounted.
        //

        if ((AcquiredVcb && !FlagOn( Vcb->VcbState, VCB_STATE_VOLUME_MOUNTED )) ||
            (!AcquiredVcb && FlagOn( Scb->ScbState, SCB_STATE_VOLUME_DISMOUNTED))) {
            
            Irp->IoStatus.Information = 0;
            Status = STATUS_VOLUME_DISMOUNTED;
            leave;
        }

#ifdef __ND_NTFS_SECONDARY__

		if(IoGetCurrentIrpStackLocation(Irp)->FileObject == NULL) {

			DebugTrace( 0, DEBUG_TRACE_ALL, ("IrpSp->FileObject is NULL, IrpSp->MajorFunction = %x, IrpSp->MinorFunction = %x\n", IrpSp->MajorFunction, IrpSp->MinorFunction) );
		}

		if (IS_SECONDARY_FILEOBJECT(IoGetCurrentIrpStackLocation(Irp)->FileObject)) {

			Status = NdNtfsSecondaryCommonQueryVolumeInfo( IrpContext, Irp );
			leave;
		}
#endif
        //
        //  Based on the information class we'll do different actions.  Each
        //  of the procedures that we're calling fills up the output buffer
        //  if possible and returns true if it successfully filled the buffer
        //  and false if it couldn't wait for any I/O to complete.
        //

        switch (FsInformationClass) {

        case FileFsVolumeInformation:

            Status = NtfsQueryFsVolumeInfo( IrpContext, Vcb, Buffer, &Length );
            break;

        case FileFsSizeInformation:

            Status = NtfsQueryFsSizeInfo( IrpContext, Vcb, Buffer, &Length );
            break;

        case FileFsDeviceInformation:

            Status = NtfsQueryFsDeviceInfo( IrpContext, Vcb, Buffer, &Length );
            break;

        case FileFsAttributeInformation:

            Status = NtfsQueryFsAttributeInfo( IrpContext, Vcb, Buffer, &Length );
            break;

        case FileFsControlInformation:

            Status = NtfsQueryFsControlInfo( IrpContext, Vcb, Buffer, &Length );
            break;

        case FileFsFullSizeInformation:
        
            Status = NtfsQueryFsFullSizeInfo( IrpContext, Vcb, Buffer, &Length );
            break;

        case FileFsObjectIdInformation:
        
            Status = NtfsQueryFsVolumeObjectIdInfo( IrpContext, Vcb, Buffer, &Length );
            break;

        default:

            Status = STATUS_INVALID_PARAMETER;
            break;
        }

        //
        //  Set the information field to the number of bytes actually filled in
        //

        Irp->IoStatus.Information = IrpSp->Parameters.QueryVolume.Length - Length;

        //
        //  Abort transaction on error by raising.
        //

        NtfsCleanupTransaction( IrpContext, Status, FALSE );

    } finally {

        DebugUnwind( NtfsCommonQueryVolumeInfo );

        if (AcquiredVcb) {
            NtfsReleaseVcb( IrpContext, Vcb );
        } else  {
            NtfsReleaseScb( IrpContext, Scb );
        }   

        DebugTrace( -1, Dbg, ("NtfsCommonQueryVolumeInfo -> %08lx\n", Status) );
    }

	if (Status != STATUS_SUCCESS && Status != STATUS_BUFFER_OVERFLOW)
		DebugTrace( 0, Dbg2, ("NtfsCommonQueryVolumeInfo %x, FsInformationClass = %d Vcb = %p\n", Status, FsInformationClass, IrpContext->Vcb) );

    NtfsCompleteRequest( IrpContext, Irp, Status );
    return Status;
}
Beispiel #7
0
VOID
NtfsFspDispatch (
    IN PVOID Context
    )

/*++

Routine Description:

    This is the main FSP thread routine that is executed to receive
    and dispatch IRP requests.  Each FSP thread begins its execution here.
    There is one thread created at system initialization time and subsequent
    threads created as needed.

Arguments:


    Context - Supplies the thread id.

Return Value:

    None - This routine never exits

--*/

{
    TOP_LEVEL_CONTEXT TopLevelContext;
    PTOP_LEVEL_CONTEXT ThreadTopLevelContext;
    OPLOCK_CLEANUP OplockCleanup; 

    PIRP Irp;
    PIRP_CONTEXT IrpContext;
    PIO_STACK_LOCATION IrpSp;
    ULONG LogFileFullCount = 0;

    PVOLUME_DEVICE_OBJECT VolDo;
    BOOLEAN Retry;
    NTSTATUS Status = STATUS_SUCCESS;
    IrpContext = (PIRP_CONTEXT)Context;

    Irp = IrpContext->OriginatingIrp;

    if (Irp != NULL) {

        IrpSp = IoGetCurrentIrpStackLocation( Irp );
    }

    //
    //  Now because we are the Fsp we will force the IrpContext to
    //  indicate true on Wait.
    //

    SetFlag( IrpContext->State, IRP_CONTEXT_STATE_WAIT );

    //
    //  If this request has an associated volume device object, remember it.
    //

    if ((Irp != NULL) &&
        (IrpSp->FileObject != NULL)) {

        VolDo = CONTAINING_RECORD( IrpSp->DeviceObject,
                                   VOLUME_DEVICE_OBJECT,
                                   DeviceObject );
    } else {

        VolDo = NULL;
    }

    //
    //  Now case on the function code.  For each major function code,
    //  either call the appropriate FSP routine or case on the minor
    //  function and then call the FSP routine.  The FSP routine that
    //  we call is responsible for completing the IRP, and not us.
    //  That way the routine can complete the IRP and then continue
    //  post processing as required.  For example, a read can be
    //  satisfied right away and then read can be done.
    //
    //  We'll do all of the work within an exception handler that
    //  will be invoked if ever some underlying operation gets into
    //  trouble (e.g., if NtfsReadSectorsSync has trouble).
    //

    while (TRUE) {

        FsRtlEnterFileSystem();

        ASSERT( IoGetTopLevelIrp() != (PIRP) &TopLevelContext );

        ThreadTopLevelContext = NtfsInitializeTopLevelIrp( &TopLevelContext, TRUE, TRUE );
        ASSERT( ThreadTopLevelContext == &TopLevelContext );

        NtfsPostRequests += 1;

        do {

            //
            //  If this is the initial try with this Irp Context, update the
            //  top level Irp fields.
            //
    
            NtfsUpdateIrpContextWithTopLevel( IrpContext, ThreadTopLevelContext );
    
            Retry = FALSE;
    
            try {

                //
                //  Always clear the exception code in the IrpContext so we respond
                //  correctly to errors encountered in the Fsp.
                //

                IrpContext->ExceptionStatus = 0;
                SetFlag( IrpContext->State, IRP_CONTEXT_STATE_IN_FSP );

                //
                //  See if we were posted due to a log file full condition, and
                //  if so, then do a clean volume checkpoint if we are the
                //  first ones to get there.  If we see a different Lsn and do
                //  not do the checkpoint, the worst that can happen is that we
                //  will get posted again if the log file is still full.
                //

                if (IrpContext->LastRestartArea.QuadPart != 0) {

                    NtfsCheckpointForLogFileFull( IrpContext );

                    if (++LogFileFullCount >= 2) {

                        SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_EXCESS_LOG_FULL );
                    }
                }

                //
                //  If we have an Irp then proceed with our normal processing.
                //

                if (Irp != NULL) {

                    switch ( IrpContext->MajorFunction ) {

                        //
                        //  For Create Operation,
                        //

                        case IRP_MJ_CREATE:

                            ClearFlag( IrpContext->State, IRP_CONTEXT_STATE_EFS_CREATE );
                            
                            if (FlagOn( IrpContext->State, IRP_CONTEXT_STATE_DASD_OPEN )) {

                                Status = NtfsCommonVolumeOpen( IrpContext, Irp );

                            } else {

                                RtlZeroMemory( &OplockCleanup, sizeof( OplockCleanup ) );
                                Status = NtfsCommonCreate( IrpContext, Irp, &OplockCleanup, NULL );
                            }
                            break;

                        //
                        //  For close operations
                        //

                        case IRP_MJ_CLOSE:

                            //
                            //  We should never post closes to this workqueue.
                            //

                            NtfsBugCheck( 0, 0, 0 );
                            break;

                        //
                        //  For read operations
                        //

                        case IRP_MJ_READ:

                            (VOID) NtfsCommonRead( IrpContext, Irp, TRUE );
                            break;

                        //
                        //  For write operations,
                        //

                        case IRP_MJ_WRITE:

                            (VOID) NtfsCommonWrite( IrpContext, Irp );
                            break;

                        //
                        //  For Query Information operations,
                        //

                        case IRP_MJ_QUERY_INFORMATION:

                            (VOID) NtfsCommonQueryInformation( IrpContext, Irp );
                            break;

                        //
                        //  For Set Information operations,
                        //

                        case IRP_MJ_SET_INFORMATION:

                            (VOID) NtfsCommonSetInformation( IrpContext, Irp );
                            break;

                        //
                        //  For Query EA operations,
                        //

                        case IRP_MJ_QUERY_EA:

                            (VOID) NtfsCommonQueryEa( IrpContext, Irp );
                            break;

                        //
                        //  For Set EA operations,
                        //

                        case IRP_MJ_SET_EA:

                            (VOID) NtfsCommonSetEa( IrpContext, Irp );
                            break;


                        //
                        //  For Flush buffers operations,
                        //

                        case IRP_MJ_FLUSH_BUFFERS:

                            (VOID) NtfsCommonFlushBuffers( IrpContext, Irp );
                            break;

                        //
                        //  For Query Volume Information operations,
                        //

                        case IRP_MJ_QUERY_VOLUME_INFORMATION:

                            (VOID) NtfsCommonQueryVolumeInfo( IrpContext, Irp );
                            break;

                        //
                        //  For Set Volume Information operations,
                        //

                        case IRP_MJ_SET_VOLUME_INFORMATION:

                            (VOID) NtfsCommonSetVolumeInfo( IrpContext, Irp );
                            break;

                        //
                        //  For File Cleanup operations,
                        //

                        case IRP_MJ_CLEANUP:

                            (VOID) NtfsCommonCleanup( IrpContext, Irp );
                            break;

                        //
                        //  For Directory Control operations,
                        //

                        case IRP_MJ_DIRECTORY_CONTROL:

                            (VOID) NtfsCommonDirectoryControl( IrpContext, Irp );
                            break;

                        //
                        //  For File System Control operations,
                        //

                        case IRP_MJ_FILE_SYSTEM_CONTROL:

                            (VOID) NtfsCommonFileSystemControl( IrpContext, Irp );
                            break;

                        //
                        //  For Lock Control operations,
                        //

                        case IRP_MJ_LOCK_CONTROL:

                            (VOID) NtfsCommonLockControl( IrpContext, Irp );
                            break;

                        //
                        //  For Device Control operations,
                        //

                        case IRP_MJ_DEVICE_CONTROL:

                            (VOID) NtfsCommonDeviceControl( IrpContext, Irp );
                            break;

                        //
                        //  For Query Security Information operations,
                        //

                        case IRP_MJ_QUERY_SECURITY:

                            (VOID) NtfsCommonQuerySecurityInfo( IrpContext, Irp );
                            break;

                        //
                        //  For Set Security Information operations,
                        //

                        case IRP_MJ_SET_SECURITY:

                            (VOID) NtfsCommonSetSecurityInfo( IrpContext, Irp );
                            break;

                        //
                        //  For Query Quota operations,
                        //

                        case IRP_MJ_QUERY_QUOTA:

                            (VOID) NtfsCommonQueryQuota( IrpContext, Irp );
                            break;

                        //
                        //  For Set Quota operations,
                        //

                        case IRP_MJ_SET_QUOTA:

                            (VOID) NtfsCommonSetQuota( IrpContext, Irp );
                            break;

                        //
                        //  For any other major operations, return an invalid
                        //  request.
                        //

                        default:

                            NtfsCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
                            break;
                    }

                //
                //  Otherwise complete the request to clean up this Irp Context.
                //

                } else {

                    NtfsCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );
                    IrpContext = NULL;
                }

                ASSERT( IoGetTopLevelIrp() != (PIRP) &TopLevelContext );
        
            } except(NtfsExceptionFilter( IrpContext, GetExceptionInformation() )) {

                PIO_STACK_LOCATION IrpSp;

                //
                //  We had some trouble trying to perform the requested
                //  operation, so we'll abort the I/O request with
                //  the error status that we get back from the
                //  execption code
                //

                if (Irp != NULL) {

                    IrpSp = IoGetCurrentIrpStackLocation( Irp );

                    Status = GetExceptionCode();

                    if ((Status == STATUS_FILE_DELETED) && 
                        ((IrpContext->MajorFunction == IRP_MJ_READ) || 
                         (IrpContext->MajorFunction == IRP_MJ_WRITE) || 
                         ((IrpContext->MajorFunction == IRP_MJ_SET_INFORMATION) &&
                          (IrpSp->Parameters.SetFile.FileInformationClass == FileEndOfFileInformation)))) {

                        IrpContext->ExceptionStatus = Status = STATUS_SUCCESS;
                    }
                }
                
                //
                //  If we failed to upgrade the volume's version during mount, we may
                //  not have put the right exception code into the irp context yet.
                //
                
                if ((IrpContext != NULL) &&
                    (FlagOn( IrpContext->State, IRP_CONTEXT_STATE_VOL_UPGR_FAILED )) &&
                    (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) &&
                    (IrpContext->MinorFunction == IRP_MN_MOUNT_VOLUME)) {

                    IrpContext->ExceptionStatus = Status;
                }

                //  
                //  This is the return status code that we want the Irp Completion routine to receive.
                //

                Status = NtfsProcessException( IrpContext, Irp, Status );

                if ((Status == STATUS_CANT_WAIT) || (Status == STATUS_LOG_FILE_FULL)) {

                    Retry = TRUE;
                }
            }

        } while (Retry);

        FsRtlExitFileSystem();

        //
        //  If there are any entries on this volume's overflow queue, service
        //  them.
        //

        if (VolDo != NULL) {

            KIRQL SavedIrql;
            PLIST_ENTRY Entry = NULL;

            //
            //  We have a volume device object so see if there is any work
            //  left to do in its overflow queue.
            //

            KeAcquireSpinLock( &VolDo->OverflowQueueSpinLock, &SavedIrql );

            while (VolDo->OverflowQueueCount > 0) {

                //
                //  There is overflow work to do in this volume so we'll
                //  decrement the Overflow count, dequeue the IRP, and release
                //  the Event
                //

                Entry = VolDo->OverflowQueue.Flink;
                IrpContext = CONTAINING_RECORD( Entry,
                                                IRP_CONTEXT,
                                                WorkQueueItem.List );
                Irp = IrpContext->OriginatingIrp;

                //
                //  If the cancel routine thinks it owns the irp ignore it
                //  

                if (NtfsSetCancelRoutine( Irp, NULL, 0, FALSE )) {
                    
                    VolDo->OverflowQueueCount -= 1;
                    RemoveEntryList( (PLIST_ENTRY)Entry );
                    break;
                
                } else {

                    //
                    //  Release the spinlock to let the cancel routine gain it and finish
                    //  its action
                    //  

                    KeReleaseSpinLock( &VolDo->OverflowQueueSpinLock, SavedIrql );
                    KeAcquireSpinLock( &VolDo->OverflowQueueSpinLock, &SavedIrql );
                    Entry = NULL;
                }
            } //  endwhile

            KeReleaseSpinLock( &VolDo->OverflowQueueSpinLock, SavedIrql );

            //
            //  There wasn't an entry, break out of the loop and return to
            //  the Ex Worker thread.
            //

            if ( Entry == NULL ) {

                break;
            }

            if (VolDo->OverflowQueueCount < OVERFLOW_QUEUE_LIMIT) {
                KeSetEvent( &VolDo->OverflowQueueEvent, IO_NO_INCREMENT, FALSE );
            }

            //
            //  set wait to TRUE, and loop.
            //

            LogFileFullCount = 0;
            SetFlag( IrpContext->State, IRP_CONTEXT_STATE_WAIT );
            continue;

        } else {

            break;
        }
    }

    //
    //  Decrement the PostedRequestCount.
    //

    if (VolDo) {

        ExInterlockedAddUlong( &VolDo->PostedRequestCount,
                               0xffffffff,
                               &VolDo->OverflowQueueSpinLock );
    }

    return;
}
Beispiel #8
0
VOID
NtfsSpecialDispatch (
    PVOID Context
    )

/*++

Routine Description:

    This routine is called when a special operation needs to be posted.
    It is called indirectly by NtfsPostSpecial.  It is assumes that the
    Vcb is protected from going away by incrementing the volemue close
    counts for a file.  If this routine fails nothing is done except
    to clean up the Vcb.  This routine also handles issues log file full
    and can't wait.

    The function to be called is stored in the PostSpecialCallout field
    of the Irp Context, and the context is stored int he OriginatingIrp.
    Both fields are zeroed before the the callout function is called.

Arguments:

    Context - Supplies a pointer to an IrpContext.

Return Value:

--*/

{
    PVCB Vcb;
    PIRP_CONTEXT IrpContext = Context;
    TOP_LEVEL_CONTEXT TopLevelContext;
    PTOP_LEVEL_CONTEXT ThreadTopLevelContext;
    POST_SPECIAL_CALLOUT PostSpecialCallout;
    PVOID SpecialContext;
    ULONG LogFileFullCount;
    BOOLEAN Retry;

    PAGED_CODE();

    FsRtlEnterFileSystem();

    do {

        Vcb = IrpContext->Vcb;
        LogFileFullCount = 0;

        //
        //  Capture the funciton pointer and context before using the IrpContext.
        //

        PostSpecialCallout = IrpContext->Union.PostSpecialCallout;
        SpecialContext = IrpContext->OriginatingIrp;
        IrpContext->Union.PostSpecialCallout = NULL;
        IrpContext->OriginatingIrp = NULL;

        ThreadTopLevelContext = NtfsInitializeTopLevelIrp( &TopLevelContext, TRUE, TRUE );
        ASSERT( ThreadTopLevelContext == &TopLevelContext );
        ASSERT( !FlagOn( IrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL ));
        ASSERT( FlagOn( IrpContext->State, IRP_CONTEXT_STATE_ALLOC_FROM_POOL ));

        //
        //  Initialize the thread top level structure, if needed.
        //

        ASSERT( IoGetTopLevelIrp() != (PIRP) &TopLevelContext );
        NtfsUpdateIrpContextWithTopLevel( IrpContext, ThreadTopLevelContext );

        //
        //  Don't let this IrpContext be deleted.
        //

        SetFlag( IrpContext->State, IRP_CONTEXT_STATE_PERSISTENT );

        do {

            Retry = FALSE;

            try {

                //
                //  See if we failed due to a log file full condition, and
                //  if so, then do a clean volume checkpoint if we are the
                //  first ones to get there.  If we see a different Lsn and do
                //  not do the checkpoint, the worst that can happen is that we
                //  will fail again if the log file is still full.
                //

                if (IrpContext->LastRestartArea.QuadPart != 0) {

                    NtfsCheckpointForLogFileFull( IrpContext );

                    if (++LogFileFullCount >= 2) {

                        SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_EXCESS_LOG_FULL );
                    }
                }

                //
                //  Call the requested function.
                //

                ASSERT( FlagOn( IrpContext->TopLevelIrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL ));
                PostSpecialCallout( IrpContext, SpecialContext );

                NtfsCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );

            } except(NtfsExceptionFilter( IrpContext, GetExceptionInformation() )) {

                NTSTATUS ExceptionCode;

                ExceptionCode = GetExceptionCode();
                ExceptionCode = NtfsProcessException( IrpContext, NULL, ExceptionCode );

                if ((ExceptionCode == STATUS_CANT_WAIT) ||
                    (ExceptionCode == STATUS_LOG_FILE_FULL)) {

                    Retry = TRUE;
                }
            }

        } while (Retry);

        //
        //  Ok to let this IrpContext be deleted.
        //

        ClearFlag( IrpContext->State, IRP_CONTEXT_STATE_PERSISTENT );

        //
        //  At this point regardless of the status the volume needs to
        //  be cleaned up and the IrpContext freed.
        //  Dereference the Vcb and check to see if it needs to be deleted.
        //  since this call might raise wrap it with a try/execpt.
        //

        try {

            //
            //  Acquire the volume exclusive so the counts can be
            //  updated.
            //

            ASSERT( FlagOn( IrpContext->State, IRP_CONTEXT_STATE_WAIT ));
            NtfsAcquireExclusiveVcb( IrpContext, Vcb, TRUE );

            InterlockedDecrement( &Vcb->SystemFileCloseCount );
            InterlockedDecrement( &Vcb->CloseCount );

            NtfsReleaseVcb( IrpContext, Vcb );

        } except( EXCEPTION_EXECUTE_HANDLER ) {

            ASSERT( FsRtlIsNtstatusExpected( GetExceptionCode() ) );
        }

        //
        //  Free the irp context.
        //

        NtfsCleanupIrpContext( IrpContext, TRUE );

        //
        //  See if there is more work on the scavenger list.
        //

        ExAcquireFastMutexUnsafe( &NtfsScavengerLock );

        ASSERT( NtfsScavengerRunning );

        IrpContext = NtfsScavengerWorkList;

        if (IrpContext != NULL) {

            //
            //  Remove the entry from the list.
            //

            NtfsScavengerWorkList = (PIRP_CONTEXT) IrpContext->WorkQueueItem.List.Flink;
            IrpContext->WorkQueueItem.List.Flink = NULL;

        } else {

            NtfsScavengerRunning = FALSE;

        }

        ExReleaseFastMutexUnsafe( &NtfsScavengerLock );

    } while ( IrpContext != NULL );

    FsRtlExitFileSystem();
}
Beispiel #9
0
NTSTATUS
NtfsCommonSetSecurityInfo (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common routine for Setting security information called by
    both the fsd and fsp threads.

Arguments:

    Irp - Supplies the Irp to process

Return Value:

    NTSTATUS - the return status for the operation

--*/

{
    NTSTATUS Status;
    PIO_STACK_LOCATION IrpSp;
    PFILE_OBJECT FileObject;

#ifdef _CAIRO_
    PQUOTA_CONTROL_BLOCK OldQuotaControl;
    ULONG OldOwnerId;
    ULONG LargeStdInfo;
#endif // _CAIRO_

    TYPE_OF_OPEN TypeOfOpen;
    PVCB Vcb;
    PFCB Fcb;
    PSCB Scb;
    PCCB Ccb;

    ASSERT_IRP_CONTEXT( IrpContext );
    ASSERT_IRP( Irp );

    PAGED_CODE();

    //
    //  Get the current Irp stack location
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    DebugTrace( +1, Dbg, ("NtfsCommonSetSecurityInfo") );
    DebugTrace( 0, Dbg, ("IrpContext = %08lx\n", IrpContext) );
    DebugTrace( 0, Dbg, ("Irp        = %08lx\n", Irp) );

    //
    //  Extract and decode the file object
    //

    FileObject = IrpSp->FileObject;
    TypeOfOpen = NtfsDecodeFileObject( IrpContext, FileObject, &Vcb, &Fcb, &Scb, &Ccb, TRUE );

    //
    //  The only type of opens we accept are user file and directory opens
    //

    if ((TypeOfOpen != UserFileOpen)
        && (TypeOfOpen != UserDirectoryOpen)) {

        Status = STATUS_INVALID_PARAMETER;

    //
    //  If the this handle does not open the entire file then refuse access.
    //

    } else if (!FlagOn( Ccb->Flags, CCB_FLAG_OPEN_AS_FILE )) {

        Status = STATUS_INVALID_PARAMETER;

    } else {

        //
        //  Our operation is to acquire the fcb, do the operation and then
        //  release the fcb
        //

        NtfsAcquireExclusiveFcb( IrpContext, Fcb, NULL, FALSE, FALSE );

        try {

#ifdef _CAIRO_

            //
            //  Capture the current OwnerId, Qutoa Control Block and
            //  size of standard information.
            //

            OldQuotaControl = Fcb->QuotaControl;
            OldOwnerId = Fcb->OwnerId;
            LargeStdInfo = Fcb->FcbState & FCB_STATE_LARGE_STD_INFO;

#endif // _CAIRO_

            Status = NtfsModifySecurity( IrpContext,
                                         Fcb,
                                         &IrpSp->Parameters.SetSecurity.SecurityInformation,
                                         IrpSp->Parameters.SetSecurity.SecurityDescriptor );

            if (NT_SUCCESS( Status )) {

#ifdef _CAIRO_
                //
                //  Make sure the new security descriptor Id is written out.
                //

                NtfsUpdateStandardInformation( IrpContext, Fcb );
#endif
            }

            //
            //  Abort transaction on error by raising.
            //

            NtfsCleanupTransaction( IrpContext, Status, FALSE );

            //
            //  Set the flag in the Ccb to indicate this change occurred.
            //

            SetFlag( Ccb->Flags,
                     CCB_FLAG_UPDATE_LAST_CHANGE | CCB_FLAG_SET_ARCHIVE );

        } finally {

            DebugUnwind( NtfsCommonSetSecurityInfo );

#ifdef _CAIRO_
            if (AbnormalTermination()) {

                //
                //  The request failed.  Restore the owner and
                //  QuotaControl are restored.
                //

                if (Fcb->QuotaControl != OldQuotaControl &&
                    Fcb->QuotaControl != NULL) {

                    //
                    //  A new quota control block was assigned.
                    //  Dereference it.
                    //

                    NtfsDereferenceQuotaControlBlock( Fcb->Vcb,
                                                      &Fcb->QuotaControl );
                }

                Fcb->QuotaControl = OldQuotaControl;
                Fcb->OwnerId = OldOwnerId;

                if (LargeStdInfo == 0) {

                    //
                    //  The standard information has be returned to
                    //  its orginal size.
                    //

                    ClearFlag( Fcb->FcbState, FCB_STATE_LARGE_STD_INFO );
                }

            } else {

                //
                //  The request succeed.  If the quota control block was
                //  changed then derefence the old block.
                //

                if (Fcb->QuotaControl != OldQuotaControl &&
                    OldQuotaControl != NULL) {

                    NtfsDereferenceQuotaControlBlock( Fcb->Vcb,
                                                      &OldQuotaControl);

                }
            }
#endif // _CAIRO_

            NtfsReleaseFcb( IrpContext, Fcb );
        }
    }

    //
    //  Now complete the request and return to our caller
    //

    NtfsCompleteRequest( &IrpContext, &Irp, Status );

    DebugTrace( -1, Dbg, ("NtfsCommonSetSecurityInfo -> %08lx", Status) );

    return Status;
}
Beispiel #10
0
NTSTATUS
NtfsCommonQuerySecurityInfo (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common routine for querying security information called by
    both the fsd and fsp threads.

Arguments:

    Irp - Supplies the Irp to process

Return Value:

    NTSTATUS - the return status for the operation

--*/

{
    NTSTATUS Status;
    PIO_STACK_LOCATION IrpSp;
    PFILE_OBJECT FileObject;

    TYPE_OF_OPEN TypeOfOpen;
    PVCB Vcb;
    PFCB Fcb;
    PSCB Scb;
    PCCB Ccb;

    BOOLEAN AcquiredFcb = TRUE;

    ASSERT_IRP_CONTEXT( IrpContext );
    ASSERT_IRP( Irp );

    PAGED_CODE();

    //
    //  Get the current Irp stack location
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    DebugTrace( +1, Dbg, ("NtfsCommonQuerySecurityInfo") );
    DebugTrace( 0, Dbg, ("IrpContext = %08lx\n", IrpContext) );
    DebugTrace( 0, Dbg, ("Irp        = %08lx\n", Irp) );

    //
    //  Extract and decode the file object
    //

    FileObject = IrpSp->FileObject;
    TypeOfOpen = NtfsDecodeFileObject( IrpContext, FileObject, &Vcb, &Fcb, &Scb, &Ccb, TRUE );

    //
    //  The only type of opens we accept are user file and directory opens
    //

    if ((TypeOfOpen != UserFileOpen)
        && (TypeOfOpen != UserDirectoryOpen)) {

        Status = STATUS_INVALID_PARAMETER;

    //
    //  If the this handle does not open the entire file then refuse access.
    //

    } else if (!FlagOn( Ccb->Flags, CCB_FLAG_OPEN_AS_FILE )) {

        Status = STATUS_INVALID_PARAMETER;

    } else {

        //
        //  Our operation is to acquire the fcb, do the operation and then
        //  release the fcb.  If the security descriptor for this file is
        //  not already loaded we will release the Fcb and then acquire both
        //  the Vcb and Fcb.  We must have the Vcb to examine our parent's
        //  security descriptor.
        //

        NtfsAcquireSharedFcb( IrpContext, Fcb, NULL, FALSE );

        try {

            if (Fcb->SharedSecurity == NULL) {

                NtfsReleaseFcb( IrpContext, Fcb );
                AcquiredFcb = FALSE;

                NtfsAcquireExclusiveFcb( IrpContext, Fcb, NULL, FALSE, FALSE );
                AcquiredFcb = TRUE;
            }

            Status = NtfsQuerySecurity( IrpContext,
                                        Fcb,
                                        &IrpSp->Parameters.QuerySecurity.SecurityInformation,
                                        (PSECURITY_DESCRIPTOR)Irp->UserBuffer,
                                        &IrpSp->Parameters.QuerySecurity.Length );

            if (  Status == STATUS_BUFFER_TOO_SMALL ) {

                Irp->IoStatus.Information = IrpSp->Parameters.QuerySecurity.Length;

                Status = STATUS_BUFFER_OVERFLOW;
            }

            //
            //  Abort transaction on error by raising.
            //

            NtfsCleanupTransaction( IrpContext, Status, FALSE );

        } finally {

            DebugUnwind( NtfsCommonQuerySecurityInfo );

            if (AcquiredFcb) {

                NtfsReleaseFcb( IrpContext, Fcb );
            }
        }
    }

    //
    //  Now complete the request and return to our caller
    //

    NtfsCompleteRequest( &IrpContext, &Irp, Status );

    DebugTrace( -1, Dbg, ("NtfsCommonQuerySecurityInfo -> %08lx", Status) );

    return Status;
}
Beispiel #11
0
NTSTATUS
NtfsCompleteMdl (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine performs the function of completing Mdl read and write
    requests.  It should be called only from NtfsFsdRead and NtfsFsdWrite.

Arguments:

    Irp - Supplies the originating Irp.

Return Value:

    NTSTATUS - Will always be STATUS_PENDING or STATUS_SUCCESS.

--*/

{
    PFILE_OBJECT FileObject;
    PIO_STACK_LOCATION IrpSp;
    PNTFS_ADVANCED_FCB_HEADER Header;

    ASSERT( FlagOn( IrpContext->TopLevelIrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL ));
    PAGED_CODE();

    DebugTrace( +1, Dbg, ("NtfsCompleteMdl\n") );
    DebugTrace( 0, Dbg, ("IrpContext = %08lx\n", IrpContext) );
    DebugTrace( 0, Dbg, ("Irp        = %08lx\n", Irp) );

    //
    // Do completion processing.
    //

    FileObject = IoGetCurrentIrpStackLocation( Irp )->FileObject;

    switch( IrpContext->MajorFunction ) {

    case IRP_MJ_READ:

        CcMdlReadComplete( FileObject, Irp->MdlAddress );
        break;

    case IRP_MJ_WRITE:

        try {

            PSCB Scb;
            VBO StartingVbo;
            LONGLONG ByteCount;
            LONGLONG ByteRange;
            BOOLEAN DoingIoAtEof = FALSE;

            ASSERT( FlagOn( IrpContext->State, IRP_CONTEXT_STATE_WAIT ));

            IrpSp = IoGetCurrentIrpStackLocation( Irp );
            Scb = (PSCB)(IrpSp->FileObject->FsContext);
            Header = &(Scb->Header);

            //
            //  Now synchronize with the FsRtl Header and Scb.
            //

            if (Header->PagingIoResource != NULL) {

                StartingVbo = IrpSp->Parameters.Write.ByteOffset.QuadPart;
                ByteCount = (LONGLONG) IrpSp->Parameters.Write.Length;
                ByteRange = StartingVbo + ByteCount + PAGE_SIZE - 1;
                ClearFlag( ((ULONG) ByteRange), PAGE_SIZE - 1 );

                ExAcquireResourceSharedLite( Header->PagingIoResource, TRUE );
                NtfsAcquireFsrtlHeader( Scb );

                //
                //  Now see if this is at EOF.
                //  Recursive flush will generate IO which ends on page boundary
                //  which is why we rounded the range
                //

                if (ByteRange > Header->ValidDataLength.QuadPart) {

                    //
                    //  Mark that we are writing to EOF.  If someone else is currently
                    //  writing to EOF, wait for them.
                    //

                    ASSERT( ByteRange - StartingVbo < MAXULONG );

                    DoingIoAtEof = !FlagOn( Header->Flags, FSRTL_FLAG_EOF_ADVANCE_ACTIVE ) ||
                                   NtfsWaitForIoAtEof( Header, (PLARGE_INTEGER)&StartingVbo, (ULONG)(ByteRange - StartingVbo) );

                    if (DoingIoAtEof) {

                        SetFlag( Header->Flags, FSRTL_FLAG_EOF_ADVANCE_ACTIVE );

#if (DBG || defined( NTFS_FREE_ASSERTS ))
                        ((PSCB) Header)->IoAtEofThread = (PERESOURCE_THREAD) ExGetCurrentResourceThread();
#endif
                        //
                        //  Store this in the IrpContext until commit or post.
                        //

                        IrpContext->CleanupStructure = Scb;
                    }
                }

                NtfsReleaseFsrtlHeader( Scb );
            }

            CcMdlWriteComplete( FileObject, &IrpSp->Parameters.Write.ByteOffset, Irp->MdlAddress );

        } finally {

            if (Header->PagingIoResource != NULL) {

                ExReleaseResourceLite( Header->PagingIoResource );
            }
        }

        break;

    default:

        DebugTrace( DEBUG_TRACE_ERROR, 0, ("Illegal Mdl Complete.\n") );

        ASSERTMSG("Illegal Mdl Complete, About to bugcheck ", FALSE);
        NtfsBugCheck( IrpContext->MajorFunction, 0, 0 );
    }

    //
    // Mdl is now deallocated.
    //

    Irp->MdlAddress = NULL;

    //
    //  Ignore errors.  CC has already cleaned up his structures.
    //

    IrpContext->ExceptionStatus = STATUS_SUCCESS;
    NtfsMinimumExceptionProcessing( IrpContext );

    //
    // Complete the request and exit right away.
    //

    NtfsCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );

    DebugTrace( -1, Dbg, ("NtfsCompleteMdl -> STATUS_SUCCESS\n") );

    return STATUS_SUCCESS;
}
Beispiel #12
0
NTSTATUS
NtfsCommonSetVolumeInfo (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common routine for set Volume Information called by both the
    fsd and fsp threads.

Arguments:

    Irp - Supplies the Irp to process

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status;
    PMyIO_STACK_LOCATION IrpSp;
    PFILE_OBJECT FileObject;

    TYPE_OF_OPEN TypeOfOpen;
    PVCB Vcb;
    PFCB Fcb;
    PSCB Scb;
    PCCB Ccb;

    ULONG Length;
    FS_INFORMATION_CLASS FsInformationClass;
    PVOID Buffer;

    ASSERT_IRP_CONTEXT( IrpContext );
    ASSERT_IRP( Irp );

    PAGED_CODE();

    //
    //  Get the current Irp stack location
    //

    IrpSp = (PMyIO_STACK_LOCATION)IoGetCurrentIrpStackLocation( Irp );

    DebugTrace( +1, Dbg, ("NtfsCommonSetVolumeInfo\n") );
    DebugTrace( 0, Dbg, ("IrpContext         = %08lx\n", IrpContext) );
    DebugTrace( 0, Dbg, ("Irp                = %08lx\n", Irp) );
    DebugTrace( 0, Dbg, ("Length             = %08lx\n", IrpSp->Parameters.SetVolume.Length) );
    DebugTrace( 0, Dbg, ("FsInformationClass = %08lx\n", IrpSp->Parameters.SetVolume.FsInformationClass) );
    DebugTrace( 0, Dbg, ("Buffer             = %08lx\n", Irp->AssociatedIrp.SystemBuffer) );

    //
    //  Reference our input parameters to make things easier
    //

    Length = IrpSp->Parameters.SetVolume.Length;
    FsInformationClass = IrpSp->Parameters.SetVolume.FsInformationClass;
    Buffer = Irp->AssociatedIrp.SystemBuffer;

    //
    //  Extract and decode the file object to get the Vcb, we don't really
    //  care what the type of open is.
    //

    FileObject = IrpSp->FileObject;
    TypeOfOpen = NtfsDecodeFileObject( IrpContext, FileObject, &Vcb, &Fcb, &Scb, &Ccb, TRUE );

    if (TypeOfOpen != UserVolumeOpen) {

        NtfsCompleteRequest( &IrpContext, &Irp, STATUS_ACCESS_DENIED );

        DebugTrace( -1, Dbg, ("NtfsCommonSetVolumeInfo -> STATUS_ACCESS_DENIED\n") );

        return STATUS_ACCESS_DENIED;
    }

    //
    //  Acquire exclusive access to the Vcb
    //

    NtfsAcquireExclusiveVcb( IrpContext, Vcb, TRUE );

    try {

        //
        //  Proceed only if the volume is mounted.
        //

        if (FlagOn( Vcb->VcbState, VCB_STATE_VOLUME_MOUNTED )) {

            //
            //  Based on the information class we'll do different actions.  Each
            //  of the procedures that we're calling performs the action if
            //  possible and returns true if it successful and false if it couldn't
            //  wait for any I/O to complete.
            //

            switch (FsInformationClass) {

            case FileFsLabelInformation:

                Status = NtfsSetFsLabelInfo( IrpContext, Vcb, Buffer );
                break;

#ifdef _CAIRO_

            case FileFsQuotaSetInformation:
    
                Status = NtfsFsQuotaSetInfo( IrpContext, Vcb, Buffer, Length );
                break;

            case FileFsControlInformation:

                Status = NtfsSetFsControlInfo( IrpContext, Vcb, Buffer );
                break;

#endif // _CAIRO_

            default:

                Status = STATUS_INVALID_PARAMETER;
                break;
            }

        } else {

            Status = STATUS_FILE_INVALID;
        }

        //
        //  Abort transaction on error by raising.
        //

        NtfsCleanupTransaction( IrpContext, Status, FALSE );

    } finally {

        DebugUnwind( NtfsCommonSetVolumeInfo );

        NtfsReleaseVcb( IrpContext, Vcb );

        if (!AbnormalTermination()) {

            NtfsCompleteRequest( &IrpContext, &Irp, Status );
        }

        DebugTrace( -1, Dbg, ("NtfsCommonSetVolumeInfo -> %08lx\n", Status) );
    }

    return Status;
}
Beispiel #13
0
NTSTATUS
NtfsCommonQueryVolumeInfo (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common routine for query Volume Information called by both the
    fsd and fsp threads.

Arguments:

    Irp - Supplies the Irp to process

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status;
    PIO_STACK_LOCATION IrpSp;
    PFILE_OBJECT FileObject;

    TYPE_OF_OPEN TypeOfOpen;
    PVCB Vcb;
    PFCB Fcb;
    PSCB Scb;
    PCCB Ccb;

    ULONG Length;
    FS_INFORMATION_CLASS FsInformationClass;
    PVOID Buffer;

    ASSERT_IRP_CONTEXT( IrpContext );
    ASSERT_IRP( Irp );

    PAGED_CODE();

    //
    //  Get the current stack location
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    DebugTrace( +1, Dbg, ("NtfsCommonQueryVolumeInfo...\n") );
    DebugTrace( 0, Dbg, ("IrpContext         = %08lx\n", IrpContext) );
    DebugTrace( 0, Dbg, ("Irp                = %08lx\n", Irp) );
    DebugTrace( 0, Dbg, ("Length             = %08lx\n", IrpSp->Parameters.QueryVolume.Length) );
    DebugTrace( 0, Dbg, ("FsInformationClass = %08lx\n", IrpSp->Parameters.QueryVolume.FsInformationClass) );
    DebugTrace( 0, Dbg, ("Buffer             = %08lx\n", Irp->AssociatedIrp.SystemBuffer) );

    //
    //  Reference our input parameters to make things easier
    //

    Length = IrpSp->Parameters.QueryVolume.Length;
    FsInformationClass = IrpSp->Parameters.QueryVolume.FsInformationClass;
    Buffer = Irp->AssociatedIrp.SystemBuffer;

    //
    //  Extract and decode the file object to get the Vcb, we don't really
    //  care what the type of open is.
    //

    FileObject = IrpSp->FileObject;
    TypeOfOpen = NtfsDecodeFileObject( IrpContext, FileObject, &Vcb, &Fcb, &Scb, &Ccb, TRUE );

    //
    //  We need exclusive access to the Vcb because we are going to verify
    //  it.  After we verify the vcb we'll convert our access to shared
    //

    NtfsAcquireSharedVcb( IrpContext, Vcb, FALSE );

    try {

        //
        //  Based on the information class we'll do different actions.  Each
        //  of the procedures that we're calling fills up the output buffer
        //  if possible and returns true if it successfully filled the buffer
        //  and false if it couldn't wait for any I/O to complete.
        //

        switch (FsInformationClass) {

        case FileFsVolumeInformation:

            Status = NtfsQueryFsVolumeInfo( IrpContext, Vcb, Buffer, &Length );
            break;

        case FileFsSizeInformation:

            Status = NtfsQueryFsSizeInfo( IrpContext, Vcb, Buffer, &Length );
            break;

        case FileFsDeviceInformation:

            Status = NtfsQueryFsDeviceInfo( IrpContext, Vcb, Buffer, &Length );
            break;

        case FileFsAttributeInformation:

            Status = NtfsQueryFsAttributeInfo( IrpContext, Vcb, Buffer, &Length );
            break;

#ifdef _CAIRO_
        case FileFsControlInformation:

            Status = NtfsQueryFsControlInfo( IrpContext, Vcb, Buffer, &Length );
            break;


        case FileFsQuotaQueryInformation:

            Status = NtfsFsQuotaQueryInfo( IrpContext, Vcb, Buffer, &Length );
            break;

#endif // _CAIRO_

        default:

            Status = STATUS_INVALID_PARAMETER;
            break;
        }

        //
        //  Set the information field to the number of bytes actually filled in
        //

        Irp->IoStatus.Information = IrpSp->Parameters.QueryVolume.Length - Length;

        //
        //  Abort transaction on error by raising.
        //

        NtfsCleanupTransaction( IrpContext, Status, FALSE );

    } finally {

        DebugUnwind( NtfsCommonQueryVolumeInfo );

        NtfsReleaseVcb( IrpContext, Vcb );

        if (!AbnormalTermination()) {

            NtfsCompleteRequest( &IrpContext, &Irp, Status );
        }

        DebugTrace( -1, Dbg, ("NtfsCommonQueryVolumeInfo -> %08lx\n", Status) );
    }

    return Status;
}