Как правильно выгрузить драйвер?

Тема в разделе "WASM.NT.KERNEL", создана пользователем serg128, 14 авг 2009.

  1. serg128

    serg128 New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2009
    Сообщения:
    55
    Вот кусок моего драйвера-фильтра:
    Код (Text):
    1. NTSTATUS DispatchRead(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
    2. {
    3.     PDEVICE_EXTENSION   devExt;
    4.     PIO_STACK_LOCATION  currentIrpStack;
    5.     PIO_STACK_LOCATION  nextIrpStack;
    6.  
    7.     devExt = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
    8.     currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
    9.     nextIrpStack = IoGetNextIrpStackLocation(Irp);
    10.  
    11.     *nextIrpStack = *currentIrpStack;
    12.     IoSetCompletionRoutine(Irp, ReadComplete, DeviceObject, TRUE, TRUE, TRUE);
    13.     // Запоминаем количество незавершенных IRP-пакетов.
    14.     numPendingIrps++;
    15.     // Копируем параметры на следующий уровень в стеке для нижележащего драйвера.
    16.     return IoCallDriver(devExt->TopOfStack, Irp);
    17. }
    18. //------------------------------------------------------------------------------
    19. NTSTATUS ReadComplete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
    20. {
    21.     PIO_STACK_LOCATION        IrpSp;
    22.     PKEYBOARD_INPUT_DATA      KeyData;
    23.  
    24.     IrpSp = IoGetCurrentIrpStackLocation(Irp);
    25.     if(NT_SUCCESS(Irp->IoStatus.Status))
    26.     {
    27.         KeyData = Irp->AssociatedIrp.SystemBuffer;
    28.         DbgPrint("ScanCode: %x ", KeyData[0].MakeCode);
    29.         DbgPrint("IRPs pending: %x", numPendingIrps);
    30.  
    31.     }
    32.     if( Irp->PendingReturned)
    33.     {
    34.         IoMarkIrpPending(Irp);
    35.     }
    36.     numPendingIrps--;
    37.     return Irp->IoStatus.Status;
    38. }
    39. //------------------------------------------------------------------------------
    40. VOID DispatchUnload(IN PDRIVER_OBJECT DriverObject)
    41. {
    42.     KTIMER kTimer;
    43.     LARGE_INTEGER timeout;
    44.  
    45.     // Получаем указатель на структуру расширения.
    46.     PDEVICE_EXTENSION pKeyboardDeviceExtension =
    47.         (PDEVICE_EXTENSION) DriverObject->DeviceObject->DeviceExtension;
    48.     DbgPrint("Driver Unload Called..\n");
    49.     // Отсоединяемся от устройства, к которому подсоединялись.
    50.     IoDetachDevice(pKeyboardDeviceExtension->TopOfStack);
    51.     DbgPrint("Keyboard hook detached from device..\n");
    52.  
    53.     //Пока существует хоть один необработанный IRP-пакет, функция Unload будет ожидать окончания его обработки:
    54.     timeout.QuadPart = 1000000; // 0,1 секунда
    55.     KeInitializeTimer(&kTimer);
    56.     while(numPendingIrps > 0)
    57.     {
    58.         // Устанавливаем таймер.
    59.         KeSetTimer(&kTimer,timeout,NULL);
    60.         KeWaitForSingleObject(&kTimer, Executive, KernelMode, FALSE, NULL);
    61.     }
    62.  
    63.     IoDeleteDevice(DriverObject->DeviceObject);
    64.     return;
    65. }
    При ручной выгрузке требует нажатия клавиши, и тогда впринципе нормально, но если выключаешь комп - тогда BSOD. Как правильно его выгрузить?
     
  2. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    Legacy-фильтры невыгружаемы (кроме файловых фильтров, поддерживающих fast detach).
     
  3. serg128

    serg128 New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2009
    Сообщения:
    55
    Ну а завершить работу системы можно корректно? Или без внешнего приложения никак?
     
  4. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    Анализ дампа падения покажи.
     
  5. serg128

    serg128 New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2009
    Сообщения:
    55
    а как его проанализировать?
     
  6. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    В отладчике WinDbg команда analyze -v после падения... Нда-с. Ну как-то несерьёзно даже.
     
  7. serg128

    serg128 New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2009
    Сообщения:
    55
    Дамп не создается :dntknw:. Настройки приаттачил.
    Может это потому, что падение происходит перезагрузкой?
     
  8. wsd

    wsd New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2007
    Сообщения:
    2.824
    serg128
    может свопа не хватает? он у тебя сколько?
     
  9. serg128

    serg128 New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2009
    Сообщения:
    55
    По теории должно хватать:
     
  10. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
  11. serg128

    serg128 New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2009
    Сообщения:
    55
    Собрал анализ дампа. Прилагаю.
    И еще вопрос: в книге нашел, что для корректной выгрузке при выключении компа, нужно регистрировать DriverObject->MajorFunction[IRP_MJ_SHUTDOWN]= DispatchShutdown; предварительно сделав IoRegisterShutdownNotification(device);.
     
  12. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    Символы подгрузи нормальные и стек правильный покажи. А вот судя по этому

    Код (Text):
    1. FAULTING_IP:
    2. kbfiltr!DispatchShutdown+0 [f:\drv\kb1\kbfiltr.c @ 175]
    ты забыл дерегистрировать обработчик IRP_MJ_SHUTDOWN вызовом IoUnregisterShutdownNotification(), ибо сказано в великом писании:

     
  13. serg128

    serg128 New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2009
    Сообщения:
    55
    Чем дальше, тем страшней... :)
    Переписал так:
    Код (Text):
    1. VOID DispatchUnload(IN PDRIVER_OBJECT DriverObject)
    2. {
    3.     // Получаем указатель на структуру расширения.
    4.     PDEVICE_EXTENSION pKeyboardDeviceExtension =
    5.         (PDEVICE_EXTENSION) DriverObject->DeviceObject->DeviceExtension;
    6.  
    7.     IoUnregisterShutdownNotification(DriverObject->DeviceObject);
    8.     return;
    9. }
    10. //------------------------------------------------------------------------------
    11. NTSTATUS DispatchShutdown(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
    12. {
    13.  
    14.     KTIMER kTimer;
    15.     LARGE_INTEGER timeout;
    16.  
    17.     // Получаем указатель на структуру расширения.
    18.     PDEVICE_EXTENSION pKeyboardDeviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
    19.     DbgPrint("Driver Unload Called..\n");
    20.     // Отсоединяемся от устройства, к которому подсоединялись.
    21.     IoDetachDevice(pKeyboardDeviceExtension->TopOfStack);
    22.     DbgPrint("Keyboard hook detached from device..\n");
    23.  
    24.     //Пока существует хоть один необработанный IRP-пакет, функция Unload будет ожидать окончания его обработки:
    25.  
    26.     timeout.QuadPart = 1000000; // 0,1 секунда
    27.     KeInitializeTimer(&kTimer);
    28.     while(numPendingIrps > 0)
    29.     {
    30.         // Устанавливаем таймер.
    31.         KeSetTimer(&kTimer,timeout,NULL);
    32.         KeWaitForSingleObject(&kTimer, Executive, KernelMode, FALSE, NULL);
    33.     }
    34.     IoDeleteDevice(DeviceObject);
    35.     return Irp->IoStatus.Status;
    36. }
    После старта драйвера, и попытки останова системы, дамп не создался, хотя был BSOD.
    Может отсоединяться от стека надо в другой ф-ции?
     
  14. serg128

    serg128 New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2009
    Сообщения:
    55
    Вот еще анализ дампа:
     
  15. TSS

    TSS New Member

    Публикаций:
    0
    Регистрация:
    13 апр 2009
    Сообщения:
    494
    Советую почитать про Cancel-Safe IRP Queues и вобще на тему IRP cancellation, потому как код вышеприведенный есть полный ахтунг.
     
  16. serg128

    serg128 New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2009
    Сообщения:
    55
    Походу получилось! Переписал так:
    Код (Text):
    1. VOID DispatchUnload(IN PDRIVER_OBJECT DriverObject)
    2. {
    3.     KTIMER kTimer;
    4.     LARGE_INTEGER timeout;
    5.  
    6.     // Получаем указатель на структуру расширения.
    7.     PDEVICE_EXTENSION pKeyboardDeviceExtension =
    8.         (PDEVICE_EXTENSION) DriverObject->DeviceObject->DeviceExtension;
    9.  
    10.     IoUnregisterShutdownNotification(DriverObject->DeviceObject);
    11.     DbgPrint("Driver Unload Called..\n");
    12.     // Отсоединяемся от устройства, к которому подсоединялись.
    13.     IoDetachDevice(pKeyboardDeviceExtension->TopOfStack);
    14.     DbgPrint("Keyboard hook detached from device..\n");
    15.  
    16.     //Пока существует хоть один необработанный IRP-пакет, функция Unload будет ожидать окончания его обработки:
    17.     timeout.QuadPart = 1000000; // 0,1 секунда
    18.     KeInitializeTimer(&kTimer);
    19.     while(numPendingIrps > 0)
    20.     {
    21.         // Устанавливаем таймер.
    22.         KeSetTimer(&kTimer,timeout,NULL);
    23.         KeWaitForSingleObject(&kTimer, Executive, KernelMode, FALSE, NULL);
    24.     }
    25.  
    26.     IoDeleteDevice(DriverObject->DeviceObject);
    27.     return;
    28. }
    29. //------------------------------------------------------------------------------
    30. NTSTATUS DispatchShutdown(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
    31. {
    32.     // Получаем указатель на структуру расширения.
    33.     PDEVICE_EXTENSION pKeyboardDeviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
    34.     IoUnregisterShutdownNotification(DeviceObject);
    35. [b]
    36.     // удаляем существующие Irp
    37.     Irp->IoStatus.Information = 0;
    38.     IoCompleteRequest(Irp, IO_NO_INCREMENT);    
    39. [/b]
    40.     // Отсоединяемся от устройства, к которому подсоединялись.
    41.     IoDetachDevice(pKeyboardDeviceExtension->TopOfStack);
    42.     IoDeleteDevice(DeviceObject);
    43.     return STATUS_SUCCESS;
    44. }
    и теперь работает корректное завершение работы в системе!
    >x64
    Насколько правильно такое решение?
    И огромное спасибо, что наставил на путь истины! :)
     
  17. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    Какое решение-то? Я у тебя в коде вообще никаких решений не вижу, одна копипаста. Если по поводу IoUnregisterShutdownNotification(), ну так это даже не решение, а единственная возможность сделать это правильно. А в остальном перепиши на WDM и многое станет проще, например, не придётся вот так трахаться с запросами в Unload-процедуре.