Exemple #1
0
NTSTATUS
FatFsdClose (
    _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
    _Inout_ PIRP Irp
    )

/*++

Routine Description:

    This routine implements the FSD part of Close.

Arguments:

    VolumeDeviceObject - Supplies the volume device object where the
        file exists

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The FSD status for the IRP

--*/

{
    NTSTATUS Status = STATUS_SUCCESS;
    PIO_STACK_LOCATION IrpSp;
    PFILE_OBJECT FileObject;

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

    BOOLEAN TopLevel;
    BOOLEAN VcbDeleted = FALSE;

    PAGED_CODE();

    //
    //  If we were called with our file system device object instead of a
    //  volume device object, just complete this request with STATUS_SUCCESS
    //

    if (FatDeviceIsFatFsdo( VolumeDeviceObject))  {

        Irp->IoStatus.Status = STATUS_SUCCESS;
        Irp->IoStatus.Information = FILE_OPENED;

        IoCompleteRequest( Irp, IO_DISK_INCREMENT );

        return STATUS_SUCCESS;
    }

    DebugTrace(+1, Dbg, "FatFsdClose\n", 0);

    //
    //  Call the common Close routine
    //

    FsRtlEnterFileSystem();

    TopLevel = FatIsIrpTopLevel( Irp );

    //
    //  Get a pointer to the current stack location and the file object
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    FileObject = IrpSp->FileObject;

    //
    //  Decode the file object and set the read-only bit in the Ccb.
    //

    TypeOfOpen = FatDecodeFileObject( FileObject, &Vcb, &Fcb, &Ccb );

    if (Ccb && IsFileObjectReadOnly(FileObject)) {

        SetFlag( Ccb->Flags, CCB_FLAG_READ_ONLY );
    }

    try {

        PCLOSE_CONTEXT CloseContext = NULL;

        //
        //  If we are top level, WAIT can be TRUE, otherwise make it FALSE
        //  to avoid deadlocks, unless this is a top
        //  level request not originating from the system process.
        //

        BOOLEAN Wait = TopLevel && (PsGetCurrentProcess() != FatData.OurProcess);

#if (NTDDI_VERSION >= NTDDI_WIN8)

        //
        //  To catch the odd case where a close comes in without a preceding cleanup,
        //  call the oplock package to get rid of any oplock state.  This can only
        //  be safely done in the FSD path.
        //
        
        if ((Fcb != NULL) &&
            !FlagOn( FileObject->Flags, FO_CLEANUP_COMPLETE ) &&
            FatIsFileOplockable( Fcb )) {
        
            //
            //  This is equivalent to handling cleanup, and it always cleans up any
            //  oplock immediately.  Also, we don't need any locking of the FCB here;
            //  the oplock's own lock will be sufficient for this purpose.
            //
        
            FsRtlCheckOplockEx( FatGetFcbOplock(Fcb),
                                Irp,
                                0,
                                NULL,
                                NULL,
                                NULL );
        }
#endif

        //
        //  Call the common Close routine if we are not delaying this close.
        //

        if ((((TypeOfOpen == UserFileOpen) ||
              (TypeOfOpen == UserDirectoryOpen)) &&
             FlagOn(Fcb->FcbState, FCB_STATE_DELAY_CLOSE) &&
             !FatData.ShutdownStarted) ||
            (FatCommonClose( Vcb, Fcb, Ccb, TypeOfOpen, Wait, TopLevel, &VcbDeleted ) == STATUS_PENDING)) {

            //
            //  Metadata streams have had close contexts preallocated.
            //

            if (TypeOfOpen == VirtualVolumeFile) {
                
                NT_ASSERT( Vcb->CloseContext != NULL );
                CloseContext = Vcb->CloseContext;
                Vcb->CloseContext = NULL;
                CloseContext->Free = TRUE;
            }
            else if ((TypeOfOpen == DirectoryFile) || (TypeOfOpen == EaFile)) {

                CloseContext = FatAllocateCloseContext( Vcb);
                NT_ASSERT( CloseContext != NULL );
                CloseContext->Free = TRUE;

            } else {

                //
                //  Free up any query template strings before using the close context fields,
                //  which overlap (union)
                //

                FatDeallocateCcbStrings( Ccb );

                CloseContext = &Ccb->CloseContext;
                CloseContext->Free = FALSE;
                
                SetFlag( Ccb->Flags, CCB_FLAG_CLOSE_CONTEXT );
            }

            //
            //  If the status is pending, then let's get the information we
            //  need into the close context we already have bagged, complete
            //  the request, and post it.  It is important we allocate nothing
            //  in the close path.
            //

            CloseContext->Vcb = Vcb;
            CloseContext->Fcb = Fcb;
            CloseContext->TypeOfOpen = TypeOfOpen;

            //
            //  Send it off, either to an ExWorkerThread or to the async
            //  close list.
            //

            FatQueueClose( CloseContext,
                           (BOOLEAN)(Fcb && FlagOn(Fcb->FcbState, FCB_STATE_DELAY_CLOSE)));
        } else {
            
            //
            //  The close proceeded synchronously, so for the metadata objects we
            //  can now drop the close context we preallocated.
            //
            
            if ((TypeOfOpen == VirtualVolumeFile) ||
                (TypeOfOpen == DirectoryFile) ||
                (TypeOfOpen == EaFile)) {

                if (TypeOfOpen == VirtualVolumeFile) {

                    //
                    //  If the VCB was deleted during the close, the close context for this
                    //  open has already been freed.
                    //

                    if (!VcbDeleted) {

                        CloseContext = Vcb->CloseContext;   
                        Vcb->CloseContext = NULL;

                        NT_ASSERT( CloseContext != NULL );

                    } else {

                        CloseContext = NULL;
                    }
                }
                else {

                    CloseContext = FatAllocateCloseContext( (VcbDeleted ? NULL : Vcb) );

                    NT_ASSERT( CloseContext != NULL );
                }

                if (CloseContext != NULL) {

                    ExFreePool( CloseContext );
                }
            }
        }

        FatCompleteRequest( FatNull, Irp, Status );

    } 
    except(FatExceptionFilter( NULL, GetExceptionInformation() )) {

        //
        //  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.
        //

        Status = FatProcessException( NULL, Irp, GetExceptionCode() );
    }

    if (TopLevel) { IoSetTopLevelIrp( NULL ); }

    FsRtlExitFileSystem();

    //
    //  And return to our caller
    //

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

    UNREFERENCED_PARAMETER( VolumeDeviceObject );

    return Status;
}
Exemple #2
0
NTSTATUS
FatFsdLockControl (
    IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
    IN PIRP Irp
)

/*++

Routine Description:

    This routine implements the FSD part of Lock control operations

Arguments:

    VolumeDeviceObject - Supplies the volume device object where the
        file exists

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The FSD status for the IRP

--*/

{
    NTSTATUS Status;
    PIRP_CONTEXT IrpContext = NULL;

    BOOLEAN TopLevel;

    DebugTrace(+1, Dbg, "FatFsdLockControl\n", 0);

    //
    //  Call the common Lock Control routine, with blocking allowed if
    //  synchronous
    //

    FsRtlEnterFileSystem();

    TopLevel = FatIsIrpTopLevel( Irp );

    try {

        IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ) );

        Status = FatCommonLockControl( IrpContext, Irp );

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

        //
        //  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
        //

        Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
    }

    if (TopLevel) {
        IoSetTopLevelIrp( NULL );
    }

    FsRtlExitFileSystem();

    //
    //  And return to our caller
    //

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

    UNREFERENCED_PARAMETER( VolumeDeviceObject );

    return Status;
}
Exemple #3
0
NTSTATUS
FatFsdRead (
    IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the driver entry to the common read routine for NtReadFile calls.
    For synchronous requests, the CommonRead is called with Wait == TRUE,
    which means the request will always be completed in the current thread,
    and never passed to the Fsp.  If it is not a synchronous request,
    CommonRead is called with Wait == FALSE, which means the request
    will be passed to the Fsp only if there is a need to block.

Arguments:

    VolumeDeviceObject - Supplies the volume device object where the
        file being Read exists

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The FSD status for the IRP

--*/

{
    PFCB Fcb = NULL;
    NTSTATUS Status;
    PIRP_CONTEXT IrpContext = NULL;

    BOOLEAN TopLevel;

    DebugTrace(+1, Dbg, "FatFsdRead\n", 0);

    //
    //  Call the common Read routine, with blocking allowed if synchronous
    //

    FsRtlEnterFileSystem();

    //
    //  We are first going to do a quick check for paging file IO.  Since this
    //  is a fast path, we must replicate the check for the fsdo.
    //

    if (!FatDeviceIsFatFsdo( IoGetCurrentIrpStackLocation(Irp)->DeviceObject))  {

        Fcb = (PFCB)(IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext);

        if ((NodeType(Fcb) == FAT_NTC_FCB) &&
            FlagOn(Fcb->FcbState, FCB_STATE_PAGING_FILE)) {

            //
            //  Do the usual STATUS_PENDING things.
            //

            IoMarkIrpPending( Irp );

            //
            //  If there is not enough stack to do this read, then post this
            //  read to the overflow queue.
            //

            if (IoGetRemainingStackSize() < OVERFLOW_READ_THRESHHOLD) {

                KEVENT Event;
                PAGING_FILE_OVERFLOW_PACKET Packet;

                Packet.Irp = Irp;
                Packet.Fcb = Fcb;

                KeInitializeEvent( &Event, NotificationEvent, FALSE );

                FsRtlPostPagingFileStackOverflow( &Packet, &Event, FatOverflowPagingFileRead );

                //
                //  And wait for the worker thread to complete the item
                //

                (VOID) KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL );

            } else {

                //
                //  Perform the actual IO, it will be completed when the io finishes.
                //

                FatPagingFileIo( Irp, Fcb );
            }

            FsRtlExitFileSystem();

            return STATUS_PENDING;
        }
    }

    try {

        TopLevel = FatIsIrpTopLevel( Irp );

        IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ) );

        //
        //  If this is an Mdl complete request, don't go through
        //  common read.
        //

        if ( FlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE) ) {

            DebugTrace(0, Dbg, "Calling FatCompleteMdl\n", 0 );
            try_return( Status = FatCompleteMdl( IrpContext, Irp ));
        }

        //
        //  Check if we have enough stack space to process this request.  If there
        //  isn't enough then we will pass the request off to the stack overflow thread.
        //

        if (IoGetRemainingStackSize() < OVERFLOW_READ_THRESHHOLD) {

            DebugTrace(0, Dbg, "Passing StackOverflowRead off\n", 0 );
            try_return( Status = FatPostStackOverflowRead( IrpContext, Irp, Fcb ) );
        }

        Status = FatCommonRead( IrpContext, Irp );

    try_exit: NOTHING;
    } except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) {

        //
        //  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
        //

        Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
    }

    if (TopLevel) { IoSetTopLevelIrp( NULL ); }

    FsRtlExitFileSystem();

    //
    //  And return to our caller
    //

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

    UNREFERENCED_PARAMETER( VolumeDeviceObject );

    return Status;
}
Exemple #4
0
NTSTATUS
FatFsdDeviceControl (
    IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine implements the FSD part of Device control operations

Arguments:

    VolumeDeviceObject - Supplies the volume device object where the
        file exists

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The FSD status for the IRP

--*/

{
    NTSTATUS Status;
    PIRP_CONTEXT IrpContext = NULL;

    BOOLEAN TopLevel;

#ifdef	__NDAS_FAT__

	PIO_STACK_LOCATION	irpSp = IoGetCurrentIrpStackLocation( Irp );

	if ((PVOID)FatControlDeviceObject == VolumeDeviceObject) {

		Status = Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
		Irp->IoStatus.Information = 0;

		IoCompleteRequest( Irp, IO_DISK_INCREMENT );

		return Status;
	}

	if (irpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL && FatData.DiskFileSystemDeviceObject == (PDEVICE_OBJECT)VolumeDeviceObject) {

		switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {

		case IOCTL_REGISTER_NDFS_CALLBACK: {

			PNDFS_CALLBACK	inputBuffer			= (PNDFS_CALLBACK)Irp->AssociatedIrp.SystemBuffer;
			ULONG			inputBufferLength	= irpSp->Parameters.DeviceIoControl.InputBufferLength;


			if ( inputBufferLength != sizeof( VolumeDeviceObject->NdfsCallback ) ) {

				Status = Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
				Irp->IoStatus.Information = 0;
				break;
			} 
			
			DebugTrace2( 0, Dbg2, ("NtfsFsdDispatch: IOCTL_REGISTER_NDFS_CALLBACK, size = %d\n", inputBuffer->Size) );		

			RtlCopyMemory( &VolumeDeviceObject->NdfsCallback, inputBuffer, sizeof(VolumeDeviceObject->NdfsCallback) );

			//ASSERT( FALSE );
			Status = Irp->IoStatus.Status = STATUS_SUCCESS;
			Irp->IoStatus.Information = 0;
			
			break;
		}
	
		case IOCTL_UNREGISTER_NDFS_CALLBACK:

			DebugTrace2( 0, Dbg2, ("NtfsFsdDispatch: IOCTL_UNREGISTER_NDFS_CALLBACK\n") );		

			RtlZeroMemory( &VolumeDeviceObject->NdfsCallback, sizeof(VolumeDeviceObject->NdfsCallback) );

			Status = Irp->IoStatus.Status = STATUS_SUCCESS;
			Irp->IoStatus.Information = 0;

			break;

		case IOCTL_SHUTDOWN: {
			
			PLIST_ENTRY				vcbListEntry;

			DebugTrace2( 0, Dbg2, ("FatFsdDeviceControl: IOCTL_SHUTDOWN\n") );		

	        for (vcbListEntry = FatData.VcbQueue.Flink;
			     vcbListEntry != &FatData.VcbQueue;
				 vcbListEntry = vcbListEntry->Flink) {

				PVCB					vcb = NULL;
#if __NDAS_FAT_PRIMARY__
				PLIST_ENTRY				primarySessionListEntry;
#endif
				PVOLUME_DEVICE_OBJECT	volDo = NULL;


				DebugTrace2( 0, Dbg2, ("NtfsFsdDispatch: volDo = %p, KeGetCurrentIrql() = %d\n", volDo, KeGetCurrentIrql()) );		

				vcb = CONTAINING_RECORD(vcbListEntry, VCB, VcbLinks);
				volDo = CONTAINING_RECORD( vcb, VOLUME_DEVICE_OBJECT, Vcb );

				DebugTrace2( 0, Dbg2, ("FatFsdDeviceControl: ND_FAT_DEVICE_FLAG_SHUTDOWN\n") );		
				SetFlag( volDo->NdFatFlags, ND_FAT_DEVICE_FLAG_SHUTDOWN );

		
#if __NDAS_FAT_PRIMARY__

				for (primarySessionListEntry = volDo->PrimarySessionQueue.Flink;
					 primarySessionListEntry != &volDo->PrimarySessionQueue; ) {

					PPRIMARY_SESSION primarySession;

					primarySession = CONTAINING_RECORD( primarySessionListEntry, PRIMARY_SESSION, ListEntry );
					primarySessionListEntry = primarySessionListEntry->Flink;
					PrimarySession_Reference( primarySession );
		
					PrimarySession_FileSystemShutdown( primarySession );

					RemoveEntryList( &primarySession->ListEntry );
					InitializeListHead(  &primarySession->ListEntry );
					PrimarySession_Dereference( primarySession );
				}
#endif
			}

			Status = Irp->IoStatus.Status = STATUS_SUCCESS;
			Irp->IoStatus.Information = 0;
			DebugTrace2( 0, Dbg2, ("NtfsFsdDispatch: IOCTL_SHUTDOWN return\n") );		

			break;
		}

		default:
				
			ASSERT( FALSE );
			Status = Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
			Irp->IoStatus.Information = 0;
		}

		IoCompleteRequest( Irp, IO_DISK_INCREMENT );
		return Status;
	}

	//if (irpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL && 
	//	IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode == IOCTL_INSERT_PRIMARY_SESSION) {

    //    return NtfsFsdDispatchSwitch( NULL, Irp, FALSE );
	//}

#endif

    DebugTrace(+1, Dbg, "FatFsdDeviceControl\n", 0);

    FsRtlEnterFileSystem();

    TopLevel = FatIsIrpTopLevel( Irp );

    try {

#if __NDAS_FAT__

		if (IoGetCurrentIrpStackLocation(Irp)->MajorFunction == IRP_MJ_DEVICE_CONTROL && 
			IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode == IOCTL_INSERT_PRIMARY_SESSION) {

			IrpContext = FatCreateIrpContext( Irp, FALSE );
		
		} else {

			IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ));
		}

#else
		IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ));
#endif

        Status = FatCommonDeviceControl( IrpContext, Irp );

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

        //
        //  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
        //

        Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
    }

    if (TopLevel) { IoSetTopLevelIrp( NULL ); }

    FsRtlExitFileSystem();

    //
    //  And return to our caller
    //

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

    UNREFERENCED_PARAMETER( VolumeDeviceObject );

    return Status;
}
Exemple #5
0
NTSTATUS
FatFsdCleanup (
    IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine implements the FSD part of closing down a handle to a
    file object.

Arguments:

    VolumeDeviceObject - Supplies the volume device object where the
        file being Cleanup exists

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The FSD status for the IRP

--*/

{
    NTSTATUS Status;
    PIRP_CONTEXT IrpContext = NULL;

    BOOLEAN TopLevel;

    PAGED_CODE();

#if __NDAS_FAT__

	if ((PVOID)FatControlDeviceObject == VolumeDeviceObject) {

		Status = Irp->IoStatus.Status = STATUS_SUCCESS;
		Irp->IoStatus.Information = FILE_OPENED;

		IoCompleteRequest( Irp, IO_DISK_INCREMENT );

		return Status;
	}

#endif

    //
    //  If we were called with our file system device object instead of a
    //  volume device object, just complete this request with STATUS_SUCCESS
    //

    if ( FatDeviceIsFatFsdo( VolumeDeviceObject))  {

        Irp->IoStatus.Status = STATUS_SUCCESS;
        Irp->IoStatus.Information = FILE_OPENED;

        IoCompleteRequest( Irp, IO_DISK_INCREMENT );

        return STATUS_SUCCESS;
    }

    DebugTrace(+1, Dbg, "FatFsdCleanup\n", 0);

    //
    //  Call the common Cleanup routine, with blocking allowed.
    //

    FsRtlEnterFileSystem();

    TopLevel = FatIsIrpTopLevel( Irp );

#if (__NDAS_FAT_PRIMARY__ || __NDAS_FAT_SECONDARY__)

	do {
	
		try {

			if (IrpContext == NULL) { 

				IrpContext = FatCreateIrpContext( Irp, TRUE );
				IrpContext->TopLevel = TopLevel;

#if __NDAS_FAT_PRIMARY__
			{
				ULONG_PTR				stackBottom;
				ULONG_PTR				stackTop;
			    BOOLEAN					validPrimaryRequest = FALSE;
				PPRIMARY_REQUEST_INFO	primaryRequestInfo;
				PIO_STACK_LOCATION		irpSp = IoGetCurrentIrpStackLocation( Irp );
    
				primaryRequestInfo = (PPRIMARY_REQUEST_INFO)IoGetTopLevelIrp();
			    IoGetStackLimits( &stackTop, &stackBottom );

			    if ( (ULONG_PTR)primaryRequestInfo <= stackBottom - sizeof(PRIMARY_REQUEST_INFO)	&&
					 (ULONG_PTR) primaryRequestInfo >= stackTop										&&
					 (!FlagOn( (ULONG_PTR) primaryRequestInfo, 0x3 ))								&&
					 primaryRequestInfo->PrimaryTag == 0xe2027482) {										

					validPrimaryRequest = TRUE;
				}
					
				if (validPrimaryRequest) {
						
					//ASSERT( FatIsTopLevelRequest(IrpContext) );

					IoSetTopLevelIrp( NULL );
					TopLevel = FatIsIrpTopLevel( Irp );
					ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_RECURSIVE_CALL );

					if (IsListEmpty(&VolumeDeviceObject->PrimarySessionQueue)) {

						NDAS_ASSERT( FALSE );
					}

					IrpContext->PrimaryRequestInfo = *primaryRequestInfo;

					DebugTrace2( 0, Dbg, ("primaryRequestInfo = %p\n", primaryRequestInfo) );
				}
			} 
#endif
			}

#if __NDAS_FAT_SECONDARY__

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

				BOOLEAN	secondaryResourceAcquired = FALSE;
				BOOLEAN secondaryRecoveryResourceAcquired = FALSE;

				ASSERT( FatIsTopLevelRequest(IrpContext) );

				SetFlag( IrpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT );

				Status = STATUS_SUCCESS;

				while (TRUE) {
										
					ASSERT( secondaryRecoveryResourceAcquired == FALSE );
					ASSERT( secondaryResourceAcquired == FALSE );

					if (FlagOn(VolumeDeviceObject->Secondary->Flags, SECONDARY_FLAG_RECONNECTING)) {
		
						if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) {

							Status = FatFsdPostRequest( IrpContext, Irp );
							break;
						}
					}
					
					if (FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED)) {

						if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) {

							Status = FatFsdPostRequest( IrpContext, Irp );
							break;
						}

						secondaryRecoveryResourceAcquired 
							= SecondaryAcquireResourceExclusiveLite( IrpContext, 
																	 &VolumeDeviceObject->RecoveryResource, 
																	 BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
								
						if (!FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) {

							SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->RecoveryResource );
							secondaryRecoveryResourceAcquired = FALSE;
							continue;
						}

						secondaryResourceAcquired 
							= SecondaryAcquireResourceExclusiveLite( IrpContext, 
																	 &VolumeDeviceObject->Resource, 
																	 BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
						try {
								
							SecondaryRecoverySessionStart( VolumeDeviceObject->Secondary, IrpContext );
								
						} finally {

							SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->Resource );
							secondaryResourceAcquired = FALSE;

							SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->RecoveryResource );
							secondaryRecoveryResourceAcquired = FALSE;
						}

						continue;
					}

					secondaryResourceAcquired 
						= SecondaryAcquireResourceSharedLite( IrpContext, 
															  &VolumeDeviceObject->Resource, 
															  BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );

					if (secondaryResourceAcquired == FALSE) {

						ASSERT( FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ||
								FlagOn(VolumeDeviceObject->Secondary->Flags, SECONDARY_FLAG_RECONNECTING) );
						continue;
					}

					break;
				}

				if (Status == STATUS_SUCCESS) {
					
					try {

						Status = FatCommonCleanup( IrpContext, Irp );
							
					} finally {

						ASSERT( ExIsResourceAcquiredSharedLite(&VolumeDeviceObject->Resource) );
						SecondaryReleaseResourceLite( NULL, &VolumeDeviceObject->Resource );
					}
				}

			} else
				Status = FatCommonCleanup( IrpContext, Irp );
#else
	        Status = FatCommonCleanup( IrpContext, Irp );
#endif

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

		    //
			//  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
			//

	        Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
		}

	} while (Status == STATUS_CANT_WAIT);
Exemple #6
0
NTSTATUS
FatFsdShutdown (
    IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine implements the FSD part of shutdown.  Note that Shutdown will
    never be done asynchronously so we will never need the Fsp counterpart
    to shutdown.

    This is the shutdown routine for the Fat file system device driver.
    This routine locks the global file system lock and then syncs all the
    mounted volumes.

Arguments:

    VolumeDeviceObject - Supplies the volume device object where the
        file exists

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - Always STATUS_SUCCESS

--*/

{
    NTSTATUS Status;
    PIRP_CONTEXT IrpContext = NULL;

    BOOLEAN TopLevel;

    PAGED_CODE();

    DebugTrace(+1, Dbg, "FatFsdShutdown\n", 0);

    //
    //  Call the common shutdown routine.
    //

    FsRtlEnterFileSystem();

    TopLevel = FatIsIrpTopLevel( Irp );

    try {

        IrpContext = FatCreateIrpContext( Irp, TRUE );

        Status = FatCommonShutdown( IrpContext, Irp );

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

        //
        //  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
        //

        Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
    }

    if (TopLevel) { IoSetTopLevelIrp( NULL ); }

    FsRtlExitFileSystem();

    //
    //  And return to our caller
    //

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

    UNREFERENCED_PARAMETER( VolumeDeviceObject );

    return Status;
}
Exemple #7
0
NTSTATUS
FatFsdPnp (
    IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine implements the FSD part of PnP operations

Arguments:

    VolumeDeviceObject - Supplies the volume device object where the
        file exists

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The FSD status for the IRP

--*/

{
    NTSTATUS Status;
    PIRP_CONTEXT IrpContext = NULL;

    BOOLEAN TopLevel;
    BOOLEAN Wait;

    DebugTrace(+1, Dbg, "FatFsdPnp\n", 0);

    FsRtlEnterFileSystem();

    TopLevel = FatIsIrpTopLevel( Irp );

    try {

        //
        //  We expect there to never be a fileobject, in which case we will always
        //  wait.  Since at the moment we don't have any concept of pending Pnp
        //  operations, this is a bit nitpicky.
        //
        
        if (IoGetCurrentIrpStackLocation( Irp )->FileObject == NULL) {

            Wait = TRUE;

        } else {

            Wait = CanFsdWait( Irp );
        }

        IrpContext = FatCreateIrpContext( Irp, Wait );

        Status = FatCommonPnp( IrpContext, Irp );

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

        //
        //  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
        //

        Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
    }

    if (TopLevel) { IoSetTopLevelIrp( NULL ); }

    FsRtlExitFileSystem();

    //
    //  And return to our caller
    //

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

    UNREFERENCED_PARAMETER( VolumeDeviceObject );

    return Status;
}
Exemple #8
0
NTSTATUS
FatFsdFlushBuffers (
    IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine implements the FSD part of Flush buffers.

Arguments:

    VolumeDeviceObject - Supplies the volume device object where the
        file being flushed exists

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The FSD status for the IRP

--*/

{
    NTSTATUS Status;
    PIRP_CONTEXT IrpContext = NULL;

    BOOLEAN TopLevel;

    PAGED_CODE();

    DebugTrace(+1, Dbg, "FatFsdFlushBuffers\n", 0);

    //
    //  Call the common Cleanup routine, with blocking allowed if synchronous
    //

    FsRtlEnterFileSystem();

    TopLevel = FatIsIrpTopLevel( Irp );

#ifdef __ND_FAT__

	do {
    
		try {

			if (IrpContext == NULL) { 

				IrpContext = FatCreateIrpContext( Irp, CanFsdWait(Irp) );
				IrpContext->TopLevel = TopLevel;
			}

#ifdef __ND_FAT_SECONDARY__

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

				BOOLEAN	secondaryResourceAcquired = FALSE;
				BOOLEAN secondaryRecoveryResourceAcquired = FALSE;

				ASSERT( FatIsTopLevelRequest(IrpContext) );

#ifdef __ND_FAT_DBG__
				ASSERT( FlagOn(IrpContext->NdFatFlags, ND_FAT_IRP_CONTEXT_FLAG_SECONDARY_FILE) );
#endif				

				Status = STATUS_SUCCESS;

				while (TRUE) {
			
					ASSERT( secondaryRecoveryResourceAcquired == FALSE );
					ASSERT( secondaryResourceAcquired == FALSE );

					if (FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) || 
						FlagOn(VolumeDeviceObject->Secondary->Flags, SECONDARY_FLAG_RECONNECTING)) {
		
						if(!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) {

							Status = FatFsdPostRequest( IrpContext, Irp );
							break;
						}
					}
					
					if (FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED)) {
						
						secondaryRecoveryResourceAcquired 
							= SecondaryAcquireResourceExclusiveLite( IrpContext, 
																	 &VolumeDeviceObject->Secondary->RecoveryResource, 
																	 BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
								
						if (!FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) {

							SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->Secondary->RecoveryResource );
							secondaryRecoveryResourceAcquired = FALSE;
							continue;
						}

						secondaryResourceAcquired 
							= SecondaryAcquireResourceExclusiveLite( IrpContext, 
																	 &VolumeDeviceObject->Secondary->Resource, 
																	 BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
						try {
								
							SessionRecovery( VolumeDeviceObject->Secondary, IrpContext );
								
						} finally {

							SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->Secondary->Resource );
							secondaryResourceAcquired = FALSE;

							SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->Secondary->RecoveryResource );
							secondaryRecoveryResourceAcquired = FALSE;
						}

						continue;
					}

					secondaryResourceAcquired 
						= SecondaryAcquireResourceSharedLite( IrpContext, 
															  &VolumeDeviceObject->Secondary->Resource, 
															  BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );

					if (secondaryResourceAcquired == FALSE) {

						ASSERT( FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ||
								FlagOn(VolumeDeviceObject->Secondary->Flags, SECONDARY_FLAG_RECONNECTING) );

						continue;
					}

					break;
				}

				if (Status == STATUS_SUCCESS) {
					
					try {

						Status = FatCommonFlushBuffers( IrpContext, Irp );
							
					} finally {

						ASSERT( ExIsResourceAcquiredSharedLite(&VolumeDeviceObject->Secondary->Resource) );
						SecondaryReleaseResourceLite( NULL, &VolumeDeviceObject->Secondary->Resource );
					}
				}

			} else
				Status = FatCommonFlushBuffers( IrpContext, Irp );
#else
	        Status = FatCommonFlushBuffers( IrpContext, Irp );
#endif
            break;

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

			//
	        //  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
		    //

			Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
		}
	
	} while (Status == STATUS_CANT_WAIT);
Exemple #9
0
NTSTATUS
FatFsdQueryVolumeInformation (
    IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine implements the Fsd part of the NtQueryVolumeInformation API
    call.

Arguments:

    VolumeDeviceObject - Supplies the volume device object where the file
        being queried exists.

    Irp - Supplies the Irp being processed.

Return Value:

    NTSTATUS - The FSD status for the Irp.

--*/

{
    NTSTATUS Status;
    PIRP_CONTEXT IrpContext = NULL;

    BOOLEAN TopLevel;

    PAGED_CODE();

#if __NDAS_FAT__

	if ((PVOID)FatControlDeviceObject == VolumeDeviceObject) {

		Status = Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
		Irp->IoStatus.Information = 0;

		IoCompleteRequest( Irp, IO_DISK_INCREMENT );

		return Status;
	}

#endif

    DebugTrace(+1, Dbg, "FatFsdQueryVolumeInformation\n", 0);

    //
    //  Call the common query routine, with blocking allowed if synchronous
    //

    FsRtlEnterFileSystem();

    TopLevel = FatIsIrpTopLevel( Irp );

#if (__NDAS_FAT_PRIMARY__ || __NDAS_FAT_SECONDARY__)

	do {
    
		try {

			if (IrpContext == NULL) { 

				IrpContext = FatCreateIrpContext( Irp, CanFsdWait(Irp) );
				IrpContext->TopLevel = TopLevel;
			}

#if __NDAS_FAT_SECONDARY__

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

				BOOLEAN	volDoResourceAcquired = FALSE;
				BOOLEAN volDoRecoveryResourceAcquired = FALSE;

				ASSERT( FatIsTopLevelRequest(IrpContext) );

				SetFlag( IrpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT );

				Status = STATUS_SUCCESS;

				for (;;) {
			
					NDAS_ASSERT( volDoRecoveryResourceAcquired == FALSE );
					NDAS_ASSERT( volDoResourceAcquired == FALSE );

					if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) {

						Status = FatFsdPostRequest( IrpContext, Irp );
						break;
					}
									
					if (FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED)) {

						volDoRecoveryResourceAcquired 
							= SecondaryAcquireResourceExclusiveLite( IrpContext, 
																	 &VolumeDeviceObject->RecoveryResource, 
																	 BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
								
						if (!FlagOn(VolumeDeviceObject->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) {

							SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->RecoveryResource );
							volDoRecoveryResourceAcquired = FALSE;
							continue;
						}

						volDoResourceAcquired 
							= SecondaryAcquireResourceExclusiveLite( IrpContext, 
																	 &VolumeDeviceObject->Resource, 
																	 BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
						try {
								
							SecondaryRecoverySessionStart( VolumeDeviceObject->Secondary, IrpContext );
								
						} finally {

							SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->Resource );
							volDoResourceAcquired = FALSE;

							SecondaryReleaseResourceLite( IrpContext, &VolumeDeviceObject->RecoveryResource );
							volDoRecoveryResourceAcquired = FALSE;
						}

						continue;
					}

					volDoResourceAcquired 
						= SecondaryAcquireResourceSharedLite( IrpContext, 
															  &VolumeDeviceObject->Resource, 
															  BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );

					NDAS_ASSERT( volDoResourceAcquired == TRUE );

					break;
				}

				if (Status == STATUS_SUCCESS) {
					
					try {

						Status = FatCommonQueryVolumeInfo( IrpContext, Irp );
							
					} finally {

						ASSERT( ExIsResourceAcquiredSharedLite(&VolumeDeviceObject->Resource) );
						SecondaryReleaseResourceLite( NULL, &VolumeDeviceObject->Resource );
					}
				}

			} else
				Status = FatCommonQueryVolumeInfo( IrpContext, Irp );
#else
	        Status = FatCommonQueryVolumeInfo( IrpContext, Irp );
#endif
            break;

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

			//
	        //  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
		    //

			Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
		}
	
	} while (Status == STATUS_CANT_WAIT);
Exemple #10
0
NTSTATUS
FatFsdClose (
    IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine implements the FSD part of Close.

Arguments:

    VolumeDeviceObject - Supplies the volume device object where the
        file exists

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The FSD status for the IRP

--*/

{
    NTSTATUS Status = STATUS_SUCCESS;
    PIO_STACK_LOCATION IrpSp;
    PFILE_OBJECT FileObject;

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

    BOOLEAN TopLevel;
    BOOLEAN VcbDeleted;

#ifdef __ND_FAT__

	if ((PVOID)FatControlDeviceObject == VolumeDeviceObject) {

		Irp->IoStatus.Status = STATUS_SUCCESS;
		Irp->IoStatus.Information = FILE_OPENED;

		IoCompleteRequest( Irp, IO_DISK_INCREMENT );

		return STATUS_SUCCESS;
	}

#endif

    //
    //  If we were called with our file system device object instead of a
    //  volume device object, just complete this request with STATUS_SUCCESS
    //

    if (FatDeviceIsFatFsdo( VolumeDeviceObject))  {

        Irp->IoStatus.Status = STATUS_SUCCESS;
        Irp->IoStatus.Information = FILE_OPENED;

        IoCompleteRequest( Irp, IO_DISK_INCREMENT );

        return STATUS_SUCCESS;
    }

    DebugTrace(+1, Dbg, "FatFsdClose\n", 0);

    //
    //  Call the common Close routine
    //

    FsRtlEnterFileSystem();

    TopLevel = FatIsIrpTopLevel( Irp );

    //
    //  Get a pointer to the current stack location and the file object
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    FileObject = IrpSp->FileObject;

    //
    //  Decode the file object and set the read-only bit in the Ccb.
    //

    TypeOfOpen = FatDecodeFileObject( FileObject, &Vcb, &Fcb, &Ccb );

    if (Ccb && IsFileObjectReadOnly(FileObject)) {

        SetFlag( Ccb->Flags, CCB_FLAG_READ_ONLY );
    }

    try {

        PCLOSE_CONTEXT CloseContext;

        //
        //  If we are top level, WAIT can be TRUE, otherwise make it FALSE
        //  to avoid deadlocks, unless this is a top
        //  level request not originating from the system process.
        //

        BOOLEAN Wait = TopLevel && (PsGetCurrentProcess() != FatData.OurProcess);

#ifdef __ND_FAT__

		if (Ccb) {
		
			SetFlag( Ccb->NdFatFlags, ND_FAT_CCB_FLAG_CLOSE );

			((PCCB)(FileObject->FsContext2))->FileObject = NULL;
			FileObject->FsContext = NULL;
			FileObject->FsContext2 = NULL;
		}

#endif

        //
        //  Call the common Close routine if we are not delaying this close.
        //

        if ((((TypeOfOpen == UserFileOpen) ||
              (TypeOfOpen == UserDirectoryOpen)) &&
             FlagOn(Fcb->FcbState, FCB_STATE_DELAY_CLOSE) &&
             !FatData.ShutdownStarted) ||
            (FatCommonClose( Vcb, Fcb, Ccb, TypeOfOpen, Wait, &VcbDeleted ) == STATUS_PENDING)) {

            //
            //  Metadata streams have had close contexts preallocated.
            //

            if (TypeOfOpen == VirtualVolumeFile ||
                TypeOfOpen == DirectoryFile ||
                TypeOfOpen == EaFile) {

                CloseContext = FatAllocateCloseContext();
                ASSERT( CloseContext != NULL );
                CloseContext->Free = TRUE;

            } else {

                //
                //  Free up any query template strings before using the close context fields,
                //  which overlap (union)
                //

                FatDeallocateCcbStrings( Ccb);

                CloseContext = &Ccb->CloseContext;
                CloseContext->Free = FALSE;
                
                SetFlag( Ccb->Flags, CCB_FLAG_CLOSE_CONTEXT );
            }

            //
            //  If the status is pending, then let's get the information we
            //  need into the close context we already have bagged, complete
            //  the request, and post it.  It is important we allocate nothing
            //  in the close path.
            //

            CloseContext->Vcb = Vcb;
            CloseContext->Fcb = Fcb;
            CloseContext->TypeOfOpen = TypeOfOpen;

            //
            //  Send it off, either to an ExWorkerThread or to the async
            //  close list.
            //

            FatQueueClose( CloseContext,
                           (BOOLEAN)(Fcb && FlagOn(Fcb->FcbState, FCB_STATE_DELAY_CLOSE)));
        } else {
            
            //
            //  The close proceeded synchronously, so for the metadata objects we
            //  can now drop the close context we preallocated.
            //
            
            if (TypeOfOpen == VirtualVolumeFile ||
                TypeOfOpen == DirectoryFile ||
                TypeOfOpen == EaFile) {

                CloseContext = FatAllocateCloseContext();
                ASSERT( CloseContext != NULL );

                ExFreePool( CloseContext );
            }

        }

        FatCompleteRequest( FatNull, Irp, Status );

    } except(FatExceptionFilter( NULL, GetExceptionInformation() )) {

        //
        //  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.
        //

        Status = FatProcessException( NULL, Irp, GetExceptionCode() );
    }

    if (TopLevel) { IoSetTopLevelIrp( NULL ); }

    FsRtlExitFileSystem();

    //
    //  And return to our caller
    //

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

    UNREFERENCED_PARAMETER( VolumeDeviceObject );

    return Status;
}