Page 1 of 1

Problem with PnP Manager (Enumerate Devices)

Posted: Mon Aug 10, 2015 2:15 pm
by vgal
During my experiments with drivers, there was a problem (uneasy for me).

Code: Select all

IoInitSystem (...)
{
    /* Load boot start drivers */
    IopInitializeBootDrivers ();//call DriverEntry () for each driver

    //When all drivers are initialized, call IopReinitializeBootDrivers()

    /* Call back drivers that asked for */
    IopReinitializeBootDrivers (); //call DriverReinitializationRoutine () in those drivers which registered by means of IoRegisterBootDriverReinitialization ()

}
From all drivers DriverReinitializationRoutine () is only at HAL (from HalpAddDevice ()) and at disk_new.sys (call from DriverEntry ()).

HAL launches IopEnumerateDevice () to create devices, and also relations between parent and child (found on the bus) devices (when the stack consists of several devices).

Are for this purpose used (in particular) IRP_MN_QUERY_DEVICE_RELATIONS and IRP_MN_QUERY_ID (for determination IDs: DeviceID, HardwareID, CompatibleID, InstanceID).
The parent device receives these IDs from child and should define what driver to use for the child device.

By the current moment for this purpose call IopInstallCriticalDevice () which takes a driver name compared ID from section "CriticalDeviceDatabase" in the registry.
For example: HKLM, "SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\*PNP0A03", "Service", 0x00000000, "pci" -
ID "*PNP0A03" there corresponds the driver "pci".

All is good, when we load LiveCD because by the time of start IopReinitializeBootDrivers () the section "CriticalDeviceDatabase" already is available in the registry.

In difference from BootCD. It is the first start of system and in the registry there are no records. At us is "txtsetup.sif" (section [HardwareIdsDatabase]) during the initial moment of loading (freeldr).
And even:
[HiveInfs. Install]
AddReg=registry.inf, AddReg

But call IopInstallCriticalDevice ()... There are no records in the register (CriticalDeviceDatabase).

What to do?

Re: Problem with PnP Manager (Enumerate Devices)

Posted: Sun Aug 16, 2015 9:04 am
by vgal
In RoS already there is a necessary structure - PNP_HARDWARE_ID.

I added new function SetupLdrLoadHardwareIdsDatabase() in reactos\boot\freeldr\freeldr\windows\setupldr.c:

Code: Select all

static VOID
SetupLdrLoadHardwareIdsDatabase(PSETUP_LOADER_BLOCK SetupBlock, HINF InfHandle, LPCSTR SearchPath)
{
    INFCONTEXT        InfContext;
    LPCSTR            Id;
    LPCSTR            DriverName;
    SIZE_T            Size;
    PVOID             Temp;
    PPNP_HARDWARE_ID  HardwareId;
    PPNP_HARDWARE_ID  HeadHardwareId;
    PPNP_HARDWARE_ID  LastHardwareId = 0;

    /* reactos\include\reactos\arc\setupblk.h
    typedef struct _PNP_HARDWARE_ID {
        struct _PNP_HARDWARE_ID *Next;
        PCHAR Id;
        PCHAR DriverName;
        PCHAR ClassGuid;
    } PNP_HARDWARE_ID, *PPNP_HARDWARE_ID;
    */

    /* Open inf section */
    if (!InfFindFirstLine(InfHandle, "HardwareIdsDatabase", NULL, &InfContext))
        return;

    /* Load all HardwareIds */
    do
    {
        if (InfGetDataField(&InfContext, 0, &Id) &&
            InfGetDataField(&InfContext, 1, &DriverName))
        {
            /* Allocate and initialize the new struct _PNP_HARDWARE_ID */
            Size = sizeof(PNP_HARDWARE_ID);
            HardwareId = FrLdrHeapAlloc(Size, TAG_HARDWARE_ID);
            if (HardwareId == NULL)
                return;
            memset(HardwareId, 0, Size);

            /* For link field */
            if(LastHardwareId)
               LastHardwareId->Next = (PPNP_HARDWARE_ID)((ULONG)HardwareId | 0x80000000);
            else
               HeadHardwareId = (PPNP_HARDWARE_ID)((ULONG)HardwareId | 0x80000000); //first record

            /* "DPRINT" */
            //ERR("SetupLdrLoadHardwareIdsDatabase: HardwareId - %p\n", HardwareId);

            LastHardwareId = HardwareId;

            /* Allocate and copy name Id */
            Size = strlen(Id) + 1;
            Temp = FrLdrHeapAlloc(Size, TAG_HARDWARE_ID);
            if (Temp == NULL)
                return;
            memmove(Temp, Id, Size);
            HardwareId->Id = (PCHAR)((ULONG)Temp | 0x80000000);

            /* Allocate and copy driver name */
            Size = strlen(DriverName) + 1;
            Temp = FrLdrHeapAlloc(Size, TAG_HARDWARE_ID);
            if (Temp == NULL)
                return;
            memmove(Temp, DriverName, Size);
            HardwareId->DriverName = (PCHAR)((ULONG)Temp | 0x80000000);
        }
    } while (InfFindNextLine(&InfContext, &InfContext));

    SetupBlock->HardwareIdDatabase = (PPNP_HARDWARE_ID)((ULONG)HeadHardwareId | 0x80000000);
}
Call new function in LoadReactOSSetup():

Code: Select all

VOID
LoadReactOSSetup(IN OperatingSystemItem* OperatingSystem,
                 IN USHORT OperatingSystemVersion)
{
...

    /* Get a list of boot drivers */
    SetupLdrScanBootDrivers(&LoaderBlock->BootDriverListHead, InfHandle, BootPath);

    /* Load HardwareIds Database */
    SetupLdrLoadHardwareIdsDatabase(SetupBlock, InfHandle, BootPath);

    /* Close the inf file */
    InfCloseFile(InfHandle);

...
}
Now in (PLOADER_PARAMETER_BLOCK) LoaderBlock->SetupLdrBlock->HardwareIdDatabase the pointer on structure PNP_HARDWARE_ID in which are stored HardwareIDs is written down.
PnP Manager can take them.

Re: Problem with PnP Manager (Enumerate Devices)

Posted: Sun Aug 16, 2015 11:27 am
by vgal
I used function IopInstallCriticalDevice () in reactos\ntoskrnl\io\pnpmgr\pnpmgr.c :

Code: Select all

VOID
NTAPI
IopInstallCriticalDevice(PDEVICE_NODE DeviceNode)
{
    extern PLOADER_PARAMETER_BLOCK IopLoaderBlock;

...

    /* Free our temp buffer */
    ExFreePool(PartialInfo);

>>> To insert there

    if ( ExpInTextModeSetup && (IopLoaderBlock != NULL) )
    {
        /* Ids from txtsetup.sif */
       PPNP_HARDWARE_ID IdDatabase;

       //ASSERT(IopLoaderBlock->SetupLdrBlock)
       //ASSERT(IopLoaderBlock->SetupLdrBlock->HardwareIdDatabase)

       while (*IdBuffer)
       {
          USHORT StringLength = (USHORT)wcslen(IdBuffer) + 1;

          IdDatabase = IopLoaderBlock->SetupLdrBlock->HardwareIdDatabase;

          do
          {
             STRING Id, ChildIdNameA;
             UNICODE_STRING ChildIdNameU;

             //ASSERT(IdDatabase->Id)
             RtlInitString(&Id, IdDatabase->Id);

             ChildIdNameU.Buffer = IdBuffer;
             ChildIdNameU.MaximumLength = ChildIdNameU.Length = (StringLength - 1) * sizeof(WCHAR);

             if ( RtlUnicodeStringToAnsiString(&ChildIdNameA, &ChildIdNameU, TRUE) < 0 )
             {
                DPRINT("IopInstallCriticalDevice: cannot convert UnicodeString - %wZ\n", &ChildIdNameU);
                continue;
             }

             if (RtlEqualString(&Id, &ChildIdNameA, TRUE))
             {
                STRING DriverNameA;
                UNICODE_STRING DriverNameU;

                //DPRINT("IopInstallCriticalDevice: Equal Ids from txtsetup.sif and HardwareId (or CompatibleId) from registry\n");

                /* Write it to the ENUM key */

                //ASSERT(IdDatabase->Id)
                RtlInitString(&DriverNameA, IdDatabase->DriverName);
                DPRINT("RtlAnsiStringToUnicodeString DriverNameA'- %s'\n", &DriverNameA);
                if ( RtlAnsiStringToUnicodeString(&DriverNameU, &DriverNameA, TRUE) < 0 )
                {
                   DPRINT("IopInstallCriticalDevice: cannot convert string %s\n", &DriverNameA);
                   continue;
                }

                Status = ZwSetValueKey(InstanceKey,
                                       &ServiceU,
                                       0,
                                       REG_SZ,
                                       DriverNameU.Buffer,
                                       DriverNameU.Length + sizeof(WCHAR));

                if (Status != STATUS_SUCCESS)
                {
                   DPRINT1("IopInstallCriticalDevice: ZwSetValueKey() failed (Status %lx)\n", Status);
                   continue;
                }

                //DPRINT("Installed service '%s' for device '%wZ'\n", &DriverNameA, &ChildIdNameU);

                RtlFreeUnicodeString(&DriverNameU);
                ExFreePool(OriginalIdBuffer);
                ZwClose(InstanceKey);

                /* That's it */
                return;
             }

             /* Next Id from IdDatabase->Id (txtsetup.sif)*/
            //ASSERT(IdDatabase->Next)
             IdDatabase = IdDatabase->Next;

          } while (IdDatabase->Next);

          /* Next HardwareId or CompatibleId from IdBuffer (registry) */
          IdBuffer += StringLength;
       }
    }
    else
    {
>>> End insert there
...
        ZwClose(CriticalDeviceKey);
    }

    ExFreePool(OriginalIdBuffer);
    ZwClose(InstanceKey);
}
It is the working code, it is tested on the real driver.

Re: Problem with PnP Manager (Enumerate Devices)

Posted: Sun Aug 16, 2015 4:47 pm
by hbelusca
Hi!
It is true that on Windows 2k3, the SetupLdr initializes the SETUP_LOADER_BLOCK members as you do for the HardwareIdDatabase member, which is then used in the setup program setupdd.sys (which is a device driver). On ReactOS all the setup is done in the text-user mode setup program, usetup.exe . From it we cannot access the SETUP_LOADER_BLOCK . In the InstallDriver function https://git.reactos.org/?p=reactos.git; ... b74e57#l36 (called from inside InstallDevice) the "HardwareIdsDatabase" section is read by hand, and install the driver if needed. My question is, whether this did work for you, or not?

Re: Problem with PnP Manager (Enumerate Devices)

Posted: Mon Aug 17, 2015 7:31 am
by vgal
I am stopped by function IopCreateArcNames () - Bugcheck 0x69.
It earlier, than InstallDriver ().

As to tell these drivers that they will work together
...
disk_new (and cdromnew (cdrom_new - 9 characters)),
atax (- ata channel driver),
pciide
...
without enumerating?

I use the non-standard pnp bootable mass storage drivers.

Re: Problem with PnP Manager (Enumerate Devices)

Posted: Tue Aug 18, 2015 9:26 am
by vgal
From DDK:
"Specifying Driver Load Order".
...
To reinforce the importance of setting the correct StartType value, the following list describes how Windows and the PnP manager use the StartType entries in INF files:
1. On system startup, the operating system loader loads drivers of type SERVICE_BOOT_START before it transfers control to the kernel. These drivers are in memory when the kernel gets control.
...
2. The PnP manager calls the DriverEntry routines of the SERVICE_BOOT_START drivers so the drivers can service the boot devices.

If a boot device has child devices, those devices are enumerated. The child devices are configured and started if their drivers are also boot-start drivers. If a device's drivers are not all boot-start drivers, the PnP manager creates a device node (devnode) for the device but does not start the device yet. :o
...

No DriverReinitializationRoutine ().
Enumerating happens at once in the course of detection of devices on the bus.

My question: where to take HardwareIDs (from IopInitializeBootDrivers() (or DriverReinitializationRoutine())) in Setup text mode (if not to use LOADER_PARAMETER_BLOCK)?

Re: Problem with PnP Manager (Enumerate Devices)

Posted: Wed Jan 11, 2017 11:05 am
by vgal
Generally, this HardwareIdDatabase is needed at an early stage for the enumeration of boot device. Which uses bootable driver such as for example pсiide, ahci or usb(o|u|e)hci. And it is necessary only once to start the installation from BootCD or BootUSB or ... maybe BootRAM or BootHD.

Re: Problem with PnP Manager (Enumerate Devices)

Posted: Wed May 24, 2017 2:03 am
by hbelusca
Hi vgal, could you re-explain to me why this would not be needed for the LiveCD? (even if it's started from a system with only external USB drives, and no hdd at all) ?

Re: Problem with PnP Manager (Enumerate Devices)

Posted: Mon May 29, 2017 3:05 pm
by vgal
Hi hbelusca, LiveCD already has Critical Device Database section via boot\bootdata\hivesys.inf. But when does the installation of ReactOS start, where will PnP take the information?
By the way, you can see the result of my experiments on my blog http://vgal.ru.com
Translator Google will help you to translate from Russian :)