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

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;

}