logo
Разработка драйвера виртуального жесткого диска

3.4.2 Обработка запросов записи/чтения

Когда пользовательское приложение или компонент ядра пытается открыть драйвер виртуального диска для записи или чтения, то диспетчер ввода вывода формирует запросы IRP с кодом IRP_MJ_CREATE. При закрытии обрабатывается запрос IRP_MJ_CLOSE. Особых действий в обработке этих пакетов не требуется, поэтому драйвер возвращает успешный статус завершения. В данном драйвере оба пакета обрабатываются в одной процедуре RamDskCreateClose:

switch ( irpStack->MajorFunction )

{

case IRP_MJ_CREATE:

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

COMPLETE_REQUEST( Irp, status, 0 );

break;

case IRP_MJ_CLOSE:

DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_INFO, ("IRP_MJ_CLOSE (%p) ", 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 " ) );

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 "

"ByteOffset: %x "

"Length: %d "

"Operation: %x ",

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 " ) );

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 содержит количество байт, которые были записаны/прочитаны.