[CMAKE]
[reactos.git] / ntoskrnl / io / pnpmgr / pnpinit.c
index 8c56072..7811632 100644 (file)
 
 /* 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;
@@ -219,4 +243,262 @@ Quickie:
     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 */