NTSTATUS
IopPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject, BOOLEAN Force);
+PDEVICE_OBJECT
+IopGetDeviceObjectFromDeviceInstance(PUNICODE_STRING DeviceInstance);
+
PDEVICE_NODE
FASTCALL
IopGetDeviceNode(PDEVICE_OBJECT DeviceObject)
VOID
IopFixupDeviceId(PWCHAR String)
{
- ULONG Length = wcslen(String), i;
+ SIZE_T Length = wcslen(String), i;
for (i = 0; i < Length; i++)
{
&DeviceNode->InstancePath,
Status);
IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
+ DeviceNode->Problem = CM_PROB_FAILED_ADD;
return Status;
}
ASSERT(!(DeviceNode->Flags & DNF_DISABLED));
- /* Build the I/O stack locaiton */
+ /* Build the I/O stack location */
RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
Stack.MajorFunction = IRP_MJ_PNP;
Stack.MinorFunction = IRP_MN_START_DEVICE;
/* Set the appropriate flag */
DeviceNode->Flags |= DNF_START_FAILED;
+ DeviceNode->Problem = CM_PROB_FAILED_START;
DPRINT1("Warning: PnP Start failed (%wZ) [Status: 0x%x]\n", &DeviceNode->InstancePath, Status);
return;
UNICODE_STRING KeyName, ClassName;
PUNICODE_STRING ServiceName1;
ULONG LegacyValue;
-#if 0
UNICODE_STRING ClassGUID;
-#endif
HANDLE InstanceHandle;
DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
{
RtlInitUnicodeString(&KeyName, L"Class");
- RtlInitUnicodeString(&ClassName, L"LegacyDriver");
- Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ClassName.Buffer, ClassName.Length);
-#if 0
+ RtlInitUnicodeString(&ClassName, L"LegacyDriver\0");
+ Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ClassName.Buffer, ClassName.Length + sizeof(UNICODE_NULL));
if (NT_SUCCESS(Status))
{
RtlInitUnicodeString(&KeyName, L"ClassGUID");
- RtlInitUnicodeString(&ClassGUID, L"{8ECC055D-047F-11D1-A537-0000F8753ED1}");
- Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ClassGUID.Buffer, ClassGUID.Length);
+ RtlInitUnicodeString(&ClassGUID, L"{8ECC055D-047F-11D1-A537-0000F8753ED1}\0");
+ Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ClassGUID.Buffer, ClassGUID.Length + sizeof(UNICODE_NULL));
+ if (NT_SUCCESS(Status))
+ {
+ RtlInitUnicodeString(&KeyName, L"DeviceDesc");
+
+ Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ServiceName1->Buffer, ServiceName1->Length + sizeof(UNICODE_NULL));
+ }
}
-#endif
}
}
/* All children must be deleted before a parent is deleted */
ASSERT(!DeviceNode->Child);
-
- KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
-
ASSERT(DeviceNode->PhysicalDeviceObject);
- ObDereferenceObject(DeviceNode->PhysicalDeviceObject);
+ KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
/* Get previous sibling */
if (DeviceNode->Parent && DeviceNode->Parent->Child != DeviceNode)
DPRINT("Context 0x%p\n", Context);
- DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
+ DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %p Context 0x%p)\n",
Context->DeviceNode, Context->FirstDeviceNode, Context->Action, Context->Context);
/* Start from the specified device node */
HANDLE InstanceKey = NULL;
UNICODE_STRING ValueName;
UNICODE_STRING ParentIdPrefix = { 0, 0, NULL };
+ UNICODE_STRING InstancePathU;
DEVICE_CAPABILITIES DeviceCapabilities;
+ PDEVICE_OBJECT OldDeviceObject;
DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode, Context);
DPRINT("PDO 0x%p\n", DeviceNode->PhysicalDeviceObject);
}
RtlFreeUnicodeString(&ParentIdPrefix);
- if (!RtlCreateUnicodeString(&DeviceNode->InstancePath, InstancePath))
+ if (!RtlCreateUnicodeString(&InstancePathU, InstancePath))
{
DPRINT("No resources\n");
/* FIXME: Cleanup and disable device */
}
+ /* Verify that this is not a duplicate */
+ OldDeviceObject = IopGetDeviceObjectFromDeviceInstance(&InstancePathU);
+ if (OldDeviceObject != NULL)
+ {
+ PDEVICE_NODE OldDeviceNode = IopGetDeviceNode(OldDeviceObject);
+
+ DPRINT1("Duplicate device instance '%wZ'\n", &InstancePathU);
+ DPRINT1("Current instance parent: '%wZ'\n", &DeviceNode->Parent->InstancePath);
+ DPRINT1("Old instance parent: '%wZ'\n", &OldDeviceNode->Parent->InstancePath);
+
+ KeBugCheckEx(PNP_DETECTED_FATAL_ERROR,
+ 0x01,
+ (ULONG_PTR)DeviceNode->PhysicalDeviceObject,
+ (ULONG_PTR)OldDeviceObject,
+ 0);
+ }
+
+ DeviceNode->InstancePath = InstancePathU;
+
DPRINT("InstancePath is %S\n", DeviceNode->InstancePath.Buffer);
/*
&DeviceNode->InstancePath);
}
- DeviceNode->Flags &= ~DNF_NEED_TO_ENUM;
-
DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
Stack.Parameters.QueryDeviceRelations.Type = BusRelations;
}
else
{
+ DeviceNode->Problem = CM_PROB_FAILED_INSTALL;
IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
}
return STATUS_SUCCESS;
/* Initialize the driver */
Status = IopInitializeDriverModule(DeviceNode, ModuleObject,
&DeviceNode->ServiceName, FALSE, &DriverObject);
+ if (!NT_SUCCESS(Status)) DeviceNode->Problem = CM_PROB_FAILED_DRIVER_ENTRY;
+ }
+ else if (Status == STATUS_DRIVER_UNABLE_TO_LOAD)
+ {
+ DPRINT1("Service '%wZ' is disabled\n", &DeviceNode->ServiceName);
+ DeviceNode->Problem = CM_PROB_DISABLED_SERVICE;
}
else
{
DPRINT("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
&DeviceNode->ServiceName, Status);
+ if (!BootDrivers) DeviceNode->Problem = CM_PROB_DRIVER_FAILED_LOAD;
}
}
Status = PipCallDriverAddDevice(DeviceNode, FALSE, DriverObject);
/* Remove the extra reference */
- //ObDereferenceObject(DriverObject);
+ ObDereferenceObject(DriverObject);
}
else
{
if (!BootDrivers)
{
IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
- IopDeviceNodeSetFlag(DeviceNode, DNF_START_FAILED);
- /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
- DPRINT1("Initialization of service %S failed (Status %x)\n",
- DeviceNode->ServiceName.Buffer, Status);
}
}
}
#define PIP_RETURN_DATA(x, y) {ReturnLength = x; Data = y; Status = STATUS_SUCCESS; break;}
#define PIP_REGISTRY_DATA(x, y) {ValueName = x; ValueType = y; break;}
-#define PIP_UNIMPLEMENTED() {UNIMPLEMENTED; while(TRUE); break;}
+#define PIP_UNIMPLEMENTED() {UNIMPLEMENTED_DBGBREAK(); break;}
/*
* @implemented
if ((PnPFlags & PNP_DEVICE_REMOVED) ||
((PnPFlags & PNP_DEVICE_FAILED) && !(PnPFlags & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED)))
{
- /* Surprise removal */
-
+ /* Flag it if it's failed */
+ if (PnPFlags & PNP_DEVICE_FAILED) DeviceNode->Problem = CM_PROB_FAILED_POST_START;
+
+ /* Send removal IRPs to all of its children */
+ IopPrepareDeviceForRemoval(PhysicalDeviceObject, TRUE);
+
+ /* Send surprise removal */
IopSendSurpriseRemoval(PhysicalDeviceObject);
/* Tell the user-mode PnP manager that a device was removed */
else if ((PnPFlags & PNP_DEVICE_FAILED) && (PnPFlags & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED))
{
/* Stop for resource rebalance */
-
Status = IopStopDevice(DeviceNode);
if (!NT_SUCCESS(Status))
{
}
Stack.Parameters.QueryDeviceRelations.Type = RemovalRelations;
-
+
Status = IopInitiatePnpIrp(DeviceObject,
&IoStatusBlock,
IRP_MN_QUERY_DEVICE_RELATIONS,
{
DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
}
-
+
if (DeviceRelations)
{
Status = IopQueryRemoveDeviceRelations(DeviceRelations, Force);
}
DeviceNode->Flags |= DNF_WILL_BE_REMOVED;
+ DeviceNode->Problem = CM_PROB_WILL_BE_REMOVED;
if (DeviceRelations)
IopSendRemoveDeviceRelations(DeviceRelations);
IopSendRemoveChildDevices(DeviceNode);
if (DeviceRelations)
IopSendRemoveDeviceRelations(DeviceRelations);
IopSendRemoveChildDevices(DeviceNode);
-
+
+ DeviceNode->Problem = CM_PROB_HELD_FOR_EJECT;
if (Capabilities.EjectSupported)
{
if (IopSendEject(PhysicalDeviceObject) != STATUS_SUCCESS)