Рефераты. Драйвер виртуального диска

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 StartingOffset; //смещение, с которого начинается раздел

LARGE_INTEGER PartitionLength;//размер раздела

DWORD HiddenSectors; //скрытых секторов

DWORD PartitionNumber; //порядковый номер раздела

BYTE PartitionType; //тип раздела

BOOLEAN BootIndicator; //TRUE - раздел является загрузочным

BOOLEAN RecognizedPartition; //распознан ли раздел

BOOLEAN RewritePartition; //TRUE - изменились параметры раздела}

Тип раздела PartitionType для виртуального диска может быть 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 <sizeof(PARTITION_INFORMATION))

{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 Cylinders; //количество цилиндров

MEDIA_TYPE MediaType; //тип носителя

ULONG TracksPerCylinder; //количество дорожек на цилиндр

ULONG SectorsPerTrack; //количество секторов на дорожку

ULONG BytesPerSector; //размер сектора в байтах

} 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) )

Страницы: 1, 2, 3, 4, 5, 6



2012 © Все права защищены
При использовании материалов активная ссылка на источник обязательна.