BSOD DriverUnload & IRP_MJ_DEVICE_CONTROL
От: BukaP  
Дата: 29.07.08 21:23
Оценка:
Добрый день!

Изучаю процесс разработки драйвера. На данном этапе хочу написать драйвер доступа к LPT.
Драйвер загружается и нормально функционирует, но при выгрузке выдает BSOD.
В SoftICE: "Break due to Page fault (0Eh). Fault=0000". Если закомментировать обработчик IRP_MJ_DEVICE_CONTROL,
BSOD не появляется. Подскажите пожалуйста где у меня кривые руки?


//================================================================================================
//    Структуры
//================================================================================================

typedef struct tagDEVICE_EXTENSION                                            //Структура реализующая контекст устройства
{
    PDRIVER_OBJECT        pDriverObject;                                        //Объект драйвера
    PDEVICE_OBJECT        pDeviceObject;                                        //Объект устройства

//==============================================================================================

    UNICODE_STRING        usDeviceName;                                        //Имя объекта устройства
    UNICODE_STRING        usSymbolicLinkName;                                    //Символическая ссылка на объект устройства

//==============================================================================================

    PVOID                pPortIO;                                            //Начальный аддресс LPT порта

//==============================================================================================
    
    KMUTEX                kmDispatchControl;                                    //Мьютекс обработки IOCTL
}
DEVICE_EXTENSION, *PDEVICE_EXTENSION, **PPDEVICE_EXTENSION;

//================================================================================================
//    Сегментирование памяти
//================================================================================================

#ifdef ALLOC_PRAGMA

#pragma alloc_text    (INIT,    DriverEntry)
#pragma alloc_text    (INIT,    DriverInitialize)

#pragma alloc_text    (PAGE,    DriverUnload)
#pragma alloc_text    (PAGE,    DeviceDispatcher)
#pragma alloc_text    (PAGE,    DeviceControl)

#endif

//================================================================================================
//    Точка входа в драйвер
//================================================================================================

NTSTATUS    DriverEntry    (                                            //Функция реализующая точку входа в драйвер
                            PDRIVER_OBJECT  pDriverObject,            //Объект драйвера
                            PUNICODE_STRING pusRegistryPath            //Путь регистрации драйвера
                        )
{
    NTSTATUS            nStatus        =    STATUS_DEVICE_CONFIGURATION_ERROR;

    DbgPrint("LptDrv    v1.0,    28/07/2008,    by Buka Prophet,    bukap@yandex.ru\r\n");
    DbgPrint(DRIVER_NAME "DriverEntry - точка входа в драйвер!\r\n");

    if    (
                                                                    //Инициализация драйвера
            (nStatus = DriverInitialize(pDriverObject, pusRegistryPath)) == STATUS_SUCCESS
        )
    {
        pDriverObject->MajorFunction[IRP_MJ_CREATE                  ]    =
        pDriverObject->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE       ]    =
        pDriverObject->MajorFunction[IRP_MJ_CLOSE                   ]    =
        pDriverObject->MajorFunction[IRP_MJ_READ                    ]    =
        pDriverObject->MajorFunction[IRP_MJ_WRITE                   ]    =
        pDriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION       ]    =
        pDriverObject->MajorFunction[IRP_MJ_QUERY_EA                ]    =
        pDriverObject->MajorFunction[IRP_MJ_SET_EA                  ]    =
        pDriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS           ]    =
        pDriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION]    =
        pDriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION  ]    =
        pDriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL       ]    =
        pDriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL     ]    =
        pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL          ]    =
        pDriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL ]    =
        pDriverObject->MajorFunction[IRP_MJ_SHUTDOWN                ]    =
        pDriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL            ]    =
        pDriverObject->MajorFunction[IRP_MJ_CLEANUP                 ]    =
        pDriverObject->MajorFunction[IRP_MJ_CREATE_MAILSLOT         ]    =
        pDriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY          ]    =
        pDriverObject->MajorFunction[IRP_MJ_SET_SECURITY            ]    =
        pDriverObject->MajorFunction[IRP_MJ_POWER                   ]    =
        pDriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL          ]    =
        pDriverObject->MajorFunction[IRP_MJ_DEVICE_CHANGE           ]    =
        pDriverObject->MajorFunction[IRP_MJ_QUERY_QUOTA             ]    =
        pDriverObject->MajorFunction[IRP_MJ_SET_QUOTA               ]    =
        pDriverObject->MajorFunction[IRP_MJ_PNP                     ]    =    DeviceDispatcher;
        pDriverObject->DriverUnload                                        =    DriverUnload;
    }

    DbgPrint(DRIVER_NAME "~DriverEntry - Возврат из точки входа в драйвер!\r\n");

    return (nStatus);
}

//================================================================================================
//    Инициализация драйвера
//================================================================================================

NTSTATUS    DriverInitialize    (                                        //Функция инициализации драйвера
                                    PDRIVER_OBJECT  pDriverObject,        //Объект драйвера
                                    PUNICODE_STRING pusRegistryPath        //Путь регистрации драйвера
                                )
{
    NTSTATUS            nStatus                =    STATUS_DEVICE_CONFIGURATION_ERROR;//Статус выполнения операции
    PDEVICE_OBJECT        pDeviceObject        =    NULL;                                //Создаваемый объект устройства
    PDEVICE_EXTENSION    pDeviceExtension    =    NULL;                                //Указатель на структуру расширения
    UNICODE_STRING        usDeviceName        =    {0};                                //Имя устройства

    DbgPrint(DRIVER_NAME "DriverInitialize - Инициализация драйвера!\r\n");

    RtlInitUnicodeString(&usDeviceName, USTRING(CSTRING(DRV_DEVICE)));    //Инициализация строки имени устройства
    DbgPrint(DRIVER_NAME "usDeviceName - \r\n%ws\r\n", usDeviceName.Buffer);

    DbgPrint(DRIVER_NAME "IoCreateDevice - Создание объекта устройства!\r\n");
    if    (
            (
                nStatus = IoCreateDevice    (
                                                pDriverObject,            //Объект драйвера
                                                DEVICE_EXTENSION_,        //Размер выделяемой памяти под структуру расширения
                                                &usDeviceName,            //Имя устройства
                                                FILE_DEVICE_CUSTOM,        //Тип устройства
                                                0,                        //Дополнительная информация об устройстве
                                                FALSE,                    //Зарезервиравоно системой (FALSE)
                                                &pDeviceObject            //Объект устройства
                                            )
            )
            == STATUS_SUCCESS
        )
    {
        DbgPrint(DRIVER_NAME "PDEVICE_EXTENSION - Заполнение контекста устройства!\r\n");

        pDeviceObject->Flags                |=    DO_BUFFERED_IO;            //Установка режима ввода/вывода с буферизацией

        pDeviceExtension                    =    pDeviceObject->DeviceExtension;
        pDeviceExtension->pDriverObject        =    pDriverObject;
        pDeviceExtension->pDeviceObject        =    pDeviceObject;
        pDeviceExtension->usDeviceName        =    usDeviceName;
        pDeviceExtension->pPortIO            =    (PVOID)LPT_PORT_ADDRESS;
        
        DbgPrint(DRIVER_NAME "IoCreateSymbolicLink - Создание символической ссылки!\r\n");
        RtlInitUnicodeString(&pDeviceExtension->usSymbolicLinkName, USTRING(CSTRING(DRV_LINK)));
        if    (
                NT_SUCCESS((nStatus = IoCreateSymbolicLink(&pDeviceExtension->usSymbolicLinkName, &pDeviceExtension->usDeviceName)))
            )
        {
            DbgPrint(DRIVER_NAME "IoCreateSymbolicLink\r\n%ws\r\n", pDeviceExtension->usSymbolicLinkName.Buffer);
            DbgPrint(DRIVER_NAME "KeInitializeMutex - Инициализация мьютекса pDeviceExtension->kmDispatchControl!\r\n");
            KeInitializeMutex(&pDeviceExtension->kmDispatchControl, 0);    //Инициализация мьютекса
        }
        else
        {
            DbgPrint(DRIVER_NAME "IoDeleteDevice - Удаление устройства по причине ошибки!\r\n");
            IoDeleteDevice(pDeviceObject);                                //Удаление объекта
        }
    }

    DbgPrint(DRIVER_NAME "~DriverInitialize - Возврат из инициализации драйвера!\r\n");

    return (nStatus);
}

//================================================================================================
//    Объялвение функций хранящихся в страничной памяти
//================================================================================================

VOID        DriverUnload        (                                            //Функция выгрузки драйвера
                                     IN    PDRIVER_OBJECT    pDriverObject        //Объект драйвера
                                )
{
    PDEVICE_OBJECT        pNextDeviceObject    =    pDriverObject->DeviceObject;
    PDEVICE_EXTENSION    pDeviceExtension    =    NULL;

    PAGED_CODE();

    DbgPrint(DRIVER_NAME "DriverUnload - Выгрузка драйвера!\r\n");

    for (;pNextDeviceObject != NULL;)
    {
        pDeviceExtension = pNextDeviceObject->DeviceExtension;

        DbgPrint(DRIVER_NAME "IoDeleteSymbolicLink - Удаление символической ссылки!\r\n");
        IoDeleteSymbolicLink(&pDeviceExtension->usSymbolicLinkName);
        
        DbgPrint(DRIVER_NAME "IoDeleteDevice - Удаление объекта устройтсва!\r\n");
        pNextDeviceObject = pDeviceExtension->pDeviceObject->NextDevice;
        IoDeleteDevice(pDeviceExtension->pDeviceObject);
    }

    DbgPrint(DRIVER_NAME  "~DriverUnload - Возврат из выгрузки драйвера!\r\n");
}

//================================================================================================
//    Обработчик IRP пакетов
//================================================================================================

NTSTATUS    DeviceDispatcher    (                                            //Функция обработки запросов к объекту устройства
                                    IN    PDEVICE_OBJECT    pDeviceObject,        //Объект драйвера
                                    IN    PIRP            pIrp            //IRP пакет
                                )
{
    NTSTATUS            nStatus        =    STATUS_NOT_IMPLEMENTED;
    PIO_STACK_LOCATION    pIsl        =    NULL;
    DWORD                nInfo        =    0;

    PAGED_CODE();

    DbgPrint(DRIVER_NAME "DeviceDispatcher - Фильтрация IRP запросов!\r\n");

    DbgPrint(DRIVER_NAME "IoGetCurrentIrpStackLocation - Вычитка IRP запроса из стека!\r\n");
    pIsl = IoGetCurrentIrpStackLocation(pIrp);                                //Получение указателя на стек IRP запроса

    switch    (pIsl->MajorFunction)
    {
    case IRP_MJ_CREATE:
        DbgPrint(DRIVER_NAME "Обработка пакета IRP_MJ_CREATE!\r\n");
    case IRP_MJ_CLEANUP:
        DbgPrint(DRIVER_NAME "Обработка пакета IRP_MJ_CLEANUP!\r\n");
    case IRP_MJ_CLOSE:
        {
            DbgPrint(DRIVER_NAME "Обработка пакета IRP_MJ_CLOSE!\r\n");

            nStatus = STATUS_SUCCESS;
            break;
        }

    case IRP_MJ_DEVICE_CONTROL:
        {
            nStatus = DeviceControl    (
                                        pDeviceObject->DeviceExtension,
                                        pIsl->Parameters.DeviceIoControl.IoControlCode,
                                        pIrp->AssociatedIrp.SystemBuffer,
                                        pIsl->Parameters.DeviceIoControl.InputBufferLength,
                                        pIrp->AssociatedIrp.SystemBuffer,
                                        pIsl->Parameters.DeviceIoControl.OutputBufferLength,
                                        &nInfo
                                    );
            break;
        }
    }

    pIrp->IoStatus.Status      = nStatus;                                        //Установка статуса обработки запроса
    pIrp->IoStatus.Information = nInfo;                                            //Число байт записанных в буфер
    
    DbgPrint(DRIVER_NAME "IoCompleteRequest - Окончание обработки IRP запроса!\r\n");
    IoCompleteRequest    (                                                        //Окончания обработки IRP пакета
                            pIrp,                                                //IRP
                            IO_NO_INCREMENT                                        //Освобождение процесса передавшего IRP пакет
                        );
        
    DbgPrint(DRIVER_NAME "~DeviceDispatcher - Возврат из фильтра IRP запросов!\r\n");

    return (nStatus);
}

NTSTATUS    DeviceControl        (                                                //Функция обработки IOCTL запросов
                                    IN    PDEVICE_EXTENSION    pDeviceExtension,    //Структура расширения
                                    IN    DWORD                nCode,                //Код IOCTL
                                    IN    PVOID                pInputBuff,            //Входной буфер
                                    IN    DWORD                nInputBuffSize,        //Размер входного буфера
                                    OUT    PVOID                pOutputBuff,        //Выходной буфер
                                    IN    DWORD                nOutputBuffSize,    //Размер выходного буфера
                                    OUT    PDWORD                pnInfo                //Записано в выходной буфер
                                )
{
    NTSTATUS    nStatus                    =    STATUS_SUCCESS;
    UCHAR        nByteRegRead            =    0;

    PAGED_CODE();

    DbgPrint(DRIVER_NAME "DeviceControl - Обработка пакета IRP_MJ_DEVICE_CONTROL!\r\n");

    DbgPrint(DRIVER_NAME "KeWaitForSingleObject - Ожидание освобождения мьютекса pDeviceExtension->kmDispatchControl!\r\n");
    
    KeWaitForSingleObject    (                                                    //Ожидание освобождения MUTEX-а
                                &pDeviceExtension->kmDispatchControl,            //Объект MUTEX-а
                                Executive,                                        //Исполнительный
                                KernelMode,                                        //Уровень ядра
                                FALSE,                                            //Не оповещать
                                NULL                                            //Ожидать бесконечно (INFINITY - User Mode)
                            );

    DbgPrint(DRIVER_NAME "KeWaitForSingleObject - Мьютекс захвачен pDeviceExtension->kmDispatchControl!\r\n");

    switch    (nCode)
    {
    case LPT_DRV_READ_DATA:
        {
            DbgPrint(DRIVER_NAME "LPT_DRV_READ_DATA - Обработка IOCTL запроса!\r\n");

            if    (pDeviceExtension->pPortIO && nInputBuffSize > 0)
            {
                nByteRegRead = READ_PORT_UCHAR((PUCHAR) LPT_PORT_ADDRESS + LPT_REG_DATA);
                DbgPrint(DRIVER_NAME "Вычитано из порта = %d\r\n", nByteRegRead);
            }

            break;
        }

    case LPT_DRV_WRITE_DATA:
        {
            DbgPrint(DRIVER_NAME "LPT_DRV_WRITE_DATA - Обработка IOCTL запроса!\r\n");
            break;
        }

    case LPT_DRV_READ_STATUS:
        {
            DbgPrint(DRIVER_NAME "LPT_DRV_READ_STATUS - Обработка IOCTL запроса!\r\n");
            break;
        }

    case LPT_DRV_READ_CNTRL:
        {
            DbgPrint(DRIVER_NAME "LPT_DRV_READ_CNTRL - Обработка IOCTL запроса!\r\n");
            break;
        }

    case LPT_DRV_WRITE_CNTRL:
        {
            DbgPrint(DRIVER_NAME "LPT_DRV_WRITE_CNTRL - Обработка IOCTL запроса!\r\n");
            break;
        }
    }

    DbgPrint(DRIVER_NAME "KeReleaseMutex - Освобождение мьютекса pDeviceExtension->kmDispatchControl!\r\n");
    KeReleaseMutex            (                                                    //Освобождение мьютекса
                                &pDeviceExtension->kmDispatchControl,            //Мьютекс
                                FALSE
                            );
    
    DbgPrint(DRIVER_NAME "~DeviceControl - Возврат из обработки пакета IRP_MJ_DEVICE_CONTROL!\r\n");

    return (nStatus);
}
Re: BSOD DriverUnload & IRP_MJ_DEVICE_CONTROL
От: BukaP  
Дата: 29.07.08 22:30
Оценка:
BSOD происходит при вызове IoDeleteSymbolicLink. Проверял через DbgPrint состояние переменной.
Делал вывод ссылки непосредственно через DbgPrint. Драйвер умирает при обращении к переменной символической ссылки
CMP WORD PTR [EAX], 00.

Если закоментировать обработчик IRP_MJ_DEVICE_CONTROL код, то обращение к переменной символической ссылки происходит нормально
и она выводится в отладчике и нормально удаляется.

/*
nStatus = DeviceControl    (
                                        pDeviceObject->DeviceExtension,
                                        pIsl->Parameters.DeviceIoControl.IoControlCode,
                                        pIrp->AssociatedIrp.SystemBuffer,
                                        pIsl->Parameters.DeviceIoControl.InputBufferLength,
                                        pIrp->AssociatedIrp.SystemBuffer,
                                        pIsl->Parameters.DeviceIoControl.OutputBufferLength,
                                        &nInfo
                                    );
*/
Re: BSOD DriverUnload & IRP_MJ_DEVICE_CONTROL
От: BukaP  
Дата: 30.07.08 06:23
Оценка:
Выполнил 4 сборки.
В Visual Studio C++ 6.0 Checked и Free, и в DDK Checked и Free. Проблема проявилось только в Visual Studio C++ 6.0 Checked.
Все таки думаю, что руки где-то кривые, только не могу понять где
Re[2]: BSOD DriverUnload & IRP_MJ_DEVICE_CONTROL
От: x64 Россия  
Дата: 30.07.08 10:13
Оценка:
BP>В Visual Studio C++ 6.0 Checked и Free, и в DDK Checked и Free. Проблема проявилось только в Visual Studio C++ 6.0 Checked.

Visual Studio не предназначена для сборки драйверов. Это аксиома. Собирать драйвера следует только утилитой BUILD из DDK.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.