📄 cddata.c
字号:
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;
}
#ifdef CD_SANITY
VOID
CdRaiseStatusEx(
IN PIRP_CONTEXT IrpContext,
IN NTSTATUS Status,
IN BOOLEAN NormalizeStatus,
IN OPTIONAL ULONG FileId,
IN OPTIONAL ULONG Line
)
{
BOOLEAN BreakIn = FALSE;
AssertVerifyDevice( IrpContext, Status);
if (CdTraceRaises) {
DbgPrint( "%p CdRaiseStatusEx 0x%x @ fid %d, line %d\n", PsGetCurrentThread(), Status, FileId, Line);
}
if (CdTestRaisedStatus && !CdBreakOnAnyRaise) {
ULONG Index;
for (Index = 0;
Index < (sizeof( CdInterestingExceptionCodes) / sizeof( CdInterestingExceptionCodes[0]));
Index++) {
if ((STATUS_SUCCESS != CdInterestingExceptionCodes[Index]) &&
(CdInterestingExceptionCodes[Index] == Status)) {
BreakIn = TRUE;
break;
}
}
}
if (BreakIn || CdBreakOnAnyRaise) {
DbgPrint( "CDFS: Breaking on raised status %08x (BI=%d,BA=%d)\n", Status, BreakIn, CdBreakOnAnyRaise);
DbgPrint( "CDFS: (FILEID %d LINE %d)\n", FileId, Line);
DbgPrint( "CDFS: Contact CDFS.SYS component owner for triage.\n");
DbgPrint( "CDFS: 'eb %p 0;eb %p 0' to disable this alert.\n", &CdTestRaisedStatus, &CdBreakOnAnyRaise);
DbgBreakPoint();
}
if (NormalizeStatus) {
IrpContext->ExceptionStatus = FsRtlNormalizeNtstatus( Status, STATUS_UNEXPECTED_IO_ERROR);
}
else {
IrpContext->ExceptionStatus = Status;
}
IrpContext->RaisedAtLineFile = (FileId << 16) | Line;
ExRaiseStatus( IrpContext->ExceptionStatus);
}
#endif
LONG
CdExceptionFilter (
IN 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 )) {
CdBugCheck( (ULONG_PTR) ExceptionPointer->ExceptionRecord,
(ULONG_PTR) ExceptionPointer->ContextRecord,
(ULONG_PTR) ExceptionPointer->ExceptionRecord->ExceptionAddress );
}
return EXCEPTION_EXECUTE_HANDLER;
}
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, or within a guarded region. 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) &&
KeAreAllApcsDisabled()) {
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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -