IopCancelPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject);
NTSTATUS
-IopPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject);
+IopPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject, BOOLEAN Force);
PDEVICE_NODE
FASTCALL
return Status;
}
- /* Check if driver added a FDO above the PDO */
Fdo = IoGetAttachedDeviceReference(DeviceNode->PhysicalDeviceObject);
- if (Fdo == DeviceNode->PhysicalDeviceObject)
- {
- /* FIXME: What do we do? Unload the driver or just disable the device? */
- DPRINT1("An FDO was not attached\n");
- ObDereferenceObject(Fdo);
- IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
- return STATUS_UNSUCCESSFUL;
- }
/* Check if we have a ACPI device (needed for power management) */
if (Fdo->DeviceType == FILE_DEVICE_ACPI)
NewList = ExAllocatePool(PagedPool, NewSize);
if (!NewList) {
- /* Fail */
- ExFreePool(PnpBusTypeGuidList);
- goto Quickie;
+ /* Fail */
+ ExFreePool(PnpBusTypeGuidList);
+ goto Quickie;
}
/* Now copy them, decrease the size too */
/*
* DESCRIPTION
- * Creates a device node
+ * Creates a device node
*
* ARGUMENTS
* ParentNode = Pointer to parent device node
* DeviceNode = Pointer to storage for created device node
*
* RETURN VALUE
- * Status
+ * Status
*/
NTSTATUS
IopCreateDeviceNode(PDEVICE_NODE ParentNode,
RtlInitUnicodeString(&ValueName, L"HardwareID");
Status = ZwSetValueKey(InstanceKey,
- &ValueName,
- 0,
- REG_MULTI_SZ,
- (PVOID)IoStatusBlock.Information,
- (TotalLength + 1) * sizeof(WCHAR));
+ &ValueName,
+ 0,
+ REG_MULTI_SZ,
+ (PVOID)IoStatusBlock.Information,
+ (TotalLength + 1) * sizeof(WCHAR));
if (!NT_SUCCESS(Status))
{
DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status);
}
}
- if (!Found)
+ if (!Found && !(Child->Flags & DNF_WILL_BE_REMOVED))
{
+ /* Send removal IRPs to all of its children */
+ IopPrepareDeviceForRemoval(Child->PhysicalDeviceObject, TRUE);
+
+ /* Send the surprise removal IRP */
IopSendSurpriseRemoval(Child->PhysicalDeviceObject);
/* Tell the user-mode PnP manager that a device was removed */
IopQueueTargetDeviceEvent(&GUID_DEVICE_SURPRISE_REMOVAL,
&Child->InstancePath);
+ /* Send the remove device IRP */
IopSendRemoveDevice(Child->PhysicalDeviceObject);
}
static
NTSTATUS
-IopQueryRemoveChildDevices(PDEVICE_NODE ParentDeviceNode)
+IopQueryRemoveChildDevices(PDEVICE_NODE ParentDeviceNode, BOOLEAN Force)
{
PDEVICE_NODE ChildDeviceNode, NextDeviceNode, FailedRemoveDevice;
NTSTATUS Status;
NextDeviceNode = ChildDeviceNode->Sibling;
KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
- Status = IopPrepareDeviceForRemoval(ChildDeviceNode->PhysicalDeviceObject);
+ Status = IopPrepareDeviceForRemoval(ChildDeviceNode->PhysicalDeviceObject, Force);
if (!NT_SUCCESS(Status))
{
FailedRemoveDevice = ChildDeviceNode;
static
NTSTATUS
-IopQueryRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations)
+IopQueryRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations, BOOLEAN Force)
{
/* This function DOES NOT dereference the device objects on SUCCESS
* but it DOES dereference device objects on FAILURE */
for (i = 0; i < DeviceRelations->Count; i++)
{
- Status = IopPrepareDeviceForRemoval(DeviceRelations->Objects[i]);
+ Status = IopPrepareDeviceForRemoval(DeviceRelations->Objects[i], Force);
if (!NT_SUCCESS(Status))
{
j = i;
}
NTSTATUS
-IopPrepareDeviceForRemoval(IN PDEVICE_OBJECT DeviceObject)
+IopPrepareDeviceForRemoval(IN PDEVICE_OBJECT DeviceObject, BOOLEAN Force)
{
PDEVICE_NODE DeviceNode = IopGetDeviceNode(DeviceObject);
IO_STACK_LOCATION Stack;
PDEVICE_RELATIONS DeviceRelations;
NTSTATUS Status;
- if (DeviceNode->UserFlags & DNUF_NOT_DISABLEABLE)
+ if ((DeviceNode->UserFlags & DNUF_NOT_DISABLEABLE) && !Force)
{
DPRINT1("Removal not allowed for %wZ\n", &DeviceNode->InstancePath);
return STATUS_UNSUCCESSFUL;
}
- if (IopQueryRemoveDevice(DeviceObject) != STATUS_SUCCESS)
+ if (!Force && IopQueryRemoveDevice(DeviceObject) != STATUS_SUCCESS)
{
DPRINT1("Removal vetoed by failing the query remove request\n");
if (DeviceRelations)
{
- Status = IopQueryRemoveDeviceRelations(DeviceRelations);
+ Status = IopQueryRemoveDeviceRelations(DeviceRelations, Force);
if (!NT_SUCCESS(Status))
return Status;
}
-
- Status = IopQueryRemoveChildDevices(DeviceNode);
+
+ Status = IopQueryRemoveChildDevices(DeviceNode, Force);
if (!NT_SUCCESS(Status))
{
if (DeviceRelations)
IopCancelRemoveDeviceRelations(DeviceRelations);
return Status;
}
-
+
+ DeviceNode->Flags |= DNF_WILL_BE_REMOVED;
if (DeviceRelations)
IopSendRemoveDeviceRelations(DeviceRelations);
IopSendRemoveChildDevices(DeviceNode);
DPRINT("Removing device: %wZ\n", &DeviceNode->InstancePath);
- Status = IopPrepareDeviceForRemoval(DeviceNode->PhysicalDeviceObject);
+ Status = IopPrepareDeviceForRemoval(DeviceNode->PhysicalDeviceObject, FALSE);
if (NT_SUCCESS(Status))
{
IopSendRemoveDevice(DeviceNode->PhysicalDeviceObject);
IopQueueTargetDeviceEvent(&GUID_DEVICE_SAFE_REMOVAL,
&DeviceNode->InstancePath);
- DeviceNode->Flags |= DNF_WILL_BE_REMOVED;
return STATUS_SUCCESS;
}
if (DeviceRelations)
{
- Status = IopQueryRemoveDeviceRelations(DeviceRelations);
+ Status = IopQueryRemoveDeviceRelations(DeviceRelations, FALSE);
if (!NT_SUCCESS(Status))
goto cleanup;
}
- Status = IopQueryRemoveChildDevices(DeviceNode);
+ Status = IopQueryRemoveChildDevices(DeviceNode, FALSE);
if (!NT_SUCCESS(Status))
{
if (DeviceRelations)
goto cleanup;
}
- if (IopPrepareDeviceForRemoval(PhysicalDeviceObject) != STATUS_SUCCESS)
+ if (IopPrepareDeviceForRemoval(PhysicalDeviceObject, FALSE) != STATUS_SUCCESS)
{
if (DeviceRelations)
IopCancelRemoveDeviceRelations(DeviceRelations);