/* GLOBALS ********************************************************************/
+typedef struct _IOPNP_DEVICE_EXTENSION
+{
+ PWCHAR CompatibleIdList;
+ ULONG CompatibleIdListSize;
+} IOPNP_DEVICE_EXTENSION, *PIOPNP_DEVICE_EXTENSION;
+
PUNICODE_STRING PiInitGroupOrderTable;
ULONG PiInitGroupOrderTableCount;
-
+INTERFACE_TYPE PnpDefaultInterfaceType;
+
/* FUNCTIONS ******************************************************************/
+INTERFACE_TYPE
+NTAPI
+IopDetermineDefaultInterfaceType(VOID)
+{
+ /* FIXME: ReactOS doesn't support MicroChannel yet */
+ return Isa;
+}
+
+NTSTATUS
+NTAPI
+IopInitializeArbiters(VOID)
+{
+ /* FIXME: TODO */
+ return STATUS_SUCCESS;
+}
+
NTSTATUS
NTAPI
+INIT_FUNCTION
PiInitCacheGroupInformation(VOID)
{
HANDLE KeyHandle;
return i;
}
+NTSTATUS
+NTAPI
+PipCallDriverAddDevice(IN PDEVICE_NODE DeviceNode,
+ IN BOOLEAN LoadDriver,
+ IN PDRIVER_OBJECT DriverObject)
+{
+ NTSTATUS Status;
+ HANDLE EnumRootKey, SubKey, ControlKey, ClassKey, PropertiesKey;
+ UNICODE_STRING ClassGuid, Properties;
+ UNICODE_STRING EnumRoot = RTL_CONSTANT_STRING(ENUM_ROOT);
+ UNICODE_STRING ControlClass =
+ RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class");
+ PKEY_VALUE_FULL_INFORMATION KeyValueInformation = NULL;
+ PWCHAR Buffer;
+
+ /* Open enumeration root key */
+ Status = IopOpenRegistryKeyEx(&EnumRootKey,
+ NULL,
+ &EnumRoot,
+ KEY_READ);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status);
+ return Status;
+ }
+
+ /* Open instance subkey */
+ Status = IopOpenRegistryKeyEx(&SubKey,
+ EnumRootKey,
+ &DeviceNode->InstancePath,
+ KEY_READ);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status);
+ ZwClose(EnumRootKey);
+ return Status;
+ }
+
+ /* Get class GUID */
+ Status = IopGetRegistryValue(SubKey,
+ REGSTR_VAL_CLASSGUID,
+ &KeyValueInformation);
+ if (NT_SUCCESS(Status))
+ {
+ /* Convert to unicode string */
+ Buffer = (PVOID)((ULONG_PTR)KeyValueInformation + KeyValueInformation->DataOffset);
+ PnpRegSzToString(Buffer, KeyValueInformation->DataLength, &ClassGuid.Length);
+ ClassGuid.MaximumLength = KeyValueInformation->DataLength;
+ ClassGuid.Buffer = Buffer;
+
+ /* Open the key */
+ Status = IopOpenRegistryKeyEx(&ControlKey,
+ NULL,
+ &ControlClass,
+ KEY_READ);
+ if (!NT_SUCCESS(Status))
+ {
+ /* No class key */
+ DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status);
+ ClassKey = NULL;
+ }
+ else
+ {
+ /* Open the class key */
+ Status = IopOpenRegistryKeyEx(&ClassKey,
+ ControlKey,
+ &ClassGuid,
+ KEY_READ);
+ ZwClose(ControlKey);
+ if (!NT_SUCCESS(Status))
+ {
+ /* No class key */
+ DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status);
+ ClassKey = NULL;
+ }
+ }
+
+ /* Check if we made it till here */
+ if (ClassKey)
+ {
+ /* Get the device properties */
+ RtlInitUnicodeString(&Properties, REGSTR_KEY_DEVICE_PROPERTIES);
+ Status = IopOpenRegistryKeyEx(&PropertiesKey,
+ ClassKey,
+ &Properties,
+ KEY_READ);
+ if (!NT_SUCCESS(Status))
+ {
+ /* No properties */
+ DPRINT("IopOpenRegistryKeyEx() failed with Status %08X\n", Status);
+ PropertiesKey = NULL;
+ }
+ }
+
+ /* Free the registry data */
+ ExFreePool(KeyValueInformation);
+ }
+
+ /* Do ReactOS-style setup */
+ IopAttachFilterDrivers(DeviceNode, TRUE);
+ Status = IopInitializeDevice(DeviceNode, DriverObject);
+ if (NT_SUCCESS(Status))
+ {
+ IopAttachFilterDrivers(DeviceNode, FALSE);
+ Status = IopStartDevice(DeviceNode);
+ }
+
+ /* Return status */
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+INIT_FUNCTION
+IopInitializePlugPlayServices(VOID)
+{
+ NTSTATUS Status;
+ ULONG Disposition;
+ HANDLE KeyHandle, EnumHandle, ParentHandle, TreeHandle;
+ UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET");
+ PDEVICE_OBJECT Pdo;
+
+ /* Initialize locks and such */
+ KeInitializeSpinLock(&IopDeviceTreeLock);
+
+ /* Get the default interface */
+ PnpDefaultInterfaceType = IopDetermineDefaultInterfaceType();
+
+ /* Initialize arbiters */
+ Status = IopInitializeArbiters();
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Setup the group cache */
+ Status = PiInitCacheGroupInformation();
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Open the current control set */
+ Status = IopOpenRegistryKeyEx(&KeyHandle,
+ NULL,
+ &KeyName,
+ KEY_ALL_ACCESS);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Create the enum key */
+ RtlInitUnicodeString(&KeyName, REGSTR_KEY_ENUM);
+ Status = IopCreateRegistryKeyEx(&EnumHandle,
+ KeyHandle,
+ &KeyName,
+ KEY_ALL_ACCESS,
+ REG_OPTION_NON_VOLATILE,
+ &Disposition);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Check if it's a new key */
+ if (Disposition == REG_CREATED_NEW_KEY)
+ {
+ /* FIXME: DACLs */
+ DPRINT1("Need to build DACL\n");
+ }
+
+ /* Create the root key */
+ ParentHandle = EnumHandle;
+ RtlInitUnicodeString(&KeyName, REGSTR_KEY_ROOTENUM);
+ Status = IopCreateRegistryKeyEx(&EnumHandle,
+ ParentHandle,
+ &KeyName,
+ KEY_ALL_ACCESS,
+ REG_OPTION_NON_VOLATILE,
+ &Disposition);
+ NtClose(ParentHandle);
+ if (!NT_SUCCESS(Status)) return Status;
+ NtClose(EnumHandle);
+
+ /* Open the root key now */
+ RtlInitUnicodeString(&KeyName, L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM");
+ Status = IopOpenRegistryKeyEx(&EnumHandle,
+ NULL,
+ &KeyName,
+ KEY_ALL_ACCESS);
+ if (NT_SUCCESS(Status))
+ {
+ /* Create the root dev node */
+ RtlInitUnicodeString(&KeyName, REGSTR_VAL_ROOT_DEVNODE);
+ Status = IopCreateRegistryKeyEx(&TreeHandle,
+ EnumHandle,
+ &KeyName,
+ KEY_ALL_ACCESS,
+ REG_OPTION_NON_VOLATILE,
+ NULL);
+ NtClose(EnumHandle);
+ if (NT_SUCCESS(Status)) NtClose(TreeHandle);
+ }
+
+ /* Create the root driver */
+ Status = IoCreateDriver(NULL, PnpRootDriverEntry);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("IoCreateDriverObject() failed\n");
+ KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
+ }
+
+ /* Create the root PDO */
+ Status = IoCreateDevice(IopRootDriverObject,
+ sizeof(IOPNP_DEVICE_EXTENSION),
+ NULL,
+ FILE_DEVICE_CONTROLLER,
+ 0,
+ FALSE,
+ &Pdo);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("IoCreateDevice() failed\n");
+ KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
+ }
+
+ /* This is a bus enumerated device */
+ Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
+
+ /* Create the root device node */
+ IopRootDeviceNode = PipAllocateDeviceNode(Pdo);
+
+ /* Set flags */
+ IopRootDeviceNode->Flags |= DNF_STARTED + DNF_PROCESSED + DNF_ENUMERATED +
+ DNF_MADEUP + DNF_NO_RESOURCE_REQUIRED +
+ DNF_ADDED;
+
+ /* Create instance path */
+ RtlCreateUnicodeString(&IopRootDeviceNode->InstancePath,
+ REGSTR_VAL_ROOT_DEVNODE);
+
+ /* Call the add device routine */
+ IopRootDriverObject->DriverExtension->AddDevice(IopRootDriverObject,
+ IopRootDeviceNode->PhysicalDeviceObject);
+
+ /* Initialize PnP-Event notification support */
+ Status = IopInitPlugPlayEvents();
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Report the device to the user-mode pnp manager */
+ IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL,
+ &IopRootDeviceNode->InstancePath);
+
+ /* Initialize the Bus Type GUID List */
+ PnpBusTypeGuidList = ExAllocatePool(PagedPool, sizeof(IO_BUS_TYPE_GUID_LIST));
+ RtlZeroMemory(PnpBusTypeGuidList, sizeof(IO_BUS_TYPE_GUID_LIST));
+ ExInitializeFastMutex(&PnpBusTypeGuidList->Lock);
+
+ /* Launch the firmware mapper */
+ Status = IopUpdateRootKey();
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Close the handle to the control set */
+ NtClose(KeyHandle);
+
+ /* We made it */
+ return STATUS_SUCCESS;
+}
+
/* EOF */