Добрый день!
Изучаю процесс разработки драйвера. На данном этапе хочу написать драйвер доступа к 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);
}
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
);
*/
Выполнил 4 сборки.
В Visual Studio C++ 6.0 Checked и Free, и в DDK Checked и Free. Проблема проявилось только в Visual Studio C++ 6.0 Checked.
Все таки думаю, что руки где-то кривые, только не могу понять где