BSoD при работе с очередью IRP

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

  1. ksu_ant

    ksu_ant New Member

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

    Я уже отправлял данный пост, но в старую тему, туда мало кто посмотрел, поэтому начинаю тему, а старое сообщение удалю.

    Дошел до очереди IRP. Образовалась небольшая (надеюсь) проблема.

    Мне надо попытаться (в качестве эксперимента) в одной функции поставить IRP в очередь, а в другой - извлечь и послать ниже по стеку.

    Делаю так:

    Глобальные

    LIST_ENTRY irpQueue;//очередь

    KSPIN_LOCK irpQueueSpinLock;//блокировка

    ...

    В DriverEntry инициализация:

    InitializeListHead(&irpQueue);

    KeInitializeSpinLock(&irpQueueSpinLock);

    ...

    Ставлю в очередь в процедуре обработки:

    KIRQL oldIrql;

    KeAcquireSpinLock(&irpQueueSpinLock, &oldIrql);

    IoMarkIrpPending(pIrp);

    ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);

    InsertTailList(&irpQueue, &pIrp->Tail.Overlay.ListEntry);

    KeReleaseSpinLock(&irpQueueSpinLock, oldIrql);

    ...

    Извлекаю из очереди и посылаю дальше (в другой процедуре):

    PIRP currentIrp = NULL;

    PLIST_ENTRY entry;

    KIRQL oldIrql;

    KeAcquireSpinLock(&irpQueueSpinLock, &oldIrql);

    ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);

    while (! IsListEmpty (&irpQueue)) {

    entry = RemoveHeadList (&irpQueue);

    currentIrp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);

    }

    KeReleaseSpinLock(&irpQueueSpinLock, oldIrql);

    IoCopyCurrentIrpStackLocationToNext(currentIrp);

    status = IoCallDriver(pdx->pLowerDevice,currentIrp);

    Все посылается устройству, команду оно выполняет, но возникает BSoD. Без обработки очереди все работало нормально.

    Подскажите, пожалуйста, где ошибка в этом коде. Заранее благодарен за помощь.
     
  2. Sten

    Sten New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2003
    Сообщения:
    39
    Почему бы не засунуть дамп памяти в WinDBG и не посмотреть, где происходит BSOD?



    Ты уверен, что выполняются условия твоих ASSERT-ов в обоих процедурах?



    Находятся ли код этих процедур в Non-paged pool?



    Что делает цикл
    Код (Text):
    1.  
    2. while (! IsListEmpty (&irpQueue)) {
    3. entry = RemoveHeadList (&irpQueue);
    4. currentIrp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);
    5. }
    6.  




    Выглядит так, как будто он удаляет из очереди все IRP и возвращает указатель на последний.



    Если тебе надо только отфорвардить IRP нижележащему драйверу в стеке и не интересует что дальше будет с этим запросом, то можешь заменить вызов IoCopyCurrentIrpStackLocationToNext() на IoSkipCurrentIrpStackLocation();
     
  3. LuckyDevil

    LuckyDevil New Member

    Публикаций:
    0
    Регистрация:
    10 мар 2005
    Сообщения:
    278
    Адрес:
    Uzbekistan
    Хотел тоже поумничать, но тут Стен и так все сказал, действительно в цикле у тебя должен находиться обработчки.
     
  4. Sten

    Sten New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2003
    Сообщения:
    39
    Вообще-то сказал далеко не все. :) Архитектура несколько странноватая - не видел никогда, чтобы сразу скопом обрабатывались все запросы в очереди. Плюс, еще надо обмозговать что делать в случае, если IoCallDriver() вернет STATUS_PENDING.
     
  5. LuckyDevil

    LuckyDevil New Member

    Публикаций:
    0
    Регистрация:
    10 мар 2005
    Сообщения:
    278
    Адрес:
    Uzbekistan
    Sten



    тут ничего особенного, к примеру при сохранении большого файла, все запросы приходится обрабатывать скопом :), насчет STATUS_PENDING, его стоит отслеживать если он действительно будет использовать это
    Код (Text):
    1. IoCopyCurrentIrpStackLocationToNext(currentIrp);
    2. status = IoCallDriver(pdx->pLowerDevice,currentIrp);
    3.  


    в этом случае ему еще придется писать свою роутин-функцию и ждать ответа, и уже после делать комплит рэквест.
     
  6. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    <font color="gray][ Sten</font><!--color--><font color="gray]: Выглядит так, как будто он удаляет из очереди все IRP и возвращает указатель на последний. ]</font><!--color-->



    Именно так оно и есть и все IRP, кроме последнего просто "повисают в воздухе". Хотя это не должно приводить к BSOD, по крайней мере сразу, т.к. если после постановки в очередь, автору IRP возвращен STATUS_PENDING, как оно и должно быть (по вышеприведенному коду этого не видно, кстати), то он (автор) будет ждать.



    ksu_ant, BSOD'ы разные бывают. Какой код и параметры? А то так решительно ничего не понятно. Посмотри примеры в ДДК и найди отличия ;)
     
  7. ksu_ant

    ksu_ant New Member

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

    Прошу прощения за вынужденное молчание, - у меня были выходные.

    Что удалось накопать за эти выходные.

    Приведенный выше код - работает. Оказывается ошибка была дальше по коду и при определенных условиях, не относящихся к сути вопроса.

    Но, заработала только тестовая версия.

    Когда я стал переписывать в реальный алгоритм, все стало гораздо интереснее :).

    Тот код, который я привел ранее, выполнялся так (т.к. это тестовый вариант): IRP анализировался в диспетчерской функции, отправлялся в другую функцию, ставился там в очередь, затем, при возврате в дисп. функцию, извлекался из очереди, как выяснилось, не верно (т.к. удаляются все, кроме последнего), и выполнялся. Все это работало.

    Теперь ситуация следующая: объявления те же, IRP ставится в очередь так:

    KIRQL oldIrql;

    KeAcquireSpinLock(&irpQueueSpinLock, &oldIrql);

    IoMarkIrpPending(pIrp);

    ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);

    InsertTailList(&irpQueue, &pIrp->Tail.Overlay.ListEntry);

    KeReleaseSpinLock(&irpQueueSpinLock, oldIrql);

    Затем, при поступлении от приложения IRP, содержащего код запрета/разрешения прохождения сигнала, надо взять первый IRP из очереди и применить к нему действие. Я пытаюсь делать это так:

    Функция извлечения IRP из очереди:

    PIRP PopIrp()

    {

    PIRP currentIrp = NULL;

    PLIST_ENTRY entry;

    KIRQL oldIrql;

    KeAcquireSpinLock(&irpQueueSpinLock, &oldIrql);

    ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);

    while (! IsListEmpty (&irpQueue)) {

    entry = RemoveHeadList (&irpQueue);

    currentIrp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);

    }

    KeReleaseSpinLock(&irpQueueSpinLock, oldIrql);

    return currentIrp;

    }

    Код обработки прохождения запроса:

    ...

    case IOCTL_ALLOW:

    if(IrpCnt>0){

    PIRP LocpIrp=NULL;

    LocpIrp=PopIrp();

    IoCopyCurrentIrpStackLocationToNext(LocpIrp);

    status = IoCallDriver(pdx->pLowerDevice, LocpIrp);

    IrpCnt--;

    }

    pIrp->IoStatus.Status = STATUS_SUCCESS;

    pIrp->IoStatus.Information = 0;

    IoCompleteRequest(pIrp,IO_NO_INCREMENT);

    break;



    При выполнении этого кода возникает BSoD. Пишет:

    An attempt was made to write to read-only memory.

    А где память трогается, - мне не понятно.

    Иногда, если запретить прохождение сигнала таким кодом:



    case IOCTL_DENY:

    PIRP LocpIrp=NULL;

    ULONG LocalBytes;

    LocpIrp=PopIrp();

    PIO_STACK_LOCATION pIoStack = IoGetCurrentIrpStackLocation(LocpIrp);

    LocalBytes = pIoStack->Parameters.Write.Length;

    LocpIrp->IoStatus.Status = STATUS_SUCCESS;

    LocpIrp->IoStatus.Information =LocalBytes;

    IoCompleteRequest( LocpIrp, IO_NO_INCREMENT );

    status=STATUS_SUCCESS;

    IrpCnt--;

    pIrp->IoStatus.Status = STATUS_SUCCESS;

    pIrp->IoStatus.Information = 0;

    IoCompleteRequest(pIrp,IO_NO_INCREMENT);

    break;

    BSoD с кодом DRIVER_IRQL_NOT_LESS_OR_EQUAL.

    Помогите, пожалуйста, разобраться, в чем проблема, и как мне сделать правильное извлечение первого IRP из очереди. Я думаю, проблема именно в функции извлечения.

    Благодарен за помощь всем откликнувшимся.
     
  8. LuckyDevil

    LuckyDevil New Member

    Публикаций:
    0
    Регистрация:
    10 мар 2005
    Сообщения:
    278
    Адрес:
    Uzbekistan
    ksu_ant, этот код
    Код (Text):
    1. PIRP PopIrp()
    2. {
    3. PIRP currentIrp = NULL;
    4. PLIST_ENTRY entry;
    5. KIRQL oldIrql;
    6. KeAcquireSpinLock(&irpQueueSpinLock, &oldIrql);
    7. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
    8. while (! IsListEmpty (&irpQueue)) {
    9. entry = RemoveHeadList (&irpQueue);
    10. currentIrp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);
    11. }
    12. KeReleaseSpinLock(&irpQueueSpinLock, oldIrql);
    13. return currentIrp;
    14. }


    совершенно не понятен, зачем создавать очередь, если в итоге обрабатывается только последний IRP?

    и далее,
    Код (Text):
    1. IoCopyCurrentIrpStackLocationToNext(LocpIrp);
    2. status = IoCallDriver(pdx->pLowerDevice, LocpIrp);


    тоже фигня, писали же выше, как правильно, судя тому что я вижу тебе нужно сделать так:
    Код (Text):
    1. IoSkipCurrentIrpStackLocation(LocpIrp);
    2. status = IoCallDriver(pdx->pLowerDevice, LocpIrp);
    3.  


    исправь это, а далее по ходу пьесы смотришь ситуацию



    Удачи.
     
  9. ksu_ant

    ksu_ant New Member

    Публикаций:
    0
    Регистрация:
    28 сен 2005
    Сообщения:
    273
    ksu_ant, этот код ... совершенно не понятен, зачем создавать очередь, если в итоге обрабатывается только последний IRP?

    Дело в том, что мне необходимо дождаться ответа пользователя на запрос о запрете/разрешении IRP, а если во время ожидания этого ответа произойдет еще несколько фильтруемых ситуаций, то они встанут в очередь, затем пошлем запросы для каждого из этой очереди последовательно, по мере поступления ответов пользователя.

    Как я понял, мне необходимо убрать цикл while для того, чтобы я последовательно выбирал первые элементы из очереди? Т.е. написать так:



    PIRP PopIrp()

    {

    PIRP currentIrp = NULL;

    PLIST_ENTRY entry;

    KIRQL oldIrql;

    KeAcquireSpinLock(&irpQueueSpinLock, &oldIrql);

    ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);



    entry = RemoveHeadList (&irpQueue);

    currentIrp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);



    KeReleaseSpinLock(&irpQueueSpinLock, oldIrql);

    return currentIrp;

    }

    И в этом случае, каждый раз будет выбираться только первый запрос из очереди. Я прав? И нужно ли при этом производить инициализацию головы очереди (InitializeListHead(&irpQueue)) каждый раз при выборе элемента из очереди?

    И если проблема только в копировании стека IRP, то почему тогда возникает BSoD в функции запрета прохождения, где стек не копируется в принципе.
     
  10. LuckyDevil

    LuckyDevil New Member

    Публикаций:
    0
    Регистрация:
    10 мар 2005
    Сообщения:
    278
    Адрес:
    Uzbekistan
    ksu_ant, не буду вдаваться в суть твоего творения, но скажу одно, если ты маркеруешь запросы как пендинг и закидываешь в список и где-то в подзадаче выполняешь удаление из списка отпенденных запросов, то тебе стоит позаботиться о том чтобы эти запросы были корректно обработаны системой, иначе они будут висеть и как результат приведут к краху системы.



    Конечно же я не спец по данному вопросу, но все же думаю что я тут прав.
     
  11. LuckyDevil

    LuckyDevil New Member

    Публикаций:
    0
    Регистрация:
    10 мар 2005
    Сообщения:
    278
    Адрес:
    Uzbekistan
    Да еще, почему бы тебе в диспетчере не делать все эти выкрутасы, т.е. нужный тебе IRP отработать, а все прочии откланить или завершить на своем уровне, не передавая далешь?
     
  12. ksu_ant

    ksu_ant New Member

    Публикаций:
    0
    Регистрация:
    28 сен 2005
    Сообщения:
    273
    Да еще, почему бы тебе в диспетчере не делать все эти выкрутасы, т.е. нужный тебе IRP отработать, а все прочии откланить или завершить на своем уровне, не передавая далешь?

    Не совсем понятно. Я, вроде, так и делаю. Анализируются IRP, ненужные - пропускаются, фильтруемые - в очередь до "особого распоряжения", коим является запрос разрешения/запрета прохождения.

    На своем уровне - не получится, - идет работа с устройством, а оно, при необходимости, должно выполнить команду, следовательно, я должен передать пакет его драйверу.
     
  13. LuckyDevil

    LuckyDevil New Member

    Публикаций:
    0
    Регистрация:
    10 мар 2005
    Сообщения:
    278
    Адрес:
    Uzbekistan


    ksu_ant, нет так нет.

    Как-то все у тебя запутано.
     
  14. ksu_ant

    ksu_ant New Member

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

    Я бы и сам рад был, чтобы было все проще, но, по-моему здесь так не выйдет.

    Толковых исходников, описывающих такой механизм (перехватываем IRP, отдаем приложению, пользователь принимает решение, приложение возвращает результат, драйвер запрещает/разрешает пропуск пакета, при этом нельзя прекращать мониторинг остальных фильтруемых ситуаций) я не нашел. Так что приходится что-то придумывать. С Вашей помощью :derisive:
     
  15. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    <font color="gray][ ksu_ant</font><!--color--><font color="gray]: А где память трогается, - мне не понятно. ]</font><!--color-->



    Любой BSOD кроме кода имеет ещё до 4 доп. параметров.



    Bug Check 0xBE: ATTEMPTED_WRITE_TO_READONLY_MEMORY

    Bug Check 0xD1: DRIVER_IRQL_NOT_LESS_OR_EQUAL



    имеют параметр, который указывает на трогаемый адрес. См. ДДК. SoftICE с включённым faults on может сильно помочь.





    <font color="gray][ ksu_ant</font><!--color--><font color="gray]: И в этом случае, каждый раз будет выбираться только первый запрос из очереди. Я прав? ]</font><!--color-->



    Да.





    <font color="gray][ ksu_ant</font><!--color--><font color="gray]: И нужно ли при этом производить инициализацию головы очереди (InitializeListHead(&irpQueue)) каждый раз при выборе элемента из очереди? ]</font><!--color-->



    Ни в коем случае! Инициализация очереди производится только однин раз при начале работы драйвера.





    <font color="gray][ ksu_ant</font><!--color--><font color="gray]: И если проблема только в копировании стека IRP, ]</font><!--color-->



    Копирование стека здесь совершенно не при чём. IoSkipCurrentIrpStackLocation вместо IoCopyCurrentIrpStackLocationToNext - это просто оптимизация. В твоём случае её желательно сделать, но это не обязательно.



    Я бы создал два примитива: EnqueueIrp и DequeueFirstIrp
    Код (Text):
    1. VOID EnqueueIrp(PIRP i_pIrp)
    2. {
    3.     KIRQL Irql;
    4.  
    5.     ASSERT( i_pIrp );
    6.     if ( i_pIrp ) {
    7.    
    8.         KeAcquireSpinLock( &irpQueueSpinLock, &Irql );
    9.         InsertTailList( &irpQueue, &i_pIrp->Tail.Overlay.ListEntry );
    10.         KeReleaseSpinLock( &irpQueueSpinLock, Irql );
    11.     }
    12. }
    13.  
    14. PIRP DequeueFirstIrp()
    15. {
    16.     PIRP r_pIrp = NULL;
    17.     PLIST_ENTRY pListEntry;
    18.     KIRQL Irql;
    19.    
    20.     KeAcquireSpinLock( &irpQueueSpinLock, &Irql );
    21.  
    22.     if ( !IsListEmpty(&irpQueue) ){
    23.  
    24.         pListEntry = RemoveHeadList( &irpQueue );
    25.         r_pIrp = CONTAINING_RECORD( pListEntry, IRP, Tail.Overlay.ListEntry );
    26.     }
    27.  
    28.     KeReleaseSpinLock( &irpQueueSpinLock, Irql );
    29.    
    30.     return r_pIrp;
    31. }


    Постановка в очередь:
    Код (Text):
    1. IoMarkIrpPending( pIrp );
    2. EnqueueIrp( pIrp );
    3. return STATUS_PENDING;


    Выборка из очереди:
    Код (Text):
    1. PIRP pIrp = DequeueFirstIrp();
    2.  
    3. if ( pIrp ) {
    4.  
    5.     if ( DENY ) {
    6.  
    7.         pIrp->IoStatus.Information = 0;
    8.         pIrp->IoStatus.Status = STATUS_NO_SUCH_FILE;    //  или другой подходящий статус
    9.  
    10.         IoCompleteRequest( pIrp, IO_NO_INCREMENT);
    11.  
    12.     } else {
    13.  
    14.         IoSkipCurrentIrpStackLocation( pIrp );
    15.         IoCallDriver( pdx->pLowerDevice, pIrp );
    16.     }
    17. }


    Это если тебе тупо нужно выбирать только самый первый IRP. В реальной же ситуации тебе наверное придется как-то различать IRP: какие блокировать, какие пропускать. Для этого нужен какой-то ключ: адрес IRP, адрес файлового объекта, просто порядковый номер и т.п. Когда ты шлёш юзеру запрос, то помечаешь его ключом и потом по ключу ищешь в очереди нужный IRP. Если представить, что ключом будет адрес самого IRP, то примитив, дергающий из очереди нужный IRP, будет такой:
    Код (Text):
    1. PIRP DequeueParticularIrp( PIRP i_pIrpToDequeue )
    2. {
    3.     PIRP  r_pIrp = NULL;
    4.     PIRP  pIrp;
    5.     KIRQL Irql;
    6.  
    7.     PLIST_ENTRY pThisEntry;
    8.     PLIST_ENTRY pNextEntry;
    9.     PLIST_ENTRY pListHead;
    10.  
    11.     ASSERT( i_pIrpToDequeue );
    12.     if ( NULL == i_pIrpToDequeue )  return NULL;
    13.  
    14.     pListHead = &irpQueue;
    15.  
    16.     KeAcquireSpinLock( &irpQueueSpinLock, &Irql );
    17.  
    18.     for ( pThisEntry = pListHead->Flink, pNextEntry = pThisEntry->Flink;
    19.           pThisEntry != pListHead;
    20.           pThisEntry = pNextEntry, pNextEntry = pThisEntry->Flink ) {
    21.  
    22.         pIrp = CONTAINING_RECORD( pThisEntry, IRP, Tail.Overlay.ListEntry );
    23.  
    24.         if ( pIrp == i_pIrpToDequeue ) {
    25.  
    26.             RemoveEntryList( pThisEntry );
    27.             r_pIrp = pIrp;
    28.         }
    29.     }
    30.  
    31.     KeReleaseSpinLock( &irpQueueSpinLock, Irql );
    32.    
    33.     return r_pIrp;
    34. }




    ЗЫ: Тут ещё с отменой париться надо будет, но пока не заморачивайся.
     
  16. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Забыл сказать.
    Код (Text):
    1.     PIO_STACK_LOCATION pIoStack = IoGetCurrentIrpStackLocation(LocpIrp);
    2.     LocalBytes = pIoStack->Parameters.Write.Length;
    3.  
    4.     LocpIrp->IoStatus.Status = STATUS_SUCCESS;
    5.     LocpIrp->IoStatus.Information =LocalBytes;
    6.  
    7.     IoCompleteRequest( LocpIrp, IO_NO_INCREMENT );
    8.     status=STATUS_SUCCESS;


    Возможно к BSOD'у это и не имеет отношение, но по-любому неправильно. Операция же не была выполнена. Information д.б. = 0, а статус д.б. статусом ошибки. К тому же надо ещё посмотреть, не заставляет ли это (Information != 0) диспетчер в/в копировать куда-нить что-нить. Тут может быть завязка на контекст процесса.
     
  17. ksu_ant

    ksu_ant New Member

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

    На одном из форумов мне также говорили про контекст процесса.

    Попробую переделать процедуры по Вашему совету. Надеюсь, получится.
     
  18. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Я тоже надеюсь, но боюсь, что всё не так просто. Слей с microsoft "Debugging Tools for Windows". Настрой систему на сброс мини крэшдампа Свойства системы -> Загрузка и восстановление. Дампы будут в %SystemRoot%\Minidump. Грузи дамп в WinDbg из "Debugging Tools for Windows" и пости, то что он (WinDbg) говорит сюда в текстовом виде. Так будет проще понять, что происходит. Ещё придется слить символы (по крайней мере для ntoskrnl) и настроить пути к ним.
     
  19. ksu_ant

    ksu_ant New Member

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

    Всех с прошедшими праздниками!

    Блокировка наконец-то заработала! Делаю так:

    PIRP LocpIrp=PopIrp();

    LocpIrp->IoStatus.Information = 0;

    LocpIrp->IoStatus.Status = STATUS_ACCESS_DENIED;

    IoCompleteRequest( LocpIrp, IO_NO_INCREMENT );

    status=STATUS_SUCCESS;//для запроса



    Но, к сожалению, пропуск пакета приводит к BSoD'у.

    Делаю так:

    PIRP LocpIrp = PopIrp();

    IoSkipCurrentIrpStackLocation( LocpIrp );

    status = IoCallDriver(pdx->pLowerDevice, LocpIrp);

    Код функции PopIrp совпадает с описанной Four-F функцией DequeueFirstIrp.

    Советуемые программы я пока не скачивал (трафика мало :-(), воспользовался WinDbg из DDK 2000 и дамп, сохраненный при BSoD. Привожу то, что было в конце анализа, так как выше было просто перечисление активных драйверов системы:



    Kernel Debugger connection established for D:\WINDOWS\MEMORY.DMP

    Kernel Version 2600 Free loaded @ ffffffff804d0000

    Bugcheck 0000008e : c0000005 804ec046 f3532b98 00000000

    Stopped at an unexpected exception: code=80000003 addr=ffffffff804fc1bb

    Hard coded breakpoint hit



    P.S.: Если это не то, что необходимо, я скачаю указанные программы и сделаю анализ с их помощью. И еще - где взять символы для ntoskrnl для WinXP без сервис-паков? А то качать > 140M полного пакета - больно круто :derisive:
     
  20. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Это уже кое-что. Лить все 140 метров конечно не обязательно. WinDbg можно настроить так, что он сам будет сливать нужные символы. Как - написано в хелпе. Есть способ проще - запусти \SoftICE\SymbolRetriever\symrtrvr.exe, кинь ему на окно ntoskrnl.exe и тыкни нужную кнопку. Символы льются в упакованном виде, так что там совсем немного. Можно ещё внизу нужные галки поставить, тогда символы и в айс вольются. В WinDbg пропиши путь к каталогу с pdb. Последний WinDbg сливать не обязательно.



    Я могу ошибится, т.к. не знаю какой sp у тя стоит, но похоже баг тут:


    Код (Text):
    1. :0041C028 IopfCallDriver  proc
    2. . . .
    3. :0041C03D    mov     [edx+60h], eax  ; Irp->Tail.Overlay.CurrentStackLocation = irpSp;
    4. :0041C040    mov     [eax+IO_STACK_LOCATION.DeviceObject], ecx ; irpSp->DeviceObject = DeviceObject;
    5. :0041C043
    6. :0041C043    movzx   eax, byte ptr [eax]       ; IO_STACK_LOCATION.MajorFunction
    7. <font color="red]:0041C046    mov     esi, [ecx+8]              ; pDriverObject = pDeviceObject->DriverObject;</font><!--color-->
    8.  
    9. ; DriverObject->MajorFunction[pIoStack->MajorFunction]( pDeviceObject, pIrp );
    10. :0041C049    push    edx
    11. :0041C04A    push    ecx
    12. :0041C04B    call    dword ptr [esi+eax*4+38h]
    13. . . .
    14. :0041C050 IopfCallDriver  endp




    У тя в pdx->pLowerDevice какая-то лажа, а не указатель на DeviceObject. Войди в айс, набери u 804ec046. Если увидишь строку, которая выделена красным, то значит я прав.



    Если есть желание, то можешь скинуть сюда или мне на мыло код DriverEntry, AddDevice и процедуры, которые ставят/достают IRP из очереди. Ну или вообще весь код, если не жалко ;)



    ЗЫ: И потопчись отладчиком по коду.