48554 (Разработка драйвера виртуального жесткого диска), страница 4

2016-07-30СтудИзба

Описание файла

Документ из архива "Разработка драйвера виртуального жесткого диска", который расположен в категории "". Всё это находится в предмете "информатика" из 1 семестр, которые можно найти в файловом архиве . Не смотря на прямую связь этого архива с , его также можно найти и в других разделах. Архив можно найти в разделе "курсовые/домашние работы", в предмете "информатика, программирование" в общих файлах.

Онлайн просмотр документа "48554"

Текст 4 страницы из документа "48554"

DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_INFO, ("IRP_MJ_CREATE (%p)\n", Irp) );

COMPLETE_REQUEST( Irp, status, 0 );

break;

case IRP_MJ_CLOSE:

DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_INFO, ("IRP_MJ_CLOSE (%p)\n", Irp) );

COMPLETE_REQUEST( Irp, status, 0 );

break;

default:

status = STATUS_NOT_IMPLEMENTED;

COMPLETE_REQUEST( Irp, status, 0 );

ASSERTMSG("BUG: we should never get here", 0);

break;

} // switch

В качестве проверки, если мы получили пакет с другим кодом, то возвратим ошибочный статус.

Обработка запросов на запись или чтение , также реализуется в одной процедуре, т.к. отличия в действиях заключаются в направлении копирования данных: из буфера в образ диска или наоборот. Для выполнения запроса, требуется, чтобы виртуальный диск находился в состоянии WORKING:

if ( devExt->DevState != WORKING )

{

// Устройство не готово или удалено, отменить любые запросы

DBGPRINT( DBG_COMP_READ, DBG_LEVEL_WARN, ("Device not ready\n" ) );

status = STATUS_INVALID_DEVICE_STATE;

COMPLETE_REQUEST( Irp, status, information );

}

Далее требуется проверить, что переданные параметры(начальное смещение Parameters.Read.ByteOffset и количество байт Parameters.Read.Length) не выходят за границы нашего диска, чтобы обеспечить корректность операции чтения/записи. Дополнительно количество байт должно быть кратно размеру сектора на диске:

if (RtlLargeIntegerGreaterThan(

RtlLargeIntegerAdd(

irpStack->Parameters.Read.ByteOffset,

RtlConvertUlongToLargeInteger(irpStack->Parameters.Read.Length)),

RtlConvertUlongToLargeInteger(devExt->DiskRegInfo.DiskSize)) ||

(irpStack->Parameters.Read.Length & (devExt->DiskGeometry.BytesPerSector - 1)))

{

DBGPRINT( DBG_COMP_READ, DBG_LEVEL_ERROR,

(

"Error invalid parameter\n"

"ByteOffset: %x\n"

"Length: %d\n"

"Operation: %x\n",

irpStack->Parameters.Read.ByteOffset,

irpStack->Parameters.Read.Length,

irpStack->MajorFunction

));

status = STATUS_INVALID_PARAMETER;

COMPLETE_REQUEST( Irp, status, information );

IoReleaseRemoveLock(&devExt->RemoveLock, Irp);

return status;

}

Если какой-либо из параметров не верен, то статус обработки запроса будет равен STATUS_INVALID_PARAMETER (неверные параметры).

Драйвер использует прямой метод передачи буфера данных, нам передается MDL список для буфера пользователя в параметре Irp->MdlAddress, который мы отображаем в адресное пространство ядра с помощью функции MmGetSystemAddressForMdlSafe:

ASSERT ( Irp->MdlAddress != NULL );

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

if ( currentAddress == NULL )

{

status = STATUS_INSUFFICIENT_RESOURCES;

COMPLETE_REQUEST( Irp, status, information );

IoReleaseRemoveLock(&devExt->RemoveLock, Irp);

DBGPRINT( DBG_COMP_READ, DBG_LEVEL_ERROR, ("Unable to get the system-space virtual address\n" ) );

return status;}

Когда адрес получен адрес буфера (currentAddress), можно произвести копирование данных с помощью функции RtlMoveMemory

information = irpStack->Parameters.Read.Length;

switch (irpStack->MajorFunction)

{

case IRP_MJ_READ:

RtlMoveMemory(

currentAddress,

devExt->DiskImage + irpStack->Parameters.Read.ByteOffset.LowPart,

irpStack->Parameters.Read.Length);

break;

case IRP_MJ_WRITE:

RtlMoveMemory(

devExt->DiskImage + irpStack->Parameters.Read.ByteOffset.LowPart,

currentAddress, irpStack->Parameters.Read.Length);

break;

default:

information = 0;

break;

}

status = STATUS_SUCCESS;

COMPLETE_REQUEST( Irp, status, information );

При этом поле information содержит количество байт, которые были записаны/прочитаны.


3.4.3 Обработка расширенных запросов

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

case IOCTL_DISK_IS_WRITABLE://проверка можно ли на диск записывать данные

{

DBGPRINT( DBG_COMP_IOCTL, DBG_LEVEL_INFO, ("IOCTL_DISK_IS_WRITABLE \n" ) );

status = STATUS_SUCCESS;

break;

}

case IOCTL_MOUNTMGR_QUERY_POINTS: // сообщить о символической ссылке для тома

{

DBGPRINT( DBG_COMP_IOCTL, DBG_LEVEL_INFO, ("IOCTL_MOUNTMGR_QUERY_POINTS\n" ) );

status = STATUS_INVALID_DEVICE_REQUEST;

break;

}

case IOCTL_DISK_FORMAT_TRACKS: //Форматировать дорожки

{

DBGPRINT( DBG_COMP_IOCTL, DBG_LEVEL_INFO, ("IOCTL_DISK_FORMAT_TRACKS\n" ) );

status = STATUS_SUCCESS ;

break;

}

case IOCTL_DISK_MEDIA_REMOVAL: //блокировать извлечение носителя

{

DBGPRINT( DBG_COMP_IOCTL, DBG_LEVEL_INFO, ("IOCTL_DISK_MEDIA_REMOVAL\n" ) );

status = STATUS_SUCCESS ;

break;

}

case IOCTL_DISK_VERIFY: //провреить данные

{

PVERIFY_INFORMATION verifyInformation;

DBGPRINT( DBG_COMP_IOCTL, DBG_LEVEL_INFO, ("IOCTL_DISK_VERIFY\n" ) );

status = STATUS_SUCCESS ;

break;

}

case IOCTL_DISK_CHECK_VERIFY:// проверить, сменился ли носитель

{

DBGPRINT( DBG_COMP_IOCTL, DBG_LEVEL_INFO, ("IOCTL_DISK_CHECK_VERIFY\n" ) );

status = STATUS_SUCCESS ;

break;

}

Запрос IOCTL_DISK_GET_PARTITION_INFO, требует сообщить информацию о разделах на диске. На рамдиске имеется один раздел. Результатом обработки запроса будет структура PARTITION_INFORMATION

typedef struct _PARTITION_INFORMATION

{

LARGE_INTEGER Ошибка! Недопустимый объект гиперссылки.; //смещение, с которого начинается раздел

LARGE_INTEGER Ошибка! Недопустимый объект гиперссылки.;//размер раздела

DWORD Ошибка! Недопустимый объект гиперссылки.; //скрытых секторов

DWORD Ошибка! Недопустимый объект гиперссылки.; //порядковый номер раздела

BYTE Ошибка! Недопустимый объект гиперссылки.; //тип раздела

BOOLEAN Ошибка! Недопустимый объект гиперссылки.; //TRUE - раздел является загрузочным

BOOLEAN Ошибка! Недопустимый объект гиперссылки.; //распознан ли раздел

BOOLEAN Ошибка! Недопустимый объект гиперссылки.; //TRUE – изменились параметры раздела

}

Тип раздела Ошибка! Недопустимый объект гиперссылки. для виртуального диска может быть PARTITION_FAT_12 или PARTITION_FAT_16(он определяется при инициализации и хранится в расширении драйвера). Остальные поля заполняются следующим образом:

case IOCTL_DISK_GET_PARTITION_INFO:

{

DBGPRINT( DBG_COMP_IOCTL, DBG_LEVEL_INFO, ("IOCTL_DISK_GET_PARTITION_INFO \n" ) );

if (irpStack->Parameters.DeviceIoControl.OutputBufferLength

{

DBGPRINT( DBG_COMP_IOCTL, DBG_LEVEL_INFO, ("Output buffer too small... \n" ) );

status = STATUS_BUFFER_TOO_SMALL; // Нужен буфер больше

information = sizeof(PARTITION_INFORMATION);

}

else

{

PPARTITION_INFORMATION outputBuffer;

outputBuffer = ( PPARTITION_INFORMATION )Irp->AssociatedIrp.SystemBuffer;

outputBuffer->PartitionType = (UCHAR)devExt->DiskRegInfo.PartitionType;

outputBuffer->BootIndicator = FALSE;

outputBuffer->RecognizedPartition = FALSE

outputBuffer->RewritePartition = FALSE;

outputBuffer->StartingOffset = RtlConvertUlongToLargeInteger(0);

outputBuffer->PartitionLength = RtlConvertUlongToLargeInteger(devExt->DiskRegInfo.DiskSize);

outputBuffer->HiddenSectors = (ULONG) (1L);

outputBuffer->PartitionNumber = (ULONG) (1L);

status = STATUS_SUCCESS;

information = sizeof( PARTITION_INFORMATION );

}

break;

}

Запросы IOCTL_DISK_GET_MEDIA_TYPES, IOCTL_DISK_GET_DRIVE _GEOMETRY нужны для поучения информации о геометрии диска, для этого надо заполнить структуру DISK_GEOMETRY описанную в разделе 2.7.:

typedef struct _DISK_GEOMETRY {

LARGE_INTEGER Ошибка! Недопустимый объект гиперссылки.; //количество цилиндров

MEDIA_TYPE Ошибка! Недопустимый объект гиперссылки.; //тип носителя

ULONG Ошибка! Недопустимый объект гиперссылки.; //количество дорожек на цилиндр

ULONG Ошибка! Недопустимый объект гиперссылки.; //количество секторов на дорожку

ULONG Ошибка! Недопустимый объект гиперссылки.; //размер сектора в байтах

} DISK_GEOMETRY, *PDISK_GEOMETRY;

Все остальные параметры заранее рассчитаны и определены при инициализации, и нужно только эту структуру скопировать из расширения устройства:

PDISK_GEOMETRY outputBuffer;

outputBuffer = ( PDISK_GEOMETRY ) Irp->AssociatedIrp.SystemBuffer;

RtlCopyMemory( outputBuffer, &(devExt->DiskGeometry), sizeof(DISK_GEOMETRY) );

status = STATUS_SUCCESS;

DBGPRINT(DBG_COMP_IOCTL,DBG_LEVEL_INFO,("IOCTL_DISK_GET_DRIVE_GEOMETRY-OK!\n"));

information = sizeof( DISK_GEOMETRY );


3.4.4 Обработка запросов Plug and Play

При запуске устройства мы получаем IRP пакет с кодом IRP_MN_START_DEVICE:

case IRP_MN_START_DEVICE:

{

KeInitializeEvent( &event, NotificationEvent, FALSE);

IoCopyCurrentIrpStackLocationToNext( Irp );

IoSetCompletionRoutine( Irp, (PIO_COMPLETION_ROUTINE) RamDskIoCompletionRoutine,

(PVOID) &event, TRUE, TRUE, TRUE );

status = IoCallDriver( devExt->LowerDeviceObject, Irp );

if (status == STATUS_PENDING)

{

KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL );

}

if ( NT_SUCCESS(status) )

{

// успешно запущен нижний драйвер

devExt->DevState = WORKING;

}

COMPLETE_REQUEST( Irp, status, 0 );

break;

}

Мы пересылаем пакет драйверу, который находится ниже при помощи вызова функции IoCallDriver. Если нижние драйвер находится в состоянии обработки (STATUS_PENDING), то просто усыплем наш драйвер с помощью функции KeWaitForSingleObject и просыпаемся по событию завершения операции нижним драйвером.

При остановке устройства(IRP_MN_STOP_DEVICE), просто пересылаем запрос нижнему драйверу и устанавливаем состояние устройства STOPPED:

case IRP_MN_STOP_DEVICE:

{

devExt->DevState = STOPPED;

Irp->IoStatus.Status = STATUS_SUCCESS;

IoSkipCurrentIrpStackLocation( Irp );

status = IoCallDriver( devExt->LowerDeviceObject, Irp );

break;

}

При обработке запросов IRP_MN_SURPRISE_REMOVAL, IRP_MN_QUERY_ REMOVE_DEVICE, IRP_MN_QUERY_STOP_DEVICE, производятся аналогичные действия, с установкой соответствующего статуса:

case IRP_MN_QUERY_STOP_DEVICE:

{

devExt->DevState = PENDINGSTOP;

Irp->IoStatus.Status = STATUS_SUCCESS;

IoSkipCurrentIrpStackLocation( Irp );

status = IoCallDriver( devExt->LowerDeviceObject, Irp );

break;

}

case IRP_MN_STOP_DEVICE:

{

devExt->DevState = STOPPED;

Irp->IoStatus.Status = STATUS_SUCCESS;

IoSkipCurrentIrpStackLocation( Irp );

status = IoCallDriver( devExt->LowerDeviceObject, Irp );

break;

}

case IRP_MN_QUERY_REMOVE_DEVICE:

{

devExt->DevState = PENDINGREMOVE;

Irp->IoStatus.Status = STATUS_SUCCESS;

IoSkipCurrentIrpStackLocation( Irp );

status = IoCallDriver( devExt->LowerDeviceObject, Irp );

break;

}

case IRP_MN_SURPRISE_REMOVAL:

{

devExt->DevState = SURPRISEREMOVED;

Irp->IoStatus.Status = STATUS_SUCCESS;

IoSkipCurrentIrpStackLocation( Irp );

status = IoCallDriver( devExt->LowerDeviceObject, Irp );

break;

}

При удалении устройства IRP_MN_REMOVE_DEVICE, мы вызываем функцию RamDskRemoveDevice, которая освобождает выделенную при инициализации память, символическую ссылку (она будет описана далее):

case IRP_MN_REMOVE_DEVICE:

{

RamDskRemoveDevice( DeviceObject, Irp );

lockHeld = FALSE;

break;

}


3.4.5 Выгрузка драйвера

Выгрузка драйвера состоит из двух частей: удаление объекта устройства и выгрузка самого драйвера.

При удалении объекта устройства, менеджер ввода вывода посылает IRP пакет IRP_MN_REMOVE_DEVICE, тогда вызывается процедура RamDskRemove Device. IRP пакет передаем дальше драйверу нижнего уровня с помощью функции IoCallDriver. Статус драйвера устанавливается в состояние устройство удалено, чтобы новые запросы не могли быть выполнены. С помощью функции IoReleaseRemoveLockAndWait ждем пока текущие запросы не обработаются.

Irp->IoStatus.Status = STATUS_SUCCESS;

IoSkipCurrentIrpStackLocation( Irp );

status = IoCallDriver( devExt->LowerDeviceObject, Irp );

devExt->DevState = REMOVED;

IoReleaseRemoveLockAndWait(&devExt->RemoveLock, Irp);

driverExtension = IoGetDriverObjectExtension(DeviceObject->DriverObject,

RAMDSK_DRIVER_EXTENSION_KEY);

ASSERT ( driverExtension != NULL );

driverExtension->DeviceInitialized = FALSE;

RamDskCleanUp( DeviceObject );

Перед удалением расширения объекта устройства в процедуре RamDskCleanUp освобождается память под образ диска, удаляется символическая ссылка и сам функциональный объект устройства. Также далее сбрасывается признак DeviceInitialized инициализации устройства.

При выгрузке самого драйвера вызывается процедура RamDskUnload, которая должна обязательно присутствовать, чтобы драйвер мог выгружаться.

VOID RamDskUnload(IN PDRIVER_OBJECT DriverObject)

{

PRAMDSK_DRIVER_EXTENSION driverExtension;

DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_INFO, ("Driver Unload\n") );

ASSERT(DriverObject->DeviceObject == NULL);

driverExtension = IoGetDriverObjectExtension(DriverObject,RAMDSK_DRIVER_EXTENSION_KEY);

ASSERT ( driverExtension != NULL );

if ( driverExtension->RegistryPath.Buffer )

{

ExFreePool( driverExtension->RegistryPath.Buffer );

Свежие статьи
Популярно сейчас
А знаете ли Вы, что из года в год задания практически не меняются? Математика, преподаваемая в учебных заведениях, никак не менялась минимум 30 лет. Найдите нужный учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Нашёл ошибку?
Или хочешь предложить что-то улучшить на этой странице? Напиши об этом и получи бонус!
Бонус рассчитывается индивидуально в каждом случае и может быть в виде баллов или бесплатной услуги от студизбы.
Предложить исправление
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
5076
Авторов
на СтудИзбе
455
Средний доход
с одного платного файла
Обучение Подробнее