Помогите помирить мой драйвер с антивирусом (не взлом)

Тема в разделе "WASM.WIN32", создана пользователем ksu_ant, 3 апр 2006.

  1. ksu_ant

    ksu_ant New Member

    Публикаций:
    0
    Регистрация:
    28 сен 2005
    Сообщения:
    273
    Здравствуйте!

    Пишу нечто вроде "родительского контроля". Отслеживается в том числе и содержимое Web-страниц.

    Так вот. Когда мой драйвер ставит IRP, который также интересен KAV (он проверяет содержимое Web), в очередь или блокирует данный запрос, возникает BSOD.

    Помогите, пожалуйста, помирить драйверы.

    Ставлю в очередь так:
    Код (Text):
    1.  
    2. KIRQL Irql;
    3. PDRIVER_CANCEL  oldCancelRoutine;
    4. KeAcquireSpinLock( &irpQueueSpinLock, &Irql );
    5. IoMarkIrpPending( pIrp );
    6. InsertTailList( &irpQueue, &pIrp->Tail.Overlay.ListEntry );
    7. oldCancelRoutine = IoSetCancelRoutine(pIrp, IrpCancelRoutine);
    8. ASSERT(!oldCancelRoutine);
    9. if (pIrp->Cancel){
    10. oldCancelRoutine = IoSetCancelRoutine(pIrp, NULL);
    11.  if (oldCancelRoutine){
    12.     RemoveEntryList(&pIrp->Tail.Overlay.ListEntry);
    13.     status = pIrp->IoStatus.Status = STATUS_CANCELLED;
    14.  } //endif
    15. } // endif
    16. KeReleaseSpinLock(&irpQueueSpinLock, Irql);
    17. if (...){   //Отправим уведомление в приложение
    18. SendEventToGUI();
    19. }
    20. status=STATUS_PENDING;
    21. return status;
    22.  


    Если данные не обрабатываются антивирусом, или антивирус выгружен, все работает правильно. Иначе - вот дамп.

    Кто знает, помогите, пожалуйста.

    И еще: можно ли из драйвера гарантированно определить в каком режиме работает модем в данный момент (т.е. в режиме обработки команд или пересылки данных)?

    Заранее спасибо.

    [​IMG] 715978175__Mini032906_01.rar
     
  2. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Мда.. заморочно. Кирдык происходит слишком далеко от твоего драйвера. К тому же в моей копии xpsp2 по смещению 0x93E04 совсем другое. Так что хрен разберёшь.



    Если кирдык стабильно происходит, подключи SoftICE, правда я не помню перехватывает ли он IRQL_NOT_LESS_OR_EQUAL на DISPATCH_LEVEL. В любом случае KeBugCheckEx он хучит и у тебя будет возможность ещё на живой системе попытаться понять в чём дело. И настрой систему на сброс дампа ядра. Дамп получиться большой, так что анализировать придется самому. А по минидампу тут нихрена не понятно.



    А вот copy&paste у тя неправильно сделан ;) Если ты дошёл до pIrp->IoStatus.Status = STATUS_CANCELLED, то должен завершить IRP, т.к. в этой точке точно известно, что IRP был отменён, но твоя IrpCancelRoutine не была вызвана, т.к. ты успел сделать IoSetCancelRoutine (Irp, NULL). Но кирдык не из-за этого, ибо на однопроцессорной машине при схваченном спинлоке мы никогда не дойдём до pIrp->IoStatus.Status = STATUS_CANCELLED, даже теоретически.



    В последнем тостере это делается так:
    Код (Text):
    1. NTSTATUS
    2. ToasterQueueRequest    (
    3.     IN OUT PFDO_DATA FdoData,
    4.     IN PIRP Irp
    5.     )
    6. {
    7.  
    8.     KIRQL               oldIrql;
    9.     PDRIVER_CANCEL      ret;
    10.    
    11.     ASSERT(HoldRequests == FdoData->QueueState);
    12.  
    13.     IoMarkIrpPending(Irp);
    14.  
    15.     KeAcquireSpinLock(&FdoData->QueueLock, &oldIrql);
    16.  
    17.     IoSetCancelRoutine (Irp, ToasterCancelQueued);
    18.  
    19.     if(TRUE == Irp->Cancel)
    20.     {
    21.         ret = IoSetCancelRoutine (Irp, NULL);
    22.  
    23.         //
    24.         // Initialize the driver-managed IRP queue's list head to prevent
    25.         // ToasterCancelQueued from potentially causing a system crash if the system
    26.         // has already called it. The list head must be initialized because the
    27.         // incoming IRP is not added to the driver-managed IRP queue, but when
    28.         // ToasterQueueRequest releases the spin lock, QueueLock, a different thread
    29.         // attempting to execute ToasterCancelQueued might resume and attempt to
    30.         // remove the IRP that is not present in the queue, resulting in a system
    31.         // crash. Therefore, initializing the list head allows ToasterCancelQueued
    32.         // to proceed, and not attempt to remove the IRP that is not present in the
    33.         // IRP queue, without resulting in a system crash.
    34.         //
    35.  
    36.         InitializeListHead(&Irp->Tail.Overlay.ListEntry);
    37.  
    38.         KeReleaseSpinLock(&FdoData->QueueLock, oldIrql);
    39.  
    40.         if(NULL != ret)
    41.         {
    42.             Irp->IoStatus.Status = STATUS_CANCELLED;
    43.             Irp->IoStatus.Information = 0;
    44.  
    45.             IoCompleteRequest (Irp, IO_NO_INCREMENT);
    46.  
    47.             //
    48.             // Fall-through to the call to ToasterIoDecrement. ToasterQueueRequest
    49.             // then returns STATUS_PENDING even though the IRP has been cancelled
    50.             // because a routine must return STATUS_PENDING if it calls
    51.             // IoMarkIrpPending.
    52.             //
    53.         }
    54.         else
    55.         {
    56.             //
    57.             // The system has already called ToasterCancelQueued. Fall-through to the
    58.             // call to ToasterIoDecrement. ToasterQueueRequest then returns
    59.             // STATUS_PENDING even though the IRP has been cancelled because a routine
    60.             // must return STATUS_PENDING if it calls IoMarkIrpPending.
    61.             //
    62.         }
    63.     }
    64.     else
    65.     {    
    66.         //
    67.         // The incoming IRP has not been canceled, therefore add it to the end of
    68.         // the driver-managed IRP queue.
    69.         //
    70.         InsertTailList(&FdoData->NewRequestsQueue,
    71.                                                 &Irp->Tail.Overlay.ListEntry);
    72.  
    73.         KeReleaseSpinLock(&FdoData->QueueLock, oldIrql);
    74.     }
    75.  
    76.     ToasterIoDecrement(FdoData);
    77.  
    78.     return STATUS_PENDING;
    79. }
    80.  
    81. VOID
    82. ToasterCancelQueued (
    83.     IN PDEVICE_OBJECT   DeviceObject,
    84.     IN PIRP             Irp
    85.     )
    86. {
    87.     PFDO_DATA fdoData = DeviceObject->DeviceExtension;
    88.  
    89.     //
    90.     // Instead of releasing the cancel spin lock and passing Irp->CancelIrql, this
    91.     // stage of the function driver passes DISPATCH_LEVEL because ToasterCancelQueued
    92.     // acquires the cancel spin lock again later.
    93.     //
    94.     IoReleaseCancelSpinLock(DISPATCH_LEVEL);
    95.  
    96.     //
    97.     // Acquire the driver-managed IRP queue spinlock and take advantage of the
    98.     // fact that the system calls ToasterCancelQueued at DPC level.
    99.     //
    100.     KeAcquireSpinLockAtDpcLevel (&fdoData->QueueLock);
    101.  
    102.     RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
    103.  
    104.     //
    105.     // Release the spinlock but stay at DISPATCH_LEVEL
    106.     //
    107.     KeReleaseSpinLockFromDpcLevel (&fdoData->QueueLock);
    108.  
    109.     //
    110.     // Lower the system's IRQL to the level it was was before the system called
    111.     // ToasterCancelQueued.
    112.     //
    113.     KeLowerIrql(Irp->CancelIrql);
    114.  
    115.     //
    116.     // Note that the above two calls could also be collapsed into a single call
    117.     // to KeReleaseSpinLock(&fdoData->QueueLock, Irp->CancelIrql);
    118.     //
    119.     Irp->IoStatus.Status = STATUS_CANCELLED;
    120.     Irp->IoStatus.Information = 0;
    121.  
    122.     IoCompleteRequest (Irp, IO_NO_INCREMENT);
    123.  
    124.     return;
    125. }


    Навороты с

    IoReleaseCancelSpinLock(DISPATCH_LEVEL);

    KeAcquireSpinLockAtDpcLevel

    KeReleaseSpinLockFromDpcLevel

    KeLowerIrql

    это чисто для оптимизации. Если не понятно что зачем, то можно сделать как в старом тостере:
    Код (Text):
    1. VOID
    2. ToasterCancelQueued (
    3.     IN PDEVICE_OBJECT   DeviceObject,
    4.     IN PIRP             Irp
    5.     )
    6. {
    7.     PFDO_DATA fdoData = DeviceObject->DeviceExtension;
    8.     KIRQL               oldIrql;
    9.  
    10.     IoReleaseCancelSpinLock( Irp->CancelIrql);
    11.  
    12.     KeAcquireSpinLock(&fdoData->QueueLock, &oldIrql);
    13.     RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
    14.     KeReleaseSpinLock(&fdoData->QueueLock, oldIrql);
    15.  
    16.     Irp->IoStatus.Status = STATUS_CANCELLED;
    17.     Irp->IoStatus.Information = 0;
    18.  
    19.     IoCompleteRequest (Irp, IO_NO_INCREMENT);
    20.  
    21.     return;
    22. }
     
  3. ksu_ant

    ksu_ant New Member

    Публикаций:
    0
    Регистрация:
    28 сен 2005
    Сообщения:
    273
    Спасибо за ответ.

    Насчет МЕГАдампа (:derisive:) - сделаю, посмотрю.

    Но вот насчет операций по отмене - я не уверен, что в данном случае это влияет на ситуацию, вроде вообще это не должно выполняться (сделано на всякий пожарный). Ну, если есть неточности, посмотрю тостер.

    Еще раз спасибо.