Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: 1 2 [Все]   Вниз
  Печать  
Автор Тема: Синий экран при обращении к драйверу PCI устройства  (Прочитано 37871 раз)
0 Пользователей и 1 Гость смотрят эту тему.
tuiui
Участник

ru
Offline Offline

« : 21-04-2010 08:00 » 

Здравствуйте, товарищи!

Использовал    Driver Studio 3.2 + VC6 + DDK 2600     для написания драйвера платы PCI. Необходимо было, чтобы драйвер писал в память PCI-платы заданное количество данных по заданному адресу.

Driver Studio создал рыбу драйвера, в код функции записи я написал:
Код:
NTSTATUS MultiplierDevice::Write(KIrp I)
{
NTSTATUS status = STATUS_SUCCESS;

//получаем буфер пользователя. Он передается через Irp.
KMemory Mem(I.Mdl());
PUCHAR pBuffer = (PUCHAR) Mem.MapToSystemSpace();

            //получаем число 4-байтных слов, которое должно быть записано.
ULONG dwTotalSize = I.WriteSize(CURRENT);
ULONG dwBytesWrite = dwTotalSize;

//получаем смещение слова в памяти
ULONG dwWordOffset = IoGetCurrentIrpStackLocation(I)->Parameters.Write.ByteOffset.LowPart;

//пишем заданное число двойных слов    
DataMemory.outd(dwWordOffset,(ULONG*)pBuffer,dwTotalSize);

//возвращаем количество прочитанных слов
I.Information() = DataMemory.Count();
I.Status() = status;

//Обработать следующий IRP-пакет.
            PnpNextIrp(I);

return status;
}

Понимаю, что код очень не красивый. Прошу не ругаться  Краснею

При обращении к драйверу командой WriteFile из приложения вылетает синий экран. Причем только тогда, когда количество записываемых данных больше какого-то определенного значения.

Пробовал вместо драйвера писать данные в txt-файл.  Все Ок. Поэтому пришел к выводу, что ошибка в коде драйвере.

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

Драйверы раньше никогда не писал. Код написан по примерам из статей.

Заранее благодарен за помощь
« Последнее редактирование: 21-04-2010 08:13 от Алексей1153++ » Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 21-04-2010 13:44 » 

так.
1. то что вы нагенерили только что - стирайте с винта нафиг))))
 
2. затем сгенерите то же самое, но в визарде нумеги(в самом начале) выбирайте пункт "не использовать классы нумеги" (или как-то так) - получится код на чистом Си.

3. и попробуйте еще раз) после этого - велкам)

PS объяснять почему "1" и "2" - уже сто раз писал) не стану повторятся)
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
tuiui
Участник

ru
Offline Offline

« Ответ #2 : 22-04-2010 05:15 » 

))) Я знал, что Ochkarik посоветует мне именно это. Ну что ж. Попробуем. Отпишусь попозже
Записан
tuiui
Участник

ru
Offline Offline

« Ответ #3 : 22-04-2010 06:21 » 

Сделал все, как вы сказали: сгенерировал новый код на чистом С. Если я правильно понял, свой код для записи в устройство надо добавлять в метод MultiplierReadDispatch (multiplier - название устройства) ?

Код:
NTSTATUS MultiplierWriteDispatch(
    IN  PDEVICE_OBJECT  DeviceObject,
    IN  PIRP            Irp
    )
{
    PMULTIPLIER_DEVICE_EXTENSION    deviceExtension;
    NTSTATUS                        status;
    PIO_STACK_LOCATION              irpStack;
    PVOID                           writeBuffer;
    ULONG                           writeLength;

    MultiplierDebugPrint(DBG_IO, DBG_TRACE, __FUNCTION__"++. IRP %p", Irp);

    deviceExtension = (PMULTIPLIER_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

    status = MultiplierCheckIoLock(&deviceExtension->IoLock, Irp);
    if (!NT_SUCCESS(status) || (status == STATUS_PENDING))
    {
        MultiplierDebugPrint(DBG_IO, DBG_WARN, __FUNCTION__"--. IRP %p STATUS %x", Irp, status);

        return status;
    }

    // Get our IRP stack location
    irpStack = IoGetCurrentIrpStackLocation(Irp);

    // Get the write buffer length
    writeLength = irpStack->Parameters.Write.Length;
    if (writeLength == 0)
    {
        // just complete 0 length request
        status = STATUS_SUCCESS;

        Irp->IoStatus.Information = 0;
        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);

        MultiplierDecrementIoCount(&deviceExtension->IoLock);

        MultiplierDebugPrint(DBG_IO, DBG_WARN, __FUNCTION__"--. IRP %p, STATUS %x", Irp, status);

        return status;
    }

    writeBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);

    MultiplierDebugPrint(DBG_IO, DBG_TRACE, __FUNCTION__"--. IRP %p STATUS %x", Irp, status);

    return status;

}

Пока что свой код не добавлял. Кстати, компилировать эту "рыбу" надо с помощью DDK Built.exe utulity? Просто получается и просто по F7. Сделал и так, и так. В обоих случаях приложение НЕ находит драйвер по символической ссылке "Multiplier0", но находит "Multiplier".

И скажите, код из моего первого примера подойдет для этого случая? Просто примеров для чистого С не нашел


Записан
tuiui
Участник

ru
Offline Offline

« Ответ #4 : 22-04-2010 07:53 » 

И еще одна странная вещь. Когда из приложения

Открываю драйвер => получаю handle => WriteFile(handle, ... ) => Закрываю приложение

Комп перезагружается молча

Если перед закрытием приложения освободить хэндл - все ок. И это при том, что функции записи в драйвере еще нет.

Буду очень признателен за пример кода метода записи в память устройства
Записан
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 22-04-2010 08:09 » 

MultiplierWriteDispatch - что-то какой-то левый код получился. Может стоит без студии взять и руками написать?
Записан
tuiui
Участник

ru
Offline Offline

« Ответ #6 : 22-04-2010 08:37 » 

дело в том, что опыта нет. Если я правильно понимаю, студия генерит каркас, где все "обслуживающие" функции создаются в правильном хорошем виде, и мне лезть туда не надо.  А надо только в методы, отвечающий за запись и чтение, вписать несколько строк своего кода (собственно, запись и чтение). Поправьте меня, если я не прав. Код, сгенерированный с использованием С++ я обрабатывал именно так и все работало. Правда BSOD вылетал. По совету Ochkarik'a сделал все на чистом С. Теперь не знаю, куда и какой код писать.
Записан
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 22-04-2010 08:54 » 

Ну раз уж вы решили действовать через студию, то я вряд ли смогу сказать что и как. Это Ochkarik'а надо ждать. Но студия, вообще говоря, не компенсирует недостаток опыта. Лучше учиться, разбираться, чтобы понимать что делаешь.
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 22-04-2010 10:14 » 

resource, студия - это не страшно) студия в режиме чистого Си - просто рыбу генерит. там нет ничего кроме функций DDK.
это в режиме классов она свои обертки использует.(почему я против них и выступал)))

tuiui, угу. все почти так)
1. когда вы генерили рыбу - там был пункт, который позволял задать требуемые ресурсы для устройства. (в том числе память, прерывания, и т.д.) вы это сделали?
2. писать по адресу - что имеется в виду? там стоит отображаемая память или DMA ресурс? если первое то см. пункт 1. в настройках визарда надо вставить Dispatch процедуры(это фактически пользовательский интерфейс драйвера) и связать их с зарезервированным ранее ресурсом отображаемой памяти.
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
tuiui
Участник

ru
Offline Offline

« Ответ #9 : 22-04-2010 10:23 » 

Спасибо.
Давайте по порядку.

При создании проекта в DS я задал ресурс DataMemory типа Memory (не DMA).

Сгенерировал код на чистом Си.

Теперь, видимо надо сделать с этим кодом что-то такое, чтобы при обращении из приложения командой
WriteFile(DriberHandle, Buffer, Count, Overlapped) -  (примерно)
В эту самую память DataMemory писался буфер Buffer, в количестве Count начиная со смещения, заданного в Overlapped.

Мне почему-то кажется, что это вещь очень стандартная.
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #10 : 22-04-2010 10:29 » 

скомпилите еще раз. но помимо ресурсов - задайте создание тестового приложения.
задайте создание Dispatch процедур (IO control или Read/Write)
там же в настройках визарда можно связать заданную функцию интерфейса драйвера ( Dispatch процедур (IO control или Read/Write) и соответствующий ресурс.

поиграйтесь настройками несколько раз - то что вам надо, делается там исключительно визардом, даже дописывать кода не надо)
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 22-04-2010 10:31 » 

жаль у меня DS не стоит... и студия несовместимая. даже скриншотов не могу сделать)
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
tuiui
Участник

ru
Offline Offline

« Ответ #12 : 22-04-2010 10:35 » 

)) Жаль. Так вот я увязал IRP_MJ_READ и IRP_MJ_WRITE с этой самой памятью DataMemory, которую задал в ресурсах. Я правильно понимаю, что обработчики этих IRP называются
MultiplierReadDispatch и MultiplierWriteDispatch? Если да, то вот код, который я получил (каким мне выдала его студия)

Код:
NTSTATUS MultiplierWriteDispatch(
    IN  PDEVICE_OBJECT  DeviceObject,
    IN  PIRP            Irp
    )
{
    PMULTIPLIER_DEVICE_EXTENSION    deviceExtension;
    NTSTATUS                        status;
    PIO_STACK_LOCATION              irpStack;
    PVOID                           writeBuffer;
    ULONG                           writeLength;

    MultiplierDebugPrint(DBG_IO, DBG_TRACE, __FUNCTION__"++. IRP %p", Irp);

    deviceExtension = (PMULTIPLIER_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

    status = MultiplierCheckIoLock(&deviceExtension->IoLock, Irp);
    if (!NT_SUCCESS(status) || (status == STATUS_PENDING))
    {
        MultiplierDebugPrint(DBG_IO, DBG_WARN, __FUNCTION__"--. IRP %p STATUS %x", Irp, status);

        return status;
    }

    // Get our IRP stack location
    irpStack = IoGetCurrentIrpStackLocation(Irp);

    // Get the write buffer length
    writeLength = irpStack->Parameters.Write.Length;
    if (writeLength == 0)
    {
        // just complete 0 length request
        status = STATUS_SUCCESS;

        Irp->IoStatus.Information = 0;
        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);

        MultiplierDecrementIoCount(&deviceExtension->IoLock);

        MultiplierDebugPrint(DBG_IO, DBG_WARN, __FUNCTION__"--. IRP %p, STATUS %x", Irp, status);

        return status;
    }

    writeBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);

    MultiplierDebugPrint(DBG_IO, DBG_TRACE, __FUNCTION__"--. IRP %p STATUS %x", Irp, status);
    
return status;
}

Для чтения - аналогично.

Просто я тут не вижу самого "акта" записи. Какие-то проверки, какие-то обработки ошибок. А где же запись?  Здесь была моя ладья...

Может DS "забыла" вставить строчки с командами записи?
« Последнее редактирование: 22-04-2010 11:50 от tuiui » Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #13 : 22-04-2010 13:46 » 

нет, по моему что то вы недоделали...
можно вас попросить скриншоты визарда по шагам  выложить?
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
tuiui
Участник

ru
Offline Offline

« Ответ #14 : 23-04-2010 05:24 » 

Вот скрины Визарда

* Шаг 1 - Шаг 5.rar (226.77 Кб - загружено 940 раз.)
Записан
tuiui
Участник

ru
Offline Offline

« Ответ #15 : 23-04-2010 05:25 » 

продолжение

* Шаг 6 - Шаг 13.rar (386.8 Кб - загружено 971 раз.)
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #16 : 23-04-2010 09:54 » 

блин. третий раз ответ пишу третий раз случайно окно закрываю)))

экран 4 - попробуйте вместо ручного задания ID, сразу выбрать установленную карту PCI. вроде бы студия сама ресурсы умела находить.

экран 5 - какие ресурсы еще выбрать можно? i/o порты, прерывания, DMA, отображаемая память?

экран 7 - для READ/WRITE вместо direct выбрать ,буферизированный ввод. формирование очереди - отключить.
добавить два IOCTL один на чтение второй на запись того же региона. тоже с буферизацией и без очереди (будет проще разбираться).

PS видимо, из за включения очереди MultiplierWriteDispatch не завершается IoCompleteRequest-ом... я собственно для PCI не пробовал генерить (или уже не помню, давно было), но делал это для USB и 1394. в обоих случаях мне в IOCTL давали доступ с тестового приложения на запись/чтение  указанных ресурсов железа...
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
tuiui
Участник

ru
Offline Offline

« Ответ #17 : 23-04-2010 10:47 » 

Экран 5 - можно выбрать только Память, Порты и DMA

Экран 7 - выбирается только Direct. В остальных случаях ругается и сама устанавливает Direct. Создал еще 2 IOCTL. Тоже не разрешает беферизацию выбирать. Пишет, что для этого типа ресурса только direct in и direct out

сгенерировал...

вид тот же. Может, я не тот файл смотрю - "iorw.c" ведь надо смотреть?

Вы рекомендуете использовать только IOCTL? Без MJ_READ/MJ_WRITE?
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #18 : 23-04-2010 11:56 » 

файл тот. там должны быть обработчики и READ/WRITE и IOCTL в конце.
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
tuiui
Участник

ru
Offline Offline

« Ответ #19 : 23-04-2010 12:08 » 

Да. Вот они

Код:
///////////////////////////////////////////////////////////////////////////////////////////////////
//  MultiplierWriteDispatch
//      Handled incoming write requests
//
//  Arguments:
//      IN  DeviceObject
//              Device object for our device
//
//      IN  Irp
//              The write IRP to handle
//
//  Return Value:
//      NT status code
//
NTSTATUS MultiplierWriteDispatch(
    IN  PDEVICE_OBJECT  DeviceObject,
    IN  PIRP            Irp
    )
{
    PMULTIPLIER_DEVICE_EXTENSION    deviceExtension;
    NTSTATUS                        status;
    PIO_STACK_LOCATION              irpStack;
    PVOID                           writeBuffer;
    ULONG                           writeLength;

    MultiplierDebugPrint(DBG_IO, DBG_TRACE, __FUNCTION__"++. IRP %p", Irp);

    deviceExtension = (PMULTIPLIER_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

    status = MultiplierCheckIoLock(&deviceExtension->IoLock, Irp);
    if (!NT_SUCCESS(status) || (status == STATUS_PENDING))
    {
        MultiplierDebugPrint(DBG_IO, DBG_WARN, __FUNCTION__"--. IRP %p STATUS %x", Irp, status);

        return status;
    }

    // Get our IRP stack location
    irpStack = IoGetCurrentIrpStackLocation(Irp);

    // Get the write buffer length
    writeLength = irpStack->Parameters.Write.Length;
    if (writeLength == 0)
    {
        // just complete 0 length request
        status = STATUS_SUCCESS;

        Irp->IoStatus.Information = 0;
        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);

        MultiplierDecrementIoCount(&deviceExtension->IoLock);

        MultiplierDebugPrint(DBG_IO, DBG_WARN, __FUNCTION__"--. IRP %p, STATUS %x", Irp, status);

        return status;
    }

    writeBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);

    MultiplierDebugPrint(DBG_IO, DBG_TRACE, __FUNCTION__"--. IRP %p STATUS %x", Irp, status);

    return status;
}

 MultiplierReadDispatch - аналогичный

А это MultiplierDeviceIoControlDispatch
Код:
///////////////////////////////////////////////////////////////////////////////////////////////////
//  MultiplierDeviceIoControlDispatch
//      Handled incoming IOCTL requests
//
//  Arguments:
//      IN  DeviceObject
//              Device object for our device
//
//      IN  Irp
//              The IOCTL IRP to handle
//
//  Return Value:
//      NT status code
//
NTSTATUS MultiplierDeviceIoControlDispatch(
    IN  PDEVICE_OBJECT  DeviceObject,
    IN  PIRP            Irp
    )
{
    PIO_STACK_LOCATION              irpStack;
    NTSTATUS                        status;
    PMULTIPLIER_DEVICE_EXTENSION    deviceExtension;
    PVOID                           inputBuffer;
    ULONG                           inputLength;
    PVOID                           outputBuffer;
    ULONG                           outputLength;

    MultiplierDebugPrint(DBG_IO, DBG_TRACE, __FUNCTION__"++. IRP %p", Irp);

    deviceExtension = (PMULTIPLIER_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

    // Get our IRP stack location
    irpStack = IoGetCurrentIrpStackLocation(Irp);

    // Get the buffer lengths
    inputLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
    outputLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;

    switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
    {

    case IOCTL_800:
        MultiplierDebugPrint(DBG_IO, DBG_INFO, __FUNCTION__": IOCTL_800");

        status = MultiplierCheckIoLock(&deviceExtension->IoLock, Irp);
        if (!NT_SUCCESS(status) || (status == STATUS_PENDING))
        {
            MultiplierDebugPrint(DBG_IO, DBG_WARN, __FUNCTION__"--. IRP %p STATUS %x", Irp, status);

            return status;
        }

        // direct ioctl
        inputBuffer = Irp->AssociatedIrp.SystemBuffer;
        if (Irp->MdlAddress != NULL)
        {
            outputBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
        }
        else
        {
            outputBuffer = NULL;
        }
        break;

    case IOCTL_801:
        MultiplierDebugPrint(DBG_IO, DBG_INFO, __FUNCTION__": IOCTL_801");

        status = MultiplierCheckIoLock(&deviceExtension->IoLock, Irp);
        if (!NT_SUCCESS(status) || (status == STATUS_PENDING))
        {
            MultiplierDebugPrint(DBG_IO, DBG_WARN, __FUNCTION__"--. IRP %p STATUS %x", Irp, status);

            return status;
        }

        // direct ioctl
        inputBuffer = Irp->AssociatedIrp.SystemBuffer;
        if (Irp->MdlAddress != NULL)
        {
            outputBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
        }
        else
        {
            outputBuffer = NULL;
        }
        break;

    default:
        status = STATUS_INVALID_DEVICE_REQUEST;
        Irp->IoStatus.Status = status;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);
        break;
    }

    MultiplierDebugPrint(DBG_IO, DBG_TRACE, __FUNCTION__"--. IRP %p STATUS %x", Irp, status);

    return status;
}

Может, вручную дописать туда что надо. Знать бы еще, что надо... Или переустановить DS. Или версию взять другую...
« Последнее редактирование: 23-04-2010 12:10 от tuiui » Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #20 : 23-04-2010 12:10 » 

нашел тут у себя фрагменты DS....
судя по ним...
у вас должен быть код:
файл WDMDriver.c
процедура $$ProjectName$$StartDevice()
в ней
    // Get our current IRP stack location
    irpStack = IoGetCurrentIrpStackLocation(Irp);
$$INCLUDE PowerPnp\startres.inc

из "startres.inc" копируется код инициализации ресурсов PCI.
Код:
$$COMMENT Resource allocation code

    // Do whatever initialization needed when starting the device:
    // gather information about it,  update the registry, etc.
    // At this point, the lower level drivers completed the IRP
    if ((irpStack->Parameters.StartDevice.AllocatedResources != NULL) &&
        (irpStack->Parameters.StartDevice.AllocatedResourcesTranslated != NULL))
    {
        // Parameters.StartDevice.AllocatedResources points to a
        // CM_RESOURCE_LIST describing the hardware resources that
        // the PnP Manager assigned to the device. This list contains
        // the resources in raw form. Use the raw resources to program
        // the device.

        partialResourceList =
            &irpStack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;

        resource = &partialResourceList->PartialDescriptors[0];

        // Parameters.StartDevice.AllocatedResourcesTranslated points
        // to a CM_RESOURCE_LIST describing the hardware resources that
        // the PnP Manager assigned to the device. This list contains
        // the resources in translated form. Use the translated resources
        // to connect the interrupt vector, map I/O space, and map memory.

        partialResourceListTranslated =
            &irpStack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;

        resourceTrans = &partialResourceListTranslated->PartialDescriptors[0];
$$IFDEF PORT_COUNT

        // reset the total port count
        portCount = 0;
$$ENDIF
$$IFDEF MEMORY_COUNT

        // reset the total memory range count
        memCount = 0;
$$ENDIF

        // search the resources
        for (ii = 0;
             ii < partialResourceList->Count;
             ++ii, ++resource, ++resourceTrans)
        {

            switch (resource->Type)
            {
            case CmResourceTypePort:
                $$ProjectName$$DebugPrint(DBG_PNP, DBG_INFO,  "Resource Type Port");
                $$ProjectName$$DebugPrint(DBG_PNP, DBG_INFO, "Port.Start %I64x", resource->u.Port.Start.QuadPart);
                $$ProjectName$$DebugPrint(DBG_PNP, DBG_INFO, "Port.Length %x", resource->u.Port.Length);
$$IFDEF PORT_COUNT

                switch (portCount)
                {
$$DEFINE INDEX = 0
$$WHILE ($$INDEX$$ < $$PORT_COUNT$$)
$$DEFINE PORT_NAME = @(PORT$$INDEX$$)
                case $$INDEX$$:
                    if (resourceTrans->Type == CmResourceTypePort)
                    {
                        DeviceExtension->b$$PORT_NAME$$IsIo = TRUE;

                        DeviceExtension->$$PORT_NAME$$Length = resourceTrans->u.Port.Length;
                        DeviceExtension->b$$PORT_NAME$$Mapped = (resourceTrans->Flags & CM_RESOURCE_PORT_IO) == 0;
                        if (DeviceExtension->b$$PORT_NAME$$Mapped)
                        {
                            DeviceExtension->$$PORT_NAME$$Base = (PUCHAR)MmMapIoSpace(
                                                                    resourceTrans->u.Port.Start,
                                                                    resourceTrans->u.Port.Length,
                                                                    MmNonCached
                                                                    );
                        }
                        else
                        {
                            DeviceExtension->$$PORT_NAME$$Base = (PUCHAR)resourceTrans->u.Port.Start.QuadPart;
                        }
                    }
                    else
                    {
                        ASSERT(resourceTrans->Type == CmResourceTypeMemory);

                        DeviceExtension->b$$PORT_NAME$$IsIo = FALSE;
                        DeviceExtension->b$$PORT_NAME$$Mapped = TRUE;

                        DeviceExtension->$$PORT_NAME$$Length = resourceTrans->u.Memory.Length;
                        DeviceExtension->$$PORT_NAME$$Base = (PUCHAR)MmMapIoSpace(
                                                            resourceTrans->u.Memory.Start,
                                                            resourceTrans->u.Memory.Length,
                                                            MmNonCached
                                                            );
                    }
                    break;
$$UNDEF PORT_NAME
$$ASSIGN INDEX = $$INDEX$$ + 1
$$ENDWHILE
$$UNDEF INDEX
                default:
                    $$ProjectName$$DebugPrint(DBG_PNP, DBG_INFO,  "Extra Port");
                    break;
                }

                ++portCount;
$$ENDIF // PORT_COUNT
                break;
            case CmResourceTypeMemory:
                $$ProjectName$$DebugPrint(DBG_PNP, DBG_TRACE, "Resource Type Memory");
                $$ProjectName$$DebugPrint(DBG_PNP, DBG_TRACE, "Memory.Start %I64x", resource->u.Memory.Start.QuadPart);
                $$ProjectName$$DebugPrint(DBG_PNP, DBG_TRACE, "Memory.Length %x", resource->u.Memory.Length);
$$IFDEF MEMORY_COUNT

                switch (memCount)
                {
$$DEFINE INDEX = 0
$$WHILE ($$INDEX$$ < $$MEMORY_COUNT$$)
$$DEFINE MEMORY_NAME = @(MEMORY$$INDEX$$)
                case $$INDEX$$:
                    if (resourceTrans->Type == CmResourceTypeMemory)
                    {
                        DeviceExtension->b$$MEMORY_NAME$$IsIo = FALSE;
                        DeviceExtension->b$$MEMORY_NAME$$Mapped = TRUE;

                        DeviceExtension->$$MEMORY_NAME$$Length = resourceTrans->u.Memory.Length;
                        DeviceExtension->$$MEMORY_NAME$$Base = (PUCHAR)MmMapIoSpace(
                                                            resourceTrans->u.Memory.Start,
                                                            resourceTrans->u.Memory.Length,
                                                            MmNonCached
                                                            );
                    }
                    else
                    {
                        ASSERT(resourceTrans->Type == CmResourceTypePort);

                        DeviceExtension->b$$MEMORY_NAME$$IsIo = TRUE;

                        DeviceExtension->$$MEMORY_NAME$$Length = resourceTrans->u.Port.Length;
                        DeviceExtension->b$$MEMORY_NAME$$Mapped = (resourceTrans->Flags & CM_RESOURCE_PORT_IO) == 0;
                        if (DeviceExtension->b$$MEMORY_NAME$$Mapped)
                        {
                            DeviceExtension->$$MEMORY_NAME$$Base = (PUCHAR)MmMapIoSpace(
                                                                    resourceTrans->u.Port.Start,
                                                                    resourceTrans->u.Port.Length,
                                                                    MmNonCached
                                                                    );
                        }
                        else
                        {
                            DeviceExtension->$$MEMORY_NAME$$Base = (PUCHAR)resourceTrans->u.Port.Start.QuadPart;
                        }
                    }
                    break;
$$UNDEF MEMORY_NAME
$$ASSIGN INDEX = $$INDEX$$ + 1
$$ENDWHILE
$$UNDEF INDEX
                default:
                    $$ProjectName$$DebugPrint(DBG_PNP, DBG_INFO,  "Extra Memory Range");
                    break;
                }

                ++memCount;
$$ENDIF // MEMORY_COUNT
                break;
            case CmResourceTypeInterrupt:
                $$ProjectName$$DebugPrint(DBG_PNP, DBG_TRACE, "Resource Type Interrupt");
                $$ProjectName$$DebugPrint(DBG_PNP, DBG_TRACE, "Interrupt.Level %x", resourceTrans->u.Interrupt.Level);
                $$ProjectName$$DebugPrint(DBG_PNP, DBG_TRACE, "Interrupt.Vector %x", resourceTrans->u.Interrupt.Vector);
                $$ProjectName$$DebugPrint(DBG_PNP, DBG_TRACE, "Interrupt.Affinity %x\n", resourceTrans->u.Interrupt.Affinity);
$$IFDEF INTERRUPT

                DeviceExtension->$$ProjectName$$InterruptVector = resourceTrans->u.Interrupt.Vector;
                DeviceExtension->$$ProjectName$$InterruptLevel = (KIRQL)resourceTrans->u.Interrupt.Level;
                DeviceExtension->$$ProjectName$$InterruptAffinity = resourceTrans->u.Interrupt.Affinity;
                DeviceExtension->b$$ProjectName$$InterruptShared = resourceTrans->ShareDisposition == CmResourceShareShared;
                DeviceExtension->$$ProjectName$$InterruptMode =
                    (resourceTrans->Flags == CM_RESOURCE_INTERRUPT_LATCHED) ? Latched : LevelSensitive;
$$ENDIF // INTERRUPT
                break;
            default:
                $$ProjectName$$DebugPrint(DBG_PNP, DBG_TRACE, "Unknown Resource Type %x", resourceTrans->Type);
                break;
            }
        }
    }

    //*****************************************************************
    //*****************************************************************
    // TODO: check that all required resources have been allocated
    //*****************************************************************
    //*****************************************************************
$$IFDEF PORT_COUNT

    if (portCount < $$PORT_COUNT$$)
    {
        return STATUS_DEVICE_CONFIGURATION_ERROR;
    }
$$DEFINE INDEX = 0
$$WHILE ($$INDEX$$ < $$PORT_COUNT$$)
$$DEFINE PORT_NAME = @(PORT$$INDEX$$)
   
    if (DeviceExtension->$$PORT_NAME$$Base == NULL)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }
$$UNDEF PORT_NAME
$$ASSIGN INDEX = $$INDEX$$ + 1
$$ENDWHILE
$$UNDEF INDEX
$$ENDIF // PORT_COUNT
$$IFDEF MEMORY_COUNT

    if (memCount < $$MEMORY_COUNT$$)
    {
        return STATUS_DEVICE_CONFIGURATION_ERROR;
    }
$$DEFINE INDEX = 0
$$WHILE ($$INDEX$$ < $$MEMORY_COUNT$$)
$$DEFINE MEMORY_NAME = @(MEMORY$$INDEX$$)
   
    if (DeviceExtension->$$MEMORY_NAME$$Base == NULL)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }
$$UNDEF MEMORY_NAME
$$ASSIGN INDEX = $$INDEX$$ + 1
$$ENDWHILE
$$UNDEF INDEX
$$ENDIF // MEMORY_COUNT
$$IFDEF INTERRUPT

    if (DeviceExtension->$$ProjectName$$InterruptVector == 0)
    {
        return STATUS_DEVICE_CONFIGURATION_ERROR;
    }
$$ENDIF // INTERRUPT

вам нужен ресурс CmResourceTypeMemory. после инициализации адреса и длинна
DeviceExtension->$$MEMORY_NAME$$Base
DeviceExtension->$$MEMORY_NAME$$Length
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
tuiui
Участник

ru
Offline Offline

« Ответ #21 : 23-04-2010 12:15 » 

Файла этого нет (
И такого типа ресурсов нет
А размер и базовый адрес имеющейся памяти инициализируется вроде нормально.
В структуре DeviceExtension он присутствует. Я пробовал делать заглушку. Из приложения выполнял WriteFile, а в драйвере сделал, чтобы он возвращал размер памяти. Все ок.

То есть в драйвере, кажется, все имеется для записи. И указатель на буфер и базовый адрес памяти, и размер записываемого буфера. Не хватает только собственно записи - передачи запроса ниже к аппаратуре  Здесь была моя ладья...

Может у нас разные версии Driver Studio? Может, в новой версии что-то поменялось.
« Последнее редактирование: 23-04-2010 12:20 от tuiui » Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #22 : 23-04-2010 12:41 » 

нет, сейчаспроинсталировал, действительно... не дописывает... абыдно)
ну тогда остается только:
memcpy() вписать)
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #23 : 23-04-2010 12:43 » 

студию фтопку   Улыбаюсь
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #24 : 23-04-2010 12:47 » 

resource, ша в топку то?) я пол года гемороился пока в ручную это делал)
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
tuiui
Участник

ru
Offline Offline

« Ответ #25 : 23-04-2010 17:12 » 

)) Ochkarik, я рад, что мы пришли к общему результату. Но можно ли поподробнее насчет того, что именно вписать и куда ))
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #26 : 23-04-2010 18:07 » 

по общей идее, если у вас ресурс отображаемой памяти. то вам надо просто скопировать память. а вот откуда и куда - надо вспоминать...
флаги METHOD_IN_DIRECT, METHOD_OUT_DIRECT не помню какой в какую сторону.
http://msdn.microsoft.com/en-us/library/ff558709(VS.85).aspx
или в read/write выставить соответствующие....
вам надо сделать memcpy() из буфера получаемого от приложения в отображаемую память (DeviceExtension->$$MEMORY_NAME$$Base и DeviceExtension->$$MEMORY_NAME$$Length)
например в MultiplierWriteDispatch - вроде где пользовательский буфер - понятно?)


ЗЫ насчет того что CmResourceTypeMemory- "И такого типа ресурсов нет", это очень подозрительно. а какой естЬ?)
вам точно отображаемая память нужна?) драйвер вообще подошел к железке? вы его проинсталировали?
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
tuiui
Участник

ru
Offline Offline

« Ответ #27 : 26-04-2010 04:59 » 

CmResourceTypeMemory - я считал, что вы имеете в виду тип ресурса в визарде студии )) Типа Memory, Port, DMA и еще CmResourceTypeMemory )) Видимо, я неправильно понял. Будем вставлять memcpy(). 
Записан
tuiui
Участник

ru
Offline Offline

« Ответ #28 : 26-04-2010 09:20 » 

Блин... Не могу никак присобачить туда этот memcpy(). Помогите кто-нибудь ))
 
У memcpy() в качестве параметров:

- адрес источника. Это понятно. Его мне выдала студия.
Код:
writeBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);

- количество данных. Тоже понятно.
Код:
writeLength = irpStack->Parameters.Write.Length;

- адрес назначения... Как его получить?! Как узнать адрес, в который отображена моя память?

Вот бы мне пример кода ) Буду счастлив беспредельно.
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #29 : 26-04-2010 14:39 » 

адрес-длинна:
deviceExtension->_____Base
deviceExtension->_____Length
у вас где то в коде примерно так должно быть.
ищите процедуру StartDevice() (она вызывается по IRP_MJ_PNP+IRP_MN_START_DEVICE)
в ней должен быть код похожий на https://forum.shelek.ru/index.php/topic,24191.msg233624.html#msg233624
этот код как раз и инициализирует отображаемую память.
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
tuiui
Участник

ru
Offline Offline

« Ответ #30 : 27-04-2010 10:27 » 

Спасибо. После долгих стараний наконец что-то родилось:
Код:
NTSTATUS MultiplierCWriteDispatch(
    IN  PDEVICE_OBJECT  DeviceObject,
    IN  PIRP            Irp
    )
{
    PMULTIPLIERC_DEVICE_EXTENSION   deviceExtension;
    NTSTATUS                        status;
    PIO_STACK_LOCATION              irpStack;
    PVOID                           writeBuffer;
    ULONG                           writeLength;    
    ULONG                           byteOffset;
    PVOID                           Address;
    
deviceExtension = (PMULTIPLIERC_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
    
status = MultiplierCCheckIoLock(&deviceExtension->IoLock, Irp);
    if (!NT_SUCCESS(status) || (status == STATUS_PENDING))
    {
        return status;
    }    

irpStack = IoGetCurrentIrpStackLocation(Irp);    
    
//Получаем количество данных для записи
    writeLength = irpStack->Parameters.Write.Length;
    if (writeLength == 0)
    {        
        status = STATUS_SUCCESS;
        Irp->IoStatus.Information = 0;
        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        MultiplierCDecrementIoCount(&deviceExtension->IoLock);
        return status;
    }

//Получаем адрес буфера для чтения  
writeBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);    

//Получаем смещение байта
byteOffset = irpStack->Parameters.Write.ByteOffset.LowPart;

//Получаем адрес для записи
    Address = deviceExtension->DataMemoryBase+byteOffset*4;

//Запись
memcpy(Address, writeBuffer, writeLength*4);

    //Возвращаем количество записанных слов
status = STATUS_SUCCESS;
    Irp->IoStatus.Information = writeLength;
    Irp->IoStatus.Status = status;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    MultiplierCDecrementIoCount(&deviceExtension->IoLock);
return status;  
}

И вот опять пришли к тому, с чего все началось. Только теперь имеем чистый C. Драйвер установился, прекрасно пишет небольшие объемы данных. Но при попытке записать в устройство более 150 двойных слов - синий экран (((

В синем экране:

0x50 PAGE_FAULT_IN_NONPAGED_AREA

Ошибочное обращение к области памяти в системном адресном пространстве

Параметры Описание
1 Адрес, обращение по которому вызвало сбой (некоторое значение)
2 Код доступа при возникновении ошибки 0 — чтение, 1 — запись (у меня 0)
3 Адрес инструкции, из которой был осуществлен ошибочный доступ (некоторое значение)
4 Зарезервировано (0)

Значит ошибка при ЧТЕНИИ. При чтении буфера, очевидно ) Наверняка я с синтаксисом накосячил.
« Последнее редактирование: 27-04-2010 12:46 от tuiui » Записан
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #31 : 27-04-2010 13:42 » 

Цитата
memcpy(Address, writeBuffer, writeLength*4);

Я постов предыдущих много пропустил, и возможно поэтому не пойму, откуда тут взялся memcpy.
Ошибка не из-за этого, но всё-равно надо писать RtlCopyMemory.

По поводу самой ошибки. Вопрос - зачем умножать на 4 ?
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #32 : 27-04-2010 16:34 » 

   //Получаем смещение байта
   byteOffset = irpStack->Parameters.Write.ByteOffset.LowPart;
-> это что? и зачем?)

и почему действительно *4?

при доступе обязательно проверяйте выход за пределы выделенной вам памяти.  в драйвере ВСЕГДА надо проверять все что приходит от приложения.  в не зависимости от того что приложение тоже вами написано)

RtlCopyMemory - справедливо. действительно лучше пользовать ее.
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #33 : 27-04-2010 20:44 » 

Ну не дожидаясь ответа от ТС, я сам себе так понимаю, что writeLength это размер write-буфера. Умножаем на 4 (зачем? а зачем тигру полоски? он же не зебра) и оказываемся за пределами буфера
« Последнее редактирование: 27-04-2010 20:55 от resource » Записан
tuiui
Участник

ru
Offline Offline

« Ответ #34 : 28-04-2010 05:12 » 

1. ByteOffset - это смещение относительно начала памяти устройства. Другими словами, это адрес в памяти устройства, с которого начинается запись. Передается этот параметр через структуру overlapped при вызове WriteFile (последний параметр). Мне же надо как-то из приложения передавать этот адрес.

2. Умножение на 4. Дело в том, что плата обменивается с памятью 4-байтными словами. А смещение поступает в байтах. Я хочу, чтобы смещение тоже задавалось двойными словами. То есть если напишем WriteFile(п1,п2,п3,8), то запись должна начинаться с 8-го двойного слова. Поэтому умножаю на 4. С размером буфера - то же самое. Если пишу 20, то он записывает 20 байт. А мне надо 20 двойных слов.

3. RtlCopyMemory - пробовал. Тот же результат.

Может указатель на буфер пользователя делать такого типа, чтобы RtlCopyMemory понимала, что речь идет о буфере а двойными словами

ЗЫ Скорее всего, как раз в этом *4 ошибка и есть. Но не должно же быть, вроде... Думаю, надо разобраться подробно, что происходит при вызове WriteFile, кто и как наращивает счетчики адресов. Может, если в качестве источника в WriteFile указывать массив двойных слов, то не надо умножать на 4.
« Последнее редактирование: 28-04-2010 05:32 от tuiui » Записан
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #35 : 28-04-2010 05:59 » 

Про слова, двойные слова, тройные или еще какие - это вариант гиблый, т.к. менеджеру ввода/вывода глубоко наплевать на все эти слова (это к вопросу о том, что происходит при вызове WriteFile). Честно говоря, такой фокус вижу впервые. На будущее, если в документации написано "размер в байтах", значит надо передавать размер в байтах. Ну можно же написать себе макрос и спокойно им пользоваться
Записан
tuiui
Участник

ru
Offline Offline

« Ответ #36 : 28-04-2010 07:50 » 

Благодарю за помощь. Сделал все в байтах. Теперь при записи по адресу d1048575 все ок. А при записи по адресу d1048576 синий экран )) На борту платы 1 Мб памяти. Отсюда вывод: надо в драйвере сделать защиту от дурака. То бишь как-то отлавливать возможные выходы за диапазон, отведенный плате в памяти.
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #37 : 28-04-2010 08:46 » 

d1048575 -шо за адрес? невыровненный... как-то подозрительно.
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #38 : 28-04-2010 09:33 » 

вы по одному байту записываете? а плата это поддерживает?)

PS пардон. случайно ваше предыдущее сообщение удалил(((

PPS
аааа! дошло.... я привык что адреса обычно в шеснадцатиричном формате выкладывают) "d" - не заметил)
а проверять естественно. проверять надо все что приходит от приложения. ОБЯЗАТЕЛЬНО
« Последнее редактирование: 28-04-2010 09:37 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #39 : 28-04-2010 09:36 » 

PS пардон. случайно ваше предыдущее сообщение удалил(((
инстинкт сработал Отлично
Записан

tuiui
Участник

ru
Offline Offline

« Ответ #40 : 28-04-2010 09:38 » 

))) пришлось переделать проект под плис, чтобы поддерживала. Можно вас попросить код набросать, как бы мне отлавливать эти ошибки дурака.
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #41 : 28-04-2010 09:39 » 

а чего там набрасывать...
это как проверка выхода за пределы массива. все исходные данные у вас уже есть...
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
tuiui
Участник

ru
Offline Offline

« Ответ #42 : 28-04-2010 09:49 » 

все хорошо. Ошибки, связанные с выходом за границу адресов, отлавливаются, возвращается 0. Но вот когда пишем данные в количестве, равном 0, синий экран ) В драйвере есть такая вещь:

Код:
//Получаем количество данных для записи
writeLength = irpStack->Parameters.Write.Length;    
if (writeLength == 0)
    {        
        status = STATUS_SUCCESS;
        Irp->IoStatus.Information = 0;
        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        MultiplierCDecrementIoCount(&deviceExtension->IoLock);
        return status;
    }

Почему она не отлавливает запись нулевого количества???  Здесь была моя ладья...

А может отлавливает, но сама вызывает ошибку!
« Последнее редактирование: 28-04-2010 11:38 от tuiui » Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #43 : 28-04-2010 11:59 » 

попробуйте
        Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
// Irp->IoStatus.Information не присваивать.
..
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        MultiplierCDecrementIoCount(&deviceExtension->IoLock);
 return STATUS_SUCCESS;
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #44 : 28-04-2010 12:08 » 

хммм, интересно... Information то в 0 выставляется. Странно. Не знаю почему такая. Точно не должно такого быть. Тут надо смотреть отладчиком. Там всё сразу видно будет.

 Но тут просто больше не из за чего падать кроме как.......... IoLock'и я бы закомментарил.

Уверен, что дело именно в этом. Что там за функции такие? Покажите код.
« Последнее редактирование: 28-04-2010 12:13 от resource » Записан
tuiui
Участник

ru
Offline Offline

« Ответ #45 : 28-04-2010 12:38 » 

Тот код, что я привел, генерирует студия. В комментариях написано "просто завершить запрос нулевой длины". Что интересно, точно такие же конструкции используются для завершения запроса при выходе за диапазон адресов. Прям скопировал тупо эти 6 строчек везде, где нужно "аварийно" завершить работу.

resource, какой код вы просите показать?
« Последнее редактирование: 28-04-2010 12:42 от tuiui » Записан
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #46 : 28-04-2010 13:03 » 

MultiplierCCheckIoLock и MultiplierCDecrementIoCount
Записан
tuiui
Участник

ru
Offline Offline

« Ответ #47 : 28-04-2010 13:11 » 

Код:
///////////////////////////////////////////////////////////////////////////////////////////////////
//  MultiplierCCheckIoLock
//      checks if IRP is allowed to proceed.
//
//  Arguments:
//      IN  IoLock
//              io lock for our device
//
//      IN  Irp
//              new IRP
//
//  Return Value:
//      Status
//
NTSTATUS MultiplierCCheckIoLock(
    IN  PMULTIPLIERC_IO_LOCK    IoLock,
    IN  PIRP                        Irp
    )
{
    NTSTATUS            status;
    KIRQL               oldIrql;
    PMULTIPLIERC_DEVICE_EXTENSION   deviceExtension;

    deviceExtension = (PMULTIPLIERC_DEVICE_EXTENSION)IoLock->DeviceObject->DeviceExtension;

    KeAcquireSpinLock(&IoLock->IoLock, &oldIrql);

    // check if device has been removed
    if (IoLock->ErrorStatus != STATUS_SUCCESS)
    {
        status = IoLock->ErrorStatus;
        KeReleaseSpinLock(&IoLock->IoLock, oldIrql);

        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);

        return status;
    }

    // check if io is stalled
    if (IoLock->StallCount > 0)
    {
        // check if Irp is not the one sent by MultiplierCUnlockIo
        if (IoLock->CurrentIrp != Irp)
        {
            // save device extension into the IRP
            Irp->Tail.Overlay.DriverContext[0] = IoLock;

            // stall the IRP
            InsertTailList(&IoLock->StallIrpList, &Irp->Tail.Overlay.ListEntry);

            // insert our queue cancel routine into the IRP
            IoSetCancelRoutine(Irp, MultiplierCPendingIoCancelRoutine);

            // see if IRP was canceled
            if (Irp->Cancel && (IoSetCancelRoutine(Irp, NULL) != NULL))
            {
                // IRP was canceled
                RemoveEntryList(&Irp->Tail.Overlay.ListEntry);

                // drop the lock
                KeReleaseSpinLock(&IoLock->IoLock, oldIrql);

                // cancel the IRP
                status = STATUS_CANCELLED;
                Irp->IoStatus.Status = status;
                IoCompleteRequest(Irp, IO_NO_INCREMENT);

                return status;
            }

            // mark irp pending since STATUS_PENDING is returned
            IoMarkIrpPending(Irp);
            status = STATUS_PENDING;

            // drop the lock
            KeReleaseSpinLock(&IoLock->IoLock, oldIrql);

            // io is stalled. Make sure it is not because of
            // device is powered down.

            if (deviceExtension->DevicePowerState > PowerDeviceD0)
            {
                POWER_STATE powerState;

                powerState.DeviceState = PowerDeviceD0;
                status = PoRequestPowerIrp(
                            deviceExtension->PhysicalDeviceObject,
                            IRP_MN_SET_POWER,
                            powerState,
                            NULL,
                            NULL,
                            NULL
                            );
            }

            return status;
        }
        else
        {
            IoLock->CurrentIrp = NULL;
        }
    }

    // increment active io count
    ++IoLock->ActiveIrpCount;

    // drop the lock
    KeReleaseSpinLock(&IoLock->IoLock, oldIrql);

    status = STATUS_SUCCESS;
    return status;
}

Код:
///////////////////////////////////////////////////////////////////////////////////////////////////
//  MultiplierCDecrementIoCount
//      decrements active io count.
//
//  Arguments:
//      IN  IoLock
//              io lock for our device
//
//  Return Value:
//      None
//
VOID MultiplierCDecrementIoCount(
    IN  PMULTIPLIERC_IO_LOCK    IoLock
    )
{
    KIRQL       oldIrql;

    KeAcquireSpinLock(&IoLock->IoLock, &oldIrql);

    if (--IoLock->ActiveIrpCount == 0)
    {
        KeSetEvent(&IoLock->StallCompleteEvent, IO_NO_INCREMENT, FALSE);
    }

    KeReleaseSpinLock(&IoLock->IoLock, oldIrql);

    return;
}
« Последнее редактирование: 28-04-2010 13:14 от tuiui » Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #48 : 28-04-2010 14:02 » 

код приложения еще можно посмотреть? тот, что  вызывает эту функцию драйвера
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #49 : 28-04-2010 19:30 » 

Ну это уже гадание на кофейной гуще. Есть бсод - есть дамп. Глянуть отладчиком и всё сразу ясно станет
Записан
tuiui
Участник

ru
Offline Offline

« Ответ #50 : 29-04-2010 05:05 » 

Ochkarik, если я правильно понимаю, от приложения не должна зависеть стабильность драйвера. Он ведь должен быть защищен от любого дурака.
А с отладчиком не умею работать (
Записан
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #51 : 29-04-2010 05:14 » 

Про приложение это совершенно верно подмечено. Но думаю, что Ochkarik хотел на него глянуть, так, на всякий случай.

С отладчиком дружить надо. По-другому никак. Собственно для анализа дампа даже не надо второй машины. Я бы даже не обломился и посмотрел бы ваш дамп. Мне канал позволяет сливать такие объемы. Но бесплатные файлообменники вряд ли позволять забирать его с нормальной скоростью. Да и у вас канал, возможно не такой широкий, чтоб заливать столько. Так что, без отладчика никуда.
Записан
tuiui
Участник

ru
Offline Offline

« Ответ #52 : 29-04-2010 05:32 » 

Я просто не совсем даже и понимаю принцип его работы и что он позволяет сделать...

Простите мне мое дилетантство, но можно ли в код драйвера встроить некие контрольные точки? Чтоб, например, выводилась в файл информация о том, куда зашли, какую ошибку отловили?

А пока вот что я могу сказать.
В драйвере последовательность проверок такая:

1. Проверка на слишком большой (маленький) адрес

2. Проверка на нулевую длину

Вызываю WriteFile с нормальным адресом и нулевым количеством - BSOD

Вызываю WriteFile с некорректным адресом и нормальным количеством. Все нормально. Возвращает ноль, ничего не вылетает.

Вызываю WriteFile с некорректным адресом и нулевым количеством - BSOD !!

Отсюда вывод, что он даже не доходит до проверки на нулевую длину. Он даже не доходит до проверки на адрес. Иначе бы на первой проверке обработка завершилась. Куда же тогда смотреть?   Не понял
« Последнее редактирование: 29-04-2010 06:13 от tuiui » Записан
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #53 : 29-04-2010 06:28 » 

Контрольные точки то можно, но нужны они как раз при работе под отладчиком. И это логично, иначе как еще остановить драйвер, этож надо всю систему останавливать. И оно так и происходит, поэтому нужны 2 машины. Но чтоб дамп анализировать, 2 не надо.

В вашем случае, можно воспользоваться функцией DbgPrint. Такая софтина как, например, DebugView покажет всё, что выводится при помощи DbgPrint. Арсенал не богатый, но без отладчика не приходится расчитывать на что-то серьезное.
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #54 : 29-04-2010 10:41 » 

offtopic:
"Ochkarik, если я правильно понимаю, от приложения не должна зависеть стабильность драйвера. Он ведь должен быть защищен от любого дурака. "
- да! НО! если при написании драйвера осуществлены все возможные проверки и отслежены все не корректные запросы. в противном случае...)
не думайте что ЛЮБОЙ драйвер защищен. вся его защита от падения - это работа программиста. ОС за этим не следит.
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
tuiui
Участник

ru
Offline Offline

« Ответ #55 : 29-04-2010 12:58 » 

Нашел, в чем была проблема. Оказывается, ошибка возникала при получении ссылки на буфер с данными ) Почему - объяснить не могу. Видимо, когда нулевая длина, система не передает ссылку на буфер. Так что сначала надо проверять длину буфера данных. И только если она больше нуля, пытаться получить ссылку на этот буфер:
Код:
//Получаем стек IRP
irpStack = IoGetCurrentIrpStackLocation(Irp);    
    
//Получаем количество данных для записи
writeLength = irpStack->Parameters.Write.Length;

//Завершение запроса при нулевом количестве данных
if (writeLength == 0)
    {                  
        Irp->IoStatus.Status = STATUS_SUCCESS;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return STATUS_SUCCESS;      
    }
 
//Получаем адрес буфера для чтения  
writeBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);  

Так что пока все нормально. Буду гонять еще драйвер. Если что-то всплывет - сообщу ))
Записан
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #56 : 29-04-2010 19:43 » 

Что-то вы уж совсем какие-то сказки выдумываете про буфер. В посте #30 точно такая же обработка идет. Разница (как видно) в том, что вы убрали IoLock'и (что собственно и было рекомендовано в #44)
Записан
tuiui
Участник

ru
Offline Offline

« Ответ #57 : 30-04-2010 05:36 » 

В посте #30 не было проверки на адреса. Там вылетало из-за этого )) А тут черт теперь разберешь. Но помню точно, что комментил IoLock, как вы рекомендовали. Не помогло тогда. Но я его все же убрал ) Наверно, не зря. Но даже без него вылетало, если пытаться буфер получать раньше обработки его длины.

В любом случае, большое всем вам спасибо. Вы мне очень помогли!
Записан
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #58 : 30-04-2010 06:13 » 

Да действительно, в #30 не было проверки. Ну так и в коде, приведенном в #55 ее тоже нет. Проверять, что возвращает MmGetSystemAddressForMdlSafe полюбому надо. Но если дело было в этом, то интересно почему она возвращала NULL для буфера ненулевой длины. Или чего она возвращала вообще. Ну да ладно...
Записан
Страниц: 1 2 [Все]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines