Мое почтение всем. При получении IRP_MN_STOP_DEVICE я собираюсь ставить все приходящие IRP в очередь и возвращать STATUS_PENDING. А после получения IRP_MN_START_DEVICE вытаскивать IRP из очереди и перестартовывать их. Вопрос в том, как это лучше делать. Проблема в том, что устройство может снова получить IRP_MN_STOP_DEVICE во время обработки IRP_MN_START_DEVICE. У меня есть мысль такого кода, но не уверен, что он будет работать: Код (Text): NTSTATUS IrpMjCreate(...) { if (pDeviceExtension ->State == STOPPED) { InsertHoldOnQueue(pIrp); IoMarkIrpPending(pIrp); status = STATUS_PENDING; } return status; } NTSTATUS IrpMjStartDevice(...) { PLIST_ENTRY pListEntry; ForwardSynchronously(...); for (pListEntry = pDeviceExtension ->ListHoldOnIrps.Flink; pListEntry != &pDeviceExtension ->ListHoldOnIrps; pListEntry = pListEntry.Flink) { pIrp = RemoveHoldOnQueue(pListEntry); MajorFunction = GetMajorFunction(pIrp); if (pDeviceExtenstion ->pDriverObject ->MajorFunction[MajorFunction](...) == STATUS_PENDING) { break; } } } Что мне не нравится, в этом случае я не могу вернуть STATUS_PENDING из IrpMjCreate ни по какой причине кроме как остановка устройства. Наверняка есть какие-то best practices по перезапуску. Буду рад, если кто-нибудь поделится. Заранее благодарен.
Так, я поторопился: проверять состояние устройства можно просто после попытки перезапуска IRP: Код (Text): pDeviceExtension = pDeviceObject ->DeviceExtension; KeAcquireSpinLock(&pDeviceExtension ->Lock, &Irql); pDeviceExtension ->State = DEVICE_STARTED; KeReleaseSpinLock(&pDeviceExtension ->Lock, Irql); DeviceStarted = TRUE; for(pListEntry = pDeviceExtension ->ListHoldIrps.Flink; pListEntry != &pDeviceExtension ->ListHoldIrps && DeviceStarted; pListEntry = pListEntry ->Flink) { RemoveIrpQueueGeneric(&pDeviceExtension ->LockQueueHold, pListEntry); pIrpToRestart = CONTAINING_RECORD(pListEntry, IRP, Tail.Overlay.ListEntry); pStackLocation = IoGetCurrentIrpStackLocation(pIrpToRestart); pDeviceExtension ->pDriverObject ->MajorFunction[pStackLocation ->MajorFunction](pDeviceObject, pIrpToRestart); KeAcquireSpinLock(&pDeviceExtension ->Lock, &Irql); DeviceStarted = pDeviceExtension ->State == DEVICE_STARTED; KeReleaseSpinLock(&pDeviceExtension ->Lock, Irql); } Но все равно хотелось бы услышать комментарии.