- 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
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
i8042Pnp(
IN PDEVICE_OBJECT DeviceObject,
TRACE_(I8042PRT, "IRP_MJ_PNP / IRP_MN_QUERY_PNP_DEVICE_STATE\n");
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:
{
ERR_(I8042PRT, "IRP_MJ_PNP / unknown minor function 0x%x\n", MinorFunction);
/* Remove from ClassDeviceExtension->ListHead list */
KeAcquireSpinLock(&ClassDeviceExtension->ListSpinLock, &OldIrql);
- RemoveHeadList(DeviceExtension->ListEntry.Blink);
+ RemoveEntryList(&DeviceExtension->ListEntry);
KeReleaseSpinLock(&ClassDeviceExtension->ListSpinLock, OldIrql);
/* Remove entry from HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\[DeviceBaseName] */
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
- case IRP_MN_REMOVE_DEVICE:
case IRP_MN_STOP_DEVICE:
if (DeviceExtension->FileHandle)
{
}
Status = STATUS_SUCCESS;
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:
Status = Irp->IoStatus.Status;
/* Remove from ClassDeviceExtension->ListHead list */
KeAcquireSpinLock(&ClassDeviceExtension->ListSpinLock, &OldIrql);
- RemoveHeadList(DeviceExtension->ListEntry.Blink);
+ RemoveEntryList(&DeviceExtension->ListEntry);
KeReleaseSpinLock(&ClassDeviceExtension->ListSpinLock, OldIrql);
/* Remove entry from HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\[DeviceBaseName] */
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
- case IRP_MN_REMOVE_DEVICE:
case IRP_MN_STOP_DEVICE:
if (DeviceExtension->FileHandle)
{
}
Status = STATUS_SUCCESS;
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:
Status = Irp->IoStatus.Status;
PLDR_DATA_TABLE_ENTRY ModuleObject;
PDRIVER_OBJECT DriverObject;
NTSTATUS Status;
+
+ /* No filter value present */
+ if (ValueType == REG_NONE)
+ return STATUS_SUCCESS;
for (Filters = ValueData;
((ULONG_PTR)Filters - (ULONG_PTR)ValueData) < ValueLength &&
/* Load and initialize the filter driver */
Status = IopLoadServiceModule(&ServiceName, &ModuleObject);
if (!NT_SUCCESS(Status))
- continue;
+ return Status;
Status = IopInitializeDriverModule(DeviceNode, ModuleObject, &ServiceName,
FALSE, &DriverObject);
if (!NT_SUCCESS(Status))
- continue;
+ return Status;
}
Status = IopInitializeDevice(DeviceNode, DriverObject);
/* Remove extra reference */
ObDereferenceObject(DriverObject);
+
+ if (!NT_SUCCESS(Status))
+ return Status;
}
return STATUS_SUCCESS;
QueryTable[0].Name = L"LowerFilters";
else
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,
(PWSTR)SubKey,
QueryTable,
DeviceNode,
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
&Class, KEY_READ);
if (!NT_SUCCESS(Status))
{
+ /* It's okay if there's no class key */
DPRINT1("ZwOpenKey() failed with Status %08X\n", Status);
ZwClose(EnumRootKey);
- return Status;
+ return STATUS_SUCCESS;
}
QueryTable[0].QueryRoutine = IopAttachFilterDriversCallback;
else
QueryTable[0].Name = L"UpperFilters";
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,
(PWSTR)SubKey,
QueryTable,
/* Clean up */
ZwClose(SubKey);
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;
EnumRootKey,
&DeviceNode->InstancePath,
KEY_READ);
+ ZwClose(EnumRootKey);
if (!NT_SUCCESS(Status))
{
DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status);
- ZwClose(EnumRootKey);
return Status;
}
ClassKey,
&Properties,
KEY_READ);
+ ZwClose(ClassKey);
if (!NT_SUCCESS(Status))
{
/* No properties */
DPRINT("IopOpenRegistryKeyEx() failed with Status %08X\n", Status);
PropertiesKey = NULL;
}
+ else
+ {
+ ZwClose(PropertiesKey);
+ }
}
/* Free the registry data */
}
/* Do ReactOS-style setup */
- IopAttachFilterDrivers(DeviceNode, TRUE);
+ Status = IopAttachFilterDrivers(DeviceNode, TRUE);
+ if (!NT_SUCCESS(Status))
+ {
+ IopRemoveDevice(DeviceNode);
+ return Status;
+ }
Status = IopInitializeDevice(DeviceNode, DriverObject);
if (NT_SUCCESS(Status))
{
- IopAttachFilterDrivers(DeviceNode, FALSE);
+ Status = IopAttachFilterDrivers(DeviceNode, FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ IopRemoveDevice(DeviceNode);
+ return Status;
+ }
+
Status = IopStartDevice(DeviceNode);
}
{
IO_STACK_LOCATION Stack;
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));
Stack.MajorFunction = IRP_MJ_PNP;
Stack.MinorFunction = IRP_MN_REMOVE_DEVICE;
return Status;
}
- DeviceNode->Flags |= DNF_WILL_BE_REMOVED;
- DeviceNode->Problem = CM_PROB_WILL_BE_REMOVED;
if (DeviceRelations)
IopSendRemoveDeviceRelations(DeviceRelations);
IopSendRemoveChildDevices(DeviceNode);