Ejemplo n.º 1
0
//  Local support routine
//

VOID
CdQueryNetworkInfo (
    IN PIRP_CONTEXT IrpContext,
    IN PFCB Fcb,
    IN OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
    IN OUT PULONG Length
    )

/*++

 Description:

    This routine performs the query network open information function for Cdfs

Arguments:

    Fcb - Supplies the Fcb being queried, it has been verified

    Buffer - Supplies a pointer to the buffer where the information is to
        be returned

    Length - Supplies the length of the buffer in bytes, and receives the
        remaining bytes free in the buffer upon return.

Return Value:

    None

--*/

{
    PAGED_CODE();

    //
    //  We only support creation, last modify and last write times on Cdfs.
    //

    Buffer->LastWriteTime.QuadPart =
    Buffer->CreationTime.QuadPart =
    Buffer->ChangeTime.QuadPart = Fcb->CreationTime;

    Buffer->LastAccessTime.QuadPart = 0;

    Buffer->FileAttributes = Fcb->FileAttributes;

    //
    //  We get the sizes from the header.  Return a size of zero
    //  for all directories.
    //

    if (FlagOn( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) {

        Buffer->AllocationSize.QuadPart =
        Buffer->EndOfFile.QuadPart = 0;

    } else {

        Buffer->AllocationSize.QuadPart = Fcb->AllocationSize.QuadPart;
        Buffer->EndOfFile.QuadPart = Fcb->FileSize.QuadPart;
    }

    //
    //  Update the length and status output variables
    //

    *Length -= sizeof( FILE_NETWORK_OPEN_INFORMATION );

    return;
}
Ejemplo n.º 2
0
NTSTATUS
CdProcessException (
    IN PIRP_CONTEXT IrpContext OPTIONAL,
    IN PIRP Irp,
    IN NTSTATUS ExceptionCode
    )

/*++

Routine Description:

    This routine processes an exception.  It either completes the request
    with the exception status in the IrpContext, sends this off to the Fsp
    workque or causes it to be retried in the current thread if a verification
    is needed.

    If the volume needs to be verified (STATUS_VERIFY_REQUIRED) and we can
    do the work in the current thread we will translate the status code
    to STATUS_CANT_WAIT to indicate that we need to retry the request.

Arguments:

    Irp - Supplies the Irp being processed

    ExceptionCode - Supplies the normalized exception status being handled

Return Value:

    NTSTATUS - Returns the results of either posting the Irp or the
        saved completion status.

--*/

{
    PDEVICE_OBJECT Device;
    PVPB Vpb;
    PETHREAD Thread;

    ASSERT_OPTIONAL_IRP_CONTEXT( IrpContext );
    ASSERT_IRP( Irp );
    
    //
    //  If there is not an irp context, then complete the request with the
    //  current status code.
    //

    if (!ARGUMENT_PRESENT( IrpContext )) {

        CdCompleteRequest( NULL, Irp, ExceptionCode );
        return ExceptionCode;
    }

    //
    //  Get the real exception status from the IrpContext.
    //

    ExceptionCode = IrpContext->ExceptionStatus;

    //
    //  If we are not a top level request then we just complete the request
    //  with the current status code.
    //

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

        CdCompleteRequest( IrpContext, Irp, ExceptionCode );
        return ExceptionCode;
    }

    //
    //  Check if we are posting this request.  One of the following must be true
    //  if we are to post a request.
    //
    //      - Status code is STATUS_CANT_WAIT and the request is asynchronous
    //          or we are forcing this to be posted.
    //
    //      - Status code is STATUS_VERIFY_REQUIRED and we are at APC level
    //          or higher.  Can't wait for IO in the verify path in this case.
    //
    //  Set the MORE_PROCESSING flag in the IrpContext to keep if from being
    //  deleted if this is a retryable condition.
    //
    //
    //  Note that (children of) CdFsdPostRequest can raise (Mdl allocation).
    //

    try {
    
        if (ExceptionCode == STATUS_CANT_WAIT) {

            if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_FORCE_POST )) {

                ExceptionCode = CdFsdPostRequest( IrpContext, Irp );
            }

        } else if (ExceptionCode == STATUS_VERIFY_REQUIRED) {

            if (KeGetCurrentIrql() >= APC_LEVEL) {

                ExceptionCode = CdFsdPostRequest( IrpContext, Irp );
            }
        }
    }
    except( CdExceptionFilter( IrpContext, GetExceptionInformation() ))  {
    
        ExceptionCode = GetExceptionCode();        
    }
    
    //
    //  If we posted the request or our caller will retry then just return here.
    //

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

        return ExceptionCode;
    }

    ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_MORE_PROCESSING );

    //
    //  Store this error into the Irp for posting back to the Io system.
    //

    Irp->IoStatus.Status = ExceptionCode;

    if (IoIsErrorUserInduced( ExceptionCode )) {

        //
        //  Check for the various error conditions that can be caused by,
        //  and possibly resolved my the user.
        //

        if (ExceptionCode == STATUS_VERIFY_REQUIRED) {

            //
            //  Now we are at the top level file system entry point.
            //
            //  If we have already posted this request then the device to
            //  verify is in the original thread.  Find this via the Irp.
            //

            Device = IoGetDeviceToVerify( Irp->Tail.Overlay.Thread );
            IoSetDeviceToVerify( Irp->Tail.Overlay.Thread, NULL );
            
            //
            //  If there is no device in that location then check in the
            //  current thread.
            //

            if (Device == NULL) {

                Device = IoGetDeviceToVerify( PsGetCurrentThread() );
                IoSetDeviceToVerify( PsGetCurrentThread(), NULL );

                ASSERT( Device != NULL );

                //
                //  Let's not BugCheck just because the driver messes up.
                //

                if (Device == NULL) {

                    ExceptionCode = STATUS_DRIVER_INTERNAL_ERROR;

                    CdCompleteRequest( IrpContext, Irp, ExceptionCode );

                    return ExceptionCode;
                }
            }

            //
            //  CdPerformVerify() will do the right thing with the Irp.
            //  If we return STATUS_CANT_WAIT then the current thread
            //  can retry the request.
            //

            return CdPerformVerify( IrpContext, Irp, Device );
        }

        //
        //  The other user induced conditions generate an error unless
        //  they have been disabled for this request.
        //

        if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_POPUPS )) {

            CdCompleteRequest( IrpContext, Irp, ExceptionCode );

            return ExceptionCode;

        } 
        //
        //  Generate a pop-up.
        //
        else {

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

                Vpb = IoGetCurrentIrpStackLocation( Irp )->FileObject->Vpb;

            } else {

                Vpb = NULL;
            }

            //
            //  The device to verify is either in my thread local storage
            //  or that of the thread that owns the Irp.
            //

            Thread = Irp->Tail.Overlay.Thread;
            Device = IoGetDeviceToVerify( Thread );

            if (Device == NULL) {

                Thread = PsGetCurrentThread();
                Device = IoGetDeviceToVerify( Thread );

                ASSERT( Device != NULL );

                //
                //  Let's not BugCheck just because the driver messes up.
                //

                if (Device == NULL) {

                    CdCompleteRequest( IrpContext, Irp, ExceptionCode );

                    return ExceptionCode;
                }
            }

            //
            //  This routine actually causes the pop-up.  It usually
            //  does this by queuing an APC to the callers thread,
            //  but in some cases it will complete the request immediately,
            //  so it is very important to IoMarkIrpPending() first.
            //

            IoMarkIrpPending( Irp );
            IoRaiseHardError( Irp, Vpb, Device );

            //
            //  We will be handing control back to the caller here, so
            //  reset the saved device object.
            //

            IoSetDeviceToVerify( Thread, NULL );

            //
            //  The Irp will be completed by Io or resubmitted.  In either
            //  case we must clean up the IrpContext here.
            //

            CdCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );
            return STATUS_PENDING;
        }
    }

    //
    //  This is just a run of the mill error.
    //

    CdCompleteRequest( IrpContext, Irp, ExceptionCode );

    return ExceptionCode;
}
Ejemplo n.º 3
0
VOID
CdSetThreadContext (
    IN PIRP_CONTEXT IrpContext,
    IN PTHREAD_CONTEXT ThreadContext
    )

/*++

Routine Description:

    This routine is called at each Fsd/Fsp entry point set up the IrpContext
    and thread local storage to track top level requests.  If there is
    not a Cdfs context in the thread local storage then we use the input one.
    Otherwise we use the one already there.  This routine also updates the
    IrpContext based on the state of the top-level context.

    If the TOP_LEVEL flag in the IrpContext is already set when we are called
    then we force this request to appear top level.

Arguments:

    ThreadContext - Address on stack for local storage if not already present.

    ForceTopLevel - We force this request to appear top level regardless of
        any previous stack value.

Return Value:

    None

--*/

{
    PTHREAD_CONTEXT CurrentThreadContext;
    ULONG_PTR StackTop;
    ULONG_PTR StackBottom;

    PAGED_CODE();

    ASSERT_IRP_CONTEXT( IrpContext );

    //
    //  Get the current top-level irp out of the thread storage.
    //  If NULL then this is the top-level request.
    //

    CurrentThreadContext = (PTHREAD_CONTEXT) IoGetTopLevelIrp();

    if (CurrentThreadContext == NULL) {

        SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_TOP_LEVEL );
    }

    //
    //  Initialize the input context unless we are using the current
    //  thread context block.  We use the new block if our caller
    //  specified this or the existing block is invalid.
    //
    //  The following must be true for the current to be a valid Cdfs context.
    //
    //      Structure must lie within current stack.
    //      Address must be ULONG aligned.
    //      Cdfs signature must be present.
    //
    //  If this is not a valid Cdfs context then use the input thread
    //  context and store it in the top level context.
    //

    IoGetStackLimits( &StackTop, &StackBottom);

    if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TOP_LEVEL ) ||
        (((ULONG_PTR) CurrentThreadContext > StackBottom - sizeof( THREAD_CONTEXT )) ||
         ((ULONG_PTR) CurrentThreadContext <= StackTop) ||
         FlagOn( (ULONG_PTR) CurrentThreadContext, 0x3 ) ||
         (CurrentThreadContext->Cdfs != 0x53464443))) {

        ThreadContext->Cdfs = 0x53464443;
        ThreadContext->SavedTopLevelIrp = (PIRP) CurrentThreadContext;
        ThreadContext->TopLevelIrpContext = IrpContext;
        IoSetTopLevelIrp( (PIRP) ThreadContext );

        IrpContext->TopLevel = IrpContext;
        IrpContext->ThreadContext = ThreadContext;

        SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_TOP_LEVEL_CDFS );

    //
    //  Otherwise use the IrpContext in the thread context.
    //

    } else {

        IrpContext->TopLevel = CurrentThreadContext->TopLevelIrpContext;
    }

    return;
}
Ejemplo n.º 4
0
long PlugInShell_SetPluginState(const unsigned long inNewState)
{
    long macError = eDSNoErr;
    bool isAcquired = false;

    LOG_ENTER("inNewState = 0x%08x (%s)", inNewState, StateToString(inNewState));

    GS_VERIFY_INITIALIZED(macError);

    if (FlagOn(inNewState, ~(kActive | kInactive)))
    {
        LOG("Ignoring unexpected state flags: 0x%08x", FlagOn(inNewState, ~(kActive | kInactive)));
    }

    if (!FlagOn(inNewState, kActive | kInactive))
    {
        // Nothing to do.
        LOG("Nothing to do because inactive/active flags are not specified.");
        macError = eDSNoErr;
        GOTO_CLEANUP();
    }

    if (FlagOn(inNewState, kActive) && FlagOn(inNewState, kInactive))
    {
        LOG_ERROR("Cannot set active and inactive at the same time.");
        macError = ePlugInError;
        GOTO_CLEANUP();
    }

    GS_ACQUIRE_EXCLUSIVE();
    isAcquired = true;

    LOG("Current State = 0x%08x", GlobalState.PluginState);

    if ( (FlagOn(inNewState, kActive | kInactive) == FlagOn(GlobalState.PluginState, kActive | kInactive)) )
    {
        // Nothing to do.
        LOG("Nothing to do because the state matches");
        macError = eDSNoErr;
        GOTO_CLEANUP();
    }

    if ( FlagOn(inNewState, kActive) )
    {
        LOG("Activating");
        macError = Activate();
        GOTO_CLEANUP_ON_MACERROR(macError);

        SetFlag(GlobalState.PluginState, kActive);
        ClearFlag(GlobalState.PluginState, kInactive);
    }
    else if ( FlagOn(inNewState, kInactive) )
    {
        LOG("De-activating");
        macError = Deactivate();
        GOTO_CLEANUP_ON_MACERROR(macError);

        ClearFlag(GlobalState.PluginState, kActive);
        SetFlag(GlobalState.PluginState, kInactive);
    }
    else
    {
        // This should never happen.
        LOG_ERROR("Benign unexpected code path.");
        macError = eDSNoErr;
    }

cleanup:

    if (isAcquired)
    {
        LOG("Final State = 0x%08x", GlobalState.PluginState);
        GS_RELEASE();
    }

    LOG_LEAVE("--> %d", macError);
    return macError;
}
Ejemplo n.º 5
0
__drv_mustHoldCriticalRegion    
NTSTATUS
FatProcessException (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp,
    IN NTSTATUS ExceptionCode
    )

/*++

Routine Description:

    This routine process an exception.  It either completes the request
    with the saved exception status or it sends it off to IoRaiseHardError()

Arguments:

    Irp - Supplies the Irp being processed

    ExceptionCode - Supplies the normalized exception status being handled

Return Value:

    NTSTATUS - Returns the results of either posting the Irp or the
        saved completion status.

--*/

{
    PVCB Vcb;
    PIO_STACK_LOCATION IrpSp;
    FAT_VOLUME_STATE TransitionState = VolumeDirty;
    ULONG SavedFlags = 0;

    PAGED_CODE();

    DebugTrace(0, Dbg, "FatProcessException\n", 0);

    //
    //  If there is not an irp context, we must have had insufficient resources.
    //

    if ( !ARGUMENT_PRESENT( IrpContext ) ) {

        FatCompleteRequest( FatNull, Irp, ExceptionCode );

        return ExceptionCode;
    }

    //
    //  Get the real exception status from IrpContext->ExceptionStatus, and
    //  reset it.
    //

    ExceptionCode = IrpContext->ExceptionStatus;
    FatResetExceptionState( IrpContext );

    //
    //  If this is an Mdl write request, then take care of the Mdl
    //  here so that things get cleaned up properly.  Cc now leaves
    //  the MDL in place so a filesystem can retry after clearing an
    //  internal condition (FAT does not).
    //

    if ((IrpContext->MajorFunction == IRP_MJ_WRITE) &&
        (FlagOn( IrpContext->MinorFunction, IRP_MN_COMPLETE_MDL ) == IRP_MN_COMPLETE_MDL) &&
        (Irp->MdlAddress != NULL)) {

        PIO_STACK_LOCATION LocalIrpSp = IoGetCurrentIrpStackLocation(Irp);

        CcMdlWriteAbort( LocalIrpSp->FileObject, Irp->MdlAddress );
        Irp->MdlAddress = NULL;
    }

    //
    //  If we are going to post the request, we may have to lock down the
    //  user's buffer, so do it here in a try except so that we failed the
    //  request if the LockPages fails.
    //
    //  Also unpin any repinned Bcbs, protected by the try {} except {} filter.
    //

    try {

        SavedFlags = IrpContext->Flags;

        //
        //  Make sure we don't try to write through Bcbs
        //

        SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_WRITE_THROUGH);

        FatUnpinRepinnedBcbs( IrpContext );

        IrpContext->Flags = SavedFlags;

        //
        //  If we will have to post the request, do it here.  Note
        //  that the last thing FatPrePostIrp() does is mark the Irp pending,
        //  so it is critical that we actually return PENDING.  Nothing
        //  from this point to return can fail, so we are OK.
        //
        //  We cannot do a verify operations at APC level because we
        //  have to wait for Io operations to complete.
        //

        if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_RECURSIVE_CALL) &&
            (((ExceptionCode == STATUS_VERIFY_REQUIRED) && KeAreAllApcsDisabled()) ||
             (ExceptionCode == STATUS_CANT_WAIT))) {

            ExceptionCode = FatFsdPostRequest( IrpContext, Irp );
        }

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

        ExceptionCode = IrpContext->ExceptionStatus;
        IrpContext->ExceptionStatus = 0;

        IrpContext->Flags = SavedFlags;
    }

    //
    //  If we posted the request, just return here.
    //

    if (ExceptionCode == STATUS_PENDING) {

        return ExceptionCode;
    }

    Irp->IoStatus.Status = ExceptionCode;

    //
    //  If this request is not a "top-level" irp, just complete it.
    //

    if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_RECURSIVE_CALL)) {

        //
        //  If there is a cache operation above us, commute verify
        //  to a lock conflict.  This will cause retries so that
        //  we have a chance of getting through without needing
        //  to return an unaesthetic error for the operation.
        //

        if (IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP &&
            ExceptionCode == STATUS_VERIFY_REQUIRED) {

            ExceptionCode = STATUS_FILE_LOCK_CONFLICT;
        }
        
        FatCompleteRequest( IrpContext, Irp, ExceptionCode );

        return ExceptionCode;
    }

    if (IoIsErrorUserInduced(ExceptionCode)) {

        //
        //  Check for the various error conditions that can be caused by,
        //  and possibly resolved by the user.
        //

        if (ExceptionCode == STATUS_VERIFY_REQUIRED) {

            PDEVICE_OBJECT Device;

            DebugTrace(0, Dbg, "Perform Verify Operation\n", 0);

            //
            //  Now we are at the top level file system entry point.
            //
            //  Grab the device to verify from the thread local storage
            //  and stick it in the information field for transportation
            //  to the fsp.  We also clear the field at this time.
            //

            Device = IoGetDeviceToVerify( Irp->Tail.Overlay.Thread );
            IoSetDeviceToVerify( Irp->Tail.Overlay.Thread, NULL );

            if ( Device == NULL ) {

                Device = IoGetDeviceToVerify( PsGetCurrentThread() );
                IoSetDeviceToVerify( PsGetCurrentThread(), NULL );

                ASSERT( Device != NULL );
            }

            //
            //  Let's not BugCheck just because the driver messed up.
            //

            if (Device == NULL) {

                ExceptionCode = STATUS_DRIVER_INTERNAL_ERROR;

                FatCompleteRequest( IrpContext, Irp, ExceptionCode );

                return ExceptionCode;
            }

            //
            //  FatPerformVerify() will do the right thing with the Irp.

            return FatPerformVerify( IrpContext, Irp, Device );
        }

        //
        //  The other user induced conditions generate an error unless
        //  they have been disabled for this request.
        //

        if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_POPUPS)) {

            FatCompleteRequest( IrpContext, Irp, ExceptionCode );

            return ExceptionCode;

        } else {

            //
            //  Generate a pop-up
            //

            PDEVICE_OBJECT RealDevice;
            PVPB Vpb;
            PETHREAD Thread;

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

                Vpb = IoGetCurrentIrpStackLocation(Irp)->FileObject->Vpb;

            } else {

                Vpb = NULL;
            }

            //
            //  The device to verify is either in my thread local storage
            //  or that of the thread that owns the Irp.
            //

            Thread = Irp->Tail.Overlay.Thread;
            RealDevice = IoGetDeviceToVerify( Thread );

            if ( RealDevice == NULL ) {

                Thread = PsGetCurrentThread();
                RealDevice = IoGetDeviceToVerify( Thread );

                ASSERT( RealDevice != NULL );
            }

            //
            //  Let's not BugCheck just because the driver messed up.
            //

            if (RealDevice == NULL) {

                FatCompleteRequest( IrpContext, Irp, ExceptionCode );

                return ExceptionCode;
            }

            //
            //  This routine actually causes the pop-up.  It usually
            //  does this by queuing an APC to the callers thread,
            //  but in some cases it will complete the request immediately,
            //  so it is very important to IoMarkIrpPending() first.
            //

            IoMarkIrpPending( Irp );
            IoRaiseHardError( Irp, Vpb, RealDevice );

            //
            //  We will be handing control back to the caller here, so
            //  reset the saved device object.
            //

            IoSetDeviceToVerify( Thread, NULL );

            //
            //  The Irp will be completed by Io or resubmitted.  In either
            //  case we must clean up the IrpContext here.
            //

            FatDeleteIrpContext( IrpContext );
            return STATUS_PENDING;
        }
    }

    //
    //  This is just a run of the mill error.  If is a STATUS that we
    //  raised ourselves, and the information would be use for the
    //  user, raise an informational pop-up.
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );
    Vcb = IrpContext->Vcb;

    //
    //  Now, if the Vcb is unknown to us this means that the error was raised
    //  in the process of a mount and before we even had a chance to build
    //  a full Vcb - and was really handled there.
    //

    if (Vcb != NULL) {

        if ( !FatDeviceIsFatFsdo( IrpSp->DeviceObject) &&
             !NT_SUCCESS(ExceptionCode) &&
             !FsRtlIsTotalDeviceFailure(ExceptionCode) ) {

            TransitionState = VolumeDirtyWithSurfaceTest;
        }

        //
        //  If this was a STATUS_FILE_CORRUPT or similar error indicating some
        //  nastiness out on the media, then mark the volume permanently dirty.
        //

        if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_POPUPS) &&
            ( TransitionState == VolumeDirtyWithSurfaceTest ||
              (ExceptionCode == STATUS_FILE_CORRUPT_ERROR) ||
              (ExceptionCode == STATUS_DISK_CORRUPT_ERROR) ||
              (ExceptionCode == STATUS_EA_CORRUPT_ERROR) ||
              (ExceptionCode == STATUS_INVALID_EA_NAME) ||
              (ExceptionCode == STATUS_EA_LIST_INCONSISTENT) ||
              (ExceptionCode == STATUS_NO_EAS_ON_FILE) )) {

            ASSERT( NodeType(Vcb) == FAT_NTC_VCB );
            ASSERT( !FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_RECURSIVE_CALL));

            SetFlag( Vcb->VcbState, VCB_STATE_FLAG_MOUNTED_DIRTY );
            SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);

            //
            //  Do the "dirty" work, ignoring any error.  We need to take the Vcb here
            //  to synchronize against the verify path tearing things down, since
            //  we dropped all synchronization when backing up due to the exception.
            //

            FatAcquireExclusiveVcbNoOpCheck( IrpContext, Vcb);
            
            try {

                if (VcbGood == Vcb->VcbCondition) {

                    FatMarkVolume( IrpContext, Vcb, TransitionState );
                }
            } 
            except( FatExceptionFilter( IrpContext, GetExceptionInformation() ) ) {

                NOTHING;
            }

            FatReleaseVcb( IrpContext, Vcb);
        }
    }
Ejemplo n.º 6
0
NTSTATUS
NdasNtfsSecondaryCommonQueryVolumeInfo (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )
{
	NTSTATUS					status;
	PVOLUME_DEVICE_OBJECT		volDo = CONTAINING_RECORD( IrpContext->Vcb, VOLUME_DEVICE_OBJECT, Vcb );
	BOOLEAN						secondarySessionResourceAcquired = FALSE;

	PIO_STACK_LOCATION			irpSp = IoGetCurrentIrpStackLocation(Irp);
	PFILE_OBJECT				fileObject = irpSp->FileObject;

	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;

	LARGE_INTEGER				timeOut;

	struct QueryVolume			queryVolume;
	PVOID						inputBuffer = NULL;
	ULONG						inputBufferLength = 0;
	PVOID						outputBuffer = Irp->AssociatedIrp.SystemBuffer;
	ULONG						outputBufferLength;


	ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );

	if(volDo->Secondary == NULL) {

		status = Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
		Irp->IoStatus.Information = 0;
		return status;
	}

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

		typeOfOpen = NtfsDecodeFileObject( IrpContext, 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 );
		}

		queryVolume.FsInformationClass	= irpSp->Parameters.QueryVolume.FsInformationClass;
		queryVolume.Length				= irpSp->Parameters.QueryVolume.Length;
		outputBufferLength				= queryVolume.Length;

		secondaryRequest = AllocateWinxpSecondaryRequest( volDo->Secondary, 
														  IRP_MJ_QUERY_VOLUME_INFORMATION,
														  outputBufferLength );

		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_QUERY_VOLUME_INFORMATION, 
										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->QueryVolume.Length			   = outputBufferLength;
		ndfsWinxpRequestHeader->QueryVolume.FsInformationClass = queryVolume.FsInformationClass;

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

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

		if(status != STATUS_SUCCESS) {

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

		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 = NTOHL(ndfsWinxpReplytHeader->Status4);
		Irp->IoStatus.Information = NTOHL(ndfsWinxpReplytHeader->Information32);

		if (status != STATUS_SUCCESS)
			DebugTrace( 0, Dbg, ("Status = %x, Irp->IoStatus.Information = %d, queryVolume.FsInformationClass =%d\n", 
								  status, Irp->IoStatus.Information, queryVolume.FsInformationClass) );
		
		if(NTOHL(secondaryRequest->NdfsReplyHeader.MessageSize4) - 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,
						   (UINT8 *)(ndfsWinxpReplytHeader+1),
						   Irp->IoStatus.Information );
		
		}
		else
			ASSERT( NTOHL(ndfsWinxpReplytHeader->Information32) == 0 );

try_exit:  NOTHING;
    } finally {

		if( secondarySessionResourceAcquired == TRUE ) {

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

		if(secondaryRequest)
			DereferenceSecondaryRequest( secondaryRequest );
	}

	return status;
}
Ejemplo n.º 7
0
NTSTATUS
NdasNtfsSecondaryCommonQueryEa (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )
{
	NTSTATUS					status;
	PVOLUME_DEVICE_OBJECT		volDo = CONTAINING_RECORD( IrpContext->Vcb, VOLUME_DEVICE_OBJECT, Vcb );
	BOOLEAN						secondarySessionResourceAcquired = FALSE;

	PIO_STACK_LOCATION			irpSp = IoGetCurrentIrpStackLocation(Irp);
	PFILE_OBJECT				fileObject = irpSp->FileObject;

	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;
	UINT8							*ndfsWinxpRequestData;

	LARGE_INTEGER				timeOut;

	struct QueryEa				queryEa;
	PVOID						inputBuffer;
	ULONG						inputBufferLength;
	PVOID						outputBuffer = NtfsMapUserBuffer (Irp );
	ULONG						outputBufferLength;

	ULONG						bufferLength;
	ULONG						returnedDataSize;


	ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );


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

		return NtfsPostRequest( IrpContext, Irp );
	}


	if(volDo->Secondary == NULL) {

		status = Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
		Irp->IoStatus.Information = 0;
		return status;
	}

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

		typeOfOpen = NtfsDecodeFileObject( IrpContext, 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 );
		}

		queryEa.EaIndex			= irpSp->Parameters.QueryEa.EaIndex;
		queryEa.EaList			= irpSp->Parameters.QueryEa.EaList;
		queryEa.EaListLength	= irpSp->Parameters.QueryEa.EaListLength;
		queryEa.Length			= irpSp->Parameters.QueryEa.Length;

		inputBuffer				= queryEa.EaList;
		outputBufferLength		= queryEa.Length;

		if(inputBuffer != NULL) {

			PFILE_GET_EA_INFORMATION	fileGetEa = (PFILE_GET_EA_INFORMATION)inputBuffer;

			inputBufferLength = 0;
		
			while(fileGetEa->NextEntryOffset) {

				inputBufferLength += fileGetEa->NextEntryOffset;
				fileGetEa = (PFILE_GET_EA_INFORMATION)((UINT8 *)fileGetEa + fileGetEa->NextEntryOffset);
			}

			inputBufferLength += (sizeof(FILE_GET_EA_INFORMATION) - sizeof(CHAR) + fileGetEa->EaNameLength);
		}
		else
			inputBufferLength = 0;

		DebugTrace( 0, Dbg,
			("NdasNtfsSecondaryCommonQueryEa: BooleanFlagOn(IrpSp->Flags, SL_INDEX_SPECIFIED) = %d queryEa.EaIndex = %d queryEa.EaList = %p queryEa.Length = %d, inputBufferLength = %d\n",
			 BooleanFlagOn(irpSp->Flags, SL_INDEX_SPECIFIED), queryEa.EaIndex, queryEa.EaList, queryEa.EaListLength, inputBufferLength) );

		bufferLength = (inputBufferLength >= outputBufferLength) ? inputBufferLength : outputBufferLength;

		ASSERT( bufferLength <= volDo->Secondary->Thread.SessionContext.PrimaryMaxDataSize );

		secondaryRequest = AllocateWinxpSecondaryRequest( volDo->Secondary, 
														  IRP_MJ_QUERY_EA,
														  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_QUERY_EA, 
										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->QueryEa.Length			= queryEa.Length;
		ndfsWinxpRequestHeader->QueryEa.EaIndex			= queryEa.EaIndex;
		ndfsWinxpRequestHeader->QueryEa.EaListLength	= queryEa.EaListLength;

		ndfsWinxpRequestData = (UINT8 *)(ndfsWinxpRequestHeader+1);
		RtlCopyMemory( ndfsWinxpRequestData, inputBuffer, inputBufferLength );

		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 = NTOHL(ndfsWinxpReplytHeader->Status4);
		Irp->IoStatus.Information = NTOHL(ndfsWinxpReplytHeader->Information32);

		returnedDataSize = NTOHL(secondaryRequest->NdfsReplyHeader.MessageSize4) - sizeof(NDFS_REPLY_HEADER) - sizeof(NDFS_WINXP_REPLY_HEADER);

		if(returnedDataSize) {

			PFILE_FULL_EA_INFORMATION	fileFullEa = (PFILE_FULL_EA_INFORMATION)(ndfsWinxpReplytHeader+1);

			while(fileFullEa->NextEntryOffset) {

			DebugTrace( 0, Dbg, ("getEa scb->FullPathName = %wZ, fileFullea->EaName = %ws\n", &ccb->Lcb->ExactCaseLink.LinkName, &fileFullEa->EaName[0]) );
				fileFullEa = (PFILE_FULL_EA_INFORMATION)((UINT8 *)fileFullEa + fileFullEa->NextEntryOffset);
			}

			DebugTrace( 0, Dbg, ("getEa scb->FullPathName = %wZ, fileFullea->EaName = %ws\n", &ccb->Lcb->ExactCaseLink.LinkName, &fileFullEa->EaName[0]) );

			ASSERT( returnedDataSize <= ADD_ALIGN8(queryEa.Length) );
			ASSERT( outputBuffer );

			RtlCopyMemory( outputBuffer,
						   (UINT8 *)(ndfsWinxpReplytHeader+1),
						   (returnedDataSize < queryEa.Length) ? returnedDataSize : queryEa.Length );
		}

try_exit:  NOTHING;
    } finally {

		if( secondarySessionResourceAcquired == TRUE ) {

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

		if(secondaryRequest)
			DereferenceSecondaryRequest( secondaryRequest );
	}

	return status;
}
Ejemplo n.º 8
0
VOID
PrimarySessionThreadProc (
	IN PPRIMARY_SESSION PrimarySession
	)
{
	BOOLEAN		primarySessionTerminate = FALSE;
	NTSTATUS	status;
	_U16		slotIndex;
	PLIST_ENTRY	primarySessionRequestEntry;


	ASSERT( SESSION_SLOT_COUNT == 1 );
	ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

	DebugTrace2( 0, Dbg2, ("PrimarySessionThreadProc: Start PrimarySession = %p\n", PrimarySession) );
	
	PrimarySession_Reference( PrimarySession );

	SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_INITIALIZING );
	
	InitializeListHead( &PrimarySession->Thread.OpenedFileQueue );
	KeInitializeSpinLock( &PrimarySession->Thread.OpenedFileQSpinLock );

	KeInitializeEvent( &PrimarySession->Thread.WorkCompletionEvent, NotificationEvent, FALSE );

	PrimarySession->SessionContext.SessionSlotCount = SESSION_SLOT_COUNT;

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

		PrimarySession->Thread.SessionSlot[slotIndex].State = SLOT_WAIT;
		PrimarySession->Thread.IdleSlotCount ++;
	}

	ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_INITIALIZING );
	SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_START );
	SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED );

	KeSetEvent( &PrimarySession->ReadyEvent, IO_DISK_INCREMENT, FALSE );

	status = LpxTdiRecvWithCompletionEvent( PrimarySession->ConnectionFileObject,
										    &PrimarySession->Thread.TdiReceiveContext,
										    (PUCHAR)&PrimarySession->Thread.NdfsRequestHeader,
										    sizeof(NDFS_REQUEST_HEADER),
										    0,
										    NULL,
										    NULL );

	if (NT_SUCCESS(status)) {

		PrimarySession->Thread.TdiReceiving = TRUE;
	
	} else {
	
		ASSERT( NDASFAT_BUG );
		SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
		primarySessionTerminate = TRUE;
	} 

	while (primarySessionTerminate == FALSE) {

		PKEVENT				events[3];
		LONG				eventCount;
		NTSTATUS			eventStatus;
		LARGE_INTEGER		timeOut;


		ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

		eventCount = 0;

		events[eventCount++] = &PrimarySession->RequestEvent;

		if (!FlagOn(PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOPPING)) {

			events[eventCount++] = &PrimarySession->Thread.WorkCompletionEvent;

			if (FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN)) {
			
				if (PrimarySession->Thread.IdleSlotCount == PrimarySession->SessionContext.SessionSlotCount) {

					CloseOpenFiles( PrimarySession, TRUE );
				
					KeSetEvent( &PrimarySession->Thread.ShutdownPrimarySessionRequest->CompleteEvent, 
								IO_DISK_INCREMENT, 
								FALSE );

					SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN_WAIT );
					ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN );
				}
			}	 
		
			if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN_WAIT)) {

				if (PrimarySession->Thread.TdiReceiving == TRUE) {

					ASSERT( PrimarySession->Thread.IdleSlotCount != 0 );
					events[eventCount++] = &PrimarySession->Thread.TdiReceiveContext.CompletionEvent;
				}
			}

			ASSERT( eventCount <= THREAD_WAIT_OBJECTS );
		}

		timeOut.QuadPart = -5*HZ;
		eventStatus = KeWaitForMultipleObjects( eventCount, 
												events, 
												WaitAny, 
												Executive, 
												KernelMode,
												TRUE,
												&timeOut,
												NULL );

#if 0
		if (!FlagOn(PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOPPING)) {

			if (eventStatus == STATUS_TIMEOUT || eventStatus == 2) {
			
				if (PrimarySession->Thread.SessionState == SESSION_TREE_CONNECT) {
				
					ASSERT( PrimarySession->NetdiskPartition );
				
					if (!(PrimarySession->NetdiskPartition->NetdiskVolume[NETDISK_PRIMARY].VolumeState == VolumeMounted || 
						  PrimarySession->NetdiskPartition->NetdiskVolume[NETDISK_SECONDARY2PRIMARY].VolumeState == VolumeMounted)) {

						DebugTrace2( 0, Dbg2,
									   ("Netdisk Volume is unmounted\n") );

						if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN_WAIT))
							primarySessionTerminate = TRUE;
		
						continue;
					}
				}
			}
		}

#endif

		if (eventStatus == STATUS_TIMEOUT) {

			continue;
		}

		if (!NT_SUCCESS(eventStatus) || eventStatus >= eventCount) {

			NdasFatDbgBreakPoint();
			SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
			primarySessionTerminate = TRUE;
			continue;
		}
		
		KeClearEvent( events[eventStatus] );

		if (eventStatus == 0) {

			while (primarySessionRequestEntry = ExInterlockedRemoveHeadList( &PrimarySession->RequestQueue,
																			 &PrimarySession->RequestQSpinLock)) {

				PPRIMARY_SESSION_REQUEST	primarySessionRequest;
			
				primarySessionRequest = CONTAINING_RECORD( primarySessionRequestEntry,
														   PRIMARY_SESSION_REQUEST,
														   ListEntry );

				if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DISCONNECT ||
					primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DISCONNECT_AND_TERMINATE) {

					DebugTrace2( 0, Dbg2, 
								   ((primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DISCONNECT) ?
								   ("PRIMARY_SESSION_REQ_DISCONNECT: DisconnectFromSecondary\n") :
									("PRIMARY_SESSION_REQ_DISCONNECT_AND_TERMINATE: DisconnectFromSecondary\n")) );

					if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED)) {

						DisconnectFromSecondary( PrimarySession );
						ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED );
						SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED );
					}

					if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DISCONNECT_AND_TERMINATE)
						primarySessionTerminate = TRUE;

					if (primarySessionRequest->Synchronous == TRUE)
						KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
					else
						DereferencePrimarySessionRequest( primarySessionRequest );

				} else if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DOWN) {
					
					SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_STOPED );
					primarySessionTerminate = TRUE;

					if (primarySessionRequest->Synchronous == TRUE)
						KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
					else
						DereferencePrimarySessionRequest( primarySessionRequest );
				
				} else if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_SHUTDOWN) {

					DebugTrace2( 0, Dbg, ("PrimarySessionThreadProc: PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN\n") );
					SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN );

					ASSERT (primarySessionRequest->Synchronous == TRUE);

					PrimarySession->Thread.ShutdownPrimarySessionRequest = primarySessionRequest;

					if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED)) {

						DisconnectFromSecondary( PrimarySession );
						ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED );
						SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED );
					}

				} else if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_STOPPING) {

					SetFlag( PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOPPING );
					
					if (PrimarySession->IsLocalAddress == FALSE) {

						CloseOpenFiles( PrimarySession, FALSE );
					}

					if (primarySessionRequest->Synchronous == TRUE)
						KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
					else
						DereferencePrimarySessionRequest( primarySessionRequest );

				} else if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_CANCEL_STOPPING) {

					ClearFlag( PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOPPING );

					if (primarySessionRequest->Synchronous == TRUE)
						KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
					else
						DereferencePrimarySessionRequest( primarySessionRequest );

				} else {

					ASSERT( NDASFAT_BUG );
					SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
				}
			}

			continue;
		
		} else if (eventStatus == 1) {

			while (TRUE) {
	
				for (slotIndex = 0; slotIndex < PrimarySession->SessionContext.SessionSlotCount; slotIndex ++) {

					if (PrimarySession->Thread.SessionSlot[slotIndex].State == SLOT_FINISH)
						break;
				}

				if (slotIndex == PrimarySession->SessionContext.SessionSlotCount)
					break;
			
				PrimarySession->Thread.SessionSlot[slotIndex].State = SLOT_WAIT;
				PrimarySession->Thread.IdleSlotCount ++;

				if (PrimarySession->Thread.SessionSlot[slotIndex].Status == STATUS_SUCCESS) {

					PNDFS_REPLY_HEADER		ndfsReplyHeader;

					ndfsReplyHeader = (PNDFS_REPLY_HEADER)PrimarySession->Thread.SessionSlot[slotIndex].ReplyMessageBuffer;
										
					PrimarySession->Thread.SessionSlot[slotIndex].Status
						= SendNdfsWinxpMessage( PrimarySession,
												ndfsReplyHeader,
												PrimarySession->Thread.SessionSlot[slotIndex].NdfsWinxpReplyHeader,
												PrimarySession->Thread.SessionSlot[slotIndex].ReplyDataSize,
												slotIndex );

				}
	
				if (PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool) {

					ExFreePool(PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool);	
					PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool = NULL;
					PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePoolLength = 0;
				}
		
				if (PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool) {

					ExFreePool(PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool);	
					PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool = NULL;
					PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePoolLength = 0;
				}

				if (!(PrimarySession->Thread.SessionSlot[slotIndex].Status == STATUS_SUCCESS || 
					  PrimarySession->Thread.SessionSlot[slotIndex].Status == STATUS_PENDING)) {

					SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );

#if 0
					if (PrimarySession->NetdiskPartition) {

						NetdiskManager_ReturnPrimaryPartition( GlobalLfs.NetdiskManager, 
															   PrimarySession,
															   PrimarySession->NetdiskPartition, 
															   PrimarySession->IsLocalAddress );

						PrimarySession->NetdiskPartition = NULL;
					}
#endif

					primarySessionTerminate = TRUE;
					break;		
				 }
				
				if (PrimarySession->Thread.SessionState == SESSION_CLOSED) {

#if 0
					if (PrimarySession->NetdiskPartition) {

						NetdiskManager_ReturnPrimaryPartition( GlobalLfs.NetdiskManager, 
															   PrimarySession,
															   PrimarySession->NetdiskPartition, 
															   PrimarySession->IsLocalAddress );
	
						PrimarySession->NetdiskPartition = NULL;
					}
#endif

					primarySessionTerminate = TRUE;
					break;		
				}

				if (PrimarySession->Thread.SessionSlot[slotIndex].Status == STATUS_SUCCESS) {

					if (PrimarySession->Thread.TdiReceiving == FALSE) {

						status = LpxTdiRecvWithCompletionEvent( PrimarySession->ConnectionFileObject,
															    &PrimarySession->Thread.TdiReceiveContext,
															    (PUCHAR)&PrimarySession->Thread.NdfsRequestHeader,
															    sizeof(NDFS_REQUEST_HEADER),
															    0,
															    NULL,
															    NULL );

						if (!NT_SUCCESS(status)) {

							ASSERT( NDASFAT_BUG );

							SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
							primarySessionTerminate = TRUE;
							break;
						}
						
						PrimarySession->Thread.TdiReceiving = TRUE;
					}
				}
			}		
		
			continue;
		
		} else {

			ASSERT( eventStatus == 2 );  // Receive Event
			ASSERT( !FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN_WAIT) &&
				    !FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN) );

			if (PrimarySession->Thread.TdiReceiveContext.Result != sizeof(NDFS_REQUEST_HEADER)) {

				DebugTrace2( 0, Dbg,
							   ("DispatchRequest: Disconnected, PrimarySession = Data received:%d\n",
							   PrimarySession->Thread.TdiReceiveContext.Result) );

				SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED );
				primarySessionTerminate = TRUE;
				
				continue;		
			}

			PrimarySession->Thread.TdiReceiving = FALSE;

#if 0
			if (PrimarySession->NetdiskPartition) {

				PENABLED_NETDISK EnabledNetdisk = PrimarySession->NetdiskPartition->EnabledNetdisk;
				
				ASSERT( EnabledNetdisk );

				if (NetdiskManager_IsStoppedNetdisk(GlobalLfs.NetdiskManager, EnabledNetdisk)) {
				    
					DebugTrace2( 0, Dbg2,
								   ("PrimarySessionThread: %p Netdisk is stopped\n", PrimarySession) );

					DebugTrace2( 0, Dbg2, ("DispatchWinXpRequest: Netdisk is stopped.\n") );

					if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED)) { 
					
						// no other way to notify secondary about unmount without break backward compatability.
						
						DebugTrace2( 0, Dbg2, ("IsStoppedNetdisk: DisconnectFromSecondary\n") );
						DisconnectFromSecondary( PrimarySession );
						ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED );
						SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED );
					}

					primarySessionTerminate = TRUE;
					continue;
				}
			} 

#endif

			status = DispatchRequest( PrimarySession );

			if (!(status == STATUS_SUCCESS || status == STATUS_PENDING)) {

				primarySessionTerminate = TRUE;
				continue;		
			}

			if (PrimarySession->Thread.SessionState == SESSION_CLOSED) {

				primarySessionTerminate = TRUE;
				continue;		
			}

			if (status == STATUS_SUCCESS) {

				if (PrimarySession->Thread.TdiReceiving == FALSE) {

					status = LpxTdiRecvWithCompletionEvent( PrimarySession->ConnectionFileObject,
														    &PrimarySession->Thread.TdiReceiveContext,
														    (PUCHAR)&PrimarySession->Thread.NdfsRequestHeader,
														    sizeof(NDFS_REQUEST_HEADER),
														    0,
														    NULL,
														    NULL );

					if (!NT_SUCCESS(status)) {

						SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
						primarySessionTerminate = TRUE;
					}

					PrimarySession->Thread.TdiReceiving = TRUE;
				}
			}
			
			continue;
		}
	}

	ExAcquireFastMutexUnsafe( &PrimarySession->FastMutex );
	SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_STOPED );
	ExReleaseFastMutexUnsafe( &PrimarySession->FastMutex );

	while (TRUE) {

		LARGE_INTEGER	timeOut;
		NTSTATUS		eventStatus;


		if (PrimarySession->Thread.IdleSlotCount == PrimarySession->SessionContext.SessionSlotCount)
			break;

		timeOut.QuadPart = -10*HZ;
		eventStatus = KeWaitForSingleObject( &PrimarySession->Thread.WorkCompletionEvent,
											 Executive,
											 KernelMode,
											 FALSE,
											 &timeOut );

		KeClearEvent( &PrimarySession->Thread.WorkCompletionEvent );

		if (eventStatus == STATUS_TIMEOUT) {

			ASSERT( NDASFAT_UNEXPECTED );
			continue;
		}

		while (TRUE) {
	
			for (slotIndex = 0; slotIndex < PrimarySession->SessionContext.SessionSlotCount; slotIndex++) {

				if (PrimarySession->Thread.SessionSlot[slotIndex].State == SLOT_FINISH)
					break;
			}

			if (slotIndex == PrimarySession->SessionContext.SessionSlotCount)
				break;

			DebugTrace2( 0, Dbg, ("PrimarySessionThreadProc: eventStatus = %d\n", eventStatus) );
			
			PrimarySession->Thread.SessionSlot[slotIndex].State = SLOT_WAIT;
			PrimarySession->Thread.IdleSlotCount++;

			if (PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool) {

				ExFreePool( PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool );	
				PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool = NULL;
				PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePoolLength = 0;
			}
		
			if (PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool) {

				ExFreePool( PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool );	
				PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool = NULL;
				PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePoolLength = 0;
			}
		}		
	}
	
	if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED)) {

		DebugTrace2( 0, Dbg2, ("PsTerminateSystemThread: DisconnectFromSecondary\n") );
		DisconnectFromSecondary( PrimarySession );
		ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED );
		SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED );
	}

	CloseOpenFiles( PrimarySession, TRUE );

	while (primarySessionRequestEntry = ExInterlockedRemoveHeadList( &PrimarySession->RequestQueue,
																	 &PrimarySession->RequestQSpinLock)) {

		PPRIMARY_SESSION_REQUEST	primarySessionRequest;
			
		primarySessionRequest = CONTAINING_RECORD( primarySessionRequestEntry,
												   PRIMARY_SESSION_REQUEST,
												   ListEntry );

		if (primarySessionRequest->Synchronous == TRUE)
			KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
		else
			DereferencePrimarySessionRequest( primarySessionRequest );
	}

#if 0
	if (PrimarySession->NetdiskPartition) {

		NetdiskManager_ReturnPrimaryPartition( GlobalLfs.NetdiskManager,
											   PrimarySession,
											   PrimarySession->NetdiskPartition, 
											   PrimarySession->IsLocalAddress );

		PrimarySession->NetdiskPartition = NULL;
	}
#endif

	DebugTrace2( 0, Dbg2,
				   ("PrimarySessionThreadProc: PsTerminateSystemThread PrimarySession = %p\n", 
				    PrimarySession) );

	SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_TERMINATED );

	PrimarySession_Dereference( PrimarySession );

	PsTerminateSystemThread( STATUS_SUCCESS );
}
Ejemplo n.º 9
0
NTSTATUS
DokanQueryDirectory(
	__in PDEVICE_OBJECT DeviceObject,
	__in PIRP			Irp)
{
	PFILE_OBJECT		fileObject;
	PIO_STACK_LOCATION	irpSp;
	PDokanVCB			vcb;
	PDokanCCB			ccb;
	PDokanFCB			fcb;
	NTSTATUS			status;
	PUNICODE_STRING		searchPattern;
	ULONG				eventLength;
	PEVENT_CONTEXT		eventContext;
	ULONG				index;
	BOOLEAN				initial;
	ULONG				flags = 0;

	irpSp		= IoGetCurrentIrpStackLocation(Irp);
	fileObject	= irpSp->FileObject;

	vcb = DeviceObject->DeviceExtension;
	if (GetIdentifierType(vcb) != VCB) {
		return STATUS_INVALID_PARAMETER;
	}

	ccb = fileObject->FsContext2;
	if (ccb == NULL) {
		return STATUS_INVALID_PARAMETER;
	}
	ASSERT(ccb != NULL);

	fcb = ccb->Fcb;
	ASSERT(fcb != NULL);

	if (irpSp->Flags & SL_INDEX_SPECIFIED) {
		DDbgPrint("  index specified %d\n", irpSp->Parameters.QueryDirectory.FileIndex);
	}
	if (irpSp->Flags & SL_RETURN_SINGLE_ENTRY) {
		DDbgPrint("  return single entry\n");
	}
	if (irpSp->Flags & SL_RESTART_SCAN) {
		DDbgPrint("  restart scan\n");
	}
	if (irpSp->Parameters.QueryDirectory.FileName) {
		DDbgPrint("  pattern:%wZ\n", irpSp->Parameters.QueryDirectory.FileName);
	}
	
	switch (irpSp->Parameters.QueryDirectory.FileInformationClass) {
	case FileDirectoryInformation:
		DDbgPrint("  FileDirectoryInformation\n");
		break;
	case FileFullDirectoryInformation:
		DDbgPrint("  FileFullDirectoryInformation\n");
		break;
	case FileNamesInformation:
		DDbgPrint("  FileNamesInformation\n");
		break;
	case FileBothDirectoryInformation:
		DDbgPrint("  FileBothDirectoryInformation\n");
		break;
	case FileIdBothDirectoryInformation:
		DDbgPrint("  FileIdBothDirectoryInformation\n");
		break;
	default:
		DDbgPrint("  unknown FileInfoClass %d\n", irpSp->Parameters.QueryDirectory.FileInformationClass);
		break;
	}


	// make a MDL for UserBuffer that can be used later on another thread context
	if (Irp->MdlAddress == NULL) {
		status = DokanAllocateMdl(Irp, irpSp->Parameters.QueryDirectory.Length);
		if (!NT_SUCCESS(status)) {
			return status;
		}
		flags = DOKAN_MDL_ALLOCATED;
	}

	
	// size of EVENT_CONTEXT is sum of its length and file name length
	eventLength = sizeof(EVENT_CONTEXT) + fcb->FileName.Length;

	initial = (BOOLEAN)(ccb->SearchPattern == NULL && !(ccb->Flags & DOKAN_DIR_MATCH_ALL));

	// this is an initial query
	if (initial) {
		DDbgPrint("    initial query\n");
		// and search pattern is provided
		if (irpSp->Parameters.QueryDirectory.FileName) {
			// free current search pattern stored in CCB
			if (ccb->SearchPattern)
				ExFreePool(ccb->SearchPattern);

			// the size of search pattern
			ccb->SearchPatternLength = irpSp->Parameters.QueryDirectory.FileName->Length;
			ccb->SearchPattern = ExAllocatePool(ccb->SearchPatternLength + sizeof(WCHAR));

			if (ccb->SearchPattern == NULL) {
				return STATUS_INSUFFICIENT_RESOURCES;
			}

			RtlZeroMemory(ccb->SearchPattern, ccb->SearchPatternLength + sizeof(WCHAR));

			// copy provided search pattern to CCB
			RtlCopyMemory(ccb->SearchPattern,
				irpSp->Parameters.QueryDirectory.FileName->Buffer,
				ccb->SearchPatternLength);

		} else {
			ccb->Flags |= DOKAN_DIR_MATCH_ALL;
		}
	}

	// if search pattern is provided, add the length of it to store pattern
	if (ccb->SearchPattern) {
		eventLength += ccb->SearchPatternLength;
	}
		
	eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb);

	if (eventContext == NULL) {
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	eventContext->Context = ccb->UserContext;
	//DDbgPrint("   get Context %X\n", (ULONG)ccb->UserContext);

	// index which specified index-1 th directory entry has been returned
	// this time, 'index'th entry should be returned
	index = 0;

	if (irpSp->Flags & SL_INDEX_SPECIFIED) {
		index = irpSp->Parameters.QueryDirectory.FileIndex;
		DDbgPrint("    using FileIndex %d\n", index);
		
	} else if (FlagOn(irpSp->Flags, SL_RESTART_SCAN)) {
		DDbgPrint("    SL_RESTART_SCAN\n");
		index = 0;
		
	} else {
		index = (ULONG)ccb->Context;
		DDbgPrint("    ccb->Context %d\n", index);
	}

	eventContext->Directory.FileInformationClass	= irpSp->Parameters.QueryDirectory.FileInformationClass;
	eventContext->Directory.BufferLength			= irpSp->Parameters.QueryDirectory.Length; // length of buffer
	eventContext->Directory.FileIndex				= index; // directory index which should be returned this time

	// copying file name(directory name)
	eventContext->Directory.DirectoryNameLength = fcb->FileName.Length;
	RtlCopyMemory(eventContext->Directory.DirectoryName,
					fcb->FileName.Buffer, fcb->FileName.Length);

	// if search pattern is specified, copy it to EventContext
	if (ccb->SearchPatternLength) {
		PVOID searchBuffer;

		eventContext->Directory.SearchPatternLength = ccb->SearchPatternLength;
		eventContext->Directory.SearchPatternOffset = eventContext->Directory.DirectoryNameLength;
			
		searchBuffer = (PVOID)((SIZE_T)&eventContext->Directory.SearchPatternBase[0] +
							(SIZE_T)eventContext->Directory.SearchPatternOffset);
			
		RtlCopyMemory(searchBuffer, 
						ccb->SearchPattern,
						ccb->SearchPatternLength);

		DDbgPrint("    ccb->SearchPattern %ws\n", ccb->SearchPattern);
	}


	status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, flags);

	return status;
}
Ejemplo n.º 10
0
void OptimizeLoopInvariants(Var * proc, Loop * loop)
{
	InstrBlock * blk, * blk_exit;
	Instr * i, * i2;
	Bool change;
	Loc loc, preheader;
	UInt32 n;

//	Print("========== Invariants ================\n");
//	PrintProc(proc);

	blk_exit = loop->end->next;

	//=== Mark all instructions as variant

	for(blk = loop->header; blk != blk_exit; blk = blk->next) {
		for(i = blk->first; i != NULL; i = i->next) {
			i->flags = 0;
		}
	}

	do {
		change = false;
		for (blk = loop->header; blk != blk_exit; blk = blk->next) {
			loc.blk = blk;
			for (i = blk->first, n=1; i != NULL; i = i->next, n++) {
				loc.i = i;
				if (i->op == INSTR_LINE || IS_INSTR_BRANCH(i->op)) continue;
				if (FlagOff(i->flags, InstrInvariant)) {
					if (i->result != NULL && !OutVar(i->result)) {
						if (VarInvariant(proc, i->arg1, &loc, loop) && VarInvariant(proc, i->arg2, &loc, loop)) {
							if (VarInvariant2(proc, i->result, &loc, loop)) {
								SetFlagOn(i->flags, InstrInvariant);
								change = true;
							}
						}
					}
				}
			}
		}
	} while(change);

	// Mark all instructions that are self-referencing and are not marked as constant
/*
	for (blk = loop->header; blk != blk_exit; blk = blk->next) {
		for (i = blk->first, n=1; i != NULL; i = i->next, n++) {
			if (FlagOff(i->flags, InstrInvariant) && i->op != INSTR_LINE) {
				if (VarUsesVar(i->arg1, i->result) || VarUsesVar(i->arg2, i->result)) {
					i->flags = InstrLoopDep;
				}
			}
		}
	}

	Print("-----\n");
	PrintLoopInvariants(loop);
*/

	do {
		change = false;
		for (blk = loop->header; blk != blk_exit; blk = blk->next) {
			loc.blk = blk;
			i2 = NULL;
			for (i = blk->first, n=1; i != NULL; i = i->next, n++) {
//				loc.i = i;
				if (i->op == INSTR_LINE) continue;
				if (i2 != NULL && FlagOn(i2->flags, InstrInvariant) && FlagOff(i->flags, InstrInvariant)) {
					if (i->op == INSTR_LET && i2->op == INSTR_LET && i2->result == i->arg1) {
						SetFlagOff(i2->flags, InstrInvariant);
					}
				}
				i2 = i;
			}
		}
//		if (change) {
//			Print("-----\n");
//			PrintLoopInvariants(loop);
//		}
	} while(change);


//	Print("-----\n");
//	PrintLoopInvariants(loop);

	//==== Move all invariant instructions to preheader
	
	LoopPreheader(proc, loop->header, &preheader);
	for(blk = loop->header; blk != blk_exit; blk = blk->next) {
		i = blk->first;
		while(i != NULL) {
			i2 = i->next;
			if (FlagOn(i->flags, InstrInvariant)) {
				InstrMoveCode(preheader.blk, preheader.i, blk, i, i);
			}
			i = i2;
		}
	}
}
Ejemplo n.º 11
0
Bool OptimizeLoop(Var * proc, InstrBlock * header, InstrBlock * end)
/*
1. Find loop (starting with inner loops)
   - Every jump to label preceding the jump (backjump) forms a label
   - In nested labels, we encounter the backjump first
				<code1>
			l1@
				<code2>
			l2@
				<code3>
				if.. l2@
				<code4>
				if.. l3@
				<code5>

2. Select variable to put to register
   - Most used variable should be used
   - Some variables are already moved to index register (this is considered use too)

3. Compute cost of moving the variable to register

*/
{
	Instr * i, initial, ti, * last_mod;
	Var * top_var, * reg, * top_reg, * orig_result;
	UInt16 r, regi, changed;
	UInt32 var_size;
	Int32 q, top_q, n;
	Bool init, top_init;
	InstrBlock * blk, * last_mod_blk;
	InstrBlock * blk_exit;
	Bool var_modified;
	Bool verbose;
	Rule * rule;
	UInt8 color;

	blk_exit = end->next;

	G_VERBOSE = verbose = Verbose(proc);
	VarResetUse();
	InstrVarUse(header, blk_exit);
	InstrVarLoopDependent(header, end);

	// When processing, we assign var to register
	for(regi = 0; regi < CPU->REG_CNT; regi++) CPU->REG[regi]->var = NULL;

	while(top_var = FindMostUsedVar()) {

//		if (Verbose(proc)) {
//			Print("Most user var: "); PrintVar(top_var); PrintEOL();
//		}

		top_var->read = top_var->write = 0;
		var_size = VarByteSize(top_var);

		//====== Select the best register for the given variable
		//      let %A,%A   => index -3
		//      use of register instead of variable -1
		//      spill +3

		top_q = 0; top_reg = NULL; top_init = false;

		for(regi = 0; regi < CPU->REG_CNT; regi++) {

			reg = CPU->REG[regi];
			if (FlagOn(reg->submode, SUBMODE_IN|SUBMODE_OUT)) continue;		// exclude input/output registers
			if (reg->type->range.max == 1) continue;						// exclude flag registers
			if (var_size != VarByteSize(reg)) continue;						// exclude registers with different byte size
			if (reg->var != NULL) continue;

			if (InstrRule2(INSTR_LET, reg, top_var, NULL)) {

	//			if (StrEqual(reg->name, "x") && StrEqual(top_var->name, "i")) {
	//				Print(" ");
	//			}
				q = UsageQuotient(header, end, top_var, reg, &init);

				if (q < top_q) {
					top_q = q;
					top_reg = reg;
					top_init = init;
				}
			}
		}

		if (top_reg == NULL) continue;

		reg = top_reg;
		if (Verbose(proc)) {
			color = PrintColor(OPTIMIZE_COLOR);
			PrintFmt("*** Loop %d..%d\n", header->seq_no, end->seq_no);
			Print("Var: "); PrintVarVal(top_var); PrintEOL();
			Print("Register: "); PrintVarName(top_reg); PrintEOL();
			PrintFmt("Quotient: %d\n", top_q);
			PrintColor(color);
		}

		//TODO: If there is Let reg = var and var is not top_var, we need to spill store

		//=== Replace the use of registers

//		PrintProc(proc);

		ResetValues();
		initial.op = INSTR_LET; initial.result = top_reg; initial.arg1 = top_var; initial.arg2 = NULL;

		var_modified = false;
		// Generate instruction initializing the register used to replace the variable
		// before the start of the loop.
		// We only do this, if the variable is not initialized inside the loop.

//		if (FlagOn(top_var->flags, VarUninitialized) && !top_init) {
//			top_init = true;
//		}

 		if (top_init) {
			LoopInsertPrologue(proc, header, INSTR_LET, top_reg, top_var, NULL);
			VarSetSrcInstr(top_reg, &initial);
		}
		r = 0;

		last_mod = NULL;

		for(blk = header; blk != blk_exit; blk = blk->next) {
			if (verbose) PrintBlockHeader(blk);
			for(i = blk->first, n=0; i != NULL; i = i->next) {
retry:
				n++;
				if (i->op == INSTR_LINE) {
					if (verbose) { PrintInstrLine(n); EmitInstrInline(i); PrintEOL(); }
					continue;
				}

				// Delete unnecessary assignment
				if (i->op == INSTR_LET) {
					if (!InVar(i->arg1) && !OutVar(i->result) && VarContains(i->result, i->arg1)) {
del:
						if (verbose) { PrintInstrLine(n); EmitInstrInline(i); }
del2:					if (verbose) { PrintDelete(); }
						i = InstrDelete(blk, i);
						if (i == NULL) break;
						goto retry;	//continue;
					}
				}

				// Load the register with variable if necessary
				if (InstrReadsVar(i, top_var)) {
					if (!VarContains(top_reg, top_var)) {
						if (!(i->op == INSTR_LET && i->result == top_reg && i->arg1 == top_var)) {
							InstrInsertRule(blk, i, INSTR_LET, top_reg, top_var, NULL);
						}
					}
				}

				if (i->op == INSTR_LET && (i->result == top_var && i->arg1 == top_reg)) {
					r++;
					goto del;
				}

				if (InstrSpill(i, top_var)) {
					InstrInsertRule(blk, i, INSTR_LET, top_var, top_reg, NULL);
				}

				if (verbose) { PrintInstrLine(n); EmitInstrInline(i); }

				orig_result = i->result;

				memcpy(&ti, i, sizeof(Instr));
				changed = VarTestReplace(&ti.result, top_var, reg);
				r += changed;
				changed += VarTestReplace(&ti.arg1, top_var, reg);
				changed += VarTestReplace(&ti.arg2, top_var, reg);

				// If the instruction used variable, that contains same value as replaced register, use the register instead
				if (ti.arg1 != reg && VarContains(ti.arg1, reg)) {
					changed += VarTestReplace(&ti.result, ti.arg1, reg);
					changed += VarTestReplace(&ti.arg2, ti.arg1, reg);
					changed += VarTestReplace(&ti.arg1, ti.arg1, reg);
				}

				if (changed > 0) {

					if (i->op == INSTR_LET && ti.result == ti.arg1) {
						goto del2;
					}

					rule = InstrRule(&ti);
					if (rule != NULL && (i->rule->cycles >= rule->cycles)) {
						InstrReplaceVar(i, top_var, top_reg);

						if (i->arg1 != reg && VarContains(i->arg1, reg)) {
							VarTestReplace(&i->result, i->arg1, reg);
							VarTestReplace(&i->arg2, i->arg1, reg);
							VarTestReplace(&i->arg1, i->arg1, reg);
						}

						i->rule = rule;
						CheckInstr(i);
						PrintChange(i);
					}

				}

				if (verbose) PrintEOL();
				ResetValue(i->result);
				if (orig_result == top_var) {
//					if (!InstrIsSelfReferencing(i)) {
						VarSetSrcInstr(i->result, &initial);
//					} else {
//						VarSetSrcInstr(i->result, NULL);
//					}
					last_mod = i; last_mod_blk = blk;
				} else {
					VarSetSrcInstr(i->result, i);
				}
			}
		}

		// Value of register is not known at the end of loop, but it is not initialized at the beginning of the loop
		// We must load it before first use.

		if (!top_init && last_mod) {
			InstrInsertRule(last_mod_blk, last_mod->next, INSTR_LET, top_var, top_reg, NULL);
		}

		// If we replaced some destination by the register, store the register to destination
		if (r > 0) {
			// There may be exit label as part of the loop
			// We need to spill after it

			if (!VarIsConst(top_var)) {
				if (blk_exit == NULL || blk_exit->callers != NULL || blk_exit->from != end) {
					blk_exit = InstrBlockAlloc();
					blk_exit->to = end->to;
					blk_exit->next = end->to;
					end->next = blk_exit;
					end->to   = blk_exit;
				}
				InstrInsertRule(blk_exit, blk_exit->first, INSTR_LET, top_var, top_reg, NULL);
			}
//			InstrInsert(blk_exit, blk_exit->first, INSTR_LET, top_var, top_reg, NULL);
		}

		if (FlagOn(top_var->flags, VarLoopDependent)) {
			reg->flags |= VarLoopDependent;
		}

		return true;
	}
	return false;
}
Ejemplo n.º 12
0
VOID
CdQueryStandardInfo (
    IN PIRP_CONTEXT IrpContext,
    IN PFCB Fcb,
    IN OUT PFILE_STANDARD_INFORMATION Buffer,
    IN OUT PULONG Length
    )
/*++

Routine Description:

    This routine performs the query standard information function for cdfs.

Arguments:

    Fcb - Supplies the Fcb being queried, it has been verified

    Buffer - Supplies a pointer to the buffer where the information is to
        be returned

    Length - Supplies the length of the buffer in bytes, and receives the
        remaining bytes free in the buffer upon return.

Return Value:

    None

--*/

{
    PAGED_CODE();

    //
    //  There is only one link and delete is never pending on a Cdrom file.
    //

    Buffer->NumberOfLinks = 1;
    Buffer->DeletePending = FALSE;

    //
    //  We get the sizes from the header.  Return a size of zero
    //  for all directories.
    //

    if (FlagOn( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) {

        Buffer->AllocationSize.QuadPart =
        Buffer->EndOfFile.QuadPart = 0;

        Buffer->Directory = TRUE;

    } else {

        Buffer->AllocationSize.QuadPart = Fcb->AllocationSize.QuadPart;
        Buffer->EndOfFile.QuadPart = Fcb->FileSize.QuadPart;

        Buffer->Directory = FALSE;
    }

    //
    //  Update the length and status output variables
    //

    *Length -= sizeof( FILE_STANDARD_INFORMATION );

    return;
}
Ejemplo n.º 13
0
BOOLEAN
CdFastQueryNetworkInfo (
    IN PFILE_OBJECT FileObject,
    IN BOOLEAN Wait,
    OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
    OUT PIO_STATUS_BLOCK IoStatus,
    IN PDEVICE_OBJECT DeviceObject
    )

/*++

Routine Description:

    This routine is for the fast query call for network file information.

Arguments:

    FileObject - Supplies the file object used in this operation

    Wait - Indicates if we are allowed to wait for the information

    Buffer - Supplies the output buffer to receive the basic information

    IoStatus - Receives the final status of the operation

Return Value:

    BOOLEAN - TRUE if the operation succeeded and FALSE if the caller
        needs to take the long route.

--*/

{
    BOOLEAN Result = FALSE;
    TYPE_OF_OPEN TypeOfOpen;

    PFCB Fcb;

    PAGED_CODE();

    ASSERT_FILE_OBJECT( FileObject );

    FsRtlEnterFileSystem();

    //
    //  Decode the file object to find the type of open and the data
    //  structures.
    //

    TypeOfOpen = CdFastDecodeFileObject( FileObject, &Fcb );

    //
    //  We only support this request on user file or directory objects.
    //

    if ((TypeOfOpen != UserFileOpen) &&
        ((TypeOfOpen != UserDirectoryOpen) || !FlagOn( Fcb->FcbState, FCB_STATE_INITIALIZED))) {

        FsRtlExitFileSystem();
        return FALSE;
    }

    //
    //  Acquire the file shared to access the Fcb.
    //

    if (!ExAcquireResourceSharedLite( Fcb->Resource, Wait )) {

        FsRtlExitFileSystem();
        return FALSE;
    }

    //
    //  Use a try-finally to facilitate cleanup.
    //

    try {

        //
        //  Only deal with 'good' Fcb's.
        //

        if (CdVerifyFcbOperation( NULL, Fcb )) {

            //
            //  Fill in the input buffer from the Fcb fields.
            //

            Buffer->CreationTime.QuadPart =
            Buffer->LastWriteTime.QuadPart =
            Buffer->ChangeTime.QuadPart = Fcb->CreationTime;

            Buffer->LastAccessTime.QuadPart = 0;

            Buffer->FileAttributes = Fcb->FileAttributes;

            //
            //  Check whether this is a directory.
            //

            if (FlagOn( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) {

                Buffer->AllocationSize.QuadPart =
                Buffer->EndOfFile.QuadPart = 0;

            } else {

                Buffer->AllocationSize.QuadPart = Fcb->AllocationSize.QuadPart;
                Buffer->EndOfFile.QuadPart = Fcb->FileSize.QuadPart;
            }

            //
            //  Update the IoStatus block with the size of this data.
            //

            IoStatus->Status = STATUS_SUCCESS;
            IoStatus->Information = sizeof( FILE_NETWORK_OPEN_INFORMATION );

            Result = TRUE;
        }

    } finally {

        ExReleaseResourceLite( Fcb->Resource );

        FsRtlExitFileSystem();
    }

    return Result;
}
Ejemplo n.º 14
0
NTSTATUS
CdCommonSetInfo (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common routine for set file information called by both the
    fsd and fsp threads.  We only support operations which set the file position.

Arguments:

    Irp - Supplies the Irp to process.

Return Value:

    NTSTATUS - The return status for this operation.

--*/

{
    NTSTATUS Status = STATUS_INVALID_PARAMETER;

    TYPE_OF_OPEN TypeOfOpen;
    PFCB Fcb;
    PCCB Ccb;

    PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );

    PFILE_POSITION_INFORMATION Buffer;

    PAGED_CODE();

    //
    //  Decode the file object
    //

    TypeOfOpen = CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb );

    //
    //  We only support a SetPositionInformation on a user file.
    //

    if ((TypeOfOpen != UserFileOpen) ||
        (IrpSp->Parameters.QueryFile.FileInformationClass != FilePositionInformation)) {

        CdCompleteRequest( IrpContext, Irp, Status );
        return Status;
    }

    //
    //  Acquire shared access to this file.
    //

    CdAcquireFileShared( IrpContext, Fcb );

    try {

        //
        //  Make sure the Fcb is in a usable condition.  This
        //  will raise an error condition if the fcb is unusable
        //

        CdVerifyFcbOperation( IrpContext, Fcb );

        Buffer = Irp->AssociatedIrp.SystemBuffer;

        //
        //  Check if the file does not use intermediate buffering.  If it
        //  does not use intermediate buffering then the new position we're
        //  supplied must be aligned properly for the device
        //

        if (FlagOn( IrpSp->FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING ) &&
            ((Buffer->CurrentByteOffset.LowPart & IrpSp->DeviceObject->AlignmentRequirement) != 0)) {

            try_return( NOTHING );
        }

        //
        //  The input parameter is fine so set the current byte offset and
        //  complete the request
        //

        //
        //  Lock the Fcb to provide synchronization.
        //

        CdLockFcb( IrpContext, Fcb );
        IrpSp->FileObject->CurrentByteOffset = Buffer->CurrentByteOffset;
        CdUnlockFcb( IrpContext, Fcb );

        Status = STATUS_SUCCESS;

    try_exit: NOTHING;
    } finally {

        CdReleaseFile( IrpContext, Fcb );
    }

    //
    //  Complete the request if there was no raise.
    //

    CdCompleteRequest( IrpContext, Irp, Status );
    return Status;
}
Ejemplo n.º 15
0
__drv_mustHoldCriticalRegion
VOID
CdLookupAllocation (
    __in PIRP_CONTEXT IrpContext,
    __in PFCB Fcb,
    __in LONGLONG FileOffset,
    __out PLONGLONG DiskOffset,
    __out PULONG ByteCount
    )

/*++

Routine Description:

    This routine looks through the mapping information for the file
    to find the logical diskoffset and number of bytes at that offset.
    We only deal with logical 2048 byte sectors here.

    If the mapping isn't present we will look it up on disk now.
    This routine assumes we are looking up a valid range in the file.  This
    routine raises if it can't find mapping for the file offset.

    The Fcb may not be locked prior to calling this routine.  We will always
    acquire it here.

Arguments:

    Fcb - Fcb representing this stream.

    FileOffset - Lookup the allocation beginning at this point.

    DiskOffset - Address to store the logical disk offset.

    ByteCount - Address to store the number of contiguous bytes beginning
        at DiskOffset above.

Return Value:

    None.

--*/

{
    BOOLEAN FirstPass = TRUE;
    ULONG McbEntryOffset;
    PFCB ParentFcb = NULL;
    BOOLEAN CleanupParent = FALSE;

    BOOLEAN UnlockFcb = FALSE;

    LONGLONG CurrentFileOffset;
    ULONG CurrentMcbOffset;
    PCD_MCB_ENTRY CurrentMcbEntry;

    DIRENT_ENUM_CONTEXT DirContext = {0};
    DIRENT Dirent = {0};

    PAGED_CODE();

    ASSERT_IRP_CONTEXT( IrpContext );
    ASSERT_FCB( Fcb );

    //
    //  For DASD IO we already have clamped the read to the volume limits.
    //  We'll allow reading beyond those limits for extended DASD IO, so
    //  no MCB lookup here.
    //

    if (Fcb == Fcb->Vcb->VolumeDasdFcb) {

        *DiskOffset = FileOffset;
        return;
    }

    //
    //  Use a try finally to facilitate cleanup.
    //

    try {

        //
        //  We use a loop to perform the lookup.  If we don't find the mapping in the
        //  first pass then we look up all of the allocation and then look again.

        while (TRUE) {

            //
            //
            //  Lookup the entry containing this file offset.
            //

            CdLockFcb( IrpContext, Fcb );
            UnlockFcb = TRUE;

            McbEntryOffset = CdFindMcbEntry( IrpContext, Fcb, FileOffset );

            //
            //  If within the Mcb then we use the data out of this entry and are
            //  done.
            //

            if (McbEntryOffset < Fcb->Mcb.CurrentEntryCount) {

                CdDiskOffsetFromMcbEntry( IrpContext,
                                          Fcb->Mcb.McbArray + McbEntryOffset,
                                          FileOffset,
                                          DiskOffset,
                                          ByteCount );

                break;

            //
            //  If this is not the first pass then the disk is corrupt.
            //

            } else if (!FirstPass) {

                CdRaiseStatus( IrpContext, STATUS_DISK_CORRUPT_ERROR );
            }

            CdUnlockFcb( IrpContext, Fcb );
            UnlockFcb = FALSE;

            //
            //  Initialize the search dirent structures.
            //

            CdInitializeDirContext( IrpContext, &DirContext );
            CdInitializeDirent( IrpContext, &Dirent );

            //
            //  Otherwise we need to walk the dirents for this file until we find
            //  the one containing this entry.  The parent Fcb should always be
            //  present.
            //

            ParentFcb = Fcb->ParentFcb;
            CdAcquireFileShared( IrpContext, ParentFcb );
            CleanupParent = TRUE;

            //
            //  Do an unsafe test to see if we need to create a file object.
            //

            CdVerifyOrCreateDirStreamFile( IrpContext, ParentFcb);

            //
            //  Initialize the local variables to indicate the first dirent
            //  and lookup the first dirent.
            //

            CurrentFileOffset = 0;
            CurrentMcbOffset = 0;

            CdLookupDirent( IrpContext,
                            ParentFcb,
                            CdQueryFidDirentOffset( Fcb->FileId ),
                            &DirContext );

            //
            //  If we are adding allocation to the Mcb then add all of it.
            //

            while (TRUE ) {

                //
                //  Update the dirent from the on-disk dirent.
                //

                CdUpdateDirentFromRawDirent( IrpContext, ParentFcb, &DirContext, &Dirent );

                //
                //  Add this dirent to the Mcb if not already present.
                //

                CdLockFcb( IrpContext, Fcb );
                UnlockFcb = TRUE;

                if (CurrentMcbOffset >= Fcb->Mcb.CurrentEntryCount) {

                    CdAddAllocationFromDirent( IrpContext, Fcb, CurrentMcbOffset, CurrentFileOffset, &Dirent );
                }

                CdUnlockFcb( IrpContext, Fcb );
                UnlockFcb = FALSE;

                //
                //  If this is the last dirent for the file then exit.
                //

                if (!FlagOn( Dirent.DirentFlags, CD_ATTRIBUTE_MULTI )) {

                    break;
                }

                //
                //  If we couldn't find another entry then the directory is corrupt because
                //  the last dirent for a file doesn't exist.
                //

                if (!CdLookupNextDirent( IrpContext, ParentFcb, &DirContext, &DirContext )) {

                    CdRaiseStatus( IrpContext, STATUS_DISK_CORRUPT_ERROR );
                }

                //
                //  Update our loop variables.
                //

                CurrentMcbEntry = Fcb->Mcb.McbArray + CurrentMcbOffset;
                CurrentFileOffset += CurrentMcbEntry->ByteCount;
                CurrentMcbOffset += 1;
            }

            //
            //  All of the allocation is loaded.  Go back and look up the mapping again.
            //  It better be there this time.
            //

            FirstPass = FALSE;
        }

    } finally {

        if (CleanupParent) {

            //
            //  Release the parent and cleanup the dirent structures.
            //

            CdReleaseFile( IrpContext, ParentFcb );

            CdCleanupDirContext( IrpContext, &DirContext );
            CdCleanupDirent( IrpContext, &Dirent );
        }

        if (UnlockFcb) { CdUnlockFcb( IrpContext, Fcb ); }
    }

    return;
}
Ejemplo n.º 16
0
FINISHED
FatAcquireSharedFcb (
    IN PIRP_CONTEXT IrpContext,
    IN PFCB Fcb
    )

/*++

Routine Description:

    This routine acquires shared access to the Fcb.

    After we acquire the resource check to see if this operation is legal.
    If it isn't (ie. we get an exception), release the resource.

Arguments:

    Fcb - Supplies the Fcb to acquire

Return Value:

    FINISHED - TRUE if we have the resource and FALSE if we needed to block
        for the resource but Wait is FALSE.

--*/

{
    PAGED_CODE();

RetryFcbShared:

    if (ExAcquireResourceSharedLite( Fcb->Header.Resource, BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT))) {

        //
        //  Check for anything other than a non-cached write if the
        //  async count is non-zero in the Fcb, or if others are waiting
        //  for the resource.  Then wait for all outstanding I/O to finish,
        //  drop the resource, and wait again.
        //

        if ((Fcb->NonPaged->OutstandingAsyncWrites != 0) &&
            ((IrpContext->MajorFunction != IRP_MJ_WRITE) ||
             !FlagOn(IrpContext->OriginatingIrp->Flags, IRP_NOCACHE) ||
             (ExGetSharedWaiterCount(Fcb->Header.Resource) != 0) ||
             (ExGetExclusiveWaiterCount(Fcb->Header.Resource) != 0))) {

            KeWaitForSingleObject( Fcb->NonPaged->OutstandingAsyncEvent,
                                   Executive,
                                   KernelMode,
                                   FALSE,
                                   (PLARGE_INTEGER) NULL );

            FatReleaseFcb( IrpContext, Fcb );

            goto RetryFcbShared;
        }

        try {

            FatVerifyOperationIsLegal( IrpContext );

        } finally {

            if ( AbnormalTermination() ) {

                FatReleaseFcb( IrpContext, Fcb );
            }
        }


        return TRUE;

    } else {

        return FALSE;
Ejemplo n.º 17
0
NTSTATUS DokanOplockRequest(__in PIRP *pIrp) {
  NTSTATUS Status = STATUS_SUCCESS;
  ULONG FsControlCode;
  PDokanDCB Dcb;
  PDokanVCB Vcb;
  PDokanFCB Fcb = NULL;
  PDokanCCB Ccb;
  PFILE_OBJECT fileObject;
  PIRP Irp = *pIrp;

  ULONG OplockCount = 0;

  PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);

  BOOLEAN AcquiredVcb = FALSE;
  BOOLEAN AcquiredFcb = FALSE;

#if (NTDDI_VERSION >= NTDDI_WIN7)
  PREQUEST_OPLOCK_INPUT_BUFFER InputBuffer = NULL;
  ULONG InputBufferLength;
  ULONG OutputBufferLength;
#endif

  PAGED_CODE();

  //
  //  Save some references to make our life a little easier
  //
  FsControlCode = IrpSp->Parameters.FileSystemControl.FsControlCode;

  fileObject = IrpSp->FileObject;
  DokanPrintFileName(fileObject);

  Ccb = fileObject->FsContext2;
  if (Ccb == NULL || Ccb->Identifier.Type != CCB) {
    DDbgPrint("    DokanOplockRequest STATUS_INVALID_PARAMETER\n");
    return STATUS_INVALID_PARAMETER;
  }

  Fcb = Ccb->Fcb;
  if (Fcb == NULL || Fcb->Identifier.Type != FCB) {
    DDbgPrint("    DokanOplockRequest STATUS_INVALID_PARAMETER\n");
    return STATUS_INVALID_PARAMETER;
  }

  Vcb = Fcb->Vcb;
  if (Vcb == NULL || Vcb->Identifier.Type != VCB) {
    DDbgPrint("    DokanOplockRequest STATUS_INVALID_PARAMETER\n");
    return STATUS_INVALID_PARAMETER;
  }
  Dcb = Vcb->Dcb;

#if (NTDDI_VERSION >= NTDDI_WIN7)

  //
  //  Get the input & output buffer lengths and pointers.
  //
  if (FsControlCode == FSCTL_REQUEST_OPLOCK) {

    InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
    InputBuffer = (PREQUEST_OPLOCK_INPUT_BUFFER)Irp->AssociatedIrp.SystemBuffer;

    OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;

    //
    //  Check for a minimum length on the input and ouput buffers.
    //
    if ((InputBufferLength < sizeof(REQUEST_OPLOCK_INPUT_BUFFER)) ||
        (OutputBufferLength < sizeof(REQUEST_OPLOCK_OUTPUT_BUFFER))) {
      DDbgPrint("    DokanOplockRequest STATUS_BUFFER_TOO_SMALL\n");
      return STATUS_BUFFER_TOO_SMALL;
    }
  }

  //
  //  If the oplock request is on a directory it must be for a Read or
  //  Read-Handle
  //  oplock only.
  //
  // FIXME - should we synchronize access here on Fcb->Flags?
  if (FlagOn(Fcb->Flags, DOKAN_FILE_DIRECTORY) &&
      ((FsControlCode != FSCTL_REQUEST_OPLOCK) ||
       !FsRtlOplockIsSharedRequest(Irp))) {

    DDbgPrint("    DokanOplockRequest STATUS_INVALID_PARAMETER\n");
    return STATUS_INVALID_PARAMETER;
  }

#endif

  //
  //  Use a try finally to free the Fcb/Vcb
  //
  try {

    //
    //  We grab the Fcb exclusively for oplock requests, shared for oplock
    //  break acknowledgement.
    //
    if ((FsControlCode == FSCTL_REQUEST_OPLOCK_LEVEL_1) ||
        (FsControlCode == FSCTL_REQUEST_BATCH_OPLOCK) ||
        (FsControlCode == FSCTL_REQUEST_FILTER_OPLOCK) ||
        (FsControlCode == FSCTL_REQUEST_OPLOCK_LEVEL_2)
#if (NTDDI_VERSION >= NTDDI_WIN7)
        || ((FsControlCode == FSCTL_REQUEST_OPLOCK) &&
            FlagOn(InputBuffer->Flags, REQUEST_OPLOCK_INPUT_FLAG_REQUEST))
#endif
            ) {

      AcquiredVcb = ExAcquireResourceSharedLite(&(Fcb->Vcb->Resource), TRUE);
      DokanFCBLockRW(Fcb);
      AcquiredFcb = TRUE;

#if (NTDDI_VERSION >= NTDDI_WIN7)
      if (!Dcb->FileLockInUserMode && FsRtlOplockIsSharedRequest(Irp)) {
#else
      if (!Dcb->FileLockInUserMode &&
          FsControlCode == FSCTL_REQUEST_OPLOCK_LEVEL_2) {
#endif
        //
        //  Byte-range locks are only valid on files.
        //
        if (!FlagOn(Fcb->Flags, DOKAN_FILE_DIRECTORY)) {

//
//  Set OplockCount to nonzero if FsRtl denies access
//  based on current byte-range lock state.
//
#if (NTDDI_VERSION >= NTDDI_WIN8)
          OplockCount = (ULONG)!FsRtlCheckLockForOplockRequest(
              &Fcb->FileLock, &Fcb->AdvancedFCBHeader.AllocationSize);
#elif (NTDDI_VERSION >= NTDDI_WIN7)
          OplockCount =
              (ULONG)FsRtlAreThereCurrentOrInProgressFileLocks(&Fcb->FileLock);
#else
        OplockCount = (ULONG)FsRtlAreThereCurrentFileLocks(&Fcb->FileLock);
#endif
        }
      } else {
        // Shouldn't be something like UncleanCount counter and not FileCount
        // here?
        OplockCount = Fcb->FileCount;
      }
    } else if ((FsControlCode == FSCTL_OPLOCK_BREAK_ACKNOWLEDGE) ||
               (FsControlCode == FSCTL_OPBATCH_ACK_CLOSE_PENDING) ||
               (FsControlCode == FSCTL_OPLOCK_BREAK_NOTIFY) ||
               (FsControlCode == FSCTL_OPLOCK_BREAK_ACK_NO_2)
#if (NTDDI_VERSION >= NTDDI_WIN7)
               || ((FsControlCode == FSCTL_REQUEST_OPLOCK) &&
                   FlagOn(InputBuffer->Flags, REQUEST_OPLOCK_INPUT_FLAG_ACK))
#endif
                   ) {

      DokanFCBLockRO(Fcb);
      AcquiredFcb = TRUE;
#if (NTDDI_VERSION >= NTDDI_WIN7)
    } else if (FsControlCode == FSCTL_REQUEST_OPLOCK) {
      //
      //  The caller didn't provide either REQUEST_OPLOCK_INPUT_FLAG_REQUEST or
      //  REQUEST_OPLOCK_INPUT_FLAG_ACK on the input buffer.
      //
      DDbgPrint("    DokanOplockRequest STATUS_INVALID_PARAMETER\n");
      return STATUS_INVALID_PARAMETER;
    } else {
#else
    } else {
#endif
      DDbgPrint("    DokanOplockRequest STATUS_INVALID_PARAMETER\n");
      return STATUS_INVALID_PARAMETER;
    }

    //
    //  Fail batch, filter, and handle oplock requests if the file is marked
    //  for delete.
    //
    if (((FsControlCode == FSCTL_REQUEST_FILTER_OPLOCK) ||
         (FsControlCode == FSCTL_REQUEST_BATCH_OPLOCK)
#if (NTDDI_VERSION >= NTDDI_WIN7)
         ||
         ((FsControlCode == FSCTL_REQUEST_OPLOCK) &&
          FlagOn(InputBuffer->RequestedOplockLevel, OPLOCK_LEVEL_CACHE_HANDLE))
#endif
             ) &&
        FlagOn(Fcb->Flags, DOKAN_DELETE_ON_CLOSE)) {

      DDbgPrint("    DokanOplockRequest STATUS_DELETE_PENDING\n");
      return STATUS_DELETE_PENDING;
    }

    //
    //  Call the FsRtl routine to grant/acknowledge oplock.
    //
    Status = FsRtlOplockFsctrl(DokanGetFcbOplock(Fcb), Irp, OplockCount);

    //
    //  Once we call FsRtlOplockFsctrl, we no longer own the IRP and we should
    //  not complete it.
    //
    *pIrp = NULL;

  } finally {
NTSTATUS
FmmInstanceSetup (
    _In_ PCFLT_RELATED_OBJECTS FltObjects,
    _In_ FLT_INSTANCE_SETUP_FLAGS Flags,
    _In_ DEVICE_TYPE VolumeDeviceType,
    _In_ FLT_FILESYSTEM_TYPE VolumeFilesystemType
    )
/*++

Routine Description:

    This routine is called whenever a new instance is created on a volume. This
    gives us a chance to decide if we need to attach to this volume or not.

Arguments:

    FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing
        opaque handles to this filter, instance and its associated volume.

    Flags - Flags describing the reason for this attach request.

Return Value:

    STATUS_SUCCESS - attach
    STATUS_FLT_DO_NOT_ATTACH - do not attach

--*/
{
    PFMM_INSTANCE_CONTEXT instanceContext = NULL;
    PDEVICE_OBJECT diskDeviceObject;
    NTSTATUS status = STATUS_SUCCESS;

    UNREFERENCED_PARAMETER( VolumeDeviceType );

    PAGED_CODE();

    DebugTrace( DEBUG_TRACE_INSTANCES,
                ("[Fmm]: Instance setup started (Volume = %p, Instance = %p)\n",
                 FltObjects->Volume,
                 FltObjects->Instance) );

    //
    //  Check if the file system mounted is ntfs or fat
    //
    //  The sample picks NTFS, FAT and ReFS as examples. The metadata
    //  handling demostrated in the sample can be applied
    //  to any file system
    //

    if (VolumeFilesystemType != FLT_FSTYPE_NTFS && VolumeFilesystemType != FLT_FSTYPE_FAT && VolumeFilesystemType != FLT_FSTYPE_REFS) {

        //
        //  An unknown file system is mounted which we do not care
        //

        DebugTrace( DEBUG_TRACE_INSTANCES,
                    ("[Fmm]: Unsupported file system mounted (Volume = %p, Instance = %p)\n",
                     FltObjects->Volume,
                     FltObjects->Instance) );

        status = STATUS_NOT_SUPPORTED;
        goto FmmInstanceSetupCleanup;
    }

    //
    //  Get the disk device object and make sure it is a disk device type and does not
    //  have any of the device characteristics we do not support.
    //
    //  The sample picks the device characteristics to demonstrate how to access and
    //  check the device characteristics in order to make a decision to attach. The
    //  metadata handling demostrated in the sample is not limited to the
    //  characteristics we have used in the sample.
    //

    status = FltGetDiskDeviceObject( FltObjects->Volume, &diskDeviceObject );

    if (!NT_SUCCESS( status )) {

        DebugTrace( DEBUG_TRACE_INSTANCES | DEBUG_TRACE_ERROR,
                    ("[Fmm]: Failed to get device object (Volume = %p, Status = 0x%08X)\n",
                     FltObjects->Volume,
                     status) );
        goto FmmInstanceSetupCleanup;
    }

    if (diskDeviceObject->DeviceType != FILE_DEVICE_DISK ||
        FlagOn( diskDeviceObject->Characteristics, FMM_UNSUPPORTED_DEVICE_CHARACS )) {

        DebugTrace( DEBUG_TRACE_INSTANCES,
                    ("[Fmm]: Unsupported device type or device characteristics (Volume = %p, Instance = %p DiskDeviceObjectDeviceTYpe = 0x%x, DiskDeviceObjectCharacteristics = 0x%x)\n",
                     FltObjects->Volume,
                     FltObjects->Instance,
                     diskDeviceObject->DeviceType,
                     diskDeviceObject->Characteristics) );

        ObDereferenceObject( diskDeviceObject );
        status = STATUS_NOT_SUPPORTED;
        goto FmmInstanceSetupCleanup;
    }

    ObDereferenceObject( diskDeviceObject );

    //
    //  Allocate and initialize the context for this volume
    //

    status = FltAllocateContext( FltObjects->Filter,
                                 FLT_INSTANCE_CONTEXT,
                                 FMM_INSTANCE_CONTEXT_SIZE,
                                 NonPagedPool,
                                 &instanceContext );

    if( !NT_SUCCESS( status )) {

        DebugTrace( DEBUG_TRACE_INSTANCES | DEBUG_TRACE_ERROR,
                    ("[Fmm]: Failed to allocate instance context (Volume = %p, Instance = %p, Status = 0x%08X)\n",
                     FltObjects->Volume,
                     FltObjects->Instance,
                     status) );

        goto FmmInstanceSetupCleanup;
    }

    FLT_ASSERT( instanceContext != NULL );

    RtlZeroMemory( instanceContext, FMM_INSTANCE_CONTEXT_SIZE );

    instanceContext->Flags = 0;
    instanceContext->Instance = FltObjects->Instance;
    instanceContext->FilesystemType = VolumeFilesystemType;
    instanceContext->Volume = FltObjects->Volume;
    ExInitializeResourceLite( &instanceContext->MetadataResource );


    //
    //  Set the instance context.
    //

    status = FltSetInstanceContext( FltObjects->Instance,
                                    FLT_SET_CONTEXT_KEEP_IF_EXISTS,
                                    instanceContext,
                                    NULL );

    if( !NT_SUCCESS( status )) {

        DebugTrace( DEBUG_TRACE_INSTANCES | DEBUG_TRACE_ERROR,
                    ("[Fmm]: Failed to set instance context (Volume = %p, Instance = %p, Status = 0x%08X)\n",
                     FltObjects->Volume,
                     FltObjects->Instance,
                     status) );
        goto FmmInstanceSetupCleanup;
    }

    //
    //  Acquire exclusive access to the instance context
    //

    FmmAcquireResourceExclusive( &instanceContext->MetadataResource );

    //
    //  Sanity - the instance context cannot be in a transition state during instance setup
    //

    FLT_ASSERT( !FlagOn( instanceContext->Flags, INSTANCE_CONTEXT_F_TRANSITION) );

    //
    //  Open the filter metadata on disk
    //
    //  The sample will attach to volume if it finds its metadata file on the volume.
    //  If this is a manual attachment then the sample filter will create its metadata
    //  file and attach to the volume.
    //

    status = FmmOpenMetadata( instanceContext,
                              BooleanFlagOn( Flags, FLTFL_INSTANCE_SETUP_MANUAL_ATTACHMENT ) );

    //
    //  Relinquish exclusive access to the instance context
    //

    FmmReleaseResource( &instanceContext->MetadataResource );

    if (!NT_SUCCESS( status )) {

        goto FmmInstanceSetupCleanup;
    }


FmmInstanceSetupCleanup:

    //
    //  If FltAllocateContext suceeded then we MUST release the context,
    //  irrespective of whether FltSetInstanceContext suceeded or not.
    //
    //  FltAllocateContext increments the ref count by one.
    //  A successful FltSetInstanceContext increments the ref count by one
    //  and also associates the context with the file system object
    //
    //  FltReleaseContext decrements the ref count by one.
    //
    //  When FltSetInstanceContext succeeds, calling FltReleaseContext will
    //  leave the context with a ref count of 1 corresponding to the internal
    //  reference to the context from the file system structures
    //
    //  When FltSetInstanceContext fails, calling FltReleaseContext will
    //  leave the context with a ref count of 0 which is correct since
    //  there is no reference to the context from the file system structures
    //

    if ( instanceContext != NULL ) {

        FltReleaseContext( instanceContext );
    }


    if (NT_SUCCESS( status )) {

        DebugTrace( DEBUG_TRACE_INSTANCES,
                    ("[Fmm]: Instance setup complete (Volume = %p, Instance = %p). Filter will attach to the volume.\n",
                     FltObjects->Volume,
                     FltObjects->Instance) );
    } else {

        DebugTrace( DEBUG_TRACE_INSTANCES,
                    ("[Fmm]: Instance setup complete (Volume = %p, Instance = %p). Filter will not attach to the volume.\n",
                     FltObjects->Volume,
                     FltObjects->Instance) );
    }

    //
    //  If this is an automatic attachment (mount, load, etc) and we are not 
    //  attaching to this volume because we do not support attaching to this 
    //  volume, then simply return STATUS_FLT_DO_NOT_ATTACH. If we return 
    //  anything else fltmgr logs an event log indicating failure to attach. 
    //  Since this failure to attach is not really an error, we do not want 
    //  this failure to be logged as an error in the event log. For all other
    //  error codes besides the ones we consider "normal", if is ok for fltmgr
    //  to actually log the failure to attach.
    //
    //  If this is a manual attach attempt that we have failed then we want to 
    //  give the user a clear indication of why the attachment failed. Hence in 
    //  this case, we will not override the error status with STATUS_FLT_DO_NOT_ATTACH
    //  irrespective of the cause of the failure to attach
    //

    if (status == STATUS_NOT_SUPPORTED && 
       !FlagOn( Flags, FLTFL_INSTANCE_SETUP_MANUAL_ATTACHMENT )) {

        status = STATUS_FLT_DO_NOT_ATTACH;
    }

    return status;
}
Ejemplo n.º 19
0
NTSTATUS
NdasNtfsSecondaryCommonSetSecurityInfo (
	IN PIRP_CONTEXT IrpContext,
	IN PIRP Irp
	)
{
	NTSTATUS					status;
	PVOLUME_DEVICE_OBJECT		volDo = CONTAINING_RECORD( IrpContext->Vcb, VOLUME_DEVICE_OBJECT, Vcb );
	BOOLEAN						secondarySessionResourceAcquired = FALSE;

	PIO_STACK_LOCATION			irpSp = IoGetCurrentIrpStackLocation(Irp);
	PFILE_OBJECT				fileObject = irpSp->FileObject;

	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;
	UINT8							*ndfsWinxpRequestData;

	LARGE_INTEGER				timeOut;

	struct SetSecurity			setSecurity;
	PVOID						inputBuffer = NULL;
	ULONG						inputBufferLength = 0;

	ULONG						securityLength = 0;


	ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );


	if(volDo->Secondary == NULL) {

		status = Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
		Irp->IoStatus.Information = 0;
		return status;
	}

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

		typeOfOpen = NtfsDecodeFileObject( IrpContext, 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 );
		}

		setSecurity.SecurityDescriptor  = irpSp->Parameters.SetSecurity.SecurityDescriptor;
		setSecurity.SecurityInformation = irpSp->Parameters.SetSecurity.SecurityInformation;

		status = SeQuerySecurityDescriptorInfo( &setSecurity.SecurityInformation,
												NULL,
												&securityLength,
												&setSecurity.SecurityDescriptor );

		DebugTrace( 0, Dbg, ("NdasNtfsSecondaryCommonSetSecurityInfo: The length of the security desc:%lu\n",securityLength) );

		if( (!securityLength && status == STATUS_BUFFER_TOO_SMALL ) ||
			(securityLength &&  status != STATUS_BUFFER_TOO_SMALL ))
		{
			ASSERT(NDASNTFS_UNEXPECTED);

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


		inputBufferLength = securityLength;


		secondaryRequest = AllocateWinxpSecondaryRequest( volDo->Secondary, 
														  IRP_MJ_SET_SECURITY,
														  inputBufferLength );

		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_SET_SECURITY, 
										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->SetSecurity.Length					= inputBufferLength;
		ndfsWinxpRequestHeader->SetSecurity.SecurityInformation		= setSecurity.SecurityInformation;

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

		status = SeQuerySecurityDescriptorInfo( &setSecurity.SecurityInformation,
												(PSECURITY_DESCRIPTOR)ndfsWinxpRequestData,
												&securityLength,
												&setSecurity.SecurityDescriptor );

		if(status != STATUS_SUCCESS) {

			ASSERT(NDASNTFS_UNEXPECTED);
			DereferenceSecondaryRequest( secondaryRequest );
			secondaryRequest = NULL;

			try_return( status );
		}

		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 = NTOHL(ndfsWinxpReplytHeader->Status4);
		Irp->IoStatus.Information = NTOHL(ndfsWinxpReplytHeader->Information32);


try_exit:  NOTHING;
	} finally {

		if( secondarySessionResourceAcquired == TRUE ) {

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

		if(secondaryRequest)
			DereferenceSecondaryRequest( secondaryRequest );
	}

	return status;
}
VOID
FmmInstanceTeardownComplete (
    _In_ PCFLT_RELATED_OBJECTS FltObjects,
    _In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags
    )
/*++

Routine Description:

    This routine is called at the end of instance teardown.

Arguments:

    FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing
        opaque handles to this filter, instance and its associated volume.

    Flags - Reason why this instance is been deleted.

Return Value:

    None.

--*/
{
    PFMM_INSTANCE_CONTEXT instanceContext;
    NTSTATUS status;

    UNREFERENCED_PARAMETER( Flags );

    PAGED_CODE();

    DebugTrace( DEBUG_TRACE_INSTANCES,
                ("[Fmm]: Instance teardown complete started (Instance = %p)\n",
                 FltObjects->Instance) );

    status = FltGetInstanceContext( FltObjects->Instance,
                                    &instanceContext );

    if (NT_SUCCESS( status )) {

        //
        //  Acquire exclusive access to the instance context
        //

        FmmAcquireResourceExclusive( &instanceContext->MetadataResource );

        //
        //  Sanity - the instance context cannot be in a transition state during instance teardown complete
        //

        FLT_ASSERT( !FlagOn( instanceContext->Flags, INSTANCE_CONTEXT_F_TRANSITION) );


        if (FlagOn( instanceContext->Flags, INSTANCE_CONTEXT_F_METADATA_OPENED )) {

            //
            //  Close the metadata file
            //

            FmmCloseMetadata( instanceContext );
        }


        //
        //  Relinquish exclusive access to the instance context
        //

        FmmReleaseResource( &instanceContext->MetadataResource );

        FltReleaseContext( instanceContext );
    }

    DebugTrace( DEBUG_TRACE_INSTANCES,
                ("[Fmm]: Instance teardown complete ended (Instance = %p)\n",
                 FltObjects->Instance) );
}
Ejemplo n.º 21
0
// ---------------------------------------------------------------------------
// * PlugInShell_ProcessRequest
//
//  inData      : A pointer to a data structure representing the current
//                server call.
//
//  This routine is called continuiously throughout the operation of the
//  Directory Services process.
// ---------------------------------------------------------------------------
long
PlugInShell_ProcessRequest(void *inData)
{
    long macError = eDSNoErr;
    bool isAcquired = false;
    sHeader * pMsgHdr = (sHeader *)inData;
    unsigned long msgType = pMsgHdr ? pMsgHdr->fType : 0;

    LOG_ENTER("inData = @%p => { fType = %lu (%s) }", inData, msgType, TypeToString(msgType));

    GS_VERIFY_INITIALIZED(macError);

    if (!inData)
    {
        macError = eDSNullParameter;
        GOTO_CLEANUP();
    }

    GS_ACQUIRE_SHARED();
    isAcquired = true;

    //
    // We currently do not handle anything while not "active".
    //
    if ( !FlagOn(GlobalState.PluginState, kActive) )
    {
        macError = ePlugInNotActive;
        GOTO_CLEANUP();
    }

    //
    // We also do not handle anything while not "startup complete".
    //
    if (GlobalState.IsStartupComplete == false &&
        msgType != kOpenDirNode &&
        msgType != kDoPlugInCustomCall &&
        msgType != kServerRunLoop &&
        msgType != kKerberosMutex)
    {
       macError = ePlugInNotActive;
       LOG("Startup of dependent services not complete, therefore network accounts are offline");
       GOTO_CLEANUP();
    }

    // ISSUE-2007/05/30-dalmeida -- We should use r/w locks instead so that
    // we can behave sensibly when someone tries to de-activate the plug-in
    // while we are processing something...

    try
    {
        switch ( msgType )
        {
        case kHandleNetworkTransition:
            LOG("Got Network Transition change notice");
            macError = eDSNoErr;
            break;

        case kHandleSystemWillSleep:
            LOG("Got Handle System Will Sleep notice");
            macError = eDSNoErr;
            break;

        case kHandleSystemWillPowerOn:
            LOG("Got Handle System Will Power On notice");
            macError = eDSNoErr;
            break;

        case kOpenDirNode:
            LOG("Start of directory node query");
            macError = LWIDirNodeQuery::Open((sOpenDirNode *)inData);
            break;

        case kDoDirNodeAuth:
            GS_ACQUIRE_SHARED_ADMIN_ACCESS_LIST();
            macError = LWIDirNodeQuery::DoDirNodeAuth((sDoDirNodeAuth *)inData,
                                                       SafeIsJoined(),
                                                       GlobalState.pAllowAdminCheckData,
                                                       GlobalState.Flags);
            GS_RELEASE_ADMIN_ACCESS_LIST();
            break;

        case kCloseDirNode:
            macError = LWIDirNodeQuery::Close((sCloseDirNode *)inData);
            break;

        case kGetDirNodeInfo:
            macError = LWIDirNodeQuery::GetInfo((sGetDirNodeInfo *)inData,
                                                GlobalState.Flags,
                                                GlobalState.pNetAdapterList);
            break;

        case kGetAttributeEntry:
            macError = LWIDirNodeQuery::GetAttributeEntry((sGetAttributeEntry *)inData);
            break;

        case kGetRecordEntry:
            macError = LWIDirNodeQuery::GetAttributeEntry((sGetAttributeEntry *)inData);
            break;

        case kGetAttributeValue:
            macError = LWIDirNodeQuery::GetAttributeValue((sGetAttributeValue *)inData);
            break;

        case kCloseAttributeValueList:
            macError = LWIDirNodeQuery::CloseValueList((sCloseAttributeValueList *)inData);
            break;

         case kCloseAttributeList:
            macError = LWIDirNodeQuery::CloseAttributeList((sCloseAttributeList *)inData);
            break;

        case kGetRecordList:
            macError = LWIRecordListQuery::Run((sGetRecordList *)inData, GlobalState.Flags, GlobalState.pNetAdapterList);
            break;

        case kReleaseContinueData:
            macError = LWIRecordListQuery::ReleaseContinueData((sReleaseContinueData *)inData);
            break;

        case kDoAttributeValueSearch:
        case kDoAttributeValueSearchWithData:
            macError = LWIAttrValDataQuery::Run((sDoAttrValueSearchWithData *)inData, GlobalState.Flags, GlobalState.pNetAdapterList);
            break;

        case kDoMultipleAttributeValueSearch:
        case kDoMultipleAttributeValueSearchWithData:
            macError = LWIAttrValDataQuery::Run((sDoMultiAttrValueSearchWithData *)inData, GlobalState.Flags, GlobalState.pNetAdapterList);
            break;

        case kOpenRecord:
            LOG("Start of record query");
            macError = LWIRecordQuery::Open((sOpenRecord*)inData, GlobalState.Flags, GlobalState.pNetAdapterList);
            break;

        case kGetRecordReferenceInfo:
            macError = LWIRecordQuery::GetReferenceInfo((sGetRecRefInfo*)inData);
            break;

        case kCloseRecord:
            macError = LWIRecordQuery::Close((sCloseRecord*)inData);
            break;

        case kGetRecordAttributeInfo:
            macError = LWIRecordQuery::GetAttributeInfo((sGetRecAttribInfo*)inData);
            break;

        case kGetRecordAttributeValueByID:
            macError = LWIRecordQuery::GetAttributeValueByID((sGetRecordAttributeValueByID*)inData);
            break;

        case kGetRecordAttributeValueByIndex:
            macError = LWIRecordQuery::GetAttributeValueByIndex((sGetRecordAttributeValueByIndex*)inData);
            break;

        /* Supported update operations */
        case kAddAttribute:
            macError = LWIRecordQuery::AddAttribute((sAddAttribute*)inData);
	    break;

        case kAddAttributeValue:
            macError = LWIRecordQuery::AddAttributeValue((sAddAttributeValue*)inData);
            break;

        case kRemoveAttribute:
            macError = LWIRecordQuery::RemoveAttribute((sRemoveAttribute*)inData);
            break;

        case kFlushRecord:
            macError = LWIRecordQuery::FlushRecord((sFlushRecord*)inData);
            break;

        case kSetAttributeValues:
            macError = LWIRecordQuery::SetAttributeValues((sSetAttributeValues*)inData);
            break;

        case kSetAttributeValue:
            macError = LWIRecordQuery::SetAttributeValue((sSetAttributeValue*)inData);
            break;

        case kSetRecordName:
        case kSetRecordType:
        case kDeleteRecord:
        case kCreateRecord:
        case kCreateRecordAndOpen: /* sCreateRecord */
        case kRemoveAttributeValue:
        case kDoPlugInCustomCall:
        default:
            if ((msgType < kDSPlugInCallsBegin) || (msgType > kDSPlugInCallsEnd))
            {
                LOG("Unsupported request type: %lu (%s)", msgType, TypeToString(msgType));
            }
            else
            {
                LOG("Unknown request type: %lu", msgType);
            }
            macError = eNotHandledByThisNode;
            break;
        }
    }
    catch (LWIException& lwi)
    {
        macError = lwi.getErrorCode();
    }

cleanup:

    if (isAcquired)
    {
        GS_RELEASE();
    }

    if (pMsgHdr)
    {
        pMsgHdr->fResult = macError;
    }

    LOG_LEAVE("--> %d", macError);

    return macError;
}
Ejemplo n.º 22
0
VOID
NtfsUpdateScbFromFileObject (
    IN PIRP_CONTEXT IrpContext,
    IN PFILE_OBJECT FileObject,
    IN PSCB Scb,
    IN BOOLEAN CheckTimeStamps
    )

/*++

Routine Description:

    This routine is called to update the Scb/Fcb to reflect the changes to
    a file through the fast io path.  It only called with a file object which
    represents a user's handle.

Arguments:

    FileObject - This is the file object used in the fast io path.

    Scb - This is the Scb for this stream.

    CheckTimeStamps - Indicates whether we want to update the time stamps from the
        fast io flags as well.  This will be TRUE if our caller will update the standard information,
        attribute header and duplicate info.  FALSE if only the attribute header and duplicate info.
        The latter case is the valid data length callback from the cache manager.

Return Value:

    None.

--*/

{

    PFCB Fcb = Scb->Fcb;
    ULONG CcbFlags;
    ULONG ScbFlags = 0;
    LONGLONG CurrentTime;

#if (__NDAS_NTFS_DBG__ && __NDAS_NTFS_SECONDARY__) 
	if (FlagOn(Fcb->NdasNtfsFlags, NDAS_NTFS_FCB_FLAG_SECONDARY))
		ASSERT( FALSE );
#endif

    //
    //  If the size of the main data stream is not part of the Fcb then update it
    //  now and set the correct Fcb flag.
    //

    if (FlagOn( Scb->ScbState, SCB_STATE_UNNAMED_DATA )) {

        if (Fcb->Info.FileSize != Scb->Header.FileSize.QuadPart) {

            Fcb->Info.FileSize = Scb->Header.FileSize.QuadPart;
            SetFlag( Fcb->InfoFlags, FCB_INFO_CHANGED_FILE_SIZE );
        }

        if (Fcb->Info.AllocatedLength != Scb->TotalAllocated) {

            Fcb->Info.AllocatedLength = Scb->TotalAllocated;
            SetFlag( Fcb->InfoFlags, FCB_INFO_CHANGED_ALLOC_SIZE );
        }

        if (FlagOn( FileObject->Flags, FO_FILE_SIZE_CHANGED )) {

            SetFlag( ScbFlags, SCB_STATE_CHECK_ATTRIBUTE_SIZE );
        }

    //
    //  Remember to update the size in the attribute header for named streams as well.
    //

    } else if (FlagOn( FileObject->Flags, FO_FILE_SIZE_CHANGED )) {

        SetFlag( ScbFlags, SCB_STATE_NOTIFY_RESIZE_STREAM | SCB_STATE_CHECK_ATTRIBUTE_SIZE );
    }

    ClearFlag( FileObject->Flags, FO_FILE_SIZE_CHANGED );

    //
    //  Check whether to update the time stamps if our caller requested it.
    //

    if (CheckTimeStamps && !FlagOn( FileObject->Flags, FO_CLEANUP_COMPLETE )) {

        BOOLEAN UpdateLastAccess = FALSE;
        BOOLEAN UpdateLastChange = FALSE;
        BOOLEAN UpdateLastModify = FALSE;
        BOOLEAN SetArchive = TRUE;

        //
        //  Copy the Ccb flags to a local variable.  Then we won't have to test
        //  for the existence of the Ccb each time.
        //

        CcbFlags = 0;

        //
        //  Capture the real flags if present and clear them since we will update the Scb/Fcb.
        //

        if (FileObject->FsContext2 != NULL) {

            CcbFlags = ((PCCB) FileObject->FsContext2)->Flags;
            ClearFlag( ((PCCB) FileObject->FsContext2)->Flags,
                       (CCB_FLAG_UPDATE_LAST_MODIFY |
                        CCB_FLAG_UPDATE_LAST_CHANGE |
                        CCB_FLAG_SET_ARCHIVE) );
        }

        NtfsGetCurrentTime( IrpContext, CurrentTime );

        //
        //  If there was a write to the file then update the last change, last access
        //  and last write and the archive bit.
        //

        if (FlagOn( FileObject->Flags, FO_FILE_MODIFIED )) {

            UpdateLastModify =
            UpdateLastAccess =
            UpdateLastChange = TRUE;

        //
        //  Otherwise test each of the individual bits in the file object and
        //  Ccb.
        //

        } else {

            if (FlagOn( FileObject->Flags, FO_FILE_FAST_IO_READ )) {

                UpdateLastAccess = TRUE;
            }

            if (FlagOn( CcbFlags, CCB_FLAG_UPDATE_LAST_CHANGE )) {

                UpdateLastChange = TRUE;

                if (FlagOn( CcbFlags, CCB_FLAG_UPDATE_LAST_MODIFY )) {

                    UpdateLastModify = TRUE;
                }

                if (!FlagOn( CcbFlags, CCB_FLAG_SET_ARCHIVE )) {

                    SetArchive = FALSE;
                }
            }
        }

        //
        //  Now set the correct Fcb bits.
        //

        if (UpdateLastChange) {

            if (SetArchive) {

                ASSERTMSG( "conflict with flush", 
                           ExIsResourceAcquiredSharedLite( Fcb->Resource ) || 
                           (Fcb->PagingIoResource != NULL && 
                            ExIsResourceAcquiredSharedLite( Fcb->PagingIoResource )));

                SetFlag( Fcb->Info.FileAttributes, FILE_ATTRIBUTE_ARCHIVE );
                SetFlag( Fcb->InfoFlags, FCB_INFO_CHANGED_FILE_ATTR );
                SetFlag( Fcb->FcbState, FCB_STATE_UPDATE_STD_INFO );
            }

            if (!FlagOn( CcbFlags, CCB_FLAG_USER_SET_LAST_CHANGE_TIME )) {

                Fcb->Info.LastChangeTime = CurrentTime;
                SetFlag( Fcb->InfoFlags, FCB_INFO_CHANGED_LAST_CHANGE );
                SetFlag( Fcb->FcbState, FCB_STATE_UPDATE_STD_INFO );
            }

            if (UpdateLastModify) {

                //
                //  Remember a change to a named data stream.
                //

                if (!FlagOn( Scb->ScbState, SCB_STATE_UNNAMED_DATA ) &&
                    (Scb->AttributeTypeCode == $DATA)) {

                    SetFlag( ScbFlags, SCB_STATE_NOTIFY_MODIFY_STREAM );
                }

                if (!FlagOn( CcbFlags, CCB_FLAG_USER_SET_LAST_MOD_TIME )) {

                    Fcb->Info.LastModificationTime = CurrentTime;
                    SetFlag( Fcb->InfoFlags, FCB_INFO_CHANGED_LAST_MOD );
                    SetFlag( Fcb->FcbState, FCB_STATE_UPDATE_STD_INFO );
                }
            }
        }

        if (UpdateLastAccess &&
            !FlagOn( CcbFlags, CCB_FLAG_USER_SET_LAST_ACCESS_TIME ) &&
            !FlagOn( NtfsData.Flags, NTFS_FLAGS_DISABLE_LAST_ACCESS )) {

            Fcb->CurrentLastAccess = CurrentTime;
            SetFlag( Fcb->InfoFlags, FCB_INFO_UPDATE_LAST_ACCESS );
        }

        //
        //  Clear all of the fast io flags in the file object.
        //

        ClearFlag( FileObject->Flags, FO_FILE_MODIFIED | FO_FILE_FAST_IO_READ );
    }

    //
    //  Now store the Scb flags into the Scb.
    //

    if (ScbFlags) {

        NtfsAcquireFsrtlHeader( Scb );
        SetFlag( Scb->ScbState, ScbFlags );
        NtfsReleaseFsrtlHeader( Scb );
    }

    return;
}
Ejemplo n.º 23
0
VOID
FatRemoveNames (
    IN PIRP_CONTEXT IrpContext,
    IN PFCB Fcb
    )

/*++

Routine Description:

    This routine will remove the short name and any long names associated
    with the files from their repsective splay tree.

Arguments:

    Name - Supplies the Fcb to process.

Return Value:

    None.

--*/

{
    PDCB Parent;
    PRTL_SPLAY_LINKS NewRoot;

    PAGED_CODE();
    UNREFERENCED_PARAMETER( IrpContext );
    
    Parent = Fcb->ParentDcb;

    //
    //  We used to assert this condition, but it really isn't good.  If
    //  someone rapidly renames a directory multiple times and we can't
    //  flush the lower fcbs fast enough (that didn't go away synch.)
    //  well, well hit some of them again.
    //
    //  NT_ASSERT( FlagOn( Fcb->FcbState, FCB_STATE_NAMES_IN_SPLAY_TREE ));
    //

    if (FlagOn( Fcb->FcbState, FCB_STATE_NAMES_IN_SPLAY_TREE )) {

        //
        //  Delete the node short name.
        //

        NewRoot = RtlDelete(&Fcb->ShortName.Links);

        Parent->Specific.Dcb.RootOemNode = NewRoot;

        //
        //  Now check for the presence of long name and delete it.
        //

        if (FlagOn( Fcb->FcbState, FCB_STATE_HAS_OEM_LONG_NAME )) {

            NewRoot = RtlDelete(&Fcb->LongName.Oem.Links);

            Parent->Specific.Dcb.RootOemNode = NewRoot;

            RtlFreeOemString( &Fcb->LongName.Oem.Name.Oem );

            ClearFlag( Fcb->FcbState, FCB_STATE_HAS_OEM_LONG_NAME );
        }

        if (FlagOn( Fcb->FcbState, FCB_STATE_HAS_UNICODE_LONG_NAME )) {

            NewRoot = RtlDelete(&Fcb->LongName.Unicode.Links);

            Parent->Specific.Dcb.RootUnicodeNode = NewRoot;

            RtlFreeUnicodeString( &Fcb->LongName.Unicode.Name.Unicode );

            ClearFlag( Fcb->FcbState, FCB_STATE_HAS_UNICODE_LONG_NAME );
        }

        ClearFlag( Fcb->FcbState, FCB_STATE_NAMES_IN_SPLAY_TREE );
    }

    return;
}
Ejemplo n.º 24
0
VOID
NtfsSetFileObject (
    IN PFILE_OBJECT FileObject,
    IN TYPE_OF_OPEN TypeOfOpen,
    IN PSCB Scb,
    IN PCCB Ccb OPTIONAL
    )

/*++

Routine Description:

    This routine sets the file system pointers within the file object

Arguments:

    FileObject - Supplies a pointer to the file object being modified.

    TypeOfOpen - Supplies the type of open denoted by the file object.
        This is only used by this procedure for sanity checking.

    Scb - Supplies a pointer to Scb for the file object.

    Ccb - Optionally supplies a pointer to a ccb

Return Value:

    None.

--*/

{
    ASSERT_FILE_OBJECT( FileObject );
    ASSERT_SCB( Scb );
    ASSERT_OPTIONAL_CCB( Ccb );

    PAGED_CODE();

    DebugTrace( +1, Dbg, ("NtfsSetFileObject, FileObject = %08lx\n", FileObject) );

    //
    //  Load up the FileObject fields.
    //

    FileObject->FsContext = Scb;
    FileObject->FsContext2 = Ccb;
    FileObject->Vpb = Scb->Vcb->Vpb;

    //
    //  Typically the I/O manager has already set this flag correctly.  The notable
    //  exception is when the user did an open by file ID of file record 3, so
    //  we're doing a DASD open, but the I/O manager didn't notice, since it only
    //  checks for a zero length filename.
    //

    if (TypeOfOpen == UserVolumeOpen) {
        SetFlag( FileObject->Flags, FO_VOLUME_OPEN );
    }

    //
    //  Now store TypeOfOpen if there is a Ccb
    //

    ASSERT((Ccb != NULL) || (TypeOfOpen == StreamFileOpen) || (TypeOfOpen == UnopenedFileObject));
    if (Ccb != NULL) {
        Ccb->TypeOfOpen = (UCHAR)TypeOfOpen;
    }

    //
    //  If this file has the temporary attribute bit set, don't lazy
    //  write it unless absolutely necessary.
    //

    if (FlagOn( Scb->ScbState, SCB_STATE_TEMPORARY )) {
        SetFlag( FileObject->Flags, FO_TEMPORARY_FILE );
    }

    //
    //  And return to our caller
    //

    DebugTrace( -1, Dbg, ("NtfsSetFileObject -> VOID\n") );

    return;
}
Ejemplo n.º 25
0
NTSTATUS
CdFsdDispatch (
    IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the driver entry to all of the Fsd dispatch points.

    Conceptually the Io routine will call this routine on all requests
    to the file system.  We case on the type of request and invoke the
    correct handler for this type of request.  There is an exception filter
    to catch any exceptions in the CDFS code as well as the CDFS process
    exception routine.

    This routine allocates and initializes the IrpContext for this request as
    well as updating the top-level thread context as necessary.  We may loop
    in this routine if we need to retry the request for any reason.  The
    status code STATUS_CANT_WAIT is used to indicate this.  Suppose the disk
    in the drive has changed.  An Fsd request will proceed normally until it
    recognizes this condition.  STATUS_VERIFY_REQUIRED is raised at that point
    and the exception code will handle the verify and either return
    STATUS_CANT_WAIT or STATUS_PENDING depending on whether the request was
    posted.

Arguments:

    VolumeDeviceObject - Supplies the volume device object for this request

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The FSD status for the IRP

--*/

{
    THREAD_CONTEXT ThreadContext;
    PIRP_CONTEXT IrpContext = NULL;
    BOOLEAN Wait;

#ifdef CD_SANITY
    PVOID PreviousTopLevel;
#endif

    NTSTATUS Status;

#if DBG

    KIRQL SaveIrql = KeGetCurrentIrql();

#endif

    ASSERT_OPTIONAL_IRP( Irp );

    FsRtlEnterFileSystem();

#ifdef CD_SANITY
    PreviousTopLevel = IoGetTopLevelIrp();
#endif

    //
    //  Loop until this request has been completed or posted.
    //

    do {

        //
        //  Use a try-except to handle the exception cases.
        //

        try {

            //
            //  If the IrpContext is NULL then this is the first pass through
            //  this loop.
            //

            if (IrpContext == NULL) {

                //
                //  Decide if this request is waitable an allocate the IrpContext.
                //  If the file object in the stack location is NULL then this
                //  is a mount which is always waitable.  Otherwise we look at
                //  the file object flags.
                //

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

                    Wait = TRUE;

                } else {

                    Wait = CanFsdWait( Irp );
                }

                IrpContext = CdCreateIrpContext( Irp, Wait );

                //
                //  Update the thread context information.
                //

                CdSetThreadContext( IrpContext, &ThreadContext );

#ifdef CD_SANITY
                ASSERT( !CdTestTopLevel ||
                        SafeNodeType( IrpContext->TopLevel ) == CDFS_NTC_IRP_CONTEXT );
#endif

            //
            //  Otherwise cleanup the IrpContext for the retry.
            //

            } else {

                //
                //  Set the MORE_PROCESSING flag to make sure the IrpContext
                //  isn't inadvertently deleted here.  Then cleanup the
                //  IrpContext to perform the retry.
                //

                SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_MORE_PROCESSING );
                CdCleanupIrpContext( IrpContext, FALSE );
            }

            //
            //  Case on the major irp code.
            //

            switch (IrpContext->MajorFunction) {

            case IRP_MJ_CREATE :

                Status = CdCommonCreate( IrpContext, Irp );
                break;

            case IRP_MJ_CLOSE :

                Status = CdCommonClose( IrpContext, Irp );
                break;

            case IRP_MJ_READ :

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

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

                    Status = CdCompleteMdl( IrpContext, Irp );

                } else {

                    Status = CdCommonRead( IrpContext, Irp );
                }

                break;

            case IRP_MJ_QUERY_INFORMATION :

                Status = CdCommonQueryInfo( IrpContext, Irp );
                break;

            case IRP_MJ_SET_INFORMATION :

                Status = CdCommonSetInfo( IrpContext, Irp );
                break;

            case IRP_MJ_QUERY_VOLUME_INFORMATION :

                Status = CdCommonQueryVolInfo( IrpContext, Irp );
                break;

            case IRP_MJ_DIRECTORY_CONTROL :

                Status = CdCommonDirControl( IrpContext, Irp );
                break;

            case IRP_MJ_FILE_SYSTEM_CONTROL :

                Status = CdCommonFsControl( IrpContext, Irp );
                break;

            case IRP_MJ_DEVICE_CONTROL :

                Status = CdCommonDevControl( IrpContext, Irp );
                break;

            case IRP_MJ_LOCK_CONTROL :

                Status = CdCommonLockControl( IrpContext, Irp );
                break;

            case IRP_MJ_CLEANUP :

                Status = CdCommonCleanup( IrpContext, Irp );
                break;

            case IRP_MJ_PNP :

                Status = CdCommonPnp( IrpContext, Irp );
                break;

            default :

                Status = STATUS_INVALID_DEVICE_REQUEST;
                CdCompleteRequest( IrpContext, Irp, Status );
            }

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

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

    } while (Status == STATUS_CANT_WAIT);

#ifdef CD_SANITY
    ASSERT( !CdTestTopLevel ||
            (PreviousTopLevel == IoGetTopLevelIrp()) );
#endif

    FsRtlExitFileSystem();

    ASSERT( SaveIrql == KeGetCurrentIrql( ));

    return Status;
}
Ejemplo n.º 26
0
NTSTATUS
DispatchRequest (
	IN PPRIMARY_SESSION	PrimarySession
	)
{
	NTSTATUS				status;
	IN PNDFS_REQUEST_HEADER	ndfsRequestHeader;


	ASSERT( NTOHS(PrimarySession->Thread.NdfsRequestHeader.Mid2) < PrimarySession->SessionContext.SessionSlotCount );

	RtlCopyMemory( PrimarySession->Thread.SessionSlot[NTOHS(PrimarySession->Thread.NdfsRequestHeader.Mid2)].RequestMessageBuffer,
				   &PrimarySession->Thread.NdfsRequestHeader,
				   sizeof(NDFS_REQUEST_HEADER) );

	ndfsRequestHeader 
		= (PNDFS_REQUEST_HEADER)PrimarySession->Thread.SessionSlot[NTOHS(PrimarySession->Thread.NdfsRequestHeader.Mid2)].RequestMessageBuffer;
   
	ASSERT (PrimarySession->ReceiveOverlapped.Request[0].IoStatusBlock.Information == sizeof(NDFS_REQUEST_HEADER) );

    SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_NOISE,
				   ("DispatchRequest: PrimarySession = %p, ndfsRequestHeader->Command = %d\n", 
				   PrimarySession, ndfsRequestHeader->Command) );

	
	switch (ndfsRequestHeader->Command) {

	case NDFS_COMMAND_NEGOTIATE: {

		PNDFS_REQUEST_NEGOTIATE	ndfsRequestNegotiate;
		PNDFS_REPLY_HEADER		ndfsReplyHeader;
		PNDFS_REPLY_NEGOTIATE	ndfsReplyNegotiate;
		
		
		if (PrimarySession->Thread.SessionState != SESSION_CLOSE) {

			ASSERT( LFS_BUG );
			status = STATUS_UNSUCCESSFUL;

			break;
		}
		
		ASSERT( NTOHL(ndfsRequestHeader->MessageSize4) == sizeof(NDFS_REQUEST_HEADER) + sizeof(NDFS_REQUEST_NEGOTIATE) );
		ndfsRequestNegotiate = (PNDFS_REQUEST_NEGOTIATE)(ndfsRequestHeader+1);
	
		status = RecvMessage( PrimarySession->ConnectionFileObject,
							  &PrimarySession->RecvNdasFcStatistics,
							  NULL,
							  (UINT8 *)ndfsRequestNegotiate,
							  sizeof(NDFS_REQUEST_NEGOTIATE) );
	

		if (status != STATUS_SUCCESS) {

			ASSERT( LFS_BUG );

			break;
		}

		PrimarySession->SessionContext.Flags = ndfsRequestNegotiate->Flags;
		ndfsReplyHeader = (PNDFS_REPLY_HEADER)(ndfsRequestNegotiate+1);

		RtlCopyMemory( ndfsReplyHeader->Protocol, NDFS_PROTOCOL, sizeof(ndfsReplyHeader->Protocol) );
		ndfsReplyHeader->Status		= NDFS_SUCCESS;
		ndfsReplyHeader->Flags	    = PrimarySession->SessionContext.Flags;
		ndfsReplyHeader->Uid2		= 0;
		ndfsReplyHeader->Tid2		= 0;
		ndfsReplyHeader->Mid2		= 0;
		ndfsReplyHeader->MessageSize4 = HTONL((UINT32)(sizeof(NDFS_REPLY_HEADER)+sizeof(NDFS_REPLY_NEGOTIATE)));

		ndfsReplyNegotiate = (PNDFS_REPLY_NEGOTIATE)(ndfsReplyHeader+1);

		if (NTOHS(ndfsRequestNegotiate->NdfsMajorVersion2) == NDFS_PROTOCOL_MAJOR_3 && 
			NTOHS(ndfsRequestNegotiate->NdfsMinorVersion2) == NDFS_PROTOCOL_MINOR_0 && 
			NTOHS(ndfsRequestNegotiate->OsMajorType2) == OS_TYPE_WINDOWS			&& 
			NTOHS(ndfsRequestNegotiate->OsMinorType2) == OS_TYPE_WINXP) {

			PrimarySession->SessionContext.NdfsMajorVersion = NTOHS(ndfsRequestNegotiate->NdfsMajorVersion2);
			PrimarySession->SessionContext.NdfsMinorVersion = NTOHS(ndfsRequestNegotiate->NdfsMinorVersion2);

			ndfsReplyNegotiate->Status = NDFS_NEGOTIATE_SUCCESS;
			ndfsReplyNegotiate->NdfsMajorVersion2 = HTONS(PrimarySession->SessionContext.NdfsMajorVersion);
			ndfsReplyNegotiate->NdfsMinorVersion2 = HTONS(PrimarySession->SessionContext.NdfsMinorVersion);
			ndfsReplyNegotiate->OsMajorType2 = HTONS(OS_TYPE_WINDOWS);	
			ndfsReplyNegotiate->OsMinorType2 = HTONS(OS_TYPE_WINXP);
			ndfsReplyNegotiate->SessionKey4 = HTONL(PrimarySession->SessionContext.SessionKey);
			ndfsReplyNegotiate->MaxBufferSize4 = HTONL(PrimarySession->SessionContext.PrimaryMaxDataSize);

			RtlCopyMemory( ndfsReplyNegotiate->ChallengeBuffer,
						   &PrimarySession,
						   sizeof(PPRIMARY_SESSION) );

			ndfsReplyNegotiate->ChallengeLength2 = HTONS((UINT16)(sizeof(PPRIMARY_SESSION)));

			PrimarySession->Thread.SessionState = SESSION_NEGOTIATE;
		
		} else {

			ndfsReplyNegotiate->Status = NDFS_NEGOTIATE_UNSUCCESSFUL;
		}

		status = SendMessage( PrimarySession->ConnectionFileObject,
							  &PrimarySession->SendNdasFcStatistics,
							  NULL,
							  (UINT8 *)ndfsReplyHeader,
							  NTOHL(ndfsReplyHeader->MessageSize4) );

		if (status != STATUS_SUCCESS) {

			break;
		}

		break;
	
	}

	case NDFS_COMMAND_SETUP: {

		PNDFS_REQUEST_SETUP	ndfsRequestSetup;
		PNDFS_REPLY_HEADER	ndfsReplyHeader;
		PNDFS_REPLY_SETUP	ndfsReplySetup;

		UINT8					ndfsReplySetupStatus;

		unsigned char		idData[1];
		MD5_CTX				context;
		UINT8				responseBuffer[16]; 
		
		
		if (PrimarySession->Thread.SessionState != SESSION_NEGOTIATE) {

			ASSERT( LFS_BUG );
			status = STATUS_UNSUCCESSFUL;

			break;
		}
		
		ASSERT( NTOHL(ndfsRequestHeader->MessageSize4) == sizeof(NDFS_REQUEST_HEADER) + sizeof(NDFS_REQUEST_SETUP) );
		ndfsRequestSetup = (PNDFS_REQUEST_SETUP)(ndfsRequestHeader+1);

		status = RecvMessage( PrimarySession->ConnectionFileObject,
							  &PrimarySession->RecvNdasFcStatistics,
							  NULL,
							  (UINT8 *)ndfsRequestSetup,
							  sizeof(NDFS_REQUEST_SETUP) );
	
		if (status != STATUS_SUCCESS) {

			ASSERT( LFS_BUG );

			break;
		}
	
		do {

			ASSERT( PrimarySession->NetdiskPartition == NULL );

			if (NTOHL(ndfsRequestSetup->SessionKey4) != PrimarySession->SessionContext.SessionKey) {

				ndfsReplySetupStatus = NDFS_SETUP_UNSUCCESSFUL;				
				break;
			}

			RtlCopyMemory( PrimarySession->NetDiskAddress.Node,
						   ndfsRequestSetup->NetdiskNode,
						   6 );
			
			PrimarySession->NetDiskAddress.Port = ndfsRequestSetup->NetdiskPort2;//HTONS(ndfsRequestSetup->NetDiskPort);
			PrimarySession->UnitDiskNo = NTOHS(ndfsRequestSetup->UnitDiskNo2);
			RtlCopyMemory( PrimarySession->NdscId, ndfsRequestSetup->NdscId, NDSC_ID_LENGTH);
				
			if (PrimarySession->SessionContext.NdfsMinorVersion == NDFS_PROTOCOL_MINOR_0) {

				status = NetdiskManager_GetPrimaryPartition( GlobalLfs.NetdiskManager,
															 PrimarySession,
															 &PrimarySession->NetDiskAddress,
															 PrimarySession->UnitDiskNo,
															 PrimarySession->NdscId,
															 NULL,
															 PrimarySession->IsLocalAddress,
															 &PrimarySession->NetdiskPartition,
															 &PrimarySession->NetdiskPartitionInformation,
															 &PrimarySession->FileSystemType );

				SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
							   ("PRIM:SETUP:MIN1 PrimarySession->NetdiskPartition = %p netDiskPartitionInfo.StartingOffset = %I64x\n",
								 PrimarySession->NetdiskPartition, PrimarySession->StartingOffset.QuadPart) );

				if (status != STATUS_SUCCESS) {

					ndfsReplySetupStatus = NDFS_SETUP_UNSUCCESSFUL;
					break;
				}
			
			} else {

				NDAS_BUGON( FALSE );
			}

			
			MD5Init( &context );

			/* id byte */
			idData[0] = (unsigned char)PrimarySession->SessionContext.SessionKey;
			
			MD5Update( &context, idData, 1 );

			MD5Update( &context, 
					   PrimarySession->NetdiskPartitionInformation.NetdiskInformation.Password, 
					   8 );

			MD5Update( &context, &(UCHAR)PrimarySession, sizeof(PPRIMARY_SESSION) );
			MD5Final( responseBuffer, &context );

			if (!RtlEqualMemory(ndfsRequestSetup->ResponseBuffer,
								responseBuffer,
								16)) {

				NDAS_BUGON( LFS_BUG );
				ndfsReplySetupStatus = NDFS_SETUP_UNSUCCESSFUL;				
				break;
			}

			ndfsReplySetupStatus = NDFS_SETUP_SUCCESS;
		
		} while(0);

		ndfsReplyHeader = (PNDFS_REPLY_HEADER)(ndfsRequestSetup+1);
			
		RtlCopyMemory( ndfsReplyHeader->Protocol, NDFS_PROTOCOL, sizeof(ndfsReplyHeader->Protocol) );
		
		ndfsReplyHeader->Status		= NDFS_SUCCESS;
		ndfsReplyHeader->Flags	    = 0;
		ndfsReplyHeader->Uid2		= 0;
		ndfsReplyHeader->Tid2		= 0;
		ndfsReplyHeader->Mid2		= 0;
		ndfsReplyHeader->MessageSize4 = HTONL((UINT32)(sizeof(NDFS_REPLY_HEADER)+sizeof(NDFS_REPLY_SETUP)));

		if (ndfsReplySetupStatus == NDFS_SETUP_SUCCESS) {

			if (NTOHL(ndfsRequestSetup->MaxBufferSize4)) {

				if (PrimarySession->NetdiskPartition->FileSystemType == LFS_FILE_SYSTEM_NDAS_NTFS ||
					GlobalLfs.NdasFatRwIndirect == FALSE && PrimarySession->NetdiskPartition->FileSystemType == LFS_FILE_SYSTEM_NDAS_FAT ||
					GlobalLfs.NdasNtfsRwIndirect == FALSE && PrimarySession->NetdiskPartition->FileSystemType == LFS_FILE_SYSTEM_NDAS_NTFS) {

					PrimarySession->SessionContext.SecondaryMaxDataSize = NTOHL(ndfsRequestSetup->MaxBufferSize4);
				
				} else {

					PrimarySession->SessionContext.SecondaryMaxDataSize = 
						(NTOHL(ndfsRequestSetup->MaxBufferSize4) <= PrimarySession->SessionContext.SecondaryMaxDataSize) ? 
							   NTOHL(ndfsRequestSetup->MaxBufferSize4) : PrimarySession->SessionContext.SecondaryMaxDataSize;
				}

				//
				//	Initialize transport context for traffic control
				//

				InitTransCtx(&PrimarySession->Thread.TransportCtx, PrimarySession->SessionContext.SecondaryMaxDataSize);
			}

			SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
						   ("NDFS_COMMAND_SETUP: PrimarySession->NetdiskPartition->FileSystemType = %d "  
						    "ndfsRequestSetup->MaxBufferSize = %x PrimaryMaxDataSize:%x SecondaryMaxDataSize:%x \n",
							PrimarySession->NetdiskPartition->FileSystemType, NTOHL(ndfsRequestSetup->MaxBufferSize4), 
							PrimarySession->SessionContext.PrimaryMaxDataSize,
							PrimarySession->SessionContext.SecondaryMaxDataSize) );

			ndfsReplyHeader->Uid2 = HTONS(PrimarySession->SessionContext.Uid);
			ndfsReplyHeader->Tid2 = HTONS(PrimarySession->SessionContext.Tid);
		
		} else {

			if (PrimarySession->NetdiskPartition) {

				NetdiskManager_ReturnPrimaryPartition( GlobalLfs.NetdiskManager, 
													   PrimarySession,
													   PrimarySession->NetdiskPartition, 
													   PrimarySession->IsLocalAddress );

				PrimarySession->NetdiskPartition = NULL;
			}
		}

		ndfsReplySetup = (PNDFS_REPLY_SETUP)(ndfsReplyHeader+1);
		ndfsReplySetup->Status = ndfsReplySetupStatus;

		status = SendMessage( PrimarySession->ConnectionFileObject,
							  &PrimarySession->SendNdasFcStatistics,
							  NULL,
							  (UINT8 *)ndfsReplyHeader,
							  NTOHL(ndfsReplyHeader->MessageSize4) );

		if (status != STATUS_SUCCESS) {

			break;
		}

		if (ndfsReplySetupStatus == NDFS_SETUP_SUCCESS)
			PrimarySession->Thread.SessionState = SESSION_SETUP;
		
		break;
	}

	case NDFS_COMMAND_TREE_CONNECT:{

		PNDFS_REQUEST_TREE_CONNECT	ndfsRequestTreeConnect;
		PNDFS_REPLY_HEADER			ndfsReplyHeader;
		PNDFS_REPLY_TREE_CONNECT	ndfsReplyTreeConnect;
	
		UINT8							ndfsReplyTreeConnectStatus;
		
		
		if (!(PrimarySession->Thread.SessionState == SESSION_SETUP && \
			  NTOHS(ndfsRequestHeader->Uid2) == PrimarySession->SessionContext.Uid)) {

			ASSERT( LFS_BUG );
			status = STATUS_UNSUCCESSFUL;

			break;
		}
		
		ASSERT( NTOHL(ndfsRequestHeader->MessageSize4) == sizeof(NDFS_REQUEST_HEADER) + sizeof(NDFS_REQUEST_TREE_CONNECT) );
		ndfsRequestTreeConnect = (PNDFS_REQUEST_TREE_CONNECT)(ndfsRequestHeader+1);

		status = RecvMessage( PrimarySession->ConnectionFileObject,
							  &PrimarySession->RecvNdasFcStatistics,
							  NULL,
							  (UINT8 *)ndfsRequestTreeConnect,
							  sizeof(NDFS_REQUEST_TREE_CONNECT) );
	
		if (status != STATUS_SUCCESS) {

			ASSERT( LFS_BUG );

			break;
		}
		
		do {

			NTSTATUS			getVolumeInformationStatus;
			PNETDISK_PARTITION	netdiskPartition;


			ndfsReplyHeader = (PNDFS_REPLY_HEADER)(ndfsRequestTreeConnect+1);

			RtlCopyMemory( ndfsReplyHeader->Protocol, NDFS_PROTOCOL, sizeof(ndfsReplyHeader->Protocol) );

			ndfsReplyHeader->Status		= NDFS_SUCCESS;
			ndfsReplyHeader->Flags	    = 0;
			ndfsReplyHeader->Uid2		= HTONS(PrimarySession->SessionContext.Uid);
			ndfsReplyHeader->Tid2		= 0;
			ndfsReplyHeader->Mid2		= 0;
			ndfsReplyHeader->MessageSize4 = HTONL((UINT32)(sizeof(NDFS_REPLY_HEADER)+sizeof(NDFS_REPLY_TREE_CONNECT)));

			PrimarySession->StartingOffset.QuadPart = NTOHLL(ndfsRequestTreeConnect->StartingOffset8);

			status = NetdiskManager_GetPrimaryPartition( GlobalLfs.NetdiskManager,
														 PrimarySession,
														 &PrimarySession->NetDiskAddress,
														 PrimarySession->UnitDiskNo,
														 PrimarySession->NdscId,
														 &PrimarySession->StartingOffset,
														 PrimarySession->IsLocalAddress,
														 &netdiskPartition,
														 &PrimarySession->NetdiskPartitionInformation,
														 &PrimarySession->FileSystemType );

			SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE,
						   ("PRIM:TREE_CONNECT: netdiskPartition = %p netDiskPartitionInfo.StartingOffset = %I64x\n", 
						    netdiskPartition, PrimarySession->StartingOffset.QuadPart) );

			if (status != STATUS_SUCCESS) {
				
				if (status == STATUS_UNRECOGNIZED_VOLUME) {

					SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE,
								   ("PRIM:TREE_CONNECT: Partition is not available\n") );

					ndfsReplyTreeConnectStatus = NDFS_TREE_CONNECT_NO_PARTITION;				
				
				} else {

					ndfsReplyTreeConnectStatus = NDFS_TREE_CONNECT_UNSUCCESSFUL;
				}
			
				break;
			}

			if (FlagOn(netdiskPartition->Flags, NETDISK_PARTITION_FLAG_MOUNT_CORRUPTED)) {

				ndfsReplyTreeConnectStatus = NDFS_TREE_CORRUPTED;

				NetdiskManager_ReturnPrimaryPartition( GlobalLfs.NetdiskManager, 
													   PrimarySession,
													   netdiskPartition, 
													   PrimarySession->IsLocalAddress );
				break;
			}

			if (netdiskPartition->FileSystemType == LFS_FILE_SYSTEM_NTFS && IS_WINDOWSXP_OR_LATER()) {

				getVolumeInformationStatus = 
					GetVolumeInformation( PrimarySession, 
										  &netdiskPartition->NetdiskPartitionInformation.VolumeName );
		
				SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE,
							   ("PRIM:TREE_CONNECT: getVolumeInformationStatus = %x\n", 
								getVolumeInformationStatus) );

				if (getVolumeInformationStatus != STATUS_SUCCESS) {

					NetdiskManager_ReturnPrimaryPartition( GlobalLfs.NetdiskManager, 
														   PrimarySession,
														   netdiskPartition, 
														   PrimarySession->IsLocalAddress );

					ndfsReplyTreeConnectStatus = NDFS_TREE_CONNECT_UNSUCCESSFUL;				
					break;
				}
			}

			if (PrimarySession->NetdiskPartition) { 

				NetdiskManager_ReturnPrimaryPartition( GlobalLfs.NetdiskManager, 
													   PrimarySession,
													   PrimarySession->NetdiskPartition, 
													   PrimarySession->IsLocalAddress );
			
				PrimarySession->NetdiskPartition = NULL;
			
			} else {

				NDAS_BUGON( FALSE );
			}

			PrimarySession->NetdiskPartition = netdiskPartition;

			PrimarySession->SessionContext.Tid  = PrimarySession->NetdiskPartition->Tid;
			ndfsReplyHeader->Tid2 = HTONS(PrimarySession->SessionContext.Tid);

			ndfsReplyTreeConnectStatus = NDFS_TREE_CONNECT_SUCCESS;				
		
		} while(0);
		
		ndfsReplyTreeConnect = (PNDFS_REPLY_TREE_CONNECT)(ndfsReplyHeader+1);
		ndfsReplyTreeConnect->Status = ndfsReplyTreeConnectStatus;
		
		ndfsReplyTreeConnect->SessionSlotCount = SESSION_SLOT_COUNT;
		
		ndfsReplyTreeConnect->BytesPerFileRecordSegment4	= HTONL(PrimarySession->Thread.BytesPerFileRecordSegment);
		ndfsReplyTreeConnect->BytesPerSector4			= HTONL(PrimarySession->Thread.BytesPerSector);
		ndfsReplyTreeConnect->BytesPerCluster4			= HTONL(PrimarySession->Thread.BytesPerCluster);

		status = SendMessage( PrimarySession->ConnectionFileObject,
							  &PrimarySession->SendNdasFcStatistics,
							  NULL,
							  (UINT8 *)ndfsReplyHeader,
							  NTOHL(ndfsReplyHeader->MessageSize4) );

		if (status != STATUS_SUCCESS) {
		
			break;
		}

		if (ndfsReplyTreeConnectStatus == NDFS_TREE_CONNECT_SUCCESS) {

			status = PrimarySessionTakeOver( PrimarySession );

			if (status == STATUS_INVALID_DEVICE_REQUEST) {

				PrimarySession->Thread.SessionState = SESSION_TREE_CONNECT;
			
			} else {
				
				SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
						   ("PrimarySessionTakeOver: Success PrimarySession = %p status = %x\n", 
						    PrimarySession, status) );

				if (PrimarySession->NetdiskPartition) {

					NetdiskManager_ReturnPrimaryPartition( GlobalLfs.NetdiskManager,
														   PrimarySession,
														   PrimarySession->NetdiskPartition, 
														   PrimarySession->IsLocalAddress );	

					PrimarySession->NetdiskPartition = NULL;
				}
						
				if (status == STATUS_SUCCESS) {

					PrimarySession->ConnectionFileHandle = NULL;
					PrimarySession->ConnectionFileObject = NULL;
					
				} else {

					DisconnectFromSecondary( PrimarySession );
				} 

				SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED );

				PrimarySession->Thread.SessionState = SESSION_CLOSED;
			}
		}

		status = STATUS_SUCCESS;

		break;
	}

	case NDFS_COMMAND_LOGOFF: {

		PNDFS_REQUEST_LOGOFF	ndfsRequestLogoff;
		PNDFS_REPLY_HEADER		ndfsReplyHeader;
		PNDFS_REPLY_LOGOFF		ndfsReplyLogoff;
		

		if(PrimarySession->SessionContext.NdfsMinorVersion == NDFS_PROTOCOL_MINOR_0) {

			if(PrimarySession->Thread.SessionState != SESSION_TREE_CONNECT) {

				ASSERT( LFS_BUG );
				status = STATUS_UNSUCCESSFUL;
				break;
			}
		}

		if (!(NTOHS(ndfsRequestHeader->Uid2) == PrimarySession->SessionContext.Uid && 
			  NTOHS(ndfsRequestHeader->Tid2) == PrimarySession->SessionContext.Tid)) {

			ASSERT( LFS_BUG );
			status = STATUS_UNSUCCESSFUL;

			break;
		}
		
		ASSERT( NTOHL(ndfsRequestHeader->MessageSize4) == sizeof(NDFS_REQUEST_HEADER) + sizeof(NDFS_REQUEST_LOGOFF) );

		ndfsRequestLogoff = (PNDFS_REQUEST_LOGOFF)(ndfsRequestHeader+1);

		status = RecvMessage( PrimarySession->ConnectionFileObject,
							  &PrimarySession->RecvNdasFcStatistics,
							  NULL,
							  (UINT8 *)ndfsRequestLogoff,
							  sizeof(NDFS_REQUEST_LOGOFF) );
	

		if (status != STATUS_SUCCESS) {

			//ASSERT( LFS_BUG );

			break;
		}

		ndfsReplyHeader = (PNDFS_REPLY_HEADER)(ndfsRequestLogoff+1);

		RtlCopyMemory( ndfsReplyHeader->Protocol, NDFS_PROTOCOL, sizeof(ndfsReplyHeader->Protocol) );

		ndfsReplyHeader->Status		= NDFS_SUCCESS;
		ndfsReplyHeader->Flags	    = 0;
		ndfsReplyHeader->Uid2		= HTONS(PrimarySession->SessionContext.Uid);
		ndfsReplyHeader->Tid2		= 0;
		ndfsReplyHeader->Mid2		= 0;
		ndfsReplyHeader->MessageSize4 = HTONL((UINT32)(sizeof(NDFS_REPLY_HEADER)+sizeof(NDFS_REPLY_LOGOFF)));

		ndfsReplyLogoff = (PNDFS_REPLY_LOGOFF)(ndfsReplyHeader+1);

		if (NTOHL(ndfsRequestLogoff->SessionKey4) != PrimarySession->SessionContext.SessionKey) {

			ndfsReplyLogoff->Status = NDFS_LOGOFF_UNSUCCESSFUL;
		
		} else {

			ndfsReplyLogoff->Status = NDFS_LOGOFF_SUCCESS;
		}

		status = SendMessage( PrimarySession->ConnectionFileObject,
							  &PrimarySession->SendNdasFcStatistics,
							  NULL,
							  (UINT8 *)ndfsReplyHeader,
							  NTOHL(ndfsReplyHeader->MessageSize4) );

		if (status != STATUS_SUCCESS) {

			break;
		}

		PrimarySession->Thread.SessionState = SESSION_CLOSED;
		break;
	}

	case NDFS_COMMAND_EXECUTE: {

		UINT16	mid;

		if(PrimarySession->SessionContext.NdfsMinorVersion == NDFS_PROTOCOL_MINOR_0) {

			if (PrimarySession->Thread.SessionState != SESSION_TREE_CONNECT) {

				ASSERT( LFS_BUG );
				status = STATUS_UNSUCCESSFUL;
				break;
			}
		}

		if (!(NTOHS(ndfsRequestHeader->Uid2) == PrimarySession->SessionContext.Uid && 
			NTOHS(ndfsRequestHeader->Tid2) == PrimarySession->SessionContext.Tid)) {

			ASSERT( LFS_BUG );
			status = STATUS_UNSUCCESSFUL;

			break;
		}

		mid = NTOHS(ndfsRequestHeader->Mid2);

		PrimarySession->Thread.SessionSlot[mid].RequestMessageBufferLength = sizeof(NDFS_REQUEST_HEADER) + sizeof(NDFS_WINXP_REQUEST_HEADER) + DEFAULT_MAX_DATA_SIZE;
		RtlZeroMemory( &PrimarySession->Thread.SessionSlot[mid].RequestMessageBuffer[sizeof(NDFS_REQUEST_HEADER)], 
					   PrimarySession->Thread.SessionSlot[mid].RequestMessageBufferLength - sizeof(NDFS_REQUEST_HEADER) );

		PrimarySession->Thread.SessionSlot[mid].ReplyMessageBufferLength = sizeof(NDFS_REPLY_HEADER) + sizeof(NDFS_WINXP_REPLY_HEADER) + DEFAULT_MAX_DATA_SIZE;
		RtlZeroMemory( PrimarySession->Thread.SessionSlot[mid].ReplyMessageBuffer, 
					   PrimarySession->Thread.SessionSlot[mid].ReplyMessageBufferLength );

		ASSERT( NTOHL(ndfsRequestHeader->MessageSize4) >= sizeof(NDFS_REQUEST_HEADER) + sizeof(NDFS_WINXP_REQUEST_HEADER) );

		status = ReceiveNtfsWinxpMessage(PrimarySession, mid );

		if (status != STATUS_SUCCESS)
			break;

		if (PrimarySession->Thread.SessionSlot[mid].State != SLOT_WAIT) {

			break;
		}
	
		PrimarySession->Thread.SessionSlot[mid].State = SLOT_EXECUTING;
		PrimarySession->Thread.IdleSlotCount --;

		if (PrimarySession->SessionContext.SessionSlotCount == 1) {

			ASSERT( mid == 0 );

			DispatchWinXpRequestWorker( PrimarySession, mid );

			PrimarySession->Thread.SessionSlot[mid].State = SLOT_WAIT;
			PrimarySession->Thread.IdleSlotCount ++;

			if (PrimarySession->Thread.SessionSlot[mid].Status == STATUS_SUCCESS) {

				PNDFS_REPLY_HEADER		ndfsReplyHeader;

				ndfsReplyHeader = (PNDFS_REPLY_HEADER)PrimarySession->Thread.SessionSlot[mid].ReplyMessageBuffer;
										
				PrimarySession->Thread.SessionSlot[mid].Status = 
					SendNdfsWinxpMessage( PrimarySession,
										  ndfsReplyHeader,
										  PrimarySession->Thread.SessionSlot[mid].NdfsWinxpReplyHeader,
										  PrimarySession->Thread.SessionSlot[mid].ReplyDataSize,
										  mid );

			}
	
			if (PrimarySession->Thread.SessionSlot[mid].ExtendWinxpRequestMessagePool) {

				ExFreePool( PrimarySession->Thread.SessionSlot[mid].ExtendWinxpRequestMessagePool );	
				PrimarySession->Thread.SessionSlot[mid].ExtendWinxpRequestMessagePool = NULL;
				PrimarySession->Thread.SessionSlot[mid].ExtendWinxpReplyMessagePoolLength = 0;
			}
		
			if (PrimarySession->Thread.SessionSlot[mid].ExtendWinxpReplyMessagePool) {

				ExFreePool( PrimarySession->Thread.SessionSlot[mid].ExtendWinxpReplyMessagePool );	
				PrimarySession->Thread.SessionSlot[mid].ExtendWinxpReplyMessagePool = NULL;
				PrimarySession->Thread.SessionSlot[mid].ExtendWinxpReplyMessagePoolLength = 0;
			}

			if (PrimarySession->Thread.SessionSlot[mid].Status == STATUS_PENDING)
				NDAS_BUGON( FALSE );			
			
			if (PrimarySession->Thread.SessionSlot[mid].Status != STATUS_SUCCESS) {

				SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
										
				status = PrimarySession->Thread.SessionSlot[mid].Status;
				break;		
			}
				
			status = STATUS_SUCCESS;
			break;
		}

		NDAS_BUGON( FALSE );

		if (mid == 0)
			ExInitializeWorkItem( &PrimarySession->Thread.SessionSlot[mid].WorkQueueItem,
								  DispatchWinXpRequestWorker0,
								  PrimarySession );
		
		if (mid == 1)
			ExInitializeWorkItem( &PrimarySession->Thread.SessionSlot[mid].WorkQueueItem,
								  DispatchWinXpRequestWorker1,
								  PrimarySession );
		
		if (mid == 2)
			ExInitializeWorkItem( &PrimarySession->Thread.SessionSlot[mid].WorkQueueItem,
								  DispatchWinXpRequestWorker2,
								  PrimarySession );

		
		if (mid == 3)
			ExInitializeWorkItem( &PrimarySession->Thread.SessionSlot[mid].WorkQueueItem,
								  DispatchWinXpRequestWorker3,
								  PrimarySession );

		ExQueueWorkItem( &PrimarySession->Thread.SessionSlot[mid].WorkQueueItem, DelayedWorkQueue );	

		status = STATUS_PENDING;
		break;
	}

	default:

		ASSERT( LFS_LPX_BUG );
		status = STATUS_UNSUCCESSFUL;
		
		break;
	}

	return status;
}
Ejemplo n.º 27
0
VOID
CdCompleteRequest (
    IN PIRP_CONTEXT IrpContext OPTIONAL,
    IN PIRP Irp OPTIONAL,
    IN NTSTATUS Status
    )

/*++

Routine Description:

    This routine completes a Irp and cleans up the IrpContext.  Either or
    both of these may not be specified.

Arguments:

    Irp - Supplies the Irp being processed.

    Status - Supplies the status to complete the Irp with

Return Value:

    None.

--*/

{
    ASSERT_OPTIONAL_IRP_CONTEXT( IrpContext );
    ASSERT_OPTIONAL_IRP( Irp );

    //
    //  Cleanup the IrpContext if passed in here.
    //

    if (ARGUMENT_PRESENT( IrpContext )) {

        CdCleanupIrpContext( IrpContext, FALSE );
    }

    //
    //  If we have an Irp then complete the irp.
    //

    if (ARGUMENT_PRESENT( Irp )) {

        //
        //  Clear the information field in case we have used this Irp
        //  internally.
        //

        if (NT_ERROR( Status ) &&
            FlagOn( Irp->Flags, IRP_INPUT_OPERATION )) {

            Irp->IoStatus.Information = 0;
        }

        Irp->IoStatus.Status = Status;

        AssertVerifyDeviceIrp( Irp );
        
        IoCompleteRequest( Irp, IO_CD_ROM_INCREMENT );
    }

    return;
}
Ejemplo n.º 28
0
VOID
CdAddAllocationFromDirent (
    __in PIRP_CONTEXT IrpContext,
    __inout PFCB Fcb,
    __in ULONG McbEntryOffset,
    __in LONGLONG StartingFileOffset,
    __in PDIRENT Dirent
    )

/*++

Routine Description:

    This routine is called to add an entry into the Cd Mcb.  We grow the Mcb
    as necessary and update the new entry.

    NOTE - The Fcb has already been locked prior to makeing this call.

Arguments:

    Fcb - Fcb containing the Mcb to update.

    McbEntryOffset - Offset into the Mcb array to add this data.

    StartingFileOffset - Offset in bytes from the start of the file.

    Dirent - Dirent containing the on-disk data for this entry.

Return Value:

    None

--*/

{
    ULONG NewArraySize;
    PVOID NewMcbArray;
    PCD_MCB_ENTRY McbEntry;

    PAGED_CODE();

    UNREFERENCED_PARAMETER( IrpContext );

    ASSERT_IRP_CONTEXT( IrpContext );
    ASSERT_FCB( Fcb );
    ASSERT_LOCKED_FCB( Fcb );

    //
    //  If we need to grow the Mcb then do it now.
    //

    if (McbEntryOffset >= Fcb->Mcb.MaximumEntryCount) {

        //
        //  Allocate a new buffer and copy the old data over.
        //

        NewArraySize = Fcb->Mcb.MaximumEntryCount * 2 * sizeof( CD_MCB_ENTRY );

        NewMcbArray = FsRtlAllocatePoolWithTag( CdPagedPool,
                                                NewArraySize,
                                                TAG_MCB_ARRAY );

        RtlZeroMemory( NewMcbArray, NewArraySize );
        RtlCopyMemory( NewMcbArray,
                       Fcb->Mcb.McbArray,
                       Fcb->Mcb.MaximumEntryCount * sizeof( CD_MCB_ENTRY ));

        //
        //  Deallocate the current array unless it is embedded in the Fcb.
        //

        if (Fcb->Mcb.MaximumEntryCount != 1) {

            CdFreePool( &Fcb->Mcb.McbArray );
        }

        //
        //  Now update the Mcb with the new array.
        //

        Fcb->Mcb.MaximumEntryCount *= 2;
        Fcb->Mcb.McbArray = NewMcbArray;
    }

    //
    //  Update the new entry with the input data.
    //

    McbEntry = Fcb->Mcb.McbArray + McbEntryOffset;

    //
    //  Start with the location and length on disk.
    //

    McbEntry->DiskOffset = LlBytesFromBlocks( Fcb->Vcb, Dirent->StartingOffset );
    McbEntry->ByteCount = Dirent->DataLength;

    //
    //  Round the byte count up to a logical block boundary if this is
    //  the last extent.
    //

    if (!FlagOn( Dirent->DirentFlags, CD_ATTRIBUTE_MULTI )) {

        McbEntry->ByteCount = BlockAlign( Fcb->Vcb, McbEntry->ByteCount );
    }

    //
    //  The file offset is the logical position within this file.
    //  We know this is correct regardless of whether we bias the
    //  file size or disk offset.
    //

    McbEntry->FileOffset = StartingFileOffset;

    //
    //  Convert the interleave information from logical blocks to
    //  bytes.
    //

    if (Dirent->FileUnitSize != 0) {

        McbEntry->DataBlockByteCount = LlBytesFromBlocks( Fcb->Vcb, Dirent->FileUnitSize );
        McbEntry->TotalBlockByteCount = McbEntry->DataBlockByteCount +
                                        LlBytesFromBlocks( Fcb->Vcb, Dirent->InterleaveGapSize );

    //
    //  If the file is not interleaved then the size of the data block
    //  and total block are the same as the byte count.
    //

    } else {

        McbEntry->DataBlockByteCount =
        McbEntry->TotalBlockByteCount = McbEntry->ByteCount;
    }

    //
    //  Update the number of entries in the Mcb.  The Mcb is never sparse
    //  so whenever we add an entry it becomes the last entry in the Mcb.
    //

    Fcb->Mcb.CurrentEntryCount = McbEntryOffset + 1;

    return;
}
Ejemplo n.º 29
0
VOID
PrimarySession_Close(
	IN 	PPRIMARY_SESSION	PrimarySession
	)
{
	DebugTrace( 0, Dbg2, ("PrimarySession_Close: PrimarySession = %p\n", PrimarySession) );

	ExAcquireFastMutexUnsafe( &PrimarySession->FastMutex );
	if (FlagOn(PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOP)) {

		ExReleaseFastMutexUnsafe( &PrimarySession->FastMutex );
		return;
	}

	SetFlag( PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOP );

	ExReleaseFastMutexUnsafe( &PrimarySession->FastMutex );
	
	if (PrimarySession->ThreadHandle == NULL) {

		ASSERT( NDASNTFS_BUG );
		PrimarySession_Dereference( PrimarySession );

		return;
	}

	ASSERT( PrimarySession->ThreadObject != NULL );

	if (FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_TERMINATED)) {

		ObDereferenceObject( PrimarySession->ThreadObject );

		PrimarySession->ThreadHandle = NULL;
		PrimarySession->ThreadObject = NULL;

	
	} else {

		PPRIMARY_SESSION_REQUEST	primarySessionRequest;
		NTSTATUS					ntStatus;
		LARGE_INTEGER				timeOut;
	
		
		primarySessionRequest = AllocPrimarySessionRequest( FALSE );
		primarySessionRequest->RequestType = PRIMARY_SESSION_REQ_DISCONNECT;

		QueueingPrimarySessionRequest( PrimarySession,
									   primarySessionRequest,
									   FALSE );

		primarySessionRequest = AllocPrimarySessionRequest( FALSE );
		primarySessionRequest->RequestType = PRIMARY_SESSION_REQ_DOWN;

		QueueingPrimarySessionRequest( PrimarySession,
									   primarySessionRequest,
									   FALSE );

		timeOut.QuadPart = -NDNTFS_TIME_OUT;
		ntStatus = KeWaitForSingleObject( PrimarySession->ThreadObject,
										  Executive,
										  KernelMode,
										  FALSE,
										  &timeOut );

		if (ntStatus == STATUS_SUCCESS) {

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

			ObDereferenceObject( PrimarySession->ThreadObject );

			PrimarySession->ThreadHandle = NULL;
			PrimarySession->ThreadObject = NULL;
				
		} else {

			ASSERT( NDASNTFS_BUG );
			return;
		}
	}

#if 0
    interval.QuadPart = (5 * DELAY_ONE_SECOND);      //delay 5 seconds
    KeDelayExecutionThread( KernelMode, FALSE, &interval );
#endif

	if (PrimarySession->ConnectionFileHandle) {

		LpxTdiDisassociateAddress( PrimarySession->ConnectionFileObject );
		LpxTdiCloseConnection( PrimarySession->ConnectionFileHandle, PrimarySession->ConnectionFileObject );
	}

	PrimarySession->ConnectionFileHandle = NULL;
	PrimarySession->ConnectionFileObject = NULL;

	PrimarySession_Dereference( PrimarySession );

	return;
}
Ejemplo n.º 30
0
NTSTATUS
CdQueryAlternateNameInfo (
    IN PIRP_CONTEXT IrpContext,
    IN PFCB Fcb,
    IN PCCB Ccb,
    IN OUT PFILE_NAME_INFORMATION Buffer,
    IN OUT PULONG Length
    )

/*++

Routine Description:

    This routine performs the query alternate name information function.
    We lookup the dirent for this file and then check if there is a
    short name.

Arguments:

    Fcb - Supplies the Fcb being queried, it has been verified.

    Ccb - Ccb for this open handle.

    Buffer - Supplies a pointer to the buffer where the information is to
        be returned.

    Length - Supplies the length of the buffer in bytes, and receives the
        remaining bytes free in the buffer upon return.

Return Value:

    NTSTATUS - STATUS_SUCCESS if the whole name would fit into the user buffer,
               STATUS_OBJECT_NAME_NOT_FOUND if we can't return the name,
               STATUS_BUFFER_OVERFLOW otherwise.

--*/

{
    NTSTATUS Status = STATUS_SUCCESS;

    DIRENT_ENUM_CONTEXT DirContext;
    DIRENT Dirent;

    PUNICODE_STRING NameToUse;
    ULONG DirentOffset;

    COMPOUND_PATH_ENTRY CompoundPathEntry;
    FILE_ENUM_CONTEXT FileContext;

    PFCB ParentFcb;
    BOOLEAN ReleaseParentFcb = FALSE;

    BOOLEAN CleanupFileLookup = FALSE;
    BOOLEAN CleanupDirectoryLookup = FALSE;

    WCHAR ShortNameBuffer[ BYTE_COUNT_8_DOT_3 / 2 ];
    USHORT ShortNameLength;

    PAGED_CODE();

    //
    //  Initialize the buffer length to zero.
    //

    Buffer->FileNameLength = 0;

    //
    //  If this is the root or this file was opened using a version number then
    //  there is no short name.
    //

    if ((Fcb == Fcb->Vcb->RootIndexFcb) ||
        FlagOn( Ccb->Flags, CCB_FLAG_OPEN_WITH_VERSION)) {

        return STATUS_OBJECT_NAME_NOT_FOUND;
    }

    //
    //  Use a try-finally to cleanup the structures.
    //

    try {

        ParentFcb = Fcb->ParentFcb;
        CdAcquireFileShared( IrpContext, ParentFcb );
        ReleaseParentFcb = TRUE;
    
        //
        //  Do an unsafe test to see if we need to create a file object.
        //

        if (ParentFcb->FileObject == NULL) {

            CdCreateInternalStream( IrpContext, ParentFcb->Vcb, ParentFcb );
        }

        if (CdFidIsDirectory( Fcb->FileId)) {

            //
            //  Fcb is for a directory, so we need to dig the dirent from the parent.  In
            //  order to do this we need to get the name of the directory from its pathtable
            //  entry and then search in the parent for a matching dirent.
            //
            //  This could be optimized somewhat.
            //

            CdInitializeCompoundPathEntry( IrpContext, &CompoundPathEntry );
            CdInitializeFileContext( IrpContext, &FileContext );

            CleanupDirectoryLookup = TRUE;

            CdLookupPathEntry( IrpContext,
                               CdQueryFidPathTableOffset( Fcb->FileId ),
                               Fcb->Ordinal,
                               FALSE,
                               &CompoundPathEntry );

            CdUpdatePathEntryName( IrpContext, &CompoundPathEntry.PathEntry, TRUE );

            if (!CdFindDirectory( IrpContext,
                                  ParentFcb,
                                  &CompoundPathEntry.PathEntry.CdCaseDirName,
                                  TRUE,
                                  &FileContext )) {

                //
                //  If we failed to find the child directory by name in the parent
                //  something is quite wrong with this disc.
                //

                CdRaiseStatus( IrpContext, STATUS_DISK_CORRUPT_ERROR );
            }

            NameToUse = &FileContext.InitialDirent->Dirent.CdCaseFileName.FileName;
            DirentOffset = FileContext.InitialDirent->Dirent.DirentOffset;
        
        } else {

            //
            //  Initialize the search dirent structures.
            //
        
            CdInitializeDirContext( IrpContext, &DirContext );
            CdInitializeDirent( IrpContext, &Dirent );
    
            CleanupFileLookup = TRUE;
        
            CdLookupDirent( IrpContext,
                            ParentFcb,
                            CdQueryFidDirentOffset( Fcb->FileId ),
                            &DirContext );
    
            CdUpdateDirentFromRawDirent( IrpContext,
                                         ParentFcb,
                                         &DirContext,
                                         &Dirent );

            //
            //  Now update the dirent name.
            //
    
            CdUpdateDirentName( IrpContext, &Dirent, TRUE );
    
            NameToUse = &Dirent.CdCaseFileName.FileName;
            DirentOffset = Dirent.DirentOffset;
        }

        //
        //  If the name is 8.3 then fail this request.
        //

        if (CdIs8dot3Name( IrpContext,
                           *NameToUse )) {


            try_return( Status = STATUS_OBJECT_NAME_NOT_FOUND );
        }

        CdGenerate8dot3Name( IrpContext,
                             NameToUse,
                             DirentOffset,
                             ShortNameBuffer,
                             &ShortNameLength );

        //
        //  We now have the short name.  We have left it in Unicode form so copy it directly.
        //

        Buffer->FileNameLength = ShortNameLength;

        if (Buffer->FileNameLength + sizeof( ULONG ) > *Length) {

            Buffer->FileNameLength = *Length - sizeof( ULONG );
            Status = STATUS_BUFFER_OVERFLOW;
        }

        RtlCopyMemory( Buffer->FileName, ShortNameBuffer, Buffer->FileNameLength );

    try_exit:  NOTHING;
    } finally {

        if (CleanupFileLookup) {

            CdCleanupDirContext( IrpContext, &DirContext );
            CdCleanupDirent( IrpContext, &Dirent );

        } else if (CleanupDirectoryLookup) {

            CdCleanupCompoundPathEntry( IrpContext, &CompoundPathEntry );
            CdCleanupFileContext( IrpContext, &FileContext );
        }

        if (ReleaseParentFcb) {

            CdReleaseFile( IrpContext, ParentFcb );
        }
    }

    //
    //  Reduce the available bytes by the amount stored into this buffer.
    //

    if (Status != STATUS_OBJECT_NAME_NOT_FOUND) {

        *Length -= sizeof( ULONG ) + Buffer->FileNameLength;
    }

    return Status;
}