Корректная модификация/блокирование данных + pIrp->AssociatedIrp.SystemBuffer

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

  1. ksu_ant

    ksu_ant New Member

    Публикаций:
    0
    Регистрация:
    28 сен 2005
    Сообщения:
    273
    Значит Вы мне советуете убрать директиву #pragma CODE_PAGED из кода главного модуля. Надо будет попробовать.
     
  2. SteelRat

    SteelRat New Member

    Публикаций:
    0
    Регистрация:
    26 авг 2004
    Сообщения:
    409
    DriverEntry - секция INIT, остальное в неподкачиваемый пул (не знаю точно как в Це но в ASM без указания куда)
     
  3. ksu_ant

    ksu_ant New Member

    Публикаций:
    0
    Регистрация:
    28 сен 2005
    Сообщения:
    273
    Спасибо, попробую. Но за результат не ручаюсь, я только начинаю разбираться в особенностях написания драйверов :derisive:.
     
  4. ksu_ant

    ksu_ant New Member

    Публикаций:
    0
    Регистрация:
    28 сен 2005
    Сообщения:
    273
    Заменил я директивы #pragma CODE_PAGED на #pragma CODE_LOCKED, вроде, по коду, это должно соответствовать неподкачиваемому пулу. Работает также (т.е. имеется 2-3-х минутное "подвисание компьютера").
     
  5. SteelRat

    SteelRat New Member

    Публикаций:
    0
    Регистрация:
    26 авг 2004
    Сообщения:
    409
    Посмотри DispatchOther и DispatchPower в них ошибка - не освобождается ресурс при STATUS!=OK. Может проблема и в других ф-ях. Эта ошибка часто выходит наружу и возможно так себя и показывает :)
     
  6. SteelRat

    SteelRat New Member

    Публикаций:
    0
    Регистрация:
    26 авг 2004
    Сообщения:
    409
    И ещё, выкини CompleteRequest(pIrp, status, 0); совсем. Используй нормальный IoCompleteRequest в конце каждой ф-ции, с параметрами, взятыми из IRP.
     
  7. ksu_ant

    ksu_ant New Member

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

    Спасибо большое.

    Я даже не подозревал, что все может застопориться из-за такой мелочи - вроде же все правильно.

    Ладно, попробую вечером.
     
  8. ksu_ant

    ksu_ant New Member

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

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

    В связи с этим, возникает два вопроса: 1 - правильно ли я думаю, 2 - если правильно, как сформировать запрос, не зависящий от оборудования. Т.е. у IoBuildDeviceIoControlRequest есть параметр IoControlCode, а в DDK описаны "привязанные" к оборудованию коды (IOCTL_CDROM_xxx, и т.д.) (по крайней мере, в документации я только это нашел). Напишите, пожалуйста, как это можно осуществить (чтобы не было проблем с разным оборудованием). Если есть идеи по поводу решения проблемы, описанной ранее, т.е. без вызова IoCallDriver, напишите, пожалуйста, Ваш совет станет также очень ценным.
     
  9. SteelRat

    SteelRat New Member

    Публикаций:
    0
    Регистрация:
    26 авг 2004
    Сообщения:
    409
    1 - ночью надо спать, и не выдумывать.

    2 - "врать" (фальшивить) - нехорошо.

    В DispatchReadWrite (мне кажется она урезана для показа ?)
    Код (Text):
    1.             if (1==0){                                          //ПРИНЯТИЕ РЕШЕНИЯ О БЛОКИРОВКЕ ДАННЫХ (В ДАННОМ СЛУЧАЕ - БЕЗУСЛОВНАЯ БЛОКИРОВКА)
    2.                 //ПРОПУСТИТЬ ПАКЕТ
    3.                     IoCopyCurrentIrpStackLocationToNext(pIrp);
    4.                     IoSetCompletionRoutine(
    5.                         pIrp,
    6.                         (PIO_COMPLETION_ROUTINE)ReadWriteCompletion,
    7.                         pWorkData,
    8.                         TRUE,  TRUE,  TRUE
    9.                     );
    10.                 status = IoCallDriver(pdx->pLowerDevice, pIrp);
    11.             }
    12.                 //БЛОКИРОВАТЬ ПАКЕТ
    13.              pIrp->IoStatus.Status = STATUS_SUCCESS;
    14.                    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    15.               return STATUS_SUCCESS;
    16.  


    Убрать else, т.к. любой IRP должен закончится IoCompleteRequest, кроме PENDING, т.к. была вызвана IoCopyCurrentIrpStackLocationToNext
     
  10. ksu_ant

    ksu_ant New Member

    Публикаций:
    0
    Регистрация:
    28 сен 2005
    Сообщения:
    273
    Спасибо, попробую. Но вот в чем дело: как я думаю, удаление else, фактически не изменит ситуацию для примера с блокировкой, так как при указанном примере if (1==0)... , код, находящийся в теле else, все равно всегда (!!!) выполнялся точно также, как и будет выполняться, т.е., я думаю, - текущая ошибка останется.

    Хотя, для случая с реальной блокировкой (когда одни сигналы - пропускаются, а другие - нет), Вы правильно заметили, что else нужно убрать.

    Функция не урезана, т.к. я сейчас пытаюсь написать просто concept-функцию, способную корректно блокировать данные всегда. А потом, конечно, код увеличится, т.к. будет принимать решения.
     
  11. SteelRat

    SteelRat New Member

    Публикаций:
    0
    Регистрация:
    26 авг 2004
    Сообщения:
    409
    pIrp->IoStatus.Information тоже не заполняется. Слишком много ошибок... Блокирование пакета вроде правильное.
     
  12. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Драйвер завершающий запрос чтения/записи будет делать это примерно так (метод в/в не имеет принципиального значения, просто адрес буфера будет взят из другого места):
    Код (Text):
    1.     PIO_STACK_LOCATION  pIoStack;
    2.     NTSTATUS            status;
    3.     ULONG               cb = 0;
    4.     PUCHAR              pBuffer;
    5.  
    6.     pIoStack = IoGetCurrentIrpStackLocation( pIrp );
    7.  
    8.     pBuffer = MmGetSystemAddressForMdlSafe( pIrp->MdlAddress, NormalPagePriority );
    9.  
    10.     switch ( pIoStack->MajorFunction ) {
    11.     case IRP_MJ_READ:
    12.  
    13.         cb = pIoStack->Parameters.Read.Length;
    14.  
    15.         RtlMoveMemory(
    16.             pBuffer,
    17.             pSomePlace + pIoStack->Parameters.Read.ByteOffset.LowPart,
    18.             cb );
    19.  
    20.         break;
    21.  
    22.     case IRP_MJ_WRITE:
    23.  
    24.         cb = pIoStack->Parameters.Write.Length;
    25.  
    26.         RtlMoveMemory(
    27.             pSomePlace + pIoStack->Parameters.Write.ByteOffset.LowPart,
    28.             pBuffer,
    29.             cb );
    30.  
    31.         break;
    32.  
    33.     default:
    34.         cb = 0;
    35.     }
    36.  
    37.     status = STATUS_SUCCESS;
    38.  
    39.     pIrp->IoStatus.Status      = status;
    40.     pIrp->IoStatus.Information = cb;
    41.  
    42.     IoCompleteRequest( pIrp, IO_NO_INCREMENT );
    43.  
    44.     return status;
    Т.о. в pIrp->IoStatus.Information оказывается кол-во прочитанных/записанных байт. Т.к. ты не заполняешь это поле, то оно по умолчанию равно 0 (кажется), а status = STATUS_SUCCESS, т.е. вызывающий код на стороне пользователя видит, что запрос успешно завершился но ничего не прочитано/записано. Вопрос: "что он будет делать в этом случае?". Чего-то ждать, или попытается послать запрос ещё раз, или... Например, если повесить такой фильтр в стек клавиатуры, то система просто зависнет. Точнее говоря, процесс csrss будет с дикой скоростью отправлять запросы на чтение клавиатуры а фильтр тут же будет их завершать ибо в нормальном режиме запрос, отправленный в клавиатурный стек ставится в очередь до нажатия на клавишу. Как только клавиша нажимается, запрос завершается и csrss тут же отправляет навый. У потока, который этим занимается приоритет = 19 и если он постоянно будет слать запросы, то система практически только и будет заниматься тем, что их отправлять.



    Во-первых, лучше явно указать в поле Information, что ничего не прочитано/записано (хотя это ничего не даст, но тем не менее), и попробовать изменить status на код ошибки. Разделить обработку IRP_MJ_READ и IRP_MJ_WRITE воткнуть туда пару DbgPrint'ов и посмотреть с какой частотой они вызываются. Может это что-то даст.



    ЗЫ: Я мельком глянул код DispatchPnP. К подвисанию это не относится, но там как минимум 3 ошибки. Советую просто взять это кусок кода из DDK\src\general\toaster\filter\filter.c
     
  13. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Маленькая поправочка. Для запросов IRP_MJ_WRITE можно сделать так:
    Код (Text):
    1.  
    2.     status = STATUS_SUCCESS;
    3.  
    4.     pIrp->IoStatus.Status      = status;
    5.     pIrp->IoStatus.Information = pIoStack->Parameters.Write.Length;
    6.  
    7.     IoCompleteRequest( pIrp, IO_NO_INCREMENT );
    8.  
    9.     return status;
    Тогда автор запроса будет считать, что запись прошла удачно.
     
  14. ksu_ant

    ksu_ant New Member

    Публикаций:
    0
    Регистрация:
    28 сен 2005
    Сообщения:
    273
    Спасибо всем ОГРОМНОЕ!

    За "вычищение" ошибок и просто за полезные советы.

    Но, как оказалось, к "подвисанию" драйвер, в принципе (как правильно заметил Four-F), не был причастен. Просто пользовательская программа, работающая с оборудованием, выполняла инициализацию и ожидала ответа от аппаратной части. Так как в concept версии, которую я и пытался, с Вашей помощью, создать, не пропускались никакие запросы (ни на чтение, ни на запись), - ответа на запросы не было и программа, ожидая его, отнимала все ресурсы процессора. Когда даже у нее терпение иссякло, и она сказала, что оборудование не отвечает, все возвращалось на место.

    Еще раз спасибо. Думаю теперь я смогу заставить все это работать по-человечески.
     
  15. ksu_ant

    ksu_ant New Member

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

    Заставил (работать по-человечески) :derisive:.

    Всем участвовавшим в обсуждении, особенно SteelRat и Four-F, - троекратное спасибо!