Author: hpoussin Date: Thu Dec 6 19:25:57 2007 New Revision: 31044
URL: http://svn.reactos.org/svn/reactos?rev=31044&view=rev Log: 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!
Added: trunk/reactos/base/setup/usetup/interface/devinst.c (with props) Modified: trunk/reactos/base/setup/usetup/interface/usetup.c trunk/reactos/base/setup/usetup/usetup.rbuild trunk/reactos/boot/bootdata/txtsetup.sif
Added: trunk/reactos/base/setup/usetup/interface/devinst.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/setup/usetup/interface... ============================================================================== --- trunk/reactos/base/setup/usetup/interface/devinst.c (added) +++ trunk/reactos/base/setup/usetup/interface/devinst.c Thu Dec 6 19:25:57 2007 @@ -1,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; +}
Propchange: trunk/reactos/base/setup/usetup/interface/devinst.c ------------------------------------------------------------------------------ svn:eol-style = native
Modified: trunk/reactos/base/setup/usetup/interface/usetup.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/setup/usetup/interface... ============================================================================== --- trunk/reactos/base/setup/usetup/interface/usetup.c (original) +++ trunk/reactos/base/setup/usetup/interface/usetup.c Thu Dec 6 19:25:57 2007 @@ -84,6 +84,7 @@ LONG AutoPartition = 0; WCHAR UnattendInstallationDirectory[MAX_PATH]; BOOLEAN RepairUpdateFlag = FALSE; +HANDLE hPnpThread = INVALID_HANDLE_VALUE;
/* LOCALS *******************************************************************/
@@ -697,6 +698,13 @@ "ENTER = Reboot computer", Ir, POPUP_WAIT_ENTER); return QUIT_PAGE; + } + + /* Start PnP thread */ + if (hPnpThread != INVALID_HANDLE_VALUE) + { + NtResumeThread(hPnpThread, NULL); + hPnpThread = INVALID_HANDLE_VALUE; }
CheckUnattendedSetup(); @@ -3630,15 +3638,22 @@ }
+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");
Modified: trunk/reactos/base/setup/usetup/usetup.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/setup/usetup/usetup.rb... ============================================================================== --- trunk/reactos/base/setup/usetup/usetup.rbuild (original) +++ trunk/reactos/base/setup/usetup/usetup.rbuild Thu Dec 6 19:25:57 2007 @@ -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">
Modified: trunk/reactos/boot/bootdata/txtsetup.sif URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/bootdata/txtsetup.sif?... ============================================================================== --- trunk/reactos/boot/bootdata/txtsetup.sif (original) +++ trunk/reactos/boot/bootdata/txtsetup.sif Thu Dec 6 19:25:57 2007 @@ -29,11 +29,19 @@ 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