Я работаю над драйвером файловой системы WDM Windows, который в настоящее время имеет проблему, из-за которой USB-накопитель не извлекается во время выключения, из-за чего он становится нечитаемым. Если устройство отключается до выключения Windows, оно работает нормально и не становится нечитаемым. Есть ли способ вызвать другой IRP из моего метода IRP_MJ_SHUTDOWN, который может обработать извлечение USB-накопителя до завершения моего метода выключения? Какой IRP обрабатывает извлечение?
Так настроены IRP. Насколько я знаю, когда IRP_MJ_SHUTDOWN вызывается Windows, он вызывает метод, указанный в инструкции switch ниже. Мне нужно обработать извлечение USB этим способом.
NTSTATUS
IrpDispatch
(
IN PDEVICE_OBJECT VolDevice,
IN PIRP Irp
)
{
/* Global IRP dispatch entry */
PIO_STACK_LOCATION IrpSp;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
/* Check IRP type */
switch (IrpSp->MajorFunction)
{
case IRP_MJ_FILE_SYSTEM_CONTROL:
KdPrint(("IRP_MJ_FILE_SYSTEM_CONTROL\n"));
return HrfsFileSystemControl(VolDevice, Irp);
case IRP_MJ_READ:
KdPrint(("IRP_MJ_READ\n"));
return HrfsFsdRead(VolDevice, Irp);
/*case IRP_MJ_DEVICE_CONTROL:
KdPrint(("IRP_MJ_DEVICE_CONTROL\n"));
return HrfsFsdDeviceControl(VolDevice, Irp);*/
case IRP_MJ_QUERY_VOLUME_INFORMATION:
KdPrint(("IRP_MJ_QUERY_VOLUME_INFORMATION\n"));
return HrfsFsdQueryVolumeInformation(VolDevice, Irp);
case IRP_MJ_CREATE:
KdPrint(("IRP_MJ_CREATE\n"));
return HrfsFsdCreate(VolDevice, Irp);
case IRP_MJ_DIRECTORY_CONTROL:
KdPrint(("IRP_MJ_DIRECTORY_CONTROL\n"));
return HrfsFsdDirectoryControl(VolDevice, Irp);
case IRP_MJ_QUERY_INFORMATION:
KdPrint(("IRP_MJ_QUERY_INFORMATION\n"));
return HrfsFsdQuery(VolDevice, Irp);
case IRP_MJ_CLEANUP:
KdPrint(("IRP_MJ_CLEANUP\n"));
return HrfsFsdCleanup(VolDevice, Irp);
case IRP_MJ_CLOSE:
KdPrint(("IRP_MJ_CLOSE\n"));
return HrfsFsdClose(VolDevice, Irp);
case IRP_MJ_WRITE:
KdPrint(("IRP_MJ_WRITE\n"));
return HrfsFsdWrite(VolDevice, Irp);
case IRP_MJ_SET_INFORMATION:
KdPrint(("IRP_MJ_SET_INFORMATION\n"));
return HrfsFsdSet(VolDevice, Irp);
case IRP_MJ_LOCK_CONTROL:
KdPrint(("IRP_MJ_LOCK_CONTROL\n"));
return HrfsFsdLockControl(VolDevice, Irp);
case IRP_MJ_SET_VOLUME_INFORMATION:
KdPrint(("IRP_MJ_SET_VOLUME_INFORMATION\n"));
return HrfsFsdSetVolumeInformation(VolDevice, Irp);
case IRP_MJ_SHUTDOWN:
KdPrint(("IRP_MJ_SHUTDOWN\n"));
return HrfsIrpShutdown(VolDevice, Irp);
case IRP_MJ_PNP:
KdPrint(("IRP_MJ_PNP\n"));
return HrfsFsdPnp(VolDevice, Irp);
case IRP_MJ_FLUSH_BUFFERS:
KdPrint(("IRP_MJ_FLUSH_BUFFERS\n"));
return HrfsFsdFlushBuffers(VolDevice, Irp);
default:
KdPrint(("Unsupported now [%d]!\n", IrpSp->MajorFunction));
break;
}
/* for un-support IRP, finish it with error */
HrfsCompleteIrp(NULL, Irp, STATUS_UNSUCCESSFUL);
return STATUS_UNSUCCESSFUL;
}
Способы выключения ниже:
NTSTATUS
HrfsIrpShutdown
(
IN PDEVICE_OBJECT VolDevice,
IN PIRP Irp
)
{
/* IRP dispatch routing for shutdown request */
NTSTATUS Status;
PIRP_CONTEXT IrpContext = NULL;
BOOLEAN TopLevel;
FsRtlEnterFileSystem(); // x
TopLevel = HrfsIsIrpTopLevel(Irp); // x
try
{
IrpContext = HrfsCreateIrpContext(Irp, TRUE); // x ?
Status = HrfsShutdown(IrpContext, Irp);
}
#ifdef HRFS_ENABLE_EXCEPTION_CHECK
except(HrfsExceptionFilter(IrpContext, GetExceptionInformation()))
{
Status = HrfsProcessException(IrpContext, Irp, GetExceptionCode());
}
#else
finally
{
NOTHING;
}
#endif
if (TopLevel)
{
IoSetTopLevelIrp(NULL); // x
}
FsRtlExitFileSystem(); // x
return Status;
}
Выключение
NTSTATUS
HrfsShutdown
(
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
)
{
KEVENT Event;
PLIST_ENTRY Links;
PVCB Vcb = NULL; // +
PIRP NewIrp;
IO_STATUS_BLOCK Iosb;
BOOLEAN VcbDeleted;
KdPrint(("HRFSSHUTDOWN\n"));
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_POPUPS |
IRP_CONTEXT_FLAG_WRITE_THROUGH);
KeInitializeEvent(&Event, NotificationEvent, FALSE);
HrfsData.ShutdownStarted = TRUE;
HrfsAcquireExclusiveGlobal(IrpContext);
try
{
/* flush and clean all volume data */
Links = HrfsData.VcbQueue.Flink;
while (Links != &HrfsData.VcbQueue)
{
Vcb = CONTAINING_RECORD(Links, VCB, VcbLinks);
Links = Links->Flink;
if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_SHUTDOWN) ||
(Vcb->VcbCondition != VcbGood))
{
continue;
}
HrfsAcquireExclusiveVolume(IrpContext, Vcb);
try
{
HrfsFlushVolume(IrpContext, Vcb, Flush);
/*HrfsFlushAndCleanVolume(IrpContext,
Irp,
Vcb,
Flush);*/
if (!FlagOn(Vcb->VcbState, VCB_STATE_FLAG_MOUNTED_DIRTY))
{
CcPurgeCacheSection(&Vcb->SectionObjectPointers,
NULL,
0,
FALSE);
}
}
#ifdef HRFS_ENABLE_EXCEPTION_CHECK
except(EXCEPTION_EXECUTE_HANDLER)
{
HrfsResetExceptionState(IrpContext);
}
#else
finally
{
NOTHING;
}
#endif
try
{
//Send a shutdown IRP to lower driver
NewIrp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN,
Vcb->TargetDeviceObject,
NULL,
0,
NULL,
&Event,
&Iosb);
if (NewIrp != NULL)
{
if (NT_SUCCESS(IoCallDriver(Vcb->TargetDeviceObject, NewIrp)))
{
KeWaitForSingleObject(&Event,
Executive,
KernelMode,
FALSE,
NULL);
KeClearEvent(&Event);
}
}
}
#ifdef HRFS_ENABLE_EXCEPTION_CHECK
except(EXCEPTION_EXECUTE_HANDLER)
{
HrfsResetExceptionState(IrpContext);
}
#else
finally
{
NOTHING
}
#endif
SetFlag(Vcb->VcbState, VCB_STATE_FLAG_SHUTDOWN);
VcbDeleted = HrfsCheckForDismount(IrpContext,
Vcb,
FALSE);
if (!VcbDeleted)
{
HrfsReleaseVolume(Vcb);
}
}
}
finally
{
HrfsReleaseGlobal();
IoUnregisterFileSystem(HrfsDeviceObject);
IoDeleteDevice(HrfsDeviceObject);
HrfsCompleteIrp(IrpContext, Irp, STATUS_SUCCESS);
}
return STATUS_SUCCESS;
}