[NTOSKRNL]

- Fail device initialization if a filter fails to load so the PnP manager can try again later
- Fix some handle leaks
- Reset device node flags after a remove IRP is sent
[I8042PRT|MOUCLASS|KBDCLASS]
- Implement proper support for PnP remove IRPs
See issue #8238 for more details.

svn path=/trunk/; revision=63360
This commit is contained in:
Cameron Gutman 2014-05-18 20:39:54 +00:00
parent 05f75e278b
commit 0e26222a74
6 changed files with 118 additions and 16 deletions

View file

@ -644,6 +644,26 @@ i8042PnpStartDevice(
return Status; return Status;
} }
static VOID
i8042RemoveDevice(
IN PDEVICE_OBJECT DeviceObject)
{
PI8042_DRIVER_EXTENSION DriverExtension;
KIRQL OldIrql;
PFDO_DEVICE_EXTENSION DeviceExtension;
DriverExtension = (PI8042_DRIVER_EXTENSION)IoGetDriverObjectExtension(DeviceObject->DriverObject, DeviceObject->DriverObject);
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
KeAcquireSpinLock(&DriverExtension->DeviceListLock, &OldIrql);
RemoveEntryList(&DeviceExtension->ListEntry);
KeReleaseSpinLock(&DriverExtension->DeviceListLock, OldIrql);
IoDetachDevice(DeviceExtension->LowerDevice);
IoDeleteDevice(DeviceObject);
}
NTSTATUS NTAPI NTSTATUS NTAPI
i8042Pnp( i8042Pnp(
IN PDEVICE_OBJECT DeviceObject, IN PDEVICE_OBJECT DeviceObject,
@ -710,6 +730,23 @@ i8042Pnp(
TRACE_(I8042PRT, "IRP_MJ_PNP / IRP_MN_QUERY_PNP_DEVICE_STATE\n"); TRACE_(I8042PRT, "IRP_MJ_PNP / IRP_MN_QUERY_PNP_DEVICE_STATE\n");
return ForwardIrpAndForget(DeviceObject, Irp); return ForwardIrpAndForget(DeviceObject, Irp);
} }
case IRP_MN_QUERY_REMOVE_DEVICE:
{
TRACE_(I8042PRT, "IRP_MJ_PNP / IRP_MN_QUERY_REMOVE_DEVICE\n");
return ForwardIrpAndForget(DeviceObject, Irp);
}
case IRP_MN_CANCEL_REMOVE_DEVICE:
{
TRACE_(I8042PRT, "IRP_MJ_PNP / IRP_MN_CANCEL_REMOVE_DEVICE\n");
return ForwardIrpAndForget(DeviceObject, Irp);
}
case IRP_MN_REMOVE_DEVICE:
{
TRACE_(I8042PRT, "IRP_MJ_PNP / IRP_MN_REMOVE_DEVICE\n");
Status = ForwardIrpAndForget(DeviceObject, Irp);
i8042RemoveDevice(DeviceObject);
return Status;
}
default: default:
{ {
ERR_(I8042PRT, "IRP_MJ_PNP / unknown minor function 0x%x\n", MinorFunction); ERR_(I8042PRT, "IRP_MJ_PNP / unknown minor function 0x%x\n", MinorFunction);

View file

@ -606,7 +606,7 @@ DestroyPortDriver(
/* Remove from ClassDeviceExtension->ListHead list */ /* Remove from ClassDeviceExtension->ListHead list */
KeAcquireSpinLock(&ClassDeviceExtension->ListSpinLock, &OldIrql); KeAcquireSpinLock(&ClassDeviceExtension->ListSpinLock, &OldIrql);
RemoveHeadList(DeviceExtension->ListEntry.Blink); RemoveEntryList(&DeviceExtension->ListEntry);
KeReleaseSpinLock(&ClassDeviceExtension->ListSpinLock, OldIrql); KeReleaseSpinLock(&ClassDeviceExtension->ListSpinLock, OldIrql);
/* Remove entry from HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\[DeviceBaseName] */ /* Remove entry from HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\[DeviceBaseName] */
@ -865,7 +865,6 @@ ClassPnp(
IoCompleteRequest(Irp, IO_NO_INCREMENT); IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status; return Status;
case IRP_MN_REMOVE_DEVICE:
case IRP_MN_STOP_DEVICE: case IRP_MN_STOP_DEVICE:
if (DeviceExtension->FileHandle) if (DeviceExtension->FileHandle)
{ {
@ -874,6 +873,17 @@ ClassPnp(
} }
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
break; break;
case IRP_MN_REMOVE_DEVICE:
if (DeviceExtension->FileHandle)
{
ZwClose(DeviceExtension->FileHandle);
DeviceExtension->FileHandle = NULL;
}
IoSkipCurrentIrpStackLocation(Irp);
Status = IoCallDriver(DeviceExtension->LowerDevice, Irp);
DestroyPortDriver(DeviceObject);
return Status;
default: default:
Status = Irp->IoStatus.Status; Status = Irp->IoStatus.Status;

View file

@ -582,7 +582,7 @@ DestroyPortDriver(
/* Remove from ClassDeviceExtension->ListHead list */ /* Remove from ClassDeviceExtension->ListHead list */
KeAcquireSpinLock(&ClassDeviceExtension->ListSpinLock, &OldIrql); KeAcquireSpinLock(&ClassDeviceExtension->ListSpinLock, &OldIrql);
RemoveHeadList(DeviceExtension->ListEntry.Blink); RemoveEntryList(&DeviceExtension->ListEntry);
KeReleaseSpinLock(&ClassDeviceExtension->ListSpinLock, OldIrql); KeReleaseSpinLock(&ClassDeviceExtension->ListSpinLock, OldIrql);
/* Remove entry from HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\[DeviceBaseName] */ /* Remove entry from HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\[DeviceBaseName] */
@ -841,7 +841,6 @@ ClassPnp(
IoCompleteRequest(Irp, IO_NO_INCREMENT); IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status; return Status;
case IRP_MN_REMOVE_DEVICE:
case IRP_MN_STOP_DEVICE: case IRP_MN_STOP_DEVICE:
if (DeviceExtension->FileHandle) if (DeviceExtension->FileHandle)
{ {
@ -850,6 +849,17 @@ ClassPnp(
} }
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
break; break;
case IRP_MN_REMOVE_DEVICE:
if (DeviceExtension->FileHandle)
{
ZwClose(DeviceExtension->FileHandle);
DeviceExtension->FileHandle = NULL;
}
IoSkipCurrentIrpStackLocation(Irp);
Status = IoCallDriver(DeviceExtension->LowerDevice, Irp);
DestroyPortDriver(DeviceObject);
return Status;
default: default:
Status = Irp->IoStatus.Status; Status = Irp->IoStatus.Status;

View file

@ -558,6 +558,10 @@ IopAttachFilterDriversCallback(
PLDR_DATA_TABLE_ENTRY ModuleObject; PLDR_DATA_TABLE_ENTRY ModuleObject;
PDRIVER_OBJECT DriverObject; PDRIVER_OBJECT DriverObject;
NTSTATUS Status; NTSTATUS Status;
/* No filter value present */
if (ValueType == REG_NONE)
return STATUS_SUCCESS;
for (Filters = ValueData; for (Filters = ValueData;
((ULONG_PTR)Filters - (ULONG_PTR)ValueData) < ValueLength && ((ULONG_PTR)Filters - (ULONG_PTR)ValueData) < ValueLength &&
@ -578,18 +582,21 @@ IopAttachFilterDriversCallback(
/* Load and initialize the filter driver */ /* Load and initialize the filter driver */
Status = IopLoadServiceModule(&ServiceName, &ModuleObject); Status = IopLoadServiceModule(&ServiceName, &ModuleObject);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
continue; return Status;
Status = IopInitializeDriverModule(DeviceNode, ModuleObject, &ServiceName, Status = IopInitializeDriverModule(DeviceNode, ModuleObject, &ServiceName,
FALSE, &DriverObject); FALSE, &DriverObject);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
continue; return Status;
} }
Status = IopInitializeDevice(DeviceNode, DriverObject); Status = IopInitializeDevice(DeviceNode, DriverObject);
/* Remove extra reference */ /* Remove extra reference */
ObDereferenceObject(DriverObject); ObDereferenceObject(DriverObject);
if (!NT_SUCCESS(Status))
return Status;
} }
return STATUS_SUCCESS; return STATUS_SUCCESS;
@ -645,14 +652,23 @@ IopAttachFilterDrivers(
QueryTable[0].Name = L"LowerFilters"; QueryTable[0].Name = L"LowerFilters";
else else
QueryTable[0].Name = L"UpperFilters"; QueryTable[0].Name = L"UpperFilters";
QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Flags = 0;
QueryTable[0].DefaultType = REG_NONE;
RtlQueryRegistryValues( Status = RtlQueryRegistryValues(
RTL_REGISTRY_HANDLE, RTL_REGISTRY_HANDLE,
(PWSTR)SubKey, (PWSTR)SubKey,
QueryTable, QueryTable,
DeviceNode, DeviceNode,
NULL); NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to load device %s filters: %08X\n",
Lower ? "lower" : "upper", Status);
ZwClose(SubKey);
ZwClose(EnumRootKey);
return Status;
}
/* /*
* Now get the class GUID * Now get the class GUID
@ -696,9 +712,10 @@ IopAttachFilterDrivers(
&Class, KEY_READ); &Class, KEY_READ);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
/* It's okay if there's no class key */
DPRINT1("ZwOpenKey() failed with Status %08X\n", Status); DPRINT1("ZwOpenKey() failed with Status %08X\n", Status);
ZwClose(EnumRootKey); ZwClose(EnumRootKey);
return Status; return STATUS_SUCCESS;
} }
QueryTable[0].QueryRoutine = IopAttachFilterDriversCallback; QueryTable[0].QueryRoutine = IopAttachFilterDriversCallback;
@ -707,9 +724,10 @@ IopAttachFilterDrivers(
else else
QueryTable[0].Name = L"UpperFilters"; QueryTable[0].Name = L"UpperFilters";
QueryTable[0].EntryContext = NULL; QueryTable[0].EntryContext = NULL;
QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Flags = 0;
QueryTable[0].DefaultType = REG_NONE;
RtlQueryRegistryValues( Status = RtlQueryRegistryValues(
RTL_REGISTRY_HANDLE, RTL_REGISTRY_HANDLE,
(PWSTR)SubKey, (PWSTR)SubKey,
QueryTable, QueryTable,
@ -719,6 +737,15 @@ IopAttachFilterDrivers(
/* Clean up */ /* Clean up */
ZwClose(SubKey); ZwClose(SubKey);
ZwClose(EnumRootKey); ZwClose(EnumRootKey);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to load class %s filters: %08X\n",
Lower ? "lower" : "upper", Status);
ZwClose(SubKey);
ZwClose(EnumRootKey);
return Status;
}
} }
return STATUS_SUCCESS; return STATUS_SUCCESS;

View file

@ -275,10 +275,10 @@ PipCallDriverAddDevice(IN PDEVICE_NODE DeviceNode,
EnumRootKey, EnumRootKey,
&DeviceNode->InstancePath, &DeviceNode->InstancePath,
KEY_READ); KEY_READ);
ZwClose(EnumRootKey);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status); DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status);
ZwClose(EnumRootKey);
return Status; return Status;
} }
@ -330,12 +330,17 @@ PipCallDriverAddDevice(IN PDEVICE_NODE DeviceNode,
ClassKey, ClassKey,
&Properties, &Properties,
KEY_READ); KEY_READ);
ZwClose(ClassKey);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
/* No properties */ /* No properties */
DPRINT("IopOpenRegistryKeyEx() failed with Status %08X\n", Status); DPRINT("IopOpenRegistryKeyEx() failed with Status %08X\n", Status);
PropertiesKey = NULL; PropertiesKey = NULL;
} }
else
{
ZwClose(PropertiesKey);
}
} }
/* Free the registry data */ /* Free the registry data */
@ -343,11 +348,22 @@ PipCallDriverAddDevice(IN PDEVICE_NODE DeviceNode,
} }
/* Do ReactOS-style setup */ /* Do ReactOS-style setup */
IopAttachFilterDrivers(DeviceNode, TRUE); Status = IopAttachFilterDrivers(DeviceNode, TRUE);
if (!NT_SUCCESS(Status))
{
IopRemoveDevice(DeviceNode);
return Status;
}
Status = IopInitializeDevice(DeviceNode, DriverObject); Status = IopInitializeDevice(DeviceNode, DriverObject);
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
IopAttachFilterDrivers(DeviceNode, FALSE); Status = IopAttachFilterDrivers(DeviceNode, FALSE);
if (!NT_SUCCESS(Status))
{
IopRemoveDevice(DeviceNode);
return Status;
}
Status = IopStartDevice(DeviceNode); Status = IopStartDevice(DeviceNode);
} }

View file

@ -580,7 +580,11 @@ IopSendRemoveDevice(IN PDEVICE_OBJECT DeviceObject)
{ {
IO_STACK_LOCATION Stack; IO_STACK_LOCATION Stack;
PVOID Dummy; PVOID Dummy;
PDEVICE_NODE DeviceNode = IopGetDeviceNode(DeviceObject);
/* Drop all our state for this device in case it isn't really going away */
DeviceNode->Flags &= DNF_ENUMERATED | DNF_PROCESSED;
RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION)); RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
Stack.MajorFunction = IRP_MJ_PNP; Stack.MajorFunction = IRP_MJ_PNP;
Stack.MinorFunction = IRP_MN_REMOVE_DEVICE; Stack.MinorFunction = IRP_MN_REMOVE_DEVICE;
@ -4537,8 +4541,6 @@ IopPrepareDeviceForRemoval(IN PDEVICE_OBJECT DeviceObject, BOOLEAN Force)
return Status; return Status;
} }
DeviceNode->Flags |= DNF_WILL_BE_REMOVED;
DeviceNode->Problem = CM_PROB_WILL_BE_REMOVED;
if (DeviceRelations) if (DeviceRelations)
IopSendRemoveDeviceRelations(DeviceRelations); IopSendRemoveDeviceRelations(DeviceRelations);
IopSendRemoveChildDevices(DeviceNode); IopSendRemoveChildDevices(DeviceNode);