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
/*++ * @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; }
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; }
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; }
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; }
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; } }
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; }
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; }
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(); }