Ситуация следующая: есть PnP Device FDO (Не Bus FDO), который создаёт legacy DO (который фактически не знает о том что он как-то связан с PnP) и на него SymLink. Юзер может открыть этот legacy DO через SymLink и работать с ним. Допустим мы хотим удалить FDO, тогда в PnP dispatch routine объекта FDO приходит IRP_MN_QUERY_REMOVE_DEVICE, теперь: 1. Если legacy DO открыт, то мы возвращаем STATUS_DEVICE_BUSY, т.к устройство занято, мы не хотим выгружать его сейчас. 2. Мы закрываем legacy DO и снова пытаемся удалить FDO, но IRP_MN_QUERY_REMOVE_DEVICE повторно не приходит и устройство будет висеть в системе до перезагрузки. Вопрос: как дать понять PnP менеджеру что наше устройство можно попробовать удалить ещё раз ? чтобы он снова послал IRP_MN_QUERY_REMOVE_DEVICE, тогда я отвечу STATUS_SUCCESS, получу IRP_MN_REMOVE_DEVICE и удалю устройство. Пробовал через IoInvalidateDeviceState, но с его помощью можно лишь дать понять что устройства уже нет, тогда PnP менеджер пошлёт IRP_MN_REMOVE_DEVICE сразу, а мне нужно чтобы он сначала спросил с помощью IRP_MN_QUERY_REMOVE_DEVICE. Пробовал также делать ObReferenceObject на FDO, чтобы дать системе понять что на него есть ссылка и выгружать его нельзя, не помогло. Пробовал ObOpenObjectByPointer чтобы открыть хэндл на FDO, тоже не помогло, всё равно шлёт IRP_MN_QUERY_REMOVE_DEVICE и если я отвечаю что busy то всё, устройство не выгрузить...
g00r, первым делом, но там ничего нет по моему вопросу. да, если я верну допустим STATUS_UNSUCCESSFUL, то PnP менеджер поймёт что устройство удалять нельзя. но это в данный момент времени нельзя, а что если потом будет можно, как дать PnP менеджеру понять, что теперь всё ok и устройство удалять можно ? Мне просто непонято почему PnP менеджер не пересылает IRP_MN_QUERY_REMOVE_DEVICE когда я даю девайсу комманду remove (например из device manager'а), ведь логичнее было бы посылать этот IRP всякий раз и проверять можно ли удалить девайс сейчас или нет
Wizard109, это будет немного не то, тогда, скажем, нажимая remove в device manager'е я буду висеть и ждать пока мой виртуальный девайс можно будет закрыть, а этот момент может настать через час к примеру. Возможно, прождав какое-то время PnP менеджер сам всё поймёт и отменить запрос, да, надо будет попробовать как-нибудь, спасибо!
g00r, вот: Код (Text): case IRP_MN_QUERY_REMOVE_DEVICE: { if (!CardMakeUnavailable(DevExt->Card)) { Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; IoCompleteRequest(Irp, IO_NO_INCREMENT); VCADIRPEpilogue(TO_COMMON_EXTENSION(DevExt), Irp); return STATUS_UNSUCCESSFUL; } ReaderStallRequests(DeviceObject); KeAcquireSpinLock(&DevExt->StateLock, &OldIrql); SET_NEW_PNP_STATE(DevExt, RemovePending); KeReleaseSpinLock(&DevExt->StateLock, OldIrql); Irp->IoStatus.Status = STATUS_SUCCESS; break; } case IRP_MN_CANCEL_REMOVE_DEVICE: { KeAcquireSpinLock(&DevExt->StateLock, &OldIrql); if(DevExt->DevicePnPState == RemovePending) { RESTORE_PREVIOUS_PNP_STATE(DevExt); KeReleaseSpinLock(&DevExt->StateLock, OldIrql); ReaderRestartRequests(DeviceObject); CardMakeAvailable(DevExt->Card); } else { KeReleaseSpinLock(&DevExt->StateLock, OldIrql); } Irp->IoStatus.Status = STATUS_SUCCESS; break; } далее в конце switch: Код (Text): IoSkipCurrentIrpStackLocation(Irp); Status = IoCallDriver(DevExt->LowerDeviceObject, Irp); VCADIRPEpilogue(TO_COMMON_EXTENSION(DevExt), Irp); return Status;
g00r, при помощи 'SetupApi', грубо говоря, когда я нажму на 'Remove Device' в окне 'Device Manager'а', что аналогично вызову: Код (Text): SetupDiCallClassInstaller(DIF_REMOVE, ..., ...); первый-то раз оно приходит, а вот второй уже нет. т.е второй вызов этой функции просто ничего не делает. PnP Manager думает что девайс нельзя удалить до следующей перезагрузки и предлагает ребутнуться. Может это просто особенность работы windows...
Вроде по идеи, нужно в начале PnpDispatch вызвать IoInitializeRemoveLock(...), а после обработки запроса IoReleaseRemoveLock(...).
g00r, у меня это делается с помощью VCADIRPPrologue/VCADIRPEpilogue (там ещё дополнительные вещи проверяются), но это к делу не относится. IoAcquireRemoveLock тебя всё равно пропустит если ты не вызвал IoReleaseRemoveLockAndWait, а это обычно делается в IRP_MN_REMOVE_DEVICE, а до туда у меня дело так или иначе не доходит.
Откровенно говоря я не встречал девайса, который откладывает процедуру своего удаления на время большее чем 10 сек... М/б правдо особенность работы Windows. Т.е. если такой девайс присуцтвует, то пользователю нужно выдать мессагу с предложением перезагрузиться....
Ну да, у меня сейчас так и происходит. Просто допустим в линуксе когда я выгружаю драйвер он мне вернёт EBUSY если девайс занят, а потом я могу попробовать выгрузить ещё раз и если на этот раз девайс свободен то он выгрузится, в винде видимо так не получится...