Передача данных от драйвера клиентской программе через ассинхронные...

Тема в разделе "WASM.NT.KERNEL", создана пользователем hulk45, 1 фев 2007.

  1. hulk45

    hulk45 New Member

    Публикаций:
    0
    Регистрация:
    18 дек 2006
    Сообщения:
    10
    Народ если у кого есть немного времени объясните пожалуйста что в этом коде происходит. Если есть возможность прокоментируйте по строчкам.


    Передача данных от драйвера клиентской программе через ассинхронные запросы к устройству.Особенности генерации и обработки ассинхронных запросов.

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

    OVERLAPPED o;
    PVOID pNotificationData;
    DWORD LastError, dw;
    HANDLE hEvent = CreateEvent (NULL, // default security
    FALSE, // ресетится само
    FALSE, // пока не случилось
    NULL); // безымянное
    HANDLE hDevice = CreateFile (DeviceName, DexiredAccess,
    FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
    OPEN_EXISTING, FILE_FLAG_OVERLAPPED/*важно*/,
    NULL);
    o.hEvent = hEvent;
    for (;;)
    { DeviceIoControl (hDevice, IOCTL_NOTIFY_ME, NULL, 0, pNotificationData,
    MaxDataSize, &dw, &o);
    LastError = GetLastError ();
    if (LastError != STATUS_SUCCESS && LastError != ERROR_IO_PENDING)
    облом;
    WaitForSingleObject (hEvent, MAX_TIMEOUT/*в миллисекундах,
    INFINITE – ждать вечно*/);
    }

    В драйвере по приходу IRP с кодом IOCTL_NOTIFY_ME:

    KIRQL kCancelSpin;
    if (pNotificationIrp)/*глобальный указатель типа PIRP*/
    как-то обработать ситуацию;
    pNotificationIrp = pIrp;
    IoAcquireCancelSpinLock (&kCancelSpin);
    IoSetCancelRoutine (pIrp, CancelIrpProc);
    IoReleaseCancelSpinLock (kCancelSpin);
    IoMarkIrpPending (Irp);
    return STATUS_PENDING;

    void CancelIrpProc (PDEVICE_OBJECT DeviceObject, pPIRP Irp)
    { IoReleaseCancelSpinLock (pIrp->CancelIrql);
    pIrp->IoStatus.Status = STATUS_CANCELLED;
    pIrp->IoStatus.Information = 0;
    IoCompleteRequest (pIrp, IO_NO_INCREMENT);
    }
    В драйвере при наступлении отслеживаемого события:

    PIRP pTmpIrp;
    KIRQL kCancelSpin;
    if (!pNotificationIrp || !MmIsAddressValid (pNotificationIrp))
    return FALSE;
    IoAcquireCancelSpinLock (&kCancelSpin);
    IoSetCancelRoutine (pNotificationIrp, NULL);
    IoReleaseCancelSpinLock (kCancelSpin);
    pNotificationIrp->IoStatus.Information = сколько байт выдаем клиенту;
    pNotificationIrp->IoStatus.Status = STATUS_SUCCESS;
    записываем данные в pNotificationIrp->AssociatedIrp.SystemBuffer;
    pTmpIrp = pNotificationIrp;
    pNotificationIrp = NULL;
    IoCompleteRequest (pTmpIrp, IO_NO_INCREMENT);

    Проблема: если клиентская программа неожиданно завершается, cancel IRP может не произойти и тогда при IoCompleteRequest происходит синий экран. Надо отслеживать жизнедеятельность клиентской программы, например, через именованное событие.
     
  2. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Внимательно не смотрел, но кажется, что кто-то бредил.

    Посмотри http://www.wasm.ru/article.php?article=drvw2k14

    И в DDK есть правильный пример DDK\src\general\event
     
  3. hulk45

    hulk45 New Member

    Публикаций:
    0
    Регистрация:
    18 дек 2006
    Сообщения:
    10
    спасибо прочитал. вроде немного стало понятно.