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++)
{
PKEY_VALUE_PARTIAL_INFORMATION PartialInfo;
ULONG HidLength = 0, CidLength = 0, BufferLength;
PWCHAR IdBuffer, OriginalIdBuffer;
-
+
/* Open the device instance key */
Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, 0, &InstanceKey);
if (Status != STATUS_SUCCESS)
ZwClose(InstanceKey);
return;
}
-
+
/* Copy CID next */
CidLength = PartialInfo->DataLength;
RtlCopyMemory(((PUCHAR)IdBuffer) + HidLength, PartialInfo->Data, CidLength);
/* Free our temp buffer */
ExFreePool(PartialInfo);
-
+
InitializeObjectAttributes(&ObjectAttributes,
&CriticalDeviceKeyU,
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
while (*IdBuffer)
{
- ULONG StringLength = (ULONG)wcslen(IdBuffer) + 1, Index;
-
+ USHORT StringLength = (USHORT)wcslen(IdBuffer) + 1, Index;
+
IopFixupDeviceId(IdBuffer);
-
+
/* Look through all subkeys for a match */
for (Index = 0; TRUE; Index++)
{
ULONG NeededLength;
PKEY_BASIC_INFORMATION BasicInfo;
-
+
Status = ZwEnumerateKey(CriticalDeviceKey,
Index,
KeyBasicInformation,
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))
{
/* Advance to the next ID */
IdBuffer += StringLength;
}
-
+
ExFreePool(OriginalIdBuffer);
ZwClose(InstanceKey);
ZwClose(CriticalDeviceKey);
{
PDEVICE_OBJECT Fdo;
NTSTATUS Status;
-
+
if (!DriverObject)
{
/* Special case for bus driven devices */
&DeviceNode->InstancePath,
Status);
IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
+ DeviceNode->Problem = CM_PROB_FAILED_ADD;
return Status;
}
{
IO_STACK_LOCATION Stack;
PVOID Dummy;
-
+
RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
Stack.MajorFunction = IRP_MJ_PNP;
Stack.MinorFunction = IRP_MN_EJECT;
-
+
return IopSynchronousCall(DeviceObject, &Stack, &Dummy);
}
{
IO_STACK_LOCATION Stack;
PVOID Dummy;
-
+
RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
Stack.MajorFunction = IRP_MJ_PNP;
Stack.MinorFunction = IRP_MN_SURPRISE_REMOVAL;
-
+
/* Drivers should never fail a IRP_MN_SURPRISE_REMOVAL request */
IopSynchronousCall(DeviceObject, &Stack, &Dummy);
}
IO_STACK_LOCATION Stack;
PVOID Dummy;
NTSTATUS Status;
-
+
ASSERT(DeviceNode);
-
+
IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVE_PENDING,
&DeviceNode->InstancePath);
-
+
RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
Stack.MajorFunction = IRP_MJ_PNP;
Stack.MinorFunction = IRP_MN_QUERY_REMOVE_DEVICE;
&GUID_TARGET_DEVICE_QUERY_REMOVE,
NULL,
NULL);
-
+
if (!NT_SUCCESS(Status))
{
DPRINT1("Removal vetoed by %wZ\n", &DeviceNode->InstancePath);
{
IO_STACK_LOCATION Stack;
PVOID Dummy;
-
+
RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
Stack.MajorFunction = IRP_MJ_PNP;
Stack.MinorFunction = IRP_MN_QUERY_STOP_DEVICE;
-
+
return IopSynchronousCall(DeviceObject, &Stack, &Dummy);
}
{
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;
&GUID_TARGET_DEVICE_REMOVE_COMPLETE,
NULL,
NULL);
+ ObDereferenceObject(DeviceObject);
}
static
{
IO_STACK_LOCATION Stack;
PVOID Dummy;
-
+
RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
Stack.MajorFunction = IRP_MJ_PNP;
Stack.MinorFunction = IRP_MN_CANCEL_REMOVE_DEVICE;
-
+
/* Drivers should never fail a IRP_MN_CANCEL_REMOVE_DEVICE request */
IopSynchronousCall(DeviceObject, &Stack, &Dummy);
-
+
IopNotifyPlugPlayNotification(DeviceObject,
EventCategoryTargetDeviceChange,
&GUID_TARGET_DEVICE_REMOVE_CANCELLED,
{
IO_STACK_LOCATION Stack;
PVOID Dummy;
-
+
RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
Stack.MajorFunction = IRP_MJ_PNP;
Stack.MinorFunction = IRP_MN_STOP_DEVICE;
-
+
/* Drivers should never fail a IRP_MN_STOP_DEVICE request */
IopSynchronousCall(DeviceObject, &Stack, &Dummy);
}
NTSTATUS Status;
PVOID Dummy;
DEVICE_CAPABILITIES DeviceCapabilities;
-
+
/* Get the device node */
DeviceNode = IopGetDeviceNode(DeviceObject);
-
+
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;
-
+
Stack.Parameters.StartDevice.AllocatedResources =
DeviceNode->ResourceList;
Stack.Parameters.StartDevice.AllocatedResourcesTranslated =
/* 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;
}
-
+
DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after start)\n");
Status = IopQueryDeviceCapabilities(DeviceNode, &DeviceCapabilities);
/* Invalidate device state so IRP_MN_QUERY_PNP_DEVICE_STATE is sent */
IoInvalidateDeviceState(DeviceObject);
-
+
/* Otherwise, mark us as started */
DeviceNode->Flags |= DNF_STARTED;
DeviceNode->Flags &= ~DNF_STOPPED;
PDEVICE_OBJECT DeviceObject;
NTSTATUS Status;
PAGED_CODE();
-
+
/* Sanity check */
ASSERT((DeviceNode->Flags & DNF_ADDED));
ASSERT((DeviceNode->Flags & (DNF_RESOURCE_ASSIGNED |
DNF_RESOURCE_REPORTED |
DNF_NO_RESOURCE_REQUIRED)));
-
+
/* Get the device object */
DeviceObject = DeviceNode->PhysicalDeviceObject;
-
+
/* Check if we're not started yet */
if (!(DeviceNode->Flags & DNF_STARTED))
{
/* Start us */
IopStartDevice2(DeviceObject);
}
-
+
/* Do we need to query IDs? This happens in the case of manual reporting */
#if 0
if (DeviceNode->Flags & DNF_NEED_QUERY_IDS)
ASSERT(FALSE);
}
#endif
-
+
/* Make sure we're started, and check if we need enumeration */
if ((DeviceNode->Flags & DNF_STARTED) &&
(DeviceNode->Flags & DNF_NEED_ENUMERATION_ONLY))
/* Nothing to do */
Status = STATUS_SUCCESS;
}
-
+
/* Return */
return Status;
}
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)
NTSTATUS Status;
PDEVICE_OBJECT TopDeviceObject;
PAGED_CODE();
-
+
/* Call the top of the device stack */
TopDeviceObject = IoGetAttachedDeviceReference(DeviceObject);
-
+
/* Allocate an IRP */
Irp = IoAllocateIrp(TopDeviceObject->StackSize, FALSE);
if (!Irp) return STATUS_INSUFFICIENT_RESOURCES;
-
+
/* Initialize to failure */
Irp->IoStatus.Status = IoStatusBlock.Status = STATUS_NOT_SUPPORTED;
Irp->IoStatus.Information = IoStatusBlock.Information = 0;
-
+
/* Special case for IRP_MN_FILTER_RESOURCE_REQUIREMENTS */
if (IoStackLocation->MinorFunction == IRP_MN_FILTER_RESOURCE_REQUIREMENTS)
{
Irp->IoStatus.Information =
IoStatusBlock.Information = (ULONG_PTR)IoStackLocation->Parameters.FilterResourceRequirements.IoResourceRequirementList;
}
-
+
/* Initialize the event */
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
-
+
/* Set them up */
Irp->UserIosb = &IoStatusBlock;
Irp->UserEvent = &Event;
-
+
/* Queue the IRP */
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
IoQueueThreadIrp(Irp);
-
+
/* Copy-in the stack */
IrpStack = IoGetNextIrpStackLocation(Irp);
*IrpStack = *IoStackLocation;
-
+
/* Call the driver */
Status = IoCallDriver(TopDeviceObject, Irp);
if (Status == STATUS_PENDING)
NULL);
Status = IoStatusBlock.Status;
}
-
+
+ /* Remove the reference */
+ ObDereferenceObject(TopDeviceObject);
+
/* Return the information */
*Information = (PVOID)IoStatusBlock.Information;
return Status;
IN PIO_STACK_LOCATION Stack OPTIONAL)
{
IO_STACK_LOCATION IoStackLocation;
-
+
/* Fill out the stack information */
RtlZeroMemory(&IoStackLocation, sizeof(IO_STACK_LOCATION));
IoStackLocation.MajorFunction = IRP_MJ_PNP;
&Stack->Parameters,
sizeof(Stack->Parameters));
}
-
+
/* Do the PnP call */
IoStatusBlock->Status = IopSynchronousCall(DeviceObject,
&IoStackLocation,
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;
}
/*
- * Make sure this device node is a direct child of the parent device node
- * that is given as an argument
+ * We don't want to check for a direct child because
+ * this function is called during boot to reinitialize
+ * devices with drivers that couldn't load yet due to
+ * stage 0 limitations (ie can't load from disk yet).
*/
- if (DeviceNode->Parent != ParentDeviceNode)
- {
- DPRINT("Skipping 2+ level child\n");
- return STATUS_SUCCESS;
- }
-
if (!(DeviceNode->Flags & DNF_PROCESSED))
{
DPRINT1("Child not ready to be added\n");
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 */
UNICODE_STRING KeyString;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
-
+
/* P1 is start, pp is end */
p1 = KeyName->Buffer;
pp = (PVOID)((ULONG_PTR)p1 + KeyName->Length);
-
+
/* Create the target key */
InitializeObjectAttributes(&ObjectAttributes,
KeyName,
/* Target key failed, so we'll need to create its parent. Setup array */
HandleArray[0] = NULL;
HandleArray[1] = RootHandle;
-
+
/* Keep recursing for each missing parent */
while (Recursing)
{
/* And if we're deep enough, close the last handle */
if (NestedCloseLevel > 1) ZwClose(HandleArray[RootHandleIndex]);
-
+
/* We're setup to ping-pong between the two handle array entries */
RootHandleIndex = i;
i = (i + 1) & 1;
-
+
/* Clear the one we're attempting to open now */
HandleArray[i] = NULL;
-
+
/* Process the parent key name */
for (p = p1; ((p < pp) && (*p != OBJ_NAME_PATH_SEPARATOR)); p++);
Length = (USHORT)(p - p1) * sizeof(WCHAR);
-
+
/* Is there a parent name? */
if (Length)
{
/* Build the unicode string for it */
KeyString.Buffer = p1;
KeyString.Length = KeyString.MaximumLength = Length;
-
+
/* Now try opening the parent */
InitializeObjectAttributes(&ObjectAttributes,
&KeyString,
Recursing = FALSE;
continue;
}
-
+
/* Now see if there's more parents to create */
p1 = p + 1;
if ((p == pp) || (p1 == pp))
Recursing = FALSE;
}
}
-
+
/* Outer loop check for handle nesting that requires closing the top handle */
if (NestedCloseLevel > 1) ZwClose(HandleArray[RootHandleIndex]);
}
-
+
/* Check if we broke out of the loop due to success */
if (NT_SUCCESS(Status))
{
*Handle = HandleArray[i];
if (Disposition) *Disposition = KeyDisposition;
}
-
+
/* Return the success state */
return Status;
}
{
PDEVICE_NODE DeviceNode;
PAGED_CODE();
-
+
/* Allocate it */
DeviceNode = ExAllocatePoolWithTag(NonPagedPool, sizeof(DEVICE_NODE), 'donD');
if (!DeviceNode) return DeviceNode;
-
+
/* Statistics */
InterlockedIncrement(&IopNumberDeviceNodes);
-
+
/* Set it up */
RtlZeroMemory(DeviceNode, sizeof(DEVICE_NODE));
DeviceNode->InterfaceType = InterfaceTypeUndefined;
InitializeListHead(&DeviceNode->TargetDeviceNotify);
InitializeListHead(&DeviceNode->DockInfo.ListEntry);
InitializeListHead(&DeviceNode->PendedSetInterfaceState);
-
+
/* Check if there is a PDO */
if (PhysicalDeviceObject)
{
((PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension)->DeviceNode = DeviceNode;
PhysicalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
}
-
+
/* Return the node */
return DeviceNode;
}
/* Acquire the lock */
ExAcquireFastMutex(&PnpBusTypeGuidList->Lock);
-
+
/* Validate size */
if (Index < PnpBusTypeGuidList->GuidCount)
{
/* Failure path */
Status = STATUS_OBJECT_NAME_NOT_FOUND;
}
-
+
/* Release lock and return status */
ExReleaseFastMutex(&PnpBusTypeGuidList->Lock);
return Status;
PDEVICE_NODE DeviceNode;
UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM");
PAGED_CODE();
-
+
/* Open the enum key */
Status = IopOpenRegistryKeyEx(&KeyHandle,
NULL,
&KeyName,
KEY_READ);
if (!NT_SUCCESS(Status)) return Status;
-
+
/* Make sure we have an instance path */
DeviceNode = IopGetDeviceNode(DeviceObject);
if ((DeviceNode) && (DeviceNode->InstancePath.Length))
/* Fail */
Status = STATUS_INVALID_DEVICE_REQUEST;
}
-
+
/* Close the handle and return status */
ZwClose(KeyHandle);
return Status;
ULONG FinalSize, PartialSize, EntrySize, i, j;
PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor;
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
-
+
/* If we don't have one, that's easy */
if (!ResourceList) return 0;
-
+
/* Start with the minimum size possible */
FinalSize = FIELD_OFFSET(CM_RESOURCE_LIST, List);
-
+
/* Loop each full descriptor */
FullDescriptor = ResourceList->List;
for (i = 0; i < ResourceList->Count; i++)
/* Start with the minimum size possible */
PartialSize = FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList) +
FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors);
-
+
/* Loop each partial descriptor */
PartialDescriptor = FullDescriptor->PartialResourceList.PartialDescriptors;
for (j = 0; j < FullDescriptor->PartialResourceList.Count; j++)
{
/* Start with the minimum size possible */
EntrySize = sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
-
+
/* Check if there is extra data */
if (PartialDescriptor->Type == CmResourceTypeDeviceSpecific)
{
/* Add that data */
EntrySize += PartialDescriptor->u.DeviceSpecificData.DataSize;
}
-
+
/* The size of partial descriptors is bigger */
PartialSize += EntrySize;
-
+
/* Go to the next partial descriptor */
PartialDescriptor = (PVOID)((ULONG_PTR)PartialDescriptor + EntrySize);
}
-
+
/* The size of full descriptors is bigger */
FinalSize += PartialSize;
-
+
/* Go to the next full descriptor */
FullDescriptor = (PVOID)((ULONG_PTR)FullDescriptor + PartialSize);
}
-
+
/* Return the final size */
return FinalSize;
}
#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
/* This is the format of the returned data */
PIP_RETURN_DATA(sizeof(GUID), &BusTypeGuid);
-
+
case DevicePropertyLegacyBusType:
-
+
/* Validate correct interface type */
if (DeviceNode->ChildInterfaceType == InterfaceTypeUndefined)
return STATUS_OBJECT_NAME_NOT_FOUND;
/* This is the format of the returned data */
PIP_RETURN_DATA(sizeof(INTERFACE_TYPE), &DeviceNode->ChildInterfaceType);
-
+
case DevicePropertyBusNumber:
-
+
/* Validate correct bus number */
if ((DeviceNode->ChildBusNumber & 0x80000000) == 0x80000000)
return STATUS_OBJECT_NAME_NOT_FOUND;
-
+
/* This is the format of the returned data */
PIP_RETURN_DATA(sizeof(ULONG), &DeviceNode->ChildBusNumber);
-
+
case DevicePropertyEnumeratorName:
/* Get the instance path */
DeviceInstanceName = DeviceNode->InstancePath.Buffer;
-
+
/* Sanity checks */
ASSERT((BufferLength & 1) == 0);
ASSERT(DeviceInstanceName != NULL);
-
+
/* Get the name from the path */
EnumeratorNameEnd = wcschr(DeviceInstanceName, OBJ_NAME_PATH_SEPARATOR);
ASSERT(EnumeratorNameEnd);
/* This is the format of the returned data */
PIP_RETURN_DATA((ULONG)(EnumeratorNameEnd - DeviceInstanceName) * sizeof(WCHAR),
DeviceInstanceName);
-
+
case DevicePropertyAddress:
/* Query the device caps */
/* This is the format of the returned data */
PIP_RETURN_DATA(sizeof(ULONG), &DeviceCaps.Address);
-
+
case DevicePropertyBootConfigurationTranslated:
-
+
/* Validate we have resources */
if (!DeviceNode->BootResources)
// if (!DeviceNode->BootResourcesTranslated) // FIXFIX: Need this field
*ResultLength = 0;
return STATUS_SUCCESS;
}
-
+
/* This is the format of the returned data */
PIP_RETURN_DATA(PnpDetermineResourceListSize(DeviceNode->BootResources), // FIXFIX: Should use BootResourcesTranslated
DeviceNode->BootResources); // FIXFIX: Should use BootResourcesTranslated
case DevicePropertyPhysicalDeviceObjectName:
-
+
/* Sanity check for Unicode-sized string */
ASSERT((BufferLength & 1) == 0);
-
+
/* Allocate name buffer */
Length = BufferLength + sizeof(OBJECT_NAME_INFORMATION);
ObjectNameInfo = ExAllocatePool(PagedPool, Length);
if (!ObjectNameInfo) return STATUS_INSUFFICIENT_RESOURCES;
-
+
/* Query the PDO name */
Status = ObQueryNameString(DeviceObject,
ObjectNameInfo,
/* Let the caller know how big the name is */
*ResultLength -= sizeof(OBJECT_NAME_INFORMATION);
break;
-
+
/* Handle the registry-based properties */
case DevicePropertyUINumber:
PIP_REGISTRY_DATA(REGSTR_VAL_UI_NUMBER, REG_DWORD);
default:
return STATUS_INVALID_PARAMETER_2;
}
-
+
/* Having a registry value name implies registry data */
if (ValueName)
{
/* We know up-front how much data to expect */
*ResultLength = BufferLength;
-
+
/* Go get the data, use the LogConf subkey if necessary */
Status = PiGetDeviceRegistryProperty(DeviceObject,
ValueType,
/* Terminate the string */
((PWCHAR)PropertyBuffer)[ReturnLength / sizeof(WCHAR)] = UNICODE_NULL;
}
-
+
/* This is the success path */
Status = STATUS_SUCCESS;
}
Status = STATUS_BUFFER_TOO_SMALL;
}
}
-
+
/* Free any allocation we may have made, and return the status code */
if (ObjectNameInfo) ExFreePool(ObjectNameInfo);
return Status;
ULONG PnPFlags;
NTSTATUS Status;
IO_STATUS_BLOCK IoStatusBlock;
-
+
RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
Stack.MajorFunction = IRP_MJ_PNP;
Stack.MinorFunction = IRP_MN_QUERY_PNP_DEVICE_STATE;
-
+
Status = IopSynchronousCall(PhysicalDeviceObject, &Stack, (PVOID*)&PnPFlags);
if (!NT_SUCCESS(Status))
{
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 */
IopQueueTargetDeviceEvent(&GUID_DEVICE_SURPRISE_REMOVAL,
&DeviceNode->InstancePath);
-
+
IopSendRemoveDevice(PhysicalDeviceObject);
}
else if ((PnPFlags & PNP_DEVICE_FAILED) && (PnPFlags & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED))
{
/* Stop for resource rebalance */
-
Status = IopStopDevice(DeviceNode);
if (!NT_SUCCESS(Status))
{
PnPFlags &= ~PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED;
}
}
-
+
/* Resource rebalance */
if (PnPFlags & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED)
{
DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
-
+
Status = IopInitiatePnpIrp(PhysicalDeviceObject,
&IoStatusBlock,
IRP_MN_QUERY_RESOURCES,
DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status);
DeviceNode->BootResources = NULL;
}
-
+
DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
-
+
Status = IopInitiatePnpIrp(PhysicalDeviceObject,
&IoStatusBlock,
IRP_MN_QUERY_RESOURCE_REQUIREMENTS,
DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status);
DeviceNode->ResourceRequirements = NULL;
}
-
+
/* IRP_MN_FILTER_RESOURCE_REQUIREMENTS is called indirectly by IopStartDevice */
if (IopStartDevice(DeviceNode) != STATUS_SUCCESS)
{
PDEVICE_NODE ChildDeviceNode, NextDeviceNode, FailedRemoveDevice;
NTSTATUS Status;
KIRQL OldIrql;
-
+
KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
ChildDeviceNode = ParentDeviceNode->Child;
while (ChildDeviceNode != NULL)
{
NextDeviceNode = ChildDeviceNode->Sibling;
KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
-
+
Status = IopPrepareDeviceForRemoval(ChildDeviceNode->PhysicalDeviceObject, Force);
if (!NT_SUCCESS(Status))
{
FailedRemoveDevice = ChildDeviceNode;
goto cleanup;
}
-
+
KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
ChildDeviceNode = NextDeviceNode;
}
KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
-
+
return STATUS_SUCCESS;
-
+
cleanup:
KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
ChildDeviceNode = ParentDeviceNode->Child;
{
NextDeviceNode = ChildDeviceNode->Sibling;
KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
-
+
IopCancelPrepareDeviceForRemoval(ChildDeviceNode->PhysicalDeviceObject);
-
+
/* IRP_MN_CANCEL_REMOVE_DEVICE is also sent to the device
* that failed the IRP_MN_QUERY_REMOVE_DEVICE request */
if (ChildDeviceNode == FailedRemoveDevice)
return Status;
-
+
ChildDeviceNode = NextDeviceNode;
-
+
KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
}
KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
-
+
return Status;
}
{
PDEVICE_NODE ChildDeviceNode, NextDeviceNode;
KIRQL OldIrql;
-
+
KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
ChildDeviceNode = ParentDeviceNode->Child;
while (ChildDeviceNode != NULL)
{
NextDeviceNode = ChildDeviceNode->Sibling;
KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
-
+
IopSendRemoveDevice(ChildDeviceNode->PhysicalDeviceObject);
-
+
ChildDeviceNode = NextDeviceNode;
-
+
KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
}
KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
{
PDEVICE_NODE ChildDeviceNode, NextDeviceNode;
KIRQL OldIrql;
-
+
KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
ChildDeviceNode = ParentDeviceNode->Child;
while (ChildDeviceNode != NULL)
{
NextDeviceNode = ChildDeviceNode->Sibling;
KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
-
+
IopCancelPrepareDeviceForRemoval(ChildDeviceNode->PhysicalDeviceObject);
-
+
ChildDeviceNode = NextDeviceNode;
-
+
KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
}
KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
{
/* This function DOES NOT dereference the device objects on SUCCESS
* but it DOES dereference device objects on FAILURE */
-
+
ULONG i, j;
NTSTATUS Status;
-
+
for (i = 0; i < DeviceRelations->Count; i++)
{
Status = IopPrepareDeviceForRemoval(DeviceRelations->Objects[i], Force);
goto cleanup;
}
}
-
+
return STATUS_SUCCESS;
-
+
cleanup:
/* IRP_MN_CANCEL_REMOVE_DEVICE is also sent to the device
* that failed the IRP_MN_QUERY_REMOVE_DEVICE request */
DeviceRelations->Objects[i] = NULL;
}
ExFreePool(DeviceRelations);
-
+
return Status;
}
IopSendRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations)
{
/* This function DOES dereference the device objects in all cases */
-
+
ULONG i;
-
+
for (i = 0; i < DeviceRelations->Count; i++)
{
IopSendRemoveDevice(DeviceRelations->Objects[i]);
- ObDereferenceObject(DeviceRelations->Objects[i]);
DeviceRelations->Objects[i] = NULL;
}
-
+
ExFreePool(DeviceRelations);
}
IopCancelRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations)
{
/* This function DOES dereference the device objects in all cases */
-
+
ULONG i;
-
+
for (i = 0; i < DeviceRelations->Count; i++)
{
IopCancelPrepareDeviceForRemoval(DeviceRelations->Objects[i]);
ObDereferenceObject(DeviceRelations->Objects[i]);
DeviceRelations->Objects[i] = NULL;
}
-
+
ExFreePool(DeviceRelations);
}
IO_STATUS_BLOCK IoStatusBlock;
PDEVICE_RELATIONS DeviceRelations;
NTSTATUS Status;
-
+
IopCancelRemoveDevice(DeviceObject);
-
+
Stack.Parameters.QueryDeviceRelations.Type = RemovalRelations;
-
+
Status = IopInitiatePnpIrp(DeviceObject,
&IoStatusBlock,
IRP_MN_QUERY_DEVICE_RELATIONS,
{
DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
}
-
+
if (DeviceRelations)
IopCancelRemoveDeviceRelations(DeviceRelations);
}
DPRINT1("Removal not allowed for %wZ\n", &DeviceNode->InstancePath);
return STATUS_UNSUCCESSFUL;
}
-
+
if (!Force && IopQueryRemoveDevice(DeviceObject) != STATUS_SUCCESS)
{
DPRINT1("Removal vetoed by failing the query remove request\n");
-
+
IopCancelRemoveDevice(DeviceObject);
-
+
return STATUS_UNSUCCESSFUL;
}
-
+
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);
return Status;
}
- DeviceNode->Flags |= DNF_WILL_BE_REMOVED;
if (DeviceRelations)
IopSendRemoveDeviceRelations(DeviceRelations);
IopSendRemoveChildDevices(DeviceNode);
-
+
return STATUS_SUCCESS;
}
IO_STACK_LOCATION Stack;
DEVICE_CAPABILITIES Capabilities;
NTSTATUS Status;
-
+
IopQueueTargetDeviceEvent(&GUID_DEVICE_KERNEL_INITIATED_EJECT,
&DeviceNode->InstancePath);
-
+
if (IopQueryDeviceCapabilities(DeviceNode, &Capabilities) != STATUS_SUCCESS)
{
goto cleanup;
}
-
+
Stack.Parameters.QueryDeviceRelations.Type = EjectionRelations;
-
+
Status = IopInitiatePnpIrp(PhysicalDeviceObject,
&IoStatusBlock,
IRP_MN_QUERY_DEVICE_RELATIONS,
{
DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
}
-
+
if (DeviceRelations)
{
Status = IopQueryRemoveDeviceRelations(DeviceRelations, FALSE);
if (!NT_SUCCESS(Status))
goto cleanup;
}
-
+
Status = IopQueryRemoveChildDevices(DeviceNode, FALSE);
if (!NT_SUCCESS(Status))
{
IopCancelRemoveDeviceRelations(DeviceRelations);
goto cleanup;
}
-
+
if (IopPrepareDeviceForRemoval(PhysicalDeviceObject, FALSE) != STATUS_SUCCESS)
{
if (DeviceRelations)
IopCancelRemoveChildDevices(DeviceNode);
goto cleanup;
}
-
+
if (DeviceRelations)
IopSendRemoveDeviceRelations(DeviceRelations);
IopSendRemoveChildDevices(DeviceNode);
-
+
+ DeviceNode->Problem = CM_PROB_HELD_FOR_EJECT;
if (Capabilities.EjectSupported)
{
if (IopSendEject(PhysicalDeviceObject) != STATUS_SUCCESS)
{
DeviceNode->Flags |= DNF_DISABLED;
}
-
+
IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT,
&DeviceNode->InstancePath);
-
+
return;
-
+
cleanup:
IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT_VETOED,
&DeviceNode->InstancePath);
IN DEVICE_RELATION_TYPE Type)
{
PAGED_CODE();
-
+
switch (Type)
{
case BusRelations: