I/O control code. Послать из одного драйвера в другой

Тема в разделе "WASM.NT.KERNEL", создана пользователем Smoke_man, 22 авг 2008.

  1. Smoke_man

    Smoke_man New Member

    Публикаций:
    0
    Регистрация:
    19 сен 2006
    Сообщения:
    16
    Как послать IOCTL из одного драйвера в другой? Спасибо!
     
  2. Velheart

    Velheart New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    526
    Можно построить IRP и послать его через IoCallDriver
    upd а IRP можно построить через IoBuildDeviceIoControlRequest =)
     
  3. Smoke_man

    Smoke_man New Member

    Публикаций:
    0
    Регистрация:
    19 сен 2006
    Сообщения:
    16
    Я создаю Irp таким образом:
    Код (Text):
    1.   .......................
    2.   #define dev_link  L"\\Device\\NameDevice"
    3.  
    4.   UNICODE_STRING dev;
    5.   PKEVENT  Event = NULL;
    6.   PDEVICE_OBJECT pdoDev;
    7.   PIRP DevIrp
    8.   PIO_STATUS_BLOCK  IoStatusBlock = NULL;
    9.  
    10.   RtlInitUnicodeString( &dev, dev_link );
    11.  
    12.   status= IoAttachDevice ( fdo,&pdoDev,&com);
    13.   if (!NT_SUCCESS(status))
    14.   {    
    15.         IoDeleteDevice(fdo);
    16.         return status;
    17.   }
    18.  
    19.   PIRP DevIrp = IoBuildDeviceIoControlRequest(IOCTL_NUMBER,pdoDev,NULL,0,NULL,0,true,Event,IoStatusBlock);
    20.   IoCallDriver(pdoDev,DevIrp);
    21.  
    22.   if (!NT_SUCCESS(status))
    23.   {    
    24.         IoDeleteDevice(fdo);
    25.         return status;
    26.   }
    Но я не уверен что делаю правильно!
     
  4. Velheart

    Velheart New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    526
    Ну так это сильно зависит от того какому драйверу ты посылаешь IRP, что за IOCTL и т.д.
     
  5. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Ты делаешь неверно, потому что IoStatusBlock указывает на NULL
    + было бы неплохо проверять статус от IoCallDriver и IoStatusBlock->IoStatus, после того, как ты, конечно, передашь валидный указатель.
     
  6. Smoke_man

    Smoke_man New Member

    Публикаций:
    0
    Регистрация:
    19 сен 2006
    Сообщения:
    16
    Great, я знаю что не правильно то, что я IoStatusBlock указал на NULL...я просто не знаю откуда его взять.
     
  7. ams007

    ams007 New Member

    Публикаций:
    0
    Регистрация:
    28 апр 2007
    Сообщения:
    86
    Смотрим:
    Код (Text):
    1.    
    2. RtlInitUnicodeString(&swzSymbolicName,L"\\Device\\Имя_твоего_девайса");
    3.     ntStatus = IoGetDeviceObjectPointer(
    4.         &swzSymbolicName,
    5.         FILE_WRITE_DATA|FILE_READ_DATA,
    6.         &pFileObject,
    7.         &pDeviceObject); // получили указатель на этот девайс
    8.  
    9.     if (!NT_SUCCESS(ntStatus))
    10.         return FALSE;
    11.    
    12.     KeInitializeEvent( &kEvent, NotificationEvent, FALSE ); // евент проинициализировали
    13.  
    14.  
    15.     // теперь соберем Irp
    16. // Внимание! ioStatusBlock инициализируется тут
    17.     pIrp = IoBuildDeviceIoControlRequest(
    18.         IOCTL_ТВОЙ_КОД,
    19.         pDeviceObject,
    20.         &dwInputParam,
    21.         sizeof(ULONG),
    22.         &dwOutputParam,
    23.         sizeof(ULONG),
    24.         FALSE,
    25.         &kEvent,
    26.         &ioStatusBlock);
    27.  
    28.     if (pIrp == NULL)
    29.         return FALSE;
    30.  
    31.              // Шлем Irp
    32.     ntStatus = IoCallDriver(pDeviceObject, pIrp);
    33.  
    34.    
    35.              // Если пендинг, то...
    36.     if (ntStatus == STATUS_PENDING)
    37.     {
    38.                           // ... ждем евент
    39.         if(KeWaitForSingleObject(
    40.             (PVOID)&kEvent,
    41.             Executive,
    42.             KernelMode,
    43.             FALSE,
    44.             NULL) == STATUS_SUCCESS)
    45.         {
    46.                                       // Ахтунг! Теперь проверяем статус именно в ioStatusBlock!!!!
    47.             if ( !NT_SUCCESS(ioStatusBlock.Status))
    48.                 return FALSE;            
    49.         }        
    50.     }
    51.     else
    52.         if (!NT_SUCCESS(ntStatus))
    53.             return FALSE;
    ЗЫ:Еще можно через ф-ии группы Zw... заслать.
     
  8. Smoke_man

    Smoke_man New Member

    Публикаций:
    0
    Регистрация:
    19 сен 2006
    Сообщения:
    16
    ams007, спасибо за пример! Попробую!
     
  9. ams007

    ams007 New Member

    Публикаций:
    0
    Регистрация:
    28 апр 2007
    Сообщения:
    86
    Smoke_man, НЗ!
     
  10. Smoke_man

    Smoke_man New Member

    Публикаций:
    0
    Регистрация:
    19 сен 2006
    Сообщения:
    16
    Написал так:
    Код (Text):
    1.   PFILE_OBJECT   pFileObject;
    2.   PDEVICE_OBJECT pDeviceObject;
    3.   PIO_STATUS_BLOCK  ioStatusBlock = NULL;
    4.   PIRP pIrpSend;
    5.   PRKEVENT  kEvent = NULL;
    6.   UNICODE_STRING swzSymbolicName;
    7.   ULONG indata,outdata;
    8.  
    9.   RtlInitUnicodeString(&swzSymbolicName,L"\\Device\\NameDevice");
    10.   status = IoGetDeviceObjectPointer(
    11.         &swzSymbolicName,
    12.         FILE_WRITE_DATA|FILE_READ_DATA,
    13.         &pFileObject,
    14.         &pDeviceObject); // получили указатель на этот девайс
    15.  
    16.     if (!NT_SUCCESS(status))
    17.         return false;
    18.    
    19.     KeInitializeEvent( kEvent, NotificationEvent, false ); // евент проинициализировали
    20.    
    21.     pIrpSend = IoBuildDeviceIoControlRequest(
    22.         IOCTL_MYIOCTL,
    23.         pDeviceObject,
    24.         &indata,
    25.         sizeof(ULONG),
    26.         &outdata,
    27.         sizeof(ULONG),
    28.         false,
    29.         (PKEVENT)&kEvent,
    30.         ioStatusBlock);
    31.  
    32.     if (pIrpSend == NULL)
    33.         return false;
    34.  
    35.              
    36.     status = IoCallDriver(pDeviceObject, pIrpSend);
    37.  
    38.     if (status == STATUS_PENDING)
    39.     {
    40.                          
    41.         if(KeWaitForSingleObject(
    42.             (PVOID)&kEvent,
    43.             Executive,
    44.             KernelMode,
    45.             false,
    46.             NULL) == STATUS_SUCCESS)
    47.         {
    48.             if ( !NT_SUCCESS(ioStatusBlock->Status))
    49.                 return false;            
    50.         }        
    51.     }
    52.     else
    53.         if (!NT_SUCCESS(status))
    54.             return false;
    Но при выполнении этого кода происходит перезагрузка, либо синий экран. Где может быть ошибка?
    После тестов заметил - что на рабочем компе работает без проблем, при запуске на промышленном одноплатном компе выдает синий экран. Винда идентичная!
     
  11. ams007

    ams007 New Member

    Публикаций:
    0
    Регистрация:
    28 апр 2007
    Сообщения:
    86
    ошибка тут
    Код (Text):
    1. PIO_STATUS_BLOCK  ioStatusBlock = NULL;
    2. ...
    3.  
    4.  
    5.     pIrpSend = IoBuildDeviceIoControlRequest(
    6.         IOCTL_MYIOCTL,
    7.         pDeviceObject,
    8.         &indata,
    9.         sizeof(ULONG),
    10.         &outdata,
    11.         sizeof(ULONG),
    12.         false,
    13.         (PKEVENT)&kEvent,
    14.         ioStatusBlock);
    надо

    Код (Text):
    1. IO_STATUS_BLOCK  ioStatusBlock = NULL;
    2. ...
    3.  
    4.  
    5.     pIrpSend = IoBuildDeviceIoControlRequest(
    6.         IOCTL_MYIOCTL,
    7.         pDeviceObject,
    8.         &indata,
    9.         sizeof(ULONG),
    10.         &outdata,
    11.         sizeof(ULONG),
    12.         false,
    13.         (PKEVENT)&kEvent,
    14.         &ioStatusBlock);
    кто же за тебя под ioStatusBlock память выделит?)))) Я ж ясно написАл)))
    Та же фигня с event : KEVENT вместо PRKEVENT и операция & в соответствующем месте.
    Это же так очевидно.
     
  12. Smoke_man

    Smoke_man New Member

    Публикаций:
    0
    Регистрация:
    19 сен 2006
    Сообщения:
    16
    Всем спасибо!
     
  13. FoxB

    FoxB Member

    Публикаций:
    0
    Регистрация:
    10 июл 2003
    Сообщения:
    113
    Возникла необходимость читать/писать из/в усб-железку минуя драйвер производителя, т.е. сформировать urb для usbhubю

    есть
    vendor api->vendor dll->vendor sys-> usbhub sys

    надо
    my api->my sys-> usbhub sys

    в my.sys вызов
    -----------------------------------
    NTSTATUS QueryUSB()
    {
    PFILE_OBJECT pFileObject;
    PDEVICE_OBJECT pDeviceObject;
    IO_STATUS_BLOCK ioStatusBlock;
    PIO_STACK_LOCATION irpStack;
    PIRP pIrp;
    KEVENT kEvent;
    UNICODE_STRING swzSymbolicName;
    NTSTATUS ntStatus;
    ULONG Switch = 0;

    struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST urb;

    RtlInitUnicodeString(&swzSymbolicName, L"\\Device\\USBPDO-0");

    // RtlInitUnicodeString(&swzSymbolicName, L"\\\\.\\USB#ROOT_HUB#4&25712375&0#{f18a0e88-c30c-11d0-8815-00a0c906bed8}");
    // RtlInitUnicodeString(&swzSymbolicName, L"USB\\Vid_07f2&Pid_0001&Rev_0001");

    ntStatus = IoGetDeviceObjectPointer(
    &swzSymbolicName,
    FILE_WRITE_DATA|FILE_READ_DATA,
    &pFileObject,
    &pDeviceObject);

    if (!NT_SUCCESS(ntStatus))
    return FALSE;

    KeInitializeEvent( &kEvent, NotificationEvent, FALSE );

    pIrp = IoBuildDeviceIoControlRequest(
    IOCTL_INTERNAL_USB_SUBMIT_URB,
    pDeviceObject,
    NULL,
    NULL,
    NULL,
    NULL,
    TRUE,
    &kEvent,
    &ioStatusBlock);

    if (pIrp == NULL)
    return FALSE;

    // _asm int 3;

    pIrp->IoStatus.Status = STATUS_SUCCESS;
    pIrp->IoStatus.Information = 0;

    irpStack = IoGetCurrentIrpStackLocation (pIrp);

    irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
    irpStack->Parameters.DeviceIoControl.IoControlCode =
    IOCTL_INTERNAL_USB_SUBMIT_URB;

    irpStack->Parameters.Others.Argument1 = (PVOID) &urb;
    memset(&urb, 0, sizeof(_URB_CONTROL_VENDOR_OR_CLASS_REQUEST));

    urb.Hdr.Length = sizeof(_URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
    urb.Hdr.Function = URB_FUNCTION_VENDOR_DEVICE;//URB_FUNCTION_VENDOR_ENDPOINT

    urb.TransferFlags = USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK;
    urb.TransferBufferLength = sizeof(packet.Buffer);
    urb.TransferBuffer = packet.Buffer;

    urb.Request = packet.Request;
    urb.Value = packet.Value;
    urb.Index = packet.Index;

    ntStatus = IoCallDriver(pDeviceObject, pIrp);

    if (ntStatus == STATUS_PENDING)
    {
    if (KeWaitForSingleObject(
    (PVOID) &kEvent,
    Executive,
    KernelMode,
    FALSE,
    NULL) == STATUS_SUCCESS)
    {
    if ( !NT_SUCCESS(ioStatusBlock.Status))
    return FALSE;
    }
    }
    else
    {
    if (!NT_SUCCESS(ntStatus))
    return FALSE;
    }
    return TRUE;
    }
    -----------------------------------

    при вызове IoCallDriver все валится в BSOD со стопом 0х000000D1

    что не так?
     
  14. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    !analyze -v приводить уже не модно?)
    с первого взгляда вроде явных грубых ошибок нет

    UPD: Не уверен, но вроде нужно заменить IoGetCurrentIrpStackLocation на IoGetNextIrpStackLocation, ведь IRP только что создан
     
  15. FoxB

    FoxB Member

    Публикаций:
    0
    Регистрация:
    10 июл 2003
    Сообщения:
    113
    еще одна странность:

    при заполнении irpStack->Parameters.хххх у меня в логе USBTrace эти поля заполнены 0х0
     
  16. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    опять же,
    Ну и, конечно, отладчик в зубы, а лог анализа крешдампа в студию. Без этого будет трудно что-либо сказать
     
  17. DriversDeveloper

    DriversDeveloper Виктор Фисюк

    Публикаций:
    0
    Регистрация:
    15 мар 2008
    Сообщения:
    6
    Адрес:
    Kiev, Ukraine
    Вместо IoGetCurrentIrpStackLocation надо использовать IoGetNextIrpStackLocation.

    Зачем после вызова IoBuildDeviceIoControlRequest еще инициализируются irpStack->MajorFunction и irpStack->Parameters.DeviceIoControl.IoControlCode? Это уже сделала функция IoBuildDeviceIoControlRequest.
     
  18. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    DriversDeveloper
    Ну последнее не критично - значения то верные) Но замечание верное, я пропустил при беглом взгляде.
    А бсод скорее всего из-за IoGetCurrentIrpStackLocation
     
  19. FoxB

    FoxB Member

    Публикаций:
    0
    Регистрация:
    10 июл 2003
    Сообщения:
    113
    Great
    от бсод я избавился - сам накосячил.
    теперь с использованием IoGetCurrentIrpStackLocation после вызова IoCallDriver возвращается STATUS_INVALID_DEVICE_REQUEST

    DriversDeveloper
    использование IoGetNextIrpStackLocation - при вызове IoCallDriver происходит бсод (DRIVER_IRQL_NOT_LESS_OR_EQUAL) .

    под отладчиком сайс

    mov eax,[edx+60] <----- получаем адрес irpStack
    mov dword ptr [eax], 0F <--- IRP_MJ_INTERNAL_DEVICE_CONTROL
    mov dword ptr [eax+0c], 00220003 <--- IOCTL_INTERNAL_USB_SUBMIT_URB
    lea ecx, [esp+2c]
    mov [eax+04], ecx <----- адрес urb

    не пойму почему
    irpStack->Parameters.DeviceIoControl.IoControlCode имеет смещение irpStack->Parameters+0c
    а
    irpStack->Parameters.Others.Argument1 имеет смещение irpStack->Parameters+04

    по юниону Parameters в IRP_STACK_LOCATION они разнесены

    ради интереса добавил
    irpStack->Parameters.Create.Options = 0;

    и оно тоже имеет смещение irpStack->Parameters+04

    Код (ASM):
    1. xor ecx, ecx
    2. mov [eax+04], ecx
     
  20. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    А что изменилось по ср. с кодом, что ты приводил.

    Где? Где анализ багчека? Где !analyze -v?