Рестарт после IRP_MN_STOP_DEVICE

Тема в разделе "WASM.NT.KERNEL", создана пользователем Mika0x65, 28 авг 2011.

  1. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Мое почтение всем.

    При получении IRP_MN_STOP_DEVICE я собираюсь ставить все приходящие IRP в очередь и возвращать STATUS_PENDING. А после получения IRP_MN_START_DEVICE вытаскивать IRP из очереди и перестартовывать их. Вопрос в том, как это лучше делать. Проблема в том, что устройство может снова получить IRP_MN_STOP_DEVICE во время обработки IRP_MN_START_DEVICE. У меня есть мысль такого кода, но не уверен, что он будет работать:

    Код (Text):
    1. NTSTATUS IrpMjCreate(...)
    2. {
    3.     if (pDeviceExtension ->State == STOPPED)
    4.     {
    5.         InsertHoldOnQueue(pIrp);
    6.         IoMarkIrpPending(pIrp);
    7.         status = STATUS_PENDING;
    8.     }
    9.  
    10.     return status;
    11. }
    12.  
    13. NTSTATUS IrpMjStartDevice(...)
    14. {
    15.     PLIST_ENTRY pListEntry;
    16.     ForwardSynchronously(...);
    17.  
    18.     for (pListEntry = pDeviceExtension ->ListHoldOnIrps.Flink; pListEntry != &pDeviceExtension ->ListHoldOnIrps; pListEntry = pListEntry.Flink)
    19.     {
    20.         pIrp = RemoveHoldOnQueue(pListEntry);
    21.         MajorFunction = GetMajorFunction(pIrp);
    22.         if (pDeviceExtenstion ->pDriverObject ->MajorFunction[MajorFunction](...) == STATUS_PENDING)
    23.         {
    24.              break;
    25.         }
    26.     }
    27. }
    Что мне не нравится, в этом случае я не могу вернуть STATUS_PENDING из IrpMjCreate ни по какой причине кроме как остановка устройства. Наверняка есть какие-то best practices по перезапуску. Буду рад, если кто-нибудь поделится.

    Заранее благодарен.
     
  2. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Так, я поторопился: проверять состояние устройства можно просто после попытки перезапуска IRP:

    Код (Text):
    1.         pDeviceExtension = pDeviceObject ->DeviceExtension;
    2.  
    3.         KeAcquireSpinLock(&pDeviceExtension ->Lock, &Irql);
    4.  
    5.         pDeviceExtension ->State = DEVICE_STARTED;
    6.  
    7.         KeReleaseSpinLock(&pDeviceExtension ->Lock, Irql);
    8.  
    9.         DeviceStarted = TRUE;
    10.  
    11.         for(pListEntry = pDeviceExtension ->ListHoldIrps.Flink;
    12.             pListEntry != &pDeviceExtension ->ListHoldIrps && DeviceStarted;
    13.             pListEntry = pListEntry ->Flink)
    14.         {
    15.             RemoveIrpQueueGeneric(&pDeviceExtension ->LockQueueHold, pListEntry);
    16.  
    17.             pIrpToRestart = CONTAINING_RECORD(pListEntry, IRP, Tail.Overlay.ListEntry);
    18.  
    19.             pStackLocation = IoGetCurrentIrpStackLocation(pIrpToRestart);
    20.  
    21.             pDeviceExtension ->pDriverObject ->MajorFunction[pStackLocation ->MajorFunction](pDeviceObject, pIrpToRestart);
    22.  
    23.             KeAcquireSpinLock(&pDeviceExtension ->Lock, &Irql);
    24.  
    25.             DeviceStarted = pDeviceExtension ->State == DEVICE_STARTED;
    26.  
    27.             KeReleaseSpinLock(&pDeviceExtension ->Lock, Irql);
    28.         }
    Но все равно хотелось бы услышать комментарии.