After plug&play at 3rd boot since r18448, after plug&play in 2nd stage setup since r22607, here is plug&play in 1st stage setup!

svn path=/trunk/; revision=31044
This commit is contained in:
Hervé Poussineau 2007-12-06 16:25:57 +00:00
parent 96fcea9b72
commit fe87541e38
4 changed files with 421 additions and 1 deletions

View file

@ -0,0 +1,396 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS text-mode setup
* FILE: subsys/system/usetup/interface/devinst.c
* PURPOSE: Device installation
* PROGRAMMER: Hervé Poussineau (hpoussin@reactos.org)
*/
#include "usetup.h"
#define NDEBUG
#include <debug.h>
#define INITGUID
#include <guiddef.h>
#include <libs/umpnpmgr/sysguid.h>
BOOLEAN
ResetDevice(
IN LPCWSTR DeviceId)
{
PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
NTSTATUS Status;
RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, DeviceId);
Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
if (!NT_SUCCESS(Status))
{
DPRINT1("NtPlugPlayControl() failed with status 0x%08x\n", Status);
return FALSE;
}
return TRUE;
}
BOOLEAN
InstallDriver(
IN HINF hInf,
IN HANDLE hServices,
IN HANDLE hDeviceKey,
IN LPCWSTR DeviceId,
IN LPCWSTR HardwareId)
{
UNICODE_STRING PathPrefix = RTL_CONSTANT_STRING(L"System32\\DRIVERS\\");
UNICODE_STRING ServiceU = RTL_CONSTANT_STRING(L"Service");
UNICODE_STRING ErrorControlU = RTL_CONSTANT_STRING(L"ErrorControl");
UNICODE_STRING ImagePathU = RTL_CONSTANT_STRING(L"ImagePath");
UNICODE_STRING StartU = RTL_CONSTANT_STRING(L"Start");
UNICODE_STRING TypeU = RTL_CONSTANT_STRING(L"Type");
UNICODE_STRING StringU;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE hService;
INFCONTEXT Context;
LPWSTR Driver, ImagePath, FullImagePath;
ULONG dwValue;
ULONG Disposition;
NTSTATUS Status;
BOOLEAN deviceInstalled = FALSE;
/* Check if we know the hardware */
if (!SetupFindFirstLineW(hInf, L"HardwareIdsDatabase", HardwareId, &Context))
return FALSE;
if (!INF_GetDataField(&Context, 1, &Driver))
return FALSE;
/* Find associated driver name */
/* FIXME: check in other sections too! */
if (!SetupFindFirstLineW(hInf, L"BootBusExtenders.Load", Driver, &Context)
&& !SetupFindFirstLineW(hInf, L"Keyboard.Load", Driver, &Context))
return FALSE;
if (!INF_GetDataField(&Context, 1, &ImagePath))
return FALSE;
/* Prepare full driver path */
dwValue = PathPrefix.MaximumLength + wcslen(ImagePath) * sizeof(WCHAR);
FullImagePath = (LPWSTR)RtlAllocateHeap(ProcessHeap, 0, dwValue);
if (!FullImagePath)
{
DPRINT1("RtlAllocateHeap() failed\n");
return FALSE;
}
RtlCopyMemory(FullImagePath, PathPrefix.Buffer, PathPrefix.MaximumLength);
wcscat(FullImagePath, ImagePath);
DPRINT1("Using driver '%S' for device '%S'\n", ImagePath, DeviceId);;
/* Create service key */
RtlInitUnicodeString(&StringU, Driver);
InitializeObjectAttributes(&ObjectAttributes, &StringU, 0, hServices, NULL);
Status = NtCreateKey(&hService, KEY_SET_VALUE, &ObjectAttributes, 0, NULL, 0, &Disposition);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtCreateKey('%wZ') failed with status 0x%08x\n", &StringU, Status);
RtlFreeHeap(ProcessHeap, 0, FullImagePath);
return FALSE;
}
/* Fill service key */
if (Disposition == REG_CREATED_NEW_KEY)
{
dwValue = 0;
NtSetValueKey(
hService,
&ErrorControlU,
0,
REG_DWORD,
&dwValue,
sizeof(dwValue));
dwValue = 0;
NtSetValueKey(
hService,
&StartU,
0,
REG_DWORD,
&dwValue,
sizeof(dwValue));
dwValue = SERVICE_KERNEL_DRIVER;
NtSetValueKey(
hService,
&TypeU,
0,
REG_DWORD,
&dwValue,
sizeof(dwValue));
}
/* HACK: don't put any path in registry */
NtSetValueKey(
hService,
&ImagePathU,
0,
REG_SZ,
ImagePath,
(wcslen(ImagePath) + 1) * sizeof(WCHAR));
/* Associate device with the service we just filled */
Status = NtSetValueKey(
hDeviceKey,
&ServiceU,
0,
REG_SZ,
Driver,
(wcslen(Driver) + 1) * sizeof(WCHAR));
if (NT_SUCCESS(Status))
{
/* Restart the device, so it will use the driver we registred */
deviceInstalled = ResetDevice(DeviceId);
}
/* HACK: Update driver path */
NtSetValueKey(
hService,
&ImagePathU,
0,
REG_SZ,
FullImagePath,
(wcslen(FullImagePath) + 1) * sizeof(WCHAR));
RtlFreeHeap(ProcessHeap, 0, FullImagePath);
NtClose(hService);
return deviceInstalled;
}
VOID
InstallDevice(
IN HINF hInf,
IN HANDLE hEnum,
IN HANDLE hServices,
IN LPCWSTR DeviceId)
{
UNICODE_STRING HardwareIDU = RTL_CONSTANT_STRING(L"HardwareID");
UNICODE_STRING CompatibleIDsU = RTL_CONSTANT_STRING(L"CompatibleIDs");
UNICODE_STRING DeviceIdU;
OBJECT_ATTRIBUTES ObjectAttributes;
LPCWSTR HardwareID;
PKEY_VALUE_PARTIAL_INFORMATION pPartialInformation = NULL;
HANDLE hDeviceKey;
ULONG ulRequired;
BOOLEAN bDriverInstalled = FALSE;
NTSTATUS Status;
RtlInitUnicodeString(&DeviceIdU, DeviceId);
InitializeObjectAttributes(&ObjectAttributes, &DeviceIdU, 0, hEnum, NULL);
Status = NtOpenKey(&hDeviceKey, KEY_QUERY_VALUE | KEY_SET_VALUE, &ObjectAttributes);
if (!NT_SUCCESS(Status))
{
DPRINT("Unable to open subkey '%S'\n", DeviceId);
return;
}
Status = NtQueryValueKey(
hDeviceKey,
&HardwareIDU,
KeyValuePartialInformation,
NULL,
0,
&ulRequired);
if (Status == STATUS_BUFFER_TOO_SMALL)
{
pPartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION)RtlAllocateHeap(ProcessHeap, 0, ulRequired);
if (!pPartialInformation)
{
DPRINT1("RtlAllocateHeap() failed\n");
NtClose(hDeviceKey);
return;
}
Status = NtQueryValueKey(
hDeviceKey,
&HardwareIDU,
KeyValuePartialInformation,
pPartialInformation,
ulRequired,
&ulRequired);
}
if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
{
/* Nothing to do */
}
else if (!NT_SUCCESS(Status))
{
DPRINT1("NtQueryValueKey() failed with status 0x%08x\n", Status);
if (pPartialInformation)
RtlFreeHeap(ProcessHeap, 0, pPartialInformation);
NtClose(hDeviceKey);
return;
}
else
{
for (HardwareID = (LPCWSTR)pPartialInformation->Data;
(PUCHAR)HardwareID < pPartialInformation->Data + pPartialInformation->DataLength
&& *HardwareID
&& !bDriverInstalled;
HardwareID += wcslen(HardwareID) + 1)
{
bDriverInstalled = InstallDriver(hInf, hServices,hDeviceKey, DeviceId, HardwareID);
}
}
if (!bDriverInstalled)
{
if (pPartialInformation)
{
RtlFreeHeap(ProcessHeap, 0, pPartialInformation);
pPartialInformation = NULL;
}
Status = NtQueryValueKey(
hDeviceKey,
&CompatibleIDsU,
KeyValuePartialInformation,
NULL,
0,
&ulRequired);
if (Status == STATUS_BUFFER_TOO_SMALL)
{
pPartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION)RtlAllocateHeap(ProcessHeap, 0, ulRequired);
if (!pPartialInformation)
{
DPRINT("RtlAllocateHeap() failed\n");
NtClose(hDeviceKey);
return;
}
Status = NtQueryValueKey(
hDeviceKey,
&CompatibleIDsU,
KeyValuePartialInformation,
pPartialInformation,
ulRequired,
&ulRequired);
}
if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
{
/* Nothing to do */
}
else if (!NT_SUCCESS(Status))
{
if (pPartialInformation)
RtlFreeHeap(ProcessHeap, 0, pPartialInformation);
NtClose(hDeviceKey);
DPRINT1("NtQueryValueKey() failed with status 0x%08x\n", Status);
return;
}
else
{
for (HardwareID = (LPCWSTR)pPartialInformation->Data;
(PUCHAR)HardwareID < pPartialInformation->Data + pPartialInformation->DataLength
&& *HardwareID
&& !bDriverInstalled;
HardwareID += wcslen(HardwareID) + 1)
{
bDriverInstalled = InstallDriver(hInf, hServices,hDeviceKey, DeviceId, HardwareID);
}
}
}
if (!bDriverInstalled)
DPRINT("No driver available for %S\n", DeviceId);
RtlFreeHeap(ProcessHeap, 0, pPartialInformation);
NtClose(hDeviceKey);
}
NTSTATUS
EventThread(IN LPVOID lpParameter)
{
UNICODE_STRING EnumU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
UNICODE_STRING ServicesU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services");
PPLUGPLAY_EVENT_BLOCK PnpEvent;
OBJECT_ATTRIBUTES ObjectAttributes;
ULONG PnpEventSize;
HINF hInf;
HANDLE hEnum, hServices;
NTSTATUS Status;
hInf = *(HINF *)lpParameter;
InitializeObjectAttributes(&ObjectAttributes, &EnumU, OBJ_CASE_INSENSITIVE, NULL, NULL);
Status = NtOpenKey(&hEnum, 0, &ObjectAttributes);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU, Status);
return Status;
}
InitializeObjectAttributes(&ObjectAttributes, &ServicesU, OBJ_CASE_INSENSITIVE, NULL, NULL);
Status = NtCreateKey(&hServices, 0, &ObjectAttributes, 0, NULL, 0, NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtCreateKey('%wZ') failed with status 0x%08lx\n", &ServicesU, Status);
NtClose(hEnum);
return Status;
}
PnpEventSize = 0x1000;
PnpEvent = (PPLUGPLAY_EVENT_BLOCK)RtlAllocateHeap(ProcessHeap, 0, PnpEventSize);
if (PnpEvent == NULL)
{
NtClose(hEnum);
NtClose(hServices);
return STATUS_NO_MEMORY;
}
for (;;)
{
DPRINT("Calling NtGetPlugPlayEvent()\n");
/* Wait for the next pnp event */
Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize);
/* Resize the buffer for the PnP event if it's too small. */
if (Status == STATUS_BUFFER_TOO_SMALL)
{
PnpEventSize += 0x400;
PnpEvent = (PPLUGPLAY_EVENT_BLOCK)RtlReAllocateHeap(ProcessHeap, 0, PnpEvent, PnpEventSize);
if (PnpEvent == NULL)
{
NtClose(hEnum);
NtClose(hServices);
return STATUS_NO_MEMORY;
}
continue;
}
if (!NT_SUCCESS(Status))
{
DPRINT("NtPlugPlayEvent() failed (Status %lx)\n", Status);
break;
}
/* Process the pnp event */
DPRINT("Received PnP Event\n");
if (IsEqualIID(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL))
{
DPRINT1("Device arrival event: %S\n", PnpEvent->TargetDevice.DeviceIds);
InstallDevice(hInf, hEnum, hServices, PnpEvent->TargetDevice.DeviceIds);
}
else
{
DPRINT("Unknown event\n");
}
/* Dequeue the current pnp event and signal the next one */
NtPlugPlayControl(PlugPlayControlUserResponse, NULL, 0);
}
RtlFreeHeap(ProcessHeap, 0, PnpEvent);
NtClose(hEnum);
NtClose(hServices);
return STATUS_SUCCESS;
}
DWORD WINAPI
PnpEventThread(IN LPVOID lpParameter)
{
NTSTATUS Status;
Status = EventThread(lpParameter);
NtTerminateThread(NtCurrentThread(), Status);
return 0;
}

View file

@ -84,6 +84,7 @@ LONG UnattendFormatPartition = 0;
LONG AutoPartition = 0;
WCHAR UnattendInstallationDirectory[MAX_PATH];
BOOLEAN RepairUpdateFlag = FALSE;
HANDLE hPnpThread = INVALID_HANDLE_VALUE;
/* LOCALS *******************************************************************/
@ -699,6 +700,13 @@ SetupStartPage(PINPUT_RECORD Ir)
return QUIT_PAGE;
}
/* Start PnP thread */
if (hPnpThread != INVALID_HANDLE_VALUE)
{
NtResumeThread(hPnpThread, NULL);
hPnpThread = INVALID_HANDLE_VALUE;
}
CheckUnattendedSetup();
return INTRO_PAGE;
@ -3630,15 +3638,22 @@ FlushPage(PINPUT_RECORD Ir)
}
DWORD WINAPI
PnpEventThread(IN LPVOID lpParameter);
VOID
RunUSetup(VOID)
{
INPUT_RECORD Ir;
PAGE_NUMBER Page;
LARGE_INTEGER Time;
NTSTATUS Status;
NtQuerySystemTime(&Time);
Status = RtlCreateUserThread(NtCurrentProcess(), NULL, TRUE, 0, 0, 0, PnpEventThread, &SetupInf, &hPnpThread, NULL);
if (!NT_SUCCESS(Status))
hPnpThread = INVALID_HANDLE_VALUE;
if (!CONSOLE_Init())
{
PrintString("Unable to open the console\n\n");

View file

@ -16,6 +16,7 @@
<library>ntdll</library>
<directory name="interface">
<file>consup.c</file>
<file>devinst.c</file>
<file>usetup.c</file>
</directory>
<directory name="native">

View file

@ -29,12 +29,20 @@ i8042prt.sys=,,,,,,x,,,,,,4
kbdclass.sys=,,,,,,x,,,,,,4
l_intl.nls=,,,,,,,,,,,,2
ntfs.sys=,,,,,,,,,,,,4
ntoskrnl.exe=,,,,,,,,,,,,2
pci.sys=,,,,,,,,,,,,4
scsiport.sys=,,,,,,x,,,,,,4
uniata.sys=,,,,,,,,,,,,4
vfatfs.sys=,,,,,,,,,,,,4
[HardwareIdsDatabase]
*PNP0C08 = acpi
*PNP0A03 = pci
PCI\CC_0604 = pci
[BootBusExtenders.Load]
acpi = acpi.sys
pci = pci.sys
[Cabinets]
Cabinet=reactos.cab