Коммуникация с драйвером

Тема в разделе "WASM.NT.KERNEL", создана пользователем DoZENT, 24 июн 2007.

  1. DoZENT

    DoZENT New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2007
    Сообщения:
    50
    Необходимо из драйвера передать структуру в ринг3. Делаю так:

    ринг3 (делфа :) ):
    Код (Text):
    1.  
    2.  
    3. type
    4.   TCanIGetThisData = record
    5.  
    6.     DirName : LPWSTR;
    7.     ProcessName : PCHAR;
    8.  
    9.   end;
    10.  
    11. .....
    12.  
    13. var
    14. z : TCanIGetThisData;
    15.  
    16. .....
    17.  
    18.  hDriver := CreateFile (PChar ('\\.\' + DriverName),GENERIC_WRITE, 0, nil, OPEN_EXISTING, 0, 0);
    19.  
    20.   if (hDriver <> ERROR_FILE_NOT_FOUND) and (hDriver <> INVALID_HANDLE_VALUE) then
    21.   begin
    22.  
    23.     if DeviceIoControl (hDriver, 2, nil,0, @z,sizeof (z) , BytesReaded, nil) = FALSE then
    24.       MessageBox (0, 'Ошибка при передаче', 'caption', MB_ICONERROR)
    25.     else
    26.       if D.ProcessName <> '' then
    27.         MessageBox (0, PChar (D.ProcessName), 'adfa', MB_OK); // Здесь вылетает(((((
    28.  
    29.     CloseHandle (hDriver);
    30.  
    31.   end;
    ринг0:
    Код (Text):
    1. if ( pisl->MajorFunction == IRP_MJ_DEVICE_CONTROL)
    2. {
    3.         ULONG ControlCode = pisl->Parameters.DeviceIoControl.IoControlCode;
    4.         ULONG method = ControlCode & 0x03;
    5.  
    6.             if (pisl->Parameters.DeviceIoControl.IoControlCode == 2)
    7.             {
    8.                
    9.                 ULONG InputLength = pisl->Parameters.DeviceIoControl.InputBufferLength;            
    10.                 ULONG OutputLength = pisl->Parameters.DeviceIoControl.OutputBufferLength;
    11.                    
    12.                 DPRINT("Buffer outlength %d",OutputLength);
    13.  
    14.                 if (OutputLength < sizeof (TCanIGetThisData))
    15.                 {
    16.                     DPRINT ("Buffer is too small");
    17.                     status = STATUS_INVALID_PARAMETER;
    18.                    
    19.                 }
    20.                 else
    21.                 {
    22.  
    23.                     //Размер буфера подходит
    24.                     TCanIGetThisData *buff;
    25.                     if(method==METHOD_BUFFERED)
    26.                     {
    27.                         buff = (PCanIGetThisData)Irp->AssociatedIrp.SystemBuffer;
    28.                                         buff->DirPath = L"adsfdsaf";
    29.                         buff->ProcessName = "dsfds";
    30.  
    31.                         DPRINT("Method : BUFFERED");
    32.  
    33.                     }
    34.                     else
    35.                         if (method==METHOD_NEITHER)
    36.                         {
    37.                             buff=(TCanIGetThisData*)Irp->UserBuffer;
    38.                             buff->DirPath = L"adsfdsaf";
    39.                             buff->ProcessName = "dsfds";
    40.  
    41.                             DPRINT("Method : NEITHER");
    42.  
    43.                         }
    44.                         else
    45.                         {
    46.                             //DPRINT("-Example- Method : unsupported.");
    47.                             //status = STATUS_INVALID_DEVICE_REQUEST;
    48.  
    49.                             buff = (PCanIGetThisData) MmGetSystemAddressForMdlSafe (Irp->MdlAddress,NormalPagePriority);
    50.                             buff->DirPath = L"adsfdsaf";
    51.                             buff->ProcessName = "dsfds";
    52.                            
    53.                         }
    54.                        
    55.  
    56.  
    57.  
    58.                 }
    59.  
    60.  
    61.             }
    62.  
    63.         }
    64. }
    65.  
    66. .......
    67.  
    68. IoCompleteRequest(Irp, IO_NO_INCREMENT);
    При выводе MessageBox программа вылетает...
     
  2. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Как же ей не вылетать то? Ведь в драйвер передается структура из двух указателей. Драйвер записывает туда указатели на строки, но строки то эти находятся в теле драйвера! Когда MessageBox пытается из прочитать, то залезает в ядерные адреса и обламывается.

    ЗЫ: В коде много других ошибок.
     
  3. DoZENT

    DoZENT New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2007
    Сообщения:
    50
    Про указатели понял, но все равно не работает( Подскажите, пожалуйста, в чем ошибки этого кода.
     
  4. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    ох...

    Из тех что бросаются в глаза:

    1.

    Т.к. данные передаются из драйвера, то в CreateFile вместо/<вместе с> GENERIC_WRITE должно быть GENERIC_READ. Иначе диспечтер в/в не отобразит ядерный буфер, заполненный драйвером, в юзермодный буфер.


    2.
    Код (Text):
    1. ULONG ControlCode = pisl->Parameters.DeviceIoControl.IoControlCode;
    2. ULONG method = ControlCode & 0x03;
    3.  
    4. if (pisl->Parameters.DeviceIoControl.IoControlCode == 2)
    Уверен, что имелось в виду...

    Код (Text):
    1. ULONG ControlCode = pisl->Parameters.DeviceIoControl.IoControlCode;
    2. ULONG method = ControlCode & 0x03;
    3.  
    4. //  METHOD_OUT_DIRECT == 2
    5. if ( method == METHOD_OUT_DIRECT )
    3.
    Код (Text):
    1. if (method==METHOD_NEITHER)
    2. {
    3.     buff=(TCanIGetThisData*)Irp->UserBuffer;
    4.     buff->DirPath = L"adsfdsaf";
    5.     buff->ProcessName = "dsfds";
    6. }
    Для метода NEITHER все обращения к юзермодному буферу обязательно оборачиваются в SEH и буферы предварительно проверяются на доступность.

    Код (Text):
    1. try {
    2.  
    3.     ProbeForRead( buff, InputLength, sizeof( UCHAR ) );  //  если читаем
    4.     или
    5.     ProbeForWrite( buff, OutputLength, sizeof( UCHAR ) ); //  если пишем
    6.  
    7.     //  работаем с буфером
    8.  
    9. } except(EXCEPTION_EXECUTE_HANDLER)  {
    10.  
    11.     ntStatus = GetExceptionCode();
    12.     DPRINT("Exception 0X%08X \n", GetExceptionCode() );
    13. }
    4.
    Код (Text):
    1. if(method==METHOD_BUFFERED) {
    2.  
    3. } else {
    4.  
    5.     if (method==METHOD_NEITHER) {
    6.  
    7.     } else {
    8.  
    9.         // тут плохо
    10.     }
    11. }
    Если метод в/в не METHOD_BUFFERED и не METHOD_NEITHER, значит это METHOD_IN_DIRECT или METHOD_OUT_DIRECT, но дело в том, что METHOD_IN_DIRECT отличается от METHOD_OUT_DIRECT как небо и земля, хотя это и неочевидно, а твоём коде обрабатывается совершенно одинокого. Достаточно внимательно прочитать "Buffer Descriptions for I/O Control Codes" в DDK.


    5.
    Код (Text):
    1. if(method==METHOD_BUFFERED) {
    2.     код
    3. }
    4. else
    5.     другой код (одна строка)
    В данном случае это не ошибка, но настоятельно не рекомендую делать if/else без {}, т.к. если в коде будет макрос, что не всегда очевидно, то он может раскрыться в несколько строк и компилятор запихает в if/else только первую строку. Вобщем советую всегда тупо делать.

    Код (Text):
    1. if(method==METHOD_BUFFERED) {
    2.     код
    3. } else {
    4.     другой код
    5. }
    6. Не ошибка, но непонятно зачем городить огород с обработкой разных методов в/в. В данном случае размер данных мал, значит тупо METHOD_BUFFERED. Если есть какие-то другие соображения, то вниметельно разобраться со всеми методами поможет DDK\src\general\ioctl\.