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++)
{
while (*IdBuffer)
{
- ULONG StringLength = (ULONG)wcslen(IdBuffer) + 1, Index;
+ USHORT StringLength = (USHORT)wcslen(IdBuffer) + 1, Index;
IopFixupDeviceId(IdBuffer);
ChildIdNameU.Buffer = IdBuffer;
ChildIdNameU.MaximumLength = ChildIdNameU.Length = (StringLength - 1) * sizeof(WCHAR);
RegKeyNameU.Buffer = BasicInfo->Name;
- RegKeyNameU.MaximumLength = RegKeyNameU.Length = BasicInfo->NameLength;
+ RegKeyNameU.MaximumLength = RegKeyNameU.Length = (USHORT)BasicInfo->NameLength;
if (RtlEqualUnicodeString(&ChildIdNameU, &RegKeyNameU, TRUE))
{
&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
}
}
{
KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
Node->Parent = ParentNode;
- Node->Sibling = ParentNode->Child;
- ParentNode->Child = Node;
+ Node->Sibling = NULL;
if (ParentNode->LastChild == NULL)
+ {
+ ParentNode->Child = Node;
ParentNode->LastChild = Node;
+ }
+ else
+ {
+ ParentNode->LastChild->Sibling = Node;
+ ParentNode->LastChild = Node;
+ }
KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
Node->Level = ParentNode->Level + 1;
}
/* 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)
NULL);
Status = IoStatusBlock.Status;
}
-
+
+ /* Remove the reference */
+ ObDereferenceObject(TopDeviceObject);
+
/* Return the information */
*Information = (PVOID)IoStatusBlock.Information;
return Status;
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;
if (NT_SUCCESS(IopQueryDeviceCapabilities(DeviceNode, &DeviceCaps)) &&
DeviceCaps.RawDeviceOK)
{
- DPRINT1("%wZ is using parent bus driver (%wZ)\n", &DeviceNode->InstancePath, &ParentDeviceNode->ServiceName);
+ DPRINT("%wZ is using parent bus driver (%wZ)\n", &DeviceNode->InstancePath, &ParentDeviceNode->ServiceName);
DeviceNode->ServiceName.Length = 0;
DeviceNode->ServiceName.MaximumLength = 0;
}
else
{
+ DeviceNode->Problem = CM_PROB_FAILED_INSTALL;
IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
}
return STATUS_SUCCESS;
if (NT_SUCCESS(Status) || Status == STATUS_IMAGE_ALREADY_LOADED)
{
- /* STATUS_IMAGE_ALREADY_LOADED means this driver
- was loaded by the bootloader */
- if ((Status != STATUS_IMAGE_ALREADY_LOADED) ||
- (Status == STATUS_IMAGE_ALREADY_LOADED && !DriverObject))
- {
- /* Initialize the driver */
- Status = IopInitializeDriverModule(DeviceNode, ModuleObject,
+ /* Initialize the driver */
+ Status = IopInitializeDriverModule(DeviceNode, ModuleObject,
&DeviceNode->ServiceName, FALSE, &DriverObject);
- }
- else
- {
- Status = STATUS_SUCCESS;
- }
+ 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
{
- DPRINT1("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
+ DPRINT("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
&DeviceNode->ServiceName, Status);
+ if (!BootDrivers) DeviceNode->Problem = CM_PROB_DRIVER_FAILED_LOAD;
}
}
{
/* Initialize the device, including all filters */
Status = PipCallDriverAddDevice(DeviceNode, FALSE, DriverObject);
+
+ /* Remove the extra reference */
+ 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);
}
}
}
ULONG BootResourcesLength;
NTSTATUS Status;
- const UNICODE_STRING IdentifierPci = RTL_CONSTANT_STRING(L"PCI");
- UNICODE_STRING HardwareIdPci = RTL_CONSTANT_STRING(L"*PNP0A03\0");
- static ULONG DeviceIndexPci = 0;
const UNICODE_STRING IdentifierSerial = RTL_CONSTANT_STRING(L"SerialController");
UNICODE_STRING HardwareIdSerial = RTL_CONSTANT_STRING(L"*PNP0501\0");
static ULONG DeviceIndexSerial = 0;
const UNICODE_STRING IdentifierFloppy = RTL_CONSTANT_STRING(L"FloppyDiskPeripheral");
UNICODE_STRING HardwareIdFloppy = RTL_CONSTANT_STRING(L"*PNP0700\0");
static ULONG DeviceIndexFloppy = 0;
- const UNICODE_STRING IdentifierIsa = RTL_CONSTANT_STRING(L"ISA");
- UNICODE_STRING HardwareIdIsa = RTL_CONSTANT_STRING(L"*PNP0A00\0");
- static ULONG DeviceIndexIsa = 0;
UNICODE_STRING HardwareIdKey;
PUNICODE_STRING pHardwareId;
ULONG DeviceIndex = 0;
pHardwareId = &HardwareIdFloppy;
DeviceIndex = DeviceIndexFloppy++;
}
- else if (NT_SUCCESS(Status))
- {
- /* Try to also match the device identifier */
- if (RtlCompareUnicodeString(&ValueName, &IdentifierPci, FALSE) == 0)
- {
- pHardwareId = &HardwareIdPci;
- DeviceIndex = DeviceIndexPci++;
- }
- else if (RtlCompareUnicodeString(&ValueName, &IdentifierIsa, FALSE) == 0)
- {
- pHardwareId = &HardwareIdIsa;
- DeviceIndex = DeviceIndexIsa++;
- }
- else
- {
- DPRINT("Unknown device '%wZ'\n", &ValueName);
- goto nextdevice;
- }
- }
else
{
/* Unknown key path */
#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)