Exemple #1
0
NTSTATUS FspBufferUserBuffer(PIRP Irp, ULONG Length, LOCK_OPERATION Operation)
{
    PAGED_CODE();

    if (0 == Length || 0 != Irp->AssociatedIrp.SystemBuffer)
        return STATUS_SUCCESS;

    PVOID SystemBuffer = FspAllocNonPagedExternal(Length);
    if (0 == SystemBuffer)
        return STATUS_INSUFFICIENT_RESOURCES;

    if (IoReadAccess == Operation)
    {
        try
        {
            RtlCopyMemory(SystemBuffer, Irp->UserBuffer, Length);
        }
        except (EXCEPTION_EXECUTE_HANDLER)
        {
            FspFree(SystemBuffer);

            NTSTATUS Result = GetExceptionCode();
            return FsRtlIsNtstatusExpected(Result) ? STATUS_INVALID_USER_BUFFER : Result;
        }
    }
    else
Exemple #2
0
/*++
 * @name FsRtlNormalizeNtstatus
 * @implemented NT 4.0
 *
 *     The FsRtlNormalizeNtstatus routine normalizes an NTSTATUS error code.
 *
 * @param NtStatusToNormalize
 *        The NTSTATUS error code to Normalize.
 *
 * @param NormalizedNtStatus
 *        The NTSTATUS error code to return if the NtStatusToNormalize is not
 *        a proper expected error code by the File System Library.
 *
 * @return NtStatusToNormalize if it is an expected value, otherwise
 *         NormalizedNtStatus.
 *
 * @remarks None.
 *
 *--*/
NTSTATUS
NTAPI
FsRtlNormalizeNtstatus(IN NTSTATUS NtStatusToNormalize,
                       IN NTSTATUS NormalizedNtStatus)
{
    return(TRUE == FsRtlIsNtstatusExpected(NtStatusToNormalize)) ?
           NtStatusToNormalize : NormalizedNtStatus;
}
Exemple #3
0
LONG
ExceptionFilter(_In_ PEXCEPTION_POINTERS ExceptionPointer,
                _In_ BOOLEAN AccessingUserBuffer)
{
    NTSTATUS Status;

    /* Handle if the exception is valid or this is a usermode buffer */
    Status = ExceptionPointer->ExceptionRecord->ExceptionCode;
    if (FsRtlIsNtstatusExpected(Status) || AccessingUserBuffer)
    {
        return EXCEPTION_EXECUTE_HANDLER;
    }

    return EXCEPTION_CONTINUE_SEARCH;
}
Exemple #4
0
NTSTATUS FspFsvolWritePrepare(
    PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request)
{
    PAGED_CODE();

    if (FspWriteIrpShouldUseProcessBuffer(Irp, Request->Req.Write.Length))
    {
        NTSTATUS Result;
        PVOID Cookie;
        PVOID Address;
        PEPROCESS Process;
        PVOID SystemAddress = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);

        if (0 == SystemAddress)
            return STATUS_INSUFFICIENT_RESOURCES; /* something is seriously screwy! */

        Result = FspProcessBufferAcquire(Request->Req.Write.Length, &Cookie, &Address);
        if (!NT_SUCCESS(Result))
            return Result;

        ASSERT(0 != Address);
        try
        {
            RtlCopyMemory(Address, SystemAddress, Request->Req.Write.Length);
        }
        except (EXCEPTION_EXECUTE_HANDLER)
        {
            Result = GetExceptionCode();
            Result = FsRtlIsNtstatusExpected(Result) ? STATUS_INVALID_USER_BUFFER : Result;

            FspProcessBufferRelease(Cookie, Address);

            return Result;
        }

        /* get a pointer to the current process so that we can release the buffer later */
        Process = PsGetCurrentProcess();
        ObReferenceObject(Process);

        Request->Req.Write.Address = (UINT64)(UINT_PTR)Address;

        FspIopRequestContext(Request, RequestCookie) = (PVOID)((UINT_PTR)Cookie | 1);
        FspIopRequestContext(Request, RequestAddress) = Address;
        FspIopRequestContext(Request, RequestProcess) = Process;

        return STATUS_SUCCESS;
    }
Exemple #5
0
NTSTATUS
DokanExceptionFilter(
__in PIRP Irp,
__in PEXCEPTION_POINTERS  ExceptionPointer
)
{
    UNREFERENCED_PARAMETER(Irp);

    NTSTATUS Status = EXCEPTION_EXECUTE_HANDLER;
    NTSTATUS ExceptionCode;
    PEXCEPTION_RECORD ExceptRecord;

    ExceptRecord = ExceptionPointer->ExceptionRecord;
    ExceptionCode = ExceptRecord->ExceptionCode;

    DbgPrint("-------------------------------------------------------------\n");
    DbgPrint("Exception happends in Dokan (code %xh):\n", ExceptionCode);
    DbgPrint(".exr %p;.cxr %p;\n", ExceptionPointer->ExceptionRecord,
             ExceptionPointer->ContextRecord);
    DbgPrint("-------------------------------------------------------------\n");

    DbgBreakPoint();

    if (Status == EXCEPTION_EXECUTE_HANDLER ||
        FsRtlIsNtstatusExpected(ExceptionCode)) {
        //
        // If the exception is expected execute our handler
        //

        DDbgPrint("DokanExceptionFilter: Catching exception %xh\n", ExceptionCode);

        Status = EXCEPTION_EXECUTE_HANDLER;

    } else {

        //
        // Continue search for an higher level exception handler
        //

        DDbgPrint("DokanExceptionFilter: Passing on exception %#x\n", ExceptionCode);

        Status = EXCEPTION_CONTINUE_SEARCH;

    }

    return Status;
}
Exemple #6
0
LONG
LfsExceptionFilter (
    IN PEXCEPTION_POINTERS ExceptionPointer
    )

/*++

Routine Description:

    This routine is used to decide if we should or should not handle
    an exception status that is being raised.  It indicates that we should handle
    the exception or bug check the system.

Arguments:

    ExceptionCode - Supplies the exception code to being checked.

Return Value:

    ULONG - returns EXCEPTION_EXECUTE_HANDLER or bugchecks

--*/

{
    NTSTATUS ExceptionCode = ExceptionPointer->ExceptionRecord->ExceptionCode;

#ifdef NTFS_RESTART
    ASSERT( (ExceptionCode != STATUS_DISK_CORRUPT_ERROR) &&
            (ExceptionCode != STATUS_FILE_CORRUPT_ERROR) );
#endif

    //if (ExceptionCode != STATUS_LOG_FILE_FULL) {
    //
    //    DbgPrint("Status not LOGFILE FULL, ExceptionPointers = %08lx\n", ExceptionPointer);
    //    DbgBreakPoint();
    //}

    if (!FsRtlIsNtstatusExpected( ExceptionCode )) {

        return EXCEPTION_CONTINUE_SEARCH;

    } else {

        return EXCEPTION_EXECUTE_HANDLER;
    }
}
Exemple #7
0
LONG
CdExceptionFilter (
    _Inout_ PIRP_CONTEXT IrpContext,
    _In_ PEXCEPTION_POINTERS ExceptionPointer
    )

/*++

Routine Description:

    This routine is used to decide whether we will handle a raised exception
    status.  If CDFS explicitly raised an error then this status is already
    in the IrpContext.  We choose which is the correct status code and
    either indicate that we will handle the exception or bug-check the system.

Arguments:

    ExceptionCode - Supplies the exception code to being checked.

Return Value:

    ULONG - returns EXCEPTION_EXECUTE_HANDLER or bugchecks

--*/

{
    NTSTATUS ExceptionCode;
    BOOLEAN TestStatus = TRUE;

    ASSERT_OPTIONAL_IRP_CONTEXT( IrpContext );

    ExceptionCode = ExceptionPointer->ExceptionRecord->ExceptionCode;

    //
    // If the exception is STATUS_IN_PAGE_ERROR, get the I/O error code
    // from the exception record.
    //

    if ((ExceptionCode == STATUS_IN_PAGE_ERROR) &&
        (ExceptionPointer->ExceptionRecord->NumberParameters >= 3)) {

        ExceptionCode =
            (NTSTATUS)ExceptionPointer->ExceptionRecord->ExceptionInformation[2];
    }

    //
    //  If there is an Irp context then check which status code to use.
    //

    if (ARGUMENT_PRESENT( IrpContext )) {

        if (IrpContext->ExceptionStatus == STATUS_SUCCESS) {

            //
            //  Store the real status into the IrpContext.
            //

            IrpContext->ExceptionStatus = ExceptionCode;

        } else {

            //
            //  No need to test the status code if we raised it ourselves.
            //

            TestStatus = FALSE;
        }
    }

    AssertVerifyDevice( IrpContext, IrpContext->ExceptionStatus );
    
    //
    //  Bug check if this status is not supported.
    //

    if (TestStatus && !FsRtlIsNtstatusExpected( ExceptionCode )) {

#pragma prefast( suppress: __WARNING_USE_OTHER_FUNCTION, "We're corrupted." )    
        CdBugCheck( (ULONG_PTR) ExceptionPointer->ExceptionRecord,
                    (ULONG_PTR) ExceptionPointer->ContextRecord,
                    (ULONG_PTR) ExceptionPointer->ExceptionRecord->ExceptionAddress );

    }

    return EXCEPTION_EXECUTE_HANDLER;
}
Exemple #8
0
ULONG
FatExceptionFilter (
    IN PIRP_CONTEXT IrpContext,
    IN PEXCEPTION_POINTERS ExceptionPointer
    )

/*++

Routine Description:

    This routine is used to decide if we should or should not handle
    an exception status that is being raised.  It inserts the status
    into the IrpContext and either indicates that we should handle
    the exception or bug check the system.

Arguments:

    ExceptionPointers - The result of GetExceptionInformation() in the context
        of the exception.

Return Value:

    ULONG - returns EXCEPTION_EXECUTE_HANDLER or bugchecks

--*/

{
    NTSTATUS ExceptionCode;

    ExceptionCode = ExceptionPointer->ExceptionRecord->ExceptionCode;
    DebugTrace(0, DEBUG_TRACE_UNWIND, "FatExceptionFilter %X\n", ExceptionCode);
    DebugDump("FatExceptionFilter\n", Dbg, NULL );

    //
    // If the exception is STATUS_IN_PAGE_ERROR, get the I/O error code
    // from the exception record.
    //

    if (ExceptionCode == STATUS_IN_PAGE_ERROR) {
        if (ExceptionPointer->ExceptionRecord->NumberParameters >= 3) {
            ExceptionCode = (NTSTATUS)ExceptionPointer->ExceptionRecord->ExceptionInformation[2];
        }
    }

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

    if ( !ARGUMENT_PRESENT( IrpContext ) ) {

        if (!FsRtlIsNtstatusExpected( ExceptionCode )) {

            FatBugCheck( (ULONG_PTR)ExceptionPointer->ExceptionRecord,
                         (ULONG_PTR)ExceptionPointer->ContextRecord,
                         (ULONG_PTR)ExceptionPointer->ExceptionRecord->ExceptionAddress );
        }

        return EXCEPTION_EXECUTE_HANDLER;
    }

    //
    //  For the purposes of processing this exception, let's mark this
    //  request as being able to wait and disable  write through if we
    //  aren't posting it.
    //

    SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);

    if ( (ExceptionCode != STATUS_CANT_WAIT) &&
         (ExceptionCode != STATUS_VERIFY_REQUIRED) ) {

        SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_WRITE_THROUGH);
    }

    if ( IrpContext->ExceptionStatus == 0 ) {

        if (FsRtlIsNtstatusExpected( ExceptionCode )) {

            IrpContext->ExceptionStatus = ExceptionCode;

            return EXCEPTION_EXECUTE_HANDLER;

        } else {

            FatBugCheck( (ULONG_PTR)ExceptionPointer->ExceptionRecord,
                         (ULONG_PTR)ExceptionPointer->ContextRecord,
                         (ULONG_PTR)ExceptionPointer->ExceptionRecord->ExceptionAddress );
        }

    } else {

        //
        //  We raised this code explicitly ourselves, so it had better be
        //  expected.
        //

        ASSERT( IrpContext->ExceptionStatus == ExceptionCode );
        ASSERT( FsRtlIsNtstatusExpected( ExceptionCode ) );
    }

    return EXCEPTION_EXECUTE_HANDLER;
}
Exemple #9
0
VOID
NtfsSpecialDispatch (
    PVOID Context
    )

/*++

Routine Description:

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

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

Arguments:

    Context - Supplies a pointer to an IrpContext.

Return Value:

--*/

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

    PAGED_CODE();

    FsRtlEnterFileSystem();

    do {

        Vcb = IrpContext->Vcb;
        LogFileFullCount = 0;

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

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

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

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

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

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

        SetFlag( IrpContext->State, IRP_CONTEXT_STATE_PERSISTENT );

        do {

            Retry = FALSE;

            try {

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

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

                    NtfsCheckpointForLogFileFull( IrpContext );

                    if (++LogFileFullCount >= 2) {

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

                //
                //  Call the requested function.
                //

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

                NtfsCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );

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

                NTSTATUS ExceptionCode;

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

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

                    Retry = TRUE;
                }
            }

        } while (Retry);

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

        ClearFlag( IrpContext->State, IRP_CONTEXT_STATE_PERSISTENT );

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

        try {

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

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

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

            NtfsReleaseVcb( IrpContext, Vcb );

        } except( EXCEPTION_EXECUTE_HANDLER ) {

            ASSERT( FsRtlIsNtstatusExpected( GetExceptionCode() ) );
        }

        //
        //  Free the irp context.
        //

        NtfsCleanupIrpContext( IrpContext, TRUE );

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

        ExAcquireFastMutexUnsafe( &NtfsScavengerLock );

        ASSERT( NtfsScavengerRunning );

        IrpContext = NtfsScavengerWorkList;

        if (IrpContext != NULL) {

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

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

        } else {

            NtfsScavengerRunning = FALSE;

        }

        ExReleaseFastMutexUnsafe( &NtfsScavengerLock );

    } while ( IrpContext != NULL );

    FsRtlExitFileSystem();
}