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 содержит количество байт, которые были записаны/прочитаны.
- 1. АНАЛИТИЧЕСКИЙ РАЗДЕЛ
- 1.1 Постановка задачи
- 1.2 Архитектура Windows 2000
- 1.3 Многослойная архитектура драйверов
- 1.4 Архитектура драйверов устройств хранения
- 1.5 Выбор файловой системы
- 2. КОНСТРУКТОРСКИЙ РАЗДЕЛ
- 2.1 Структура классового драйвера
- 2.2 Организация внутреннего хранения данных диска
- 2.3 Доступ к передаваемым данным
- 2.4 Обработка запросов Plug and Play
- 2.5 Обработка расширенных запросов
- 3. ТЕХНОЛОГИЧЕСКИЙ РАЗДЕЛ
- 3.1 Выбор и обоснование языка и среды программирования
- 3.2 Структуры данных классового драйвера
- 3.3 Блокировка выгрузки устройства
- 3.4 Процедуры драйвера виртуального диска
- 3.4.1 Инициализация драйвера
- 3.4.2 Обработка запросов записи/чтения
- 3.4.3 Обработка расширенных запросов
- 3.4.4 Обработка запросов Plug and Play
- 3.4.5 Выгрузка драйвера
- 3.5 Программа настройки параметров виртуального диска
- 3.6 Установка драйвера