IoAttachDeviceToDeviceStack - вроде сдесь проблема
Сразу прошу прощения, если не в том разделе - мне показалось, что он самый подходящий раздел для этого ... :(
Проблема в следующем, пишу драйвер для устройства на PIC18F4550, драйвер инсталлируется в систему, но когда вставляешь устройство - менеджер устройств определяет следующие:
Если закомментировать в функции AddDevice строчку вызова функции IoAttachDeviceToDeviceStack - то драйвер опеределяеться в системе нормально, когда я присоединяю устройство ... :confused: При этом данная функция возвращает адрес устройства добавленного в стек, и этот адрес совпадает из адресом PhysicalDeviceObject ... :confused: Причем совпадать начинает только после 2-го или 3-го раза, когда я подключаю устройство к компьютеру ...
Прошу помощи, может кто-то из Вас уже встречался с подобной проблемой ...
Заранее благодарен.
Да, так и есть - ему нужно было обработать запрос IRP_MN_START_DEVICE ...
Написал его обработку - все прошло, драйвер завелся в системе без проблем, но вот возникла еще одна, на мой взгляд - самая страшная:
Когда удаляю устройство из системы (безопасное извлечение или просто выдергиваю его) - вознакаетСиний экран смерти, ошибка возникает в обработчике IRP_MN_REMOVE_DEVICE, а именно в месте вызова функции IoCallDriver ...
Во время этой функции - Windows "падает" ...
Что может быть не так ? - уже всю голову сломал ...
Заранее благодарен ...
синих экранов смерти - великое множество
MULTIPLE_IRP_DEVICE_REQUEST - вот мой экран ...
Что может происходить ? :confused:
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING UniRegistryPath )
{
NTSTATUS ntStatus = STATUS_INSUFFICIENT_RESOURCES;
PUNICODE_STRING ntRegisterPath = &Globals.UkroUSB_RegistryPath;
ANSI_STRING DriverName;
ntRegisterPath->MaximumLength = UniRegistryPath->Length + sizeof( UNICODE_NULL );
ntRegisterPath->Length = UniRegistryPath->Length;
ntRegisterPath->Buffer = ExAllocatePoolWithTag( PagedPool, ntRegisterPath->MaximumLength, BULKTAG );
if ( ntRegisterPath->Buffer == NULL )
{
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "Buffer is EMPTY" );
return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
}
RtlZeroMemory( ntRegisterPath->Buffer, ntRegisterPath->MaximumLength );
RtlMoveMemory( ntRegisterPath->Buffer, UniRegistryPath->Buffer, UniRegistryPath->Length );
ntRegisterPath->Buffer[ntRegisterPath->Length / sizeof( WCHAR )] = '\0';
RtlUnicodeStringToAnsiString( &DriverName, ntRegisterPath, TRUE );
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "Driver name is %s", DriverName.Buffer );
RtlFreeAnsiString( &DriverName );
ntStatus = STATUS_SUCCESS;
DriverObject->DriverUnload = ( PDRIVER_UNLOAD )UkroUSB_DriverUnload;
DriverObject->DriverExtension->AddDevice = ( PDRIVER_ADD_DEVICE )UkroUSB_AddDevice;
DriverObject->MajorFunction[IRP_MJ_PNP] = UkroUSB_DispatchPnP;
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "DriverEntry complete successfully - ERROR = %X", ntStatus );
return ntStatus;
}
NTSTATUS UkroUSB_AddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject )
{
NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
PDEVICE_OBJECT deviceObject = NULL;
PDEVICE_EXTENSION deviceExtension;
ntStatus = IoCreateDevice(
DriverObject,
sizeof( DEVICE_EXTENSION ),
NULL,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
//FILE_AUTOGENERATED_DEVICE_NAME,
FALSE,
&deviceObject );
if ( !NT_SUCCESS( ntStatus ) )
{
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "IoCreateDevice is ERROR - ERROR = %X", ntStatus );
return ntStatus;
}
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "IoCreateDevice is 0x%X to 0x%X", deviceObject, PhysicalDeviceObject );
deviceExtension = ( PDEVICE_EXTENSION ) deviceObject->DeviceExtension;
deviceExtension->DeviceObject = deviceObject;
deviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
deviceObject->Flags |= DO_DIRECT_IO;
if ( PhysicalDeviceObject->Flags & DO_POWER_PAGABLE ) deviceObject->Flags |= DO_POWER_PAGABLE;
ntStatus = IoRegisterDeviceInterface(
PhysicalDeviceObject,
( LPGUID )&GUID_CLASS_USB_UKRO,
NULL,
&deviceExtension->InterfaceName );
if ( !NT_SUCCESS( ntStatus ) )
{
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "IoRegisterDeviceInterface is ERROR - ERROR = %X", ntStatus );
IoDeleteDevice( deviceObject );
return ntStatus;
}
deviceExtension->CurrentDeviceState = Stopped;
deviceExtension->PowerDeviceState = PowerDeviceD0;
deviceExtension->SystemDeviceState = PowerSystemWorking;
KeInitializeSpinLock( &deviceExtension->DevStateLock );
if( RtlIsNtDdiVersionAvailable( NTDDI_WIN2K ) ) deviceExtension->WdmVersion = NTDDI_WIN2K;
else if( RtlIsNtDdiVersionAvailable( NTDDI_WINXP ) ) deviceExtension->WdmVersion = NTDDI_WINXP;
else if( RtlIsNtDdiVersionAvailable( NTDDI_VISTA ) ) deviceExtension->WdmVersion = NTDDI_VISTA;
else if( RtlIsNtDdiVersionAvailable( NTDDI_WIN7 ) ) deviceExtension->WdmVersion = NTDDI_WIN7;
ntStatus = IoAttachDeviceToDeviceStackSafe( deviceObject, PhysicalDeviceObject, &deviceExtension->LowerDeviceObject );
if ( !NT_SUCCESS( ntStatus ) )
{
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "IoAttachDeviceToDeviceStack is ERROR - ERROR = %X", ntStatus );
IoDeleteDevice( deviceObject );
return ntStatus;
}
deviceObject->Characteristics = deviceExtension->LowerDeviceObject->Characteristics;
deviceObject->DeviceType = deviceExtension->LowerDeviceObject->DeviceType;
deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
ntStatus = STATUS_SUCCESS;
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "AddDevice complete successfully - ERROR = %X", ntStatus );
return ntStatus;
}
NTSTATUS UkroUSB_DispatchPnP(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp )
{
PIO_STACK_LOCATION StackLocation;
PDEVICE_EXTENSION DeviceExtension;
NTSTATUS status = STATUS_UNSUCCESSFUL;
StackLocation = IoGetCurrentIrpStackLocation( Irp );
DeviceExtension = DeviceObject->DeviceExtension;
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "UkroUSB_DispatchPnP is begining 0x%X", DeviceExtension->LowerDeviceObject );
switch( StackLocation->MinorFunction )
{
case IRP_MN_START_DEVICE:
status = PnpStartDevice( DeviceObject, Irp );
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "IRP_MN_START_DEVICE is 0x%X", status );
break;
/*case IRP_MN_QUERY_STOP_DEVICE:
UNREFERENCED_PARAMETER( DeviceObject );
UNREFERENCED_PARAMETER( Irp );
status = PnpQueryStopDevice( DeviceObject, Irp );
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "IRP_MN_QUERY_STOP_DEVICE is 0x%X", status );
break;
case IRP_MN_STOP_DEVICE:
status = PnpStopDevice( DeviceObject, Irp );
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "IRP_MN_STOP_DEVICE is 0x%X", status );
break;*/
case IRP_MN_QUERY_REMOVE_DEVICE:
status = PnpQueryRemoveDevice( DeviceObject, Irp );
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "IRP_MN_QUERY_REMOVE_DEVICE is 0x%X", status );
break;
case IRP_MN_REMOVE_DEVICE:
status = IoAcquireRemoveLock( &DeviceExtension->RemoveLock, Irp );
if ( !NT_SUCCESS( status ) )
{
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "IRP_MN_QUERY_REMOVE_DEVICE is ERROR = 0x%X", status );
return status;
}
status = PnpRemoveDevice( DeviceObject, Irp );
IoReleaseRemoveLockAndWait( &DeviceExtension->RemoveLock, Irp );
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "IRP_MN_REMOVE_DEVICE is 0x%X", status );
break;
/*case IRP_MN_CANCEL_REMOVE_DEVICE:
status = PnpCancelRemoveDevice( DeviceObject, Irp );
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "IRP_MN_CANCEL_REMOVE_DEVICE is 0x%X", status );
break;
case IRP_MN_SURPRISE_REMOVAL:
status = PnpSurpriseRemoval( DeviceObject, Irp );
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "IRP_MN_SURPRISE_REMOVAL is 0x%X", status );
break;
case IRP_MN_QUERY_CAPABILITIES:
status = PnpQueryCapabilities( DeviceObject, Irp );
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "IRP_MN_QUERY_CAPABILITIES is 0x%X", status );
break;*/
default:
IoSkipCurrentIrpStackLocation( Irp );
status = IoCallDriver(DeviceExtension->LowerDeviceObject, Irp );
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "UkroUSB_DispatchPnP default, ERROR = 0x%X", status );
return status;
}
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "UkroUSB_DispatchPnP is ending, ERROR = 0x%X", status );
return status;
}
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp )
{
KIRQL oldIrql;
KEVENT startDeviceEvent;
NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
PDEVICE_EXTENSION deviceExtension;
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "PnpStartDevice is begining IRP= 0x%X", Irp );
deviceExtension = ( PDEVICE_EXTENSION )DeviceObject->DeviceExtension;
deviceExtension->ConfigurationDescriptor = NULL;
KeInitializeEvent( &startDeviceEvent, NotificationEvent, FALSE );
IoCopyCurrentIrpStackLocationToNext( Irp );
IoSetCompletionRoutine( Irp,
(PIO_COMPLETION_ROUTINE)IrpCompletionRoutine,
(PVOID)&startDeviceEvent,
TRUE,
TRUE,
TRUE );
ntStatus = IoCallDriver( deviceExtension->LowerDeviceObject, Irp );
if ( ntStatus == STATUS_PENDING )
{
KeWaitForSingleObject( &startDeviceEvent,
Executive,
KernelMode,
FALSE,
NULL );
ntStatus = Irp->IoStatus.Status;
}
if( !NT_SUCCESS( ntStatus ) )
{
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "Lower drivers failed this Irp, ERROR = 0x%X", ntStatus );
return ntStatus;
}
ntStatus = IoSetDeviceInterfaceState( &deviceExtension->InterfaceName, TRUE );
if( !NT_SUCCESS( ntStatus ) )
{
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "IoSetDeviceInterfaceState enable = failed, ERROR = 0x%X", ntStatus );
return ntStatus;
}
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "PnpStartDevice is ending IRP= 0x%X, ERROR = 0x%X", Irp, ntStatus );
return ntStatus;
}
NTSTATUS PnpQueryRemoveDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp )
{
KIRQL oldIrql;
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_EXTENSION deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;;
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "PnpQueryRemoveDevice is begining IRP = 0x%X", Irp );
UNREFERENCED_PARAMETER( DeviceObject );
UNREFERENCED_PARAMETER( Irp );
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoSkipCurrentIrpStackLocation( Irp );
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "IoSkipCurrentIrpStackLocation, Irp->IoStatus.Status = 0x%X", Irp->IoStatus.Status );
ntStatus = IoCallDriver( deviceExtension->LowerDeviceObject, Irp ); // ОШИБКА В ЭТОМ МЕСТЕ - СИНИЙ ЭКРАН СМЕРТИ
if ( !NT_SUCCESS( ntStatus ) )
{
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return ntStatus;
}
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "PnpQueryRemoveDevice is ending, ERROR = 0x%X", ntStatus );
return ntStatus;
}
NTSTATUS PnpRemoveDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp )
{
KIRQL oldIrql;
NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
PDEVICE_EXTENSION deviceExtension;
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "PnpRemoveDevice is begining IRP= 0x%X", Irp );
deviceExtension = ( PDEVICE_EXTENSION )DeviceObject->DeviceExtension;
ReleaseMemory( DeviceObject );
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoSkipCurrentIrpStackLocation( Irp );
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "IoSkipCurrentIrpStackLocation, Irp->IoStatus.Status = 0x%X", Irp->IoStatus.Status );
ntStatus = IoCallDriver( deviceExtension->LowerDeviceObject, Irp ); // ОШИБКА В ЭТОМ МЕСТЕ - СИНИЙ ЭКРАН СМЕРТИ (ЕСЛИ НЕТ ОБРАБОТЧИКА PnpQueryRemoveDevice)
if ( !NT_SUCCESS( ntStatus ) )
{
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return ntStatus;
}
IoDetachDevice( deviceExtension->LowerDeviceObject );
IoDeleteDevice( DeviceObject );
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "PnpRemoveDevice is ending ERROR = 0x%X", ntStatus );
return ntStatus;
}
NTSTATUS ReleaseMemory( IN PDEVICE_OBJECT DeviceObject )
{
PDEVICE_EXTENSION deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "ReleaseMemory is begining, DeviceObject = 0x%X", DeviceObject );
if( deviceExtension->ConfigurationDescriptor != NULL )
{
ExFreePool( deviceExtension->ConfigurationDescriptor );
deviceExtension->ConfigurationDescriptor = NULL;
}
DbgPrintEx( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, "ReleaseMemory is ending, DeviceObject = 0x%X", DeviceObject );
return STATUS_SUCCESS;
}
Прошу помощи, что может быть не так, вроде все написал по книге и почти все работает, кроме - извлечения устройства из компьютера ...
Если кто знает - помогите пожалуйста ...
Я поставил синхронизацию с помощью IoReleaseRemoveLockAndWait все объекты удаляются и функция отрабатывает успешно, а вот дальше ... :(
Да, т.к. если комментируешь вызов данной функции - все отрабатывает без проблем, правда не знаю правильно ли ... :confused:, т.к. в DDK написана последовательность команд, которая у меня не работает, а именно вызывает BSOD на IoCallDriver ... :mad: