Ошибка при попытке доступа к элементу структуры в драйвере

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

  1. ksu_ant

    ksu_ant New Member

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

    Возникла "маленькая проблема", которую я сам не в состоянии решить. Помогите, пожалуйста.

    При попытке доступа к элементу структуры - BSoD.

    Структура такая:
    Код (Text):
    1.  
    2. #define MAX_KEYS        64
    3. #define MAX_KEYHASH     32
    4. ...
    5. typedef struct _OPEN_FILE_INFORMATION {
    6.     USHORT          KeyType;        //0 None 1 2Fish 2 AES256
    7.     USHORT          KeyNum;
    8.     USHORT          KeyLength;
    9.     UCHAR           Key[MAX_KEYS][MAX_KEYHASH];
    10. } OPEN_FILE_INFORMATION, *POPEN_FILE_INFORMATION;
    11.  


    Из приложения отправляю так:
    Код (Text):
    1.  
    2. POPEN_FILE_INFORMATION  OpenFileInformation;
    3. ...
    4. DeviceIoControl(
    5.                 hDevice,
    6.                 IO_DO_ACTION,
    7.                 OpenFileInformation,
    8.                 sizeof(OPEN_FILE_INFORMATION),
    9.                 OpenFileInformation,
    10.                 sizeof(OPEN_FILE_INFORMATION),
    11.                 &BytesReturned,
    12.                 NULL
    13.             )
    14.  


    Выходные буферы не заполняются, но если их не указывать в программе, результат не отличается.Затем, в драйвере, выполняю следующее:
    Код (Text):
    1.  
    2. if (irpStack->Parameters.DeviceIoControl.InputBufferLength <sizeof(OPEN_FILE_INFORMATION))
    3. {
    4.     DbgPrint("Invalid parameter 1!\n");
    5.       status = STATUS_INVALID_PARAMETER;
    6.       Irp->IoStatus.Information = 0;
    7.       break;
    8. }
    9. if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(OPEN_FILE_INFORMATION))
    10. {
    11.     DbgPrint("Invalid parameter 2!\n");
    12.       status = STATUS_INVALID_PARAMETER;
    13.       Irp->IoStatus.Information = 0;
    14.       break;
    15. }
    16. open_file_information = (POPEN_FILE_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
    17. DbgPrint("Do Action successfully!\n");
    18. device_extension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
    19. DbgPrint("Do Action successfully again!\n");//WinDbg указывает на эту строку
    20. DbgPrint("Key Type %i\n",open_file_information->KeyType);//но на самом деле, если убрать эту строку, то ошибки нет
    21.  


    При попытке выполнения этого кода - BSoD.

    Анализ дампа - в аттаче.

    Если кому-нибудь интересно и Вы желаете подробнее изучить проблему и помочь мне найти решение, - пишите, могу выслать полный код.

    Сюда не выкладываю, чтобы не обременять своими проблемами людей, у которых немного свободного времени.



    [​IMG] _778038817__dump.txt
     
  2. netex

    netex New Member

    Публикаций:
    0
    Регистрация:
    5 дек 2005
    Сообщения:
    114
    Адрес:
    Russia
    Скорее всего у тебя проблема в методе обмена данными между user и kernel.

    Если используешь функции read write, тогда явно укажи в DEVICE_OBJECT->Flags метод обмена.

    Если используешь DeviceIoControl, тогда правильно задай ControlCode. (есть макрос CTL_CODE)



    Подробности в книге Солдатова или Art Baker и Jerry Lozano.



    Вот отрывок из Солдатова:



    "При методе METHOD_BUFFERED

    Диспетчер ввода/вывода выделяет единственный буфер в нестраничной памяти, достаточно большой, чтобы вместить входной или выходной буфер инициатора вызова. Адрес этой области размещается в пакете IRP в поле AssociatedIrp.SystemBuffer. Затем производится копирование входного (input) буфера с данными инициатора запроса в эту область. В поле UserBuffer пакета IRP заносится оригинальный адрес буфера для получения данных инициатора запроса.



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



    При методе METHOD_IN_DIRECT и METHOD_OUT_DIRECT

    Диспетчер ввода/вывода проверяет приемлемость выходного (output) буфера инициатора вызова и производит его фиксацию (lock) в физической памяти. Затем производит построение списка MDL (Memory Descriptor List) для выходного буфера и сохраняет указатель на MDL в поле MdlAddress пакета IRP.



    Кроме того, Диспетчер ввода/вывода выделяет временную область в нестраничном пуле и сохраняет этот адрес в поле AssociatedIrp.SystemBuffer пакета IRP. Производится копирование содержимого входного (input) буфера инициатора вызова в выделенный системный буфер, а в поле UserBuffer производится запись значения NULL. После этого IRP пакет поступает в вызываемую рабочую процедуру драйвера.



    При методе METHOD_NEITHER

    Диспетчер ввода/вывода помещает адрес входного (input) буфера инициатора вызова в поле Parameters.DeviceIoControl.Type3InputBuffer в текущей ячейке стека пакета IRP текущей операции ввода/вывода. В поле UserBuffer производится запись адреса выходного (output) буфера инициатора вызова, где инициатор вызова ожидает получить результаты выполнения операции. Оба этих адреса указывают в область памяти инициатора вызова."
     
  3. ksu_ant

    ksu_ant New Member

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

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

    Но явно метод ВВ не указывал.

    Если у кого есть еще мысли - буду рад помощи.
     
  4. SteelRat

    SteelRat New Member

    Публикаций:
    0
    Регистрация:
    26 авг 2004
    Сообщения:
    409
    Да, есть такие "грабли" ;) Если не указать метод в/в то будет "каша".

    Это в DriverEntry
    Код (Text):
    1.   mov eax, device_object
    2.   or (DEVICE_OBJECT PTR [eax]).Flags, DO_DIRECT_IO
    3.   mov edi, (DEVICE_OBJECT PTR [eax]).DeviceExtension
    4.  


    Это управляющий код
    Код (Text):
    1. IOCTL_GET_ADDRESS equ CTL_CODE(FILE_DEVICE_UNKNOWN, 800h, METHOD_BUFFERED, FILE_READ_ACCESS + FILE_WRITE_ACCESS)
     
  5. ksu_ant

    ksu_ant New Member

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

    Но там обрабатываются данные от системы.

    Не знал, что для передачи структуры надо это определять.

    Спасибо netex и SteelRat.

    В обед попробую (чтобы никто из окружающих в обморок не падал от BSoD да и время было компьютеру в себя прийти :)).

    VMWare или нечто подобное пока не поставил, как когда-то советовал SteelRat. Один раз попробовал скачать, но файлик битым оказался, а еще раз 60М впустую, - жалко :).

    Ребята мне обещали дать, но они в другом городе.
     
  6. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Само заполнение OPEN_FILE_INFORMATION и выделение памяти под эту структуру не наблюдается в приведенном коде (его юзерной части). Т.е. существует только переменная OpenFileInformation для хранения адреса, а выделение памяти под OPEN_FILE_INFORMATION и её заполнение отсутствует. Такой код и в юзере будет вызывать падение программы при попытке обращения к OpenFileInformation->KeyType
     
  7. ksu_ant

    ksu_ant New Member

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

    Так это же для краткости.



    Вот так выделяется (user-mode):

    OpenFileInformation = malloc(sizeof(OPEN_FILE_INFORMATION));

    memset(OpenFileInformation,

    0,

    sizeof(OPEN_FILE_INFORMATION));

    memcpy(OpenFileInformation,&ka,sizeof(ka));