diff --git a/Ext4Fsd/block.c b/Ext4Fsd/block.c index e756d66..2891b90 100644 --- a/Ext4Fsd/block.c +++ b/Ext4Fsd/block.c @@ -400,8 +400,15 @@ Ext2ReadWriteBlocks( } if (Ext2CanIWait()) { - KeWaitForSingleObject( &(pContext->Event), - Executive, KernelMode, FALSE, NULL ); + LARGE_INTEGER Timeout; + Timeout.QuadPart = (LONGLONG)-30 * 10 * 1000 * 1000; /* 30 seconds */ + Status = KeWaitForSingleObject( &(pContext->Event), + Executive, KernelMode, FALSE, &Timeout ); + if (Status == STATUS_TIMEOUT) { + /* Device likely removed — unblock and report error */ + MasterIrp->IoStatus.Status = STATUS_IO_TIMEOUT; + MasterIrp->IoStatus.Information = 0; + } KeClearEvent( &(pContext->Event) ); } else { bMasterCompleted = TRUE; @@ -496,15 +503,23 @@ Ext2ReadSync( Status = IoCallDriver(Vcb->TargetDeviceObject, Irp); if (Status == STATUS_PENDING) { - KeWaitForSingleObject( + LARGE_INTEGER Timeout; + Timeout.QuadPart = (LONGLONG)-30 * 10 * 1000 * 1000; /* 30 seconds */ + Status = KeWaitForSingleObject( Event, Suspended, KernelMode, FALSE, - NULL + &Timeout ); - Status = IoStatus.Status; + if (Status == STATUS_TIMEOUT) { + IoCancelIrp(Irp); + KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL); + Status = STATUS_IO_TIMEOUT; + } else { + Status = IoStatus.Status; + } } } __finally { @@ -610,8 +625,16 @@ Ext2DiskIoControl ( Status = IoCallDriver(DeviceObject, Irp); if (Status == STATUS_PENDING) { - KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); - Status = IoStatus.Status; + LARGE_INTEGER Timeout; + Timeout.QuadPart = (LONGLONG)-30 * 10 * 1000 * 1000; /* 30 seconds */ + Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, &Timeout); + if (Status == STATUS_TIMEOUT) { + IoCancelIrp(Irp); + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + Status = STATUS_IO_TIMEOUT; + } else { + Status = IoStatus.Status; + } } if (OutputBufferSize) { @@ -644,13 +667,21 @@ Ext2DiskShutDown(PEXT2_VCB Vcb) Status = IoCallDriver(Vcb->TargetDeviceObject, Irp); if (Status == STATUS_PENDING) { - KeWaitForSingleObject(&Event, + LARGE_INTEGER Timeout; + Timeout.QuadPart = (LONGLONG)-30 * 10 * 1000 * 1000; /* 30 seconds */ + Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, - NULL); + &Timeout); - Status = IoStatus.Status; + if (Status == STATUS_TIMEOUT) { + IoCancelIrp(Irp); + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + Status = STATUS_IO_TIMEOUT; + } else { + Status = IoStatus.Status; + } } } else { Status = IoStatus.Status; diff --git a/Ext4Fsd/fsctl.c b/Ext4Fsd/fsctl.c index ef5819f..ca2b18d 100644 --- a/Ext4Fsd/fsctl.c +++ b/Ext4Fsd/fsctl.c @@ -2019,14 +2019,22 @@ Ext2IsMediaWriteProtected ( Status = IoCallDriver(TargetDevice, Irp); if (Status == STATUS_PENDING) { + LARGE_INTEGER Timeout; + Timeout.QuadPart = (LONGLONG)-30 * 10 * 1000 * 1000; /* 30 seconds */ - (VOID) KeWaitForSingleObject( &Event, + Status = KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, - (PLARGE_INTEGER)NULL ); + &Timeout ); - Status = IoStatus.Status; + if (Status == STATUS_TIMEOUT) { + IoCancelIrp(Irp); + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + Status = STATUS_IO_TIMEOUT; + } else { + Status = IoStatus.Status; + } } return (BOOLEAN)(Status == STATUS_MEDIA_WRITE_PROTECTED); diff --git a/Ext4Fsd/pnp.c b/Ext4Fsd/pnp.c index 08371a5..fc58057 100644 --- a/Ext4Fsd/pnp.c +++ b/Ext4Fsd/pnp.c @@ -198,11 +198,20 @@ Ext2PnpQueryRemove ( IrpContext->Irp); if (Status == STATUS_PENDING) { - KeWaitForSingleObject( &Event, + LARGE_INTEGER Timeout; + Timeout.QuadPart = (LONGLONG)-30 * 10 * 1000 * 1000; /* 30 seconds */ + + Status = KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, - NULL ); + &Timeout ); + + if (Status == STATUS_TIMEOUT) { + IoCancelIrp(IrpContext->Irp); + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + } + Status = IrpContext->Irp->IoStatus.Status; } @@ -249,6 +258,9 @@ Ext2PnpRemove ( Status = Ext2LockVcb(Vcb, IrpContext->FileObject); ExReleaseResourceLite(&Vcb->MainResource); + /* Mark device removed early so concurrent I/O threads fail fast */ + SetLongFlag(Vcb->Flags, VCB_DEVICE_REMOVED); + // // Setup the Irp. We'll send it to the lower disk driver. // @@ -267,12 +279,19 @@ Ext2PnpRemove ( IrpContext->Irp); if (Status == STATUS_PENDING) { + LARGE_INTEGER Timeout; + Timeout.QuadPart = (LONGLONG)-30 * 10 * 1000 * 1000; /* 30 seconds */ - KeWaitForSingleObject( &Event, + Status = KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, - NULL ); + &Timeout ); + + if (Status == STATUS_TIMEOUT) { + IoCancelIrp(IrpContext->Irp); + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + } Status = IrpContext->Irp->IoStatus.Status; } @@ -282,7 +301,6 @@ Ext2PnpRemove ( /* dismount volume */ bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE); - SetLongFlag(Vcb->Flags, VCB_DEVICE_REMOVED); } __finally { @@ -319,6 +337,9 @@ Ext2PnpSurpriseRemove ( ExReleaseResourceLite(&Vcb->MainResource); + /* Mark device removed early so concurrent I/O threads fail fast */ + SetLongFlag(Vcb->Flags, VCB_DEVICE_REMOVED); + // // Setup the Irp. We'll send it to the lower disk driver. // @@ -337,12 +358,19 @@ Ext2PnpSurpriseRemove ( IrpContext->Irp); if (Status == STATUS_PENDING) { + LARGE_INTEGER Timeout; + Timeout.QuadPart = (LONGLONG)-30 * 10 * 1000 * 1000; /* 30 seconds */ - KeWaitForSingleObject( &Event, + Status = KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, - NULL ); + &Timeout ); + + if (Status == STATUS_TIMEOUT) { + IoCancelIrp(IrpContext->Irp); + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + } Status = IrpContext->Irp->IoStatus.Status; } @@ -352,7 +380,6 @@ Ext2PnpSurpriseRemove ( /* dismount volume */ bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE); - SetLongFlag(Vcb->Flags, VCB_DEVICE_REMOVED); } __finally { diff --git a/Ext4Fsd/read.c b/Ext4Fsd/read.c index 1cadba7..788415d 100644 --- a/Ext4Fsd/read.c +++ b/Ext4Fsd/read.c @@ -879,6 +879,12 @@ Ext2Read (IN PEXT2_IRP_CONTEXT IrpContext) FileObject = IrpContext->FileObject; + if (IsFlagOn(Vcb->Flags, VCB_DEVICE_REMOVED)) { + Status = STATUS_NO_SUCH_DEVICE; + bCompleteRequest = TRUE; + __leave; + } + if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) && Vcb->LockFile != FileObject ) { Status = STATUS_ACCESS_DENIED; diff --git a/Ext4Fsd/write.c b/Ext4Fsd/write.c index 669563d..9cad131 100644 --- a/Ext4Fsd/write.c +++ b/Ext4Fsd/write.c @@ -1359,6 +1359,11 @@ Ext2Write (IN PEXT2_IRP_CONTEXT IrpContext) __leave; } + if (IsFlagOn(Vcb->Flags, VCB_DEVICE_REMOVED)) { + Status = STATUS_NO_SUCH_DEVICE; + __leave; + } + if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) && Vcb->LockFile != FileObject ) { Status = STATUS_ACCESS_DENIED;