+ ZwClose(hHalAcpiId);
+ return Status;
+ }
+ else
+ {
+ Status = IopOpenRegistryKeyEx(&hEnum, NULL, &MultiKeyPathU, KEY_ENUMERATE_SUB_KEYS);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Nothing to do, don't return with an error status */
+ DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
+ ZwClose(hRoot);
+ return STATUS_SUCCESS;
+ }
+ Status = IopEnumerateDetectedDevices(
+ hEnum,
+ NULL,
+ hRoot,
+ TRUE,
+ NULL,
+ 0);
+ ZwClose(hEnum);
+ ZwClose(hRoot);
+ return Status;
+ }
+}
+
+NTSTATUS
+NTAPI
+IopOpenRegistryKeyEx(PHANDLE KeyHandle,
+ HANDLE ParentKey,
+ PUNICODE_STRING Name,
+ ACCESS_MASK DesiredAccess)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ *KeyHandle = NULL;
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ Name,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+ ParentKey,
+ NULL);
+
+ Status = ZwOpenKey(KeyHandle, DesiredAccess, &ObjectAttributes);
+
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+IopGetRegistryValue(IN HANDLE Handle,
+ IN PWSTR ValueName,
+ OUT PKEY_VALUE_FULL_INFORMATION *Information)
+{
+ UNICODE_STRING ValueString;
+ NTSTATUS Status;
+ PKEY_VALUE_FULL_INFORMATION FullInformation;
+ ULONG Size;
+ PAGED_CODE();
+
+ RtlInitUnicodeString(&ValueString, ValueName);
+
+ Status = ZwQueryValueKey(Handle,
+ &ValueString,
+ KeyValueFullInformation,
+ NULL,
+ 0,
+ &Size);
+ if ((Status != STATUS_BUFFER_OVERFLOW) &&
+ (Status != STATUS_BUFFER_TOO_SMALL))
+ {
+ return Status;
+ }
+
+ FullInformation = ExAllocatePool(NonPagedPool, Size);
+ if (!FullInformation) return STATUS_INSUFFICIENT_RESOURCES;
+
+ Status = ZwQueryValueKey(Handle,
+ &ValueString,
+ KeyValueFullInformation,
+ FullInformation,
+ Size,
+ &Size);
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePool(FullInformation);
+ return Status;
+ }
+
+ *Information = FullInformation;
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS INIT_FUNCTION
+NTAPI
+PnpDriverInitializeEmpty(IN struct _DRIVER_OBJECT *DriverObject, IN PUNICODE_STRING RegistryPath)
+{
+ return STATUS_SUCCESS;
+}
+
+VOID INIT_FUNCTION
+PnpInit(VOID)
+{
+ PDEVICE_OBJECT Pdo;
+ NTSTATUS Status;
+
+ DPRINT("PnpInit()\n");
+
+ KeInitializeSpinLock(&IopDeviceTreeLock);
+ ExInitializeFastMutex(&IopBusTypeGuidListLock);
+
+ /* Initialize the Bus Type GUID List */
+ IopBusTypeGuidList = ExAllocatePool(NonPagedPool, sizeof(IO_BUS_TYPE_GUID_LIST));
+ if (!IopBusTypeGuidList) {
+ DPRINT1("ExAllocatePool() failed\n");
+ KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, STATUS_NO_MEMORY, 0, 0, 0);
+ }
+
+ RtlZeroMemory(IopBusTypeGuidList, sizeof(IO_BUS_TYPE_GUID_LIST));
+ ExInitializeFastMutex(&IopBusTypeGuidList->Lock);
+
+ /* Initialize PnP-Event notification support */
+ Status = IopInitPlugPlayEvents();
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("IopInitPlugPlayEvents() failed\n");
+ KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
+ }
+
+ /*
+ * Create root device node
+ */
+
+ Status = IopCreateDriver(NULL, PnpDriverInitializeEmpty, NULL, 0, 0, &IopRootDriverObject);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("IoCreateDriverObject() failed\n");
+ KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
+ }
+
+ Status = IoCreateDevice(IopRootDriverObject, 0, NULL, FILE_DEVICE_CONTROLLER,
+ 0, FALSE, &Pdo);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("IoCreateDevice() failed\n");
+ KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
+ }
+
+ Status = IopCreateDeviceNode(NULL, Pdo, NULL, &IopRootDeviceNode);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Insufficient resources\n");
+ KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
+ }
+
+ if (!RtlCreateUnicodeString(&IopRootDeviceNode->InstancePath,
+ L"HTREE\\ROOT\\0"))
+ {
+ DPRINT1("Failed to create the instance path!\n");
+ KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, STATUS_NO_MEMORY, 0, 0, 0);
+ }
+
+ /* Report the device to the user-mode pnp manager */
+ IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL,
+ &IopRootDeviceNode->InstancePath);
+
+ IopRootDeviceNode->PhysicalDeviceObject->Flags |= DO_BUS_ENUMERATED_DEVICE;
+ PnpRootDriverEntry(IopRootDriverObject, NULL);
+ IopRootDeviceNode->PhysicalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
+ IopRootDriverObject->DriverExtension->AddDevice(
+ IopRootDriverObject,
+ IopRootDeviceNode->PhysicalDeviceObject);
+
+ /* Move information about devices detected by Freeloader to SYSTEM\CurrentControlSet\Root\ */
+ Status = IopUpdateRootKey();
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("IopUpdateRootKey() failed\n");
+ KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
+ }
+}
+
+RTL_GENERIC_COMPARE_RESULTS
+NTAPI
+PiCompareInstancePath(IN PRTL_AVL_TABLE Table,
+ IN PVOID FirstStruct,
+ IN PVOID SecondStruct)
+{
+ /* FIXME: TODO */
+ ASSERT(FALSE);
+ return 0;
+}
+
+//
+// The allocation function is called by the generic table package whenever
+// it needs to allocate memory for the table.
+//
+
+PVOID
+NTAPI
+PiAllocateGenericTableEntry(IN PRTL_AVL_TABLE Table,
+ IN CLONG ByteSize)
+{
+ /* FIXME: TODO */
+ ASSERT(FALSE);
+ return NULL;
+}
+
+VOID
+NTAPI
+PiFreeGenericTableEntry(IN PRTL_AVL_TABLE Table,
+ IN PVOID Buffer)
+{
+ /* FIXME: TODO */
+ ASSERT(FALSE);
+}
+
+VOID
+NTAPI
+PpInitializeDeviceReferenceTable(VOID)
+{
+ /* Setup the guarded mutex and AVL table */
+ KeInitializeGuardedMutex(&PpDeviceReferenceTableLock);
+ RtlInitializeGenericTableAvl(
+ &PpDeviceReferenceTable,
+ (PRTL_AVL_COMPARE_ROUTINE)PiCompareInstancePath,
+ (PRTL_AVL_ALLOCATE_ROUTINE)PiAllocateGenericTableEntry,
+ (PRTL_AVL_FREE_ROUTINE)PiFreeGenericTableEntry,
+ NULL);
+}
+
+BOOLEAN
+NTAPI
+PiInitPhase0(VOID)
+{
+ /* Initialize the resource when accessing device registry data */
+ ExInitializeResourceLite(&PpRegistryDeviceResource);
+
+ /* Setup the device reference AVL table */
+ PpInitializeDeviceReferenceTable();
+ return TRUE;
+}
+
+BOOLEAN
+NTAPI
+PpInitSystem(VOID)
+{
+ /* Check the initialization phase */
+ switch (ExpInitializationPhase)
+ {
+ case 0:
+
+ /* Do Phase 0 */
+ return PiInitPhase0();
+
+ case 1:
+
+ /* Do Phase 1 */
+ return TRUE;
+ //return PiInitPhase1();
+
+ default:
+
+ /* Don't know any other phase! Bugcheck! */
+ KeBugCheck(UNEXPECTED_INITIALIZATION_CALL);
+ return FALSE;
+ }
+}
+
+/* PUBLIC FUNCTIONS **********************************************************/
+
+/*
+ * @unimplemented
+ */
+NTSTATUS
+NTAPI
+IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject,
+ IN DEVICE_REGISTRY_PROPERTY DeviceProperty,
+ IN ULONG BufferLength,
+ OUT PVOID PropertyBuffer,
+ OUT PULONG ResultLength)
+{
+ PDEVICE_NODE DeviceNode = IopGetDeviceNode(DeviceObject);
+ DEVICE_CAPABILITIES DeviceCaps;
+ ULONG Length;
+ PVOID Data = NULL;
+ PWSTR Ptr;
+ NTSTATUS Status;
+
+ DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject, DeviceProperty);
+
+ *ResultLength = 0;
+
+ if (DeviceNode == NULL)
+ return STATUS_INVALID_DEVICE_REQUEST;
+
+ switch (DeviceProperty)
+ {
+ case DevicePropertyBusNumber:
+ Length = sizeof(ULONG);
+ Data = &DeviceNode->ChildBusNumber;
+ break;
+
+ /* Complete, untested */
+ case DevicePropertyBusTypeGuid:
+ /* Sanity check */
+ if ((DeviceNode->ChildBusTypeIndex != 0xFFFF) &&
+ (DeviceNode->ChildBusTypeIndex < IopBusTypeGuidList->GuidCount))
+ {
+ /* Return the GUID */
+ *ResultLength = sizeof(GUID);
+
+ /* Check if the buffer given was large enough */
+ if (BufferLength < *ResultLength)
+ {
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ /* Copy the GUID */
+ RtlCopyMemory(PropertyBuffer,
+ &(IopBusTypeGuidList->Guids[DeviceNode->ChildBusTypeIndex]),
+ sizeof(GUID));
+ return STATUS_SUCCESS;
+ }
+ else
+ {
+ return STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+ break;
+
+ case DevicePropertyLegacyBusType:
+ Length = sizeof(INTERFACE_TYPE);
+ Data = &DeviceNode->ChildInterfaceType;
+ break;
+
+ case DevicePropertyAddress:
+ /* Query the device caps */
+ Status = IopQueryDeviceCapabilities(DeviceNode, &DeviceCaps);
+ if (NT_SUCCESS(Status) && (DeviceCaps.Address != MAXULONG))
+ {
+ /* Return length */
+ *ResultLength = sizeof(ULONG);
+
+ /* Check if the buffer given was large enough */
+ if (BufferLength < *ResultLength)
+ {
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ /* Return address */
+ *(PULONG)PropertyBuffer = DeviceCaps.Address;
+ return STATUS_SUCCESS;
+ }
+ else
+ {
+ return STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+ break;
+
+// case DevicePropertyUINumber:
+// if (DeviceNode->CapabilityFlags == NULL)
+// return STATUS_INVALID_DEVICE_REQUEST;
+// Length = sizeof(ULONG);
+// Data = &DeviceNode->CapabilityFlags->UINumber;
+// break;
+
+ case DevicePropertyClassName:
+ case DevicePropertyClassGuid:
+ case DevicePropertyDriverKeyName:
+ case DevicePropertyManufacturer:
+ case DevicePropertyFriendlyName:
+ case DevicePropertyHardwareID:
+ case DevicePropertyCompatibleIDs:
+ case DevicePropertyDeviceDescription:
+ case DevicePropertyLocationInformation:
+ case DevicePropertyUINumber:
+ {
+ LPCWSTR RegistryPropertyName;
+ UNICODE_STRING EnumRoot = RTL_CONSTANT_STRING(ENUM_ROOT);
+ UNICODE_STRING ValueName;
+ KEY_VALUE_PARTIAL_INFORMATION *ValueInformation;
+ ULONG ValueInformationLength;
+ HANDLE KeyHandle, EnumRootHandle;
+ NTSTATUS Status;
+
+ switch (DeviceProperty)
+ {
+ case DevicePropertyClassName:
+ RegistryPropertyName = L"Class"; break;
+ case DevicePropertyClassGuid:
+ RegistryPropertyName = L"ClassGuid"; break;
+ case DevicePropertyDriverKeyName:
+ RegistryPropertyName = L"Driver"; break;
+ case DevicePropertyManufacturer:
+ RegistryPropertyName = L"Mfg"; break;
+ case DevicePropertyFriendlyName:
+ RegistryPropertyName = L"FriendlyName"; break;
+ case DevicePropertyHardwareID:
+ RegistryPropertyName = L"HardwareID"; break;
+ case DevicePropertyCompatibleIDs:
+ RegistryPropertyName = L"CompatibleIDs"; break;
+ case DevicePropertyDeviceDescription:
+ RegistryPropertyName = L"DeviceDesc"; break;
+ case DevicePropertyLocationInformation:
+ RegistryPropertyName = L"LocationInformation"; break;
+ case DevicePropertyUINumber:
+ RegistryPropertyName = L"UINumber"; break;
+ default:
+ /* Should not happen */
+ ASSERT(FALSE);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ DPRINT("Registry property %S\n", RegistryPropertyName);
+
+ /* Open Enum key */
+ Status = IopOpenRegistryKeyEx(&EnumRootHandle, NULL,
+ &EnumRoot, KEY_READ);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Error opening ENUM_ROOT, Status=0x%08x\n", Status);
+ return Status;
+ }