https://git.reactos.org/?p=reactos.git;a=commitdiff;h=94874baf198fb86536ee41...
commit 94874baf198fb86536ee41a71e016a47e37799b4 Author: Hermès Bélusca-Maïto hermes.belusca-maito@reactos.org AuthorDate: Tue Mar 22 04:14:35 2022 +0100 Commit: Hermès Bélusca-Maïto hermes.belusca-maito@reactos.org CommitDate: Sun Apr 17 04:57:42 2022 +0200
[FREELDR:NTLDR] Use NTOS kernel's CMBOOT functions to enumerate and build the boot-time driver list.
They are correct and are more performant.
- Rewrite WinLdrAddDriverToList() on the model of CmpAddDriverToList() with support for CmpIsDriverInList().
- Disable RegEnumKey() as it is now unused. --- boot/freeldr/freeldr/CMakeLists.txt | 1 + boot/freeldr/freeldr/ntldr/registry.c | 2 + boot/freeldr/freeldr/ntldr/registry.h | 2 + boot/freeldr/freeldr/ntldr/setupldr.c | 62 +++- boot/freeldr/freeldr/ntldr/winldr.c | 39 +- boot/freeldr/freeldr/ntldr/winldr.h | 30 +- boot/freeldr/freeldr/ntldr/wlregistry.c | 626 ++++++++++++-------------------- 7 files changed, 333 insertions(+), 429 deletions(-)
diff --git a/boot/freeldr/freeldr/CMakeLists.txt b/boot/freeldr/freeldr/CMakeLists.txt index 592f0af85c1..00d6dc8271b 100644 --- a/boot/freeldr/freeldr/CMakeLists.txt +++ b/boot/freeldr/freeldr/CMakeLists.txt @@ -48,6 +48,7 @@ list(APPEND FREELDR_BOOTLIB_SOURCE lib/mm/heap.c)
list(APPEND FREELDR_NTLDR_SOURCE + ${REACTOS_SOURCE_DIR}/ntoskrnl/config/cmboot.c ntldr/conversion.c ntldr/registry.c ntldr/winldr.c diff --git a/boot/freeldr/freeldr/ntldr/registry.c b/boot/freeldr/freeldr/ntldr/registry.c index 132309eb6d1..88046036e53 100644 --- a/boot/freeldr/freeldr/ntldr/registry.c +++ b/boot/freeldr/freeldr/ntldr/registry.c @@ -242,6 +242,7 @@ GetNextPathElement( return TRUE; }
+#if 0 LONG RegEnumKey( _In_ HKEY Key, @@ -312,6 +313,7 @@ RegEnumKey( TRACE("RegEnumKey done -> %u, '%.*S'\n", *NameSize, *NameSize, Name); return ERROR_SUCCESS; } +#endif
LONG RegOpenKey( diff --git a/boot/freeldr/freeldr/ntldr/registry.h b/boot/freeldr/freeldr/ntldr/registry.h index 028f75042d6..23626756986 100644 --- a/boot/freeldr/freeldr/ntldr/registry.h +++ b/boot/freeldr/freeldr/ntldr/registry.h @@ -44,6 +44,7 @@ extern HKEY CurrentControlSetKey; */ #define RegCloseKey(hKey) (ERROR_SUCCESS)
+#if 0 LONG RegEnumKey( _In_ HKEY Key, @@ -51,6 +52,7 @@ RegEnumKey( _Out_ PWCHAR Name, _Inout_ PULONG NameSize, _Out_opt_ PHKEY SubKey); +#endif
LONG RegOpenKey( diff --git a/boot/freeldr/freeldr/ntldr/setupldr.c b/boot/freeldr/freeldr/ntldr/setupldr.c index b300be50813..576222378f7 100644 --- a/boot/freeldr/freeldr/ntldr/setupldr.c +++ b/boot/freeldr/freeldr/ntldr/setupldr.c @@ -135,17 +135,22 @@ SetupLdrInitErrataInf( }
static VOID -SetupLdrScanBootDrivers(PLIST_ENTRY BootDriverListHead, HINF InfHandle, PCSTR SearchPath) +SetupLdrScanBootDrivers( + _Inout_ PLIST_ENTRY BootDriverListHead, + _In_ HINF InfHandle, + _In_ PCSTR SearchPath) { INFCONTEXT InfContext, dirContext; - BOOLEAN Success; PCSTR Media, DriverName, dirIndex, ImagePath; - WCHAR ServiceName[256]; - WCHAR ImagePathW[256]; + BOOLEAN Success; + WCHAR ImagePathW[MAX_PATH]; + WCHAR DriverNameW[256];
- /* Open inf section */ + UNREFERENCED_PARAMETER(SearchPath); + + /* Open INF section */ if (!InfFindFirstLine(InfHandle, "SourceDisksFiles", NULL, &InfContext)) - return; + goto Quit;
/* Load all listed boot drivers */ do @@ -158,30 +163,51 @@ SetupLdrScanBootDrivers(PLIST_ENTRY BootDriverListHead, HINF InfHandle, PCSTR Se InfFindFirstLine(InfHandle, "Directories", dirIndex, &dirContext) && InfGetDataField(&dirContext, 1, &ImagePath)) { - /* Convert name to widechar */ - swprintf(ServiceName, L"%S", DriverName); - /* Prepare image path */ - swprintf(ImagePathW, L"%S", ImagePath); - wcscat(ImagePathW, L"\"); - wcscat(ImagePathW, ServiceName); + RtlStringCbPrintfW(ImagePathW, sizeof(ImagePathW), + L"%S\%S", ImagePath, DriverName);
- /* Remove .sys extension */ - ServiceName[wcslen(ServiceName) - 4] = 0; + /* Convert name to unicode and remove .sys extension */ + RtlStringCbPrintfW(DriverNameW, sizeof(DriverNameW), + L"%S", DriverName); + DriverNameW[wcslen(DriverNameW) - 4] = UNICODE_NULL;
/* Add it to the list */ Success = WinLdrAddDriverToList(BootDriverListHead, - L"\Registry\Machine\System\CurrentControlSet\Services\", + FALSE, + DriverNameW, ImagePathW, - ServiceName); + NULL, + SERVICE_ERROR_NORMAL, + -1); if (!Success) { - ERR("Could not add boot driver '%s', '%s'\n", SearchPath, DriverName); - return; + ERR("Could not add boot driver '%s'\n", DriverName); + /* Ignore and continue adding other drivers */ } } } } while (InfFindNextLine(&InfContext, &InfContext)); + +Quit: + /* Finally, add the boot filesystem driver to the list */ + if (BootFileSystem) + { + TRACE("Adding filesystem driver %S\n", BootFileSystem); + Success = WinLdrAddDriverToList(BootDriverListHead, + FALSE, + BootFileSystem, + NULL, + L"Boot File System", + SERVICE_ERROR_CRITICAL, + -1); + if (!Success) + ERR("Failed to add filesystem driver %S\n", BootFileSystem); + } + else + { + TRACE("No required filesystem driver\n"); + } }
diff --git a/boot/freeldr/freeldr/ntldr/winldr.c b/boot/freeldr/freeldr/ntldr/winldr.c index 5427b14fe22..9f51a541721 100644 --- a/boot/freeldr/freeldr/ntldr/winldr.c +++ b/boot/freeldr/freeldr/ntldr/winldr.c @@ -10,6 +10,7 @@ #include "winldr.h" #include "ntldropts.h" #include "registry.h" +#include <internal/cmboot.h>
#include <debug.h> DBG_DEFAULT_CHANNEL(WINDOWS); @@ -26,6 +27,7 @@ extern BOOLEAN WinLdrTerminalConnected; extern VOID WinLdrSetupEms(IN PCSTR BootOptions);
PLOADER_SYSTEM_BLOCK WinLdrSystemBlock; +/**/PCWSTR BootFileSystem = NULL;/**/
BOOLEAN VirtualBias = FALSE; BOOLEAN SosEnabled = FALSE; @@ -363,23 +365,30 @@ WinLdrLoadBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock, PCSTR BootPath) { PLIST_ENTRY NextBd; + PBOOT_DRIVER_NODE DriverNode; PBOOT_DRIVER_LIST_ENTRY BootDriver; BOOLEAN Success; BOOLEAN ret = TRUE;
- // Walk through the boot drivers list + /* Walk through the boot drivers list */ NextBd = LoaderBlock->BootDriverListHead.Flink; - while (NextBd != &LoaderBlock->BootDriverListHead) { - BootDriver = CONTAINING_RECORD(NextBd, BOOT_DRIVER_LIST_ENTRY, Link); + DriverNode = CONTAINING_RECORD(NextBd, + BOOT_DRIVER_NODE, + ListEntry.Link); + BootDriver = &DriverNode->ListEntry;
- TRACE("BootDriver %wZ DTE %08X RegPath: %wZ\n", &BootDriver->FilePath, - BootDriver->LdrEntry, &BootDriver->RegistryPath); + /* Get the next list entry as we may remove the current one on failure */ + NextBd = BootDriver->Link.Flink; + + TRACE("BootDriver %wZ DTE %08X RegPath: %wZ\n", + &BootDriver->FilePath, BootDriver->LdrEntry, + &BootDriver->RegistryPath);
// Paths are relative (FIXME: Are they always relative?)
- // Load it + /* Load it */ UiIndicateProgress(); Success = WinLdrLoadDeviceDriver(&LoaderBlock->LoadOrderListHead, BootPath, @@ -388,23 +397,25 @@ WinLdrLoadBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock, &BootDriver->LdrEntry); if (Success) { - // Convert the RegistryPath and DTE addresses to VA since we are not going to use it anymore + /* Convert the addresses to VA since we are not going to use them anymore */ BootDriver->RegistryPath.Buffer = PaToVa(BootDriver->RegistryPath.Buffer); BootDriver->FilePath.Buffer = PaToVa(BootDriver->FilePath.Buffer); BootDriver->LdrEntry = PaToVa(BootDriver->LdrEntry); + + if (DriverNode->Group.Buffer) + DriverNode->Group.Buffer = PaToVa(DriverNode->Group.Buffer); + DriverNode->Name.Buffer = PaToVa(DriverNode->Name.Buffer); } else { - // Loading failed - cry loudly - ERR("Can't load boot driver '%wZ'!\n", &BootDriver->FilePath); - UiMessageBox("Can't load boot driver '%wZ'!", &BootDriver->FilePath); + /* Loading failed: cry loudly */ + ERR("Cannot load boot driver '%wZ'!\n", &BootDriver->FilePath); + UiMessageBox("Cannot load boot driver '%wZ'!", &BootDriver->FilePath); ret = FALSE;
- // Remove it from the list and try to continue - RemoveEntryList(NextBd); + /* Remove it from the list and try to continue */ + RemoveEntryList(&BootDriver->Link); } - - NextBd = BootDriver->Link.Flink; }
return ret; diff --git a/boot/freeldr/freeldr/ntldr/winldr.h b/boot/freeldr/freeldr/ntldr/winldr.h index ab06855f14f..20a20ba7cce 100644 --- a/boot/freeldr/freeldr/ntldr/winldr.h +++ b/boot/freeldr/freeldr/ntldr/winldr.h @@ -61,6 +61,7 @@ typedef struct _LOADER_SYSTEM_BLOCK } LOADER_SYSTEM_BLOCK, *PLOADER_SYSTEM_BLOCK;
extern PLOADER_SYSTEM_BLOCK WinLdrSystemBlock; +/**/extern PCWSTR BootFileSystem;/**/
// conversion.c @@ -71,7 +72,6 @@ VOID List_PaToVa(_In_ LIST_ENTRY *ListEntry); #endif VOID ConvertConfigToVA(PCONFIGURATION_COMPONENT_DATA Start);
- // winldr.c extern BOOLEAN SosEnabled; #ifdef _M_IX86 @@ -117,14 +117,6 @@ WinLdrInitSystemHive( BOOLEAN WinLdrScanSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, IN PCSTR SystemRoot);
-// winldr.c -VOID -WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock, - PCSTR Options, - PCSTR SystemPath, - PCSTR BootPath, - USHORT VersionToBoot); - BOOLEAN WinLdrLoadNLSData( _Inout_ PLOADER_PARAMETER_BLOCK LoaderBlock, @@ -135,10 +127,22 @@ WinLdrLoadNLSData( _In_ PCUNICODE_STRING OemHalFileName);
BOOLEAN -WinLdrAddDriverToList(LIST_ENTRY *BootDriverListHead, - PWSTR RegistryPath, - PWSTR ImagePath, - PWSTR ServiceName); +WinLdrAddDriverToList( + _Inout_ PLIST_ENTRY DriverListHead, + _In_ BOOLEAN InsertAtHead, + _In_ PCWSTR DriverName, + _In_opt_ PCWSTR ImagePath, + _In_opt_ PCWSTR GroupName, + _In_ ULONG ErrorControl, + _In_ ULONG Tag); + +// winldr.c +VOID +WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock, + PCSTR Options, + PCSTR SystemPath, + PCSTR BootPath, + USHORT VersionToBoot);
VOID WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock); diff --git a/boot/freeldr/freeldr/ntldr/wlregistry.c b/boot/freeldr/freeldr/ntldr/wlregistry.c index cc139b77111..e36aae18f2a 100644 --- a/boot/freeldr/freeldr/ntldr/wlregistry.c +++ b/boot/freeldr/freeldr/ntldr/wlregistry.c @@ -11,6 +11,7 @@ #include <freeldr.h> #include "winldr.h" #include "registry.h" +#include <internal/cmboot.h>
#include <debug.h> DBG_DEFAULT_CHANNEL(WINDOWS); @@ -26,9 +27,9 @@ WinLdrGetNLSNames( _Inout_ PUNICODE_STRING LangFileName, // CaseTable _Inout_ PUNICODE_STRING OemHalFileName);
-static VOID -WinLdrScanRegistry(IN OUT PLIST_ENTRY BootDriverListHead, - IN PCSTR SystemRoot); +static BOOLEAN +WinLdrScanRegistry( + IN OUT PLIST_ENTRY BootDriverListHead);
/* FUNCTIONS **************************************************************/ @@ -47,7 +48,6 @@ WinLdrLoadSystemHive( PVOID HiveDataPhysical; PVOID HiveDataVirtual; ULONG BytesRead; - PCWSTR FsService;
/* Concatenate path and filename to get the full name */ RtlStringCbCopyA(FullHiveName, sizeof(FullHiveName), DirectoryPath); @@ -99,23 +99,8 @@ WinLdrLoadSystemHive( return FALSE; }
- /* Add boot filesystem driver to the list */ - FsService = FsGetServiceName(FileId); - if (FsService) - { - BOOLEAN Success; - TRACE("Adding filesystem service %S\n", FsService); - Success = WinLdrAddDriverToList(&LoaderBlock->BootDriverListHead, - L"\Registry\Machine\System\CurrentControlSet\Services\", - NULL, - (PWSTR)FsService); - if (!Success) - TRACE("Failed to add filesystem service\n"); - } - else - { - TRACE("No required filesystem service\n"); - } + // FIXME: HACK: Get the boot filesystem driver name now... + BootFileSystem = FsGetServiceName(FileId);
ArcClose(FileId); return TRUE; @@ -184,7 +169,12 @@ BOOLEAN WinLdrScanSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, CHAR SearchPath[1024];
/* Scan registry and prepare boot drivers list */ - WinLdrScanRegistry(&LoaderBlock->BootDriverListHead, SystemRoot); + Success = WinLdrScanRegistry(&LoaderBlock->BootDriverListHead); + if (!Success) + { + UiMessageBox("Failed to load boot drivers!"); + return FALSE; + }
/* Get names of NLS files */ Success = WinLdrGetNLSNames(CurrentControlSetKey, @@ -517,412 +507,280 @@ Quit: return (Status == ESUCCESS); }
-static VOID -WinLdrScanRegistry(IN OUT PLIST_ENTRY BootDriverListHead, - IN PCSTR SystemRoot) +static BOOLEAN +WinLdrScanRegistry( + IN OUT PLIST_ENTRY BootDriverListHead) { - LONG rc = 0; - HKEY hOrderKey, hServiceKey, hGroupKey, hDriverKey; - PWSTR GroupNameBuffer = NULL; - WCHAR ServiceName[256]; - ULONG OrderList[128]; - ULONG BufferSize; - ULONG Index; - ULONG TagIndex; - PWSTR GroupName; - - ULONG ValueSize; - ULONG ValueType; - ULONG StartValue; - ULONG TagValue; - WCHAR DriverGroup[256]; - ULONG DriverGroupSize; - - CHAR ImagePath[256]; - WCHAR TempImagePath[256]; - BOOLEAN Success;
- /* Get 'group order list' key */ - rc = RegOpenKey(CurrentControlSetKey, L"Control\GroupOrderList", &hOrderKey); - if (rc != ERROR_SUCCESS) - { - TRACE_CH(REACTOS, "Failed to open the 'GroupOrderList' key (rc %d)\n", (int)rc); - return; - } - - /* Get 'services' key */ - rc = RegOpenKey(CurrentControlSetKey, L"Services", &hServiceKey); - if (rc != ERROR_SUCCESS) - { - TRACE_CH(REACTOS, "Failed to open the 'Services' key (rc %d)\n", (int)rc); - RegCloseKey(hOrderKey); - return; - } - - /* Get 'service group order' key */ - rc = RegOpenKey(CurrentControlSetKey, L"Control\ServiceGroupOrder", &hGroupKey); - if (rc != ERROR_SUCCESS) - { - TRACE_CH(REACTOS, "Failed to open the 'ServiceGroupOrder' key (rc %d)\n", (int)rc); + /* Find all boot drivers */ + Success = CmpFindDrivers(SystemHive, + (HCELL_INDEX)CurrentControlSetKey, + BootLoad, + BootFileSystem, + BootDriverListHead); + if (!Success) goto Quit; - }
- /* Get the Group Order List */ - BufferSize = 4096; - GroupNameBuffer = FrLdrHeapAlloc(BufferSize, TAG_WLDR_NAME); - if (!GroupNameBuffer) - { - TRACE_CH(REACTOS, "Failed to allocate buffer\n"); - RegCloseKey(hGroupKey); + /* Sort by group/tag */ + Success = CmpSortDriverList(SystemHive, + (HCELL_INDEX)CurrentControlSetKey, + BootDriverListHead); + if (!Success) goto Quit; - } - rc = RegQueryValue(hGroupKey, L"List", NULL, (PUCHAR)GroupNameBuffer, &BufferSize); - RegCloseKey(hGroupKey);
- if (rc != ERROR_SUCCESS) - { - TRACE_CH(REACTOS, "Failed to query the 'List' value (rc %d)\n", (int)rc); + /* Remove circular dependencies (cycles) and sort */ + Success = CmpResolveDriverDependencies(BootDriverListHead); + if (!Success) goto Quit; - } - TRACE_CH(REACTOS, "BufferSize: %d\n", (int)BufferSize); - TRACE_CH(REACTOS, "GroupNameBuffer: '%S'\n", GroupNameBuffer); - - /* Loop through each group */ - GroupName = GroupNameBuffer; - while (*GroupName) - { - TRACE("Driver group: '%S'\n", GroupName); - - /* Query the Order */ - BufferSize = sizeof(OrderList); - rc = RegQueryValue(hOrderKey, GroupName, NULL, (PUCHAR)OrderList, &BufferSize); - if (rc != ERROR_SUCCESS) OrderList[0] = 0; - - /* Enumerate all drivers */ - for (TagIndex = 1; TagIndex <= OrderList[0]; TagIndex++) - { - for (Index = 0; TRUE; Index++) - { - /* Get the Driver's Name */ - ValueSize = sizeof(ServiceName); - rc = RegEnumKey(hServiceKey, Index, ServiceName, &ValueSize, &hDriverKey); - TRACE("RegEnumKey(): rc %d\n", (int)rc); - - /* Make sure it's valid, and check if we're done */ - if (rc == ERROR_NO_MORE_ITEMS) - break; - if (rc != ERROR_SUCCESS) - goto Quit; - //TRACE_CH(REACTOS, "Service %d: '%S'\n", (int)Index, ServiceName); - - /* Read the Start Value */ - ValueSize = sizeof(ULONG); - rc = RegQueryValue(hDriverKey, L"Start", &ValueType, (PUCHAR)&StartValue, &ValueSize); - if (rc != ERROR_SUCCESS) StartValue = (ULONG)-1; - //TRACE_CH(REACTOS, " Start: %x\n", (int)StartValue); - - /* Read the Tag */ - ValueSize = sizeof(ULONG); - rc = RegQueryValue(hDriverKey, L"Tag", &ValueType, (PUCHAR)&TagValue, &ValueSize); - if (rc != ERROR_SUCCESS) TagValue = (ULONG)-1; - //TRACE_CH(REACTOS, " Tag: %x\n", (int)TagValue); - - /* Read the driver's group */ - DriverGroupSize = sizeof(DriverGroup); - rc = RegQueryValue(hDriverKey, L"Group", NULL, (PUCHAR)DriverGroup, &DriverGroupSize); - //TRACE_CH(REACTOS, " Group: '%S'\n", DriverGroup); - - /* Make sure it should be started */ - if ((StartValue == 0) && - (TagValue == OrderList[TagIndex]) && - (_wcsicmp(DriverGroup, GroupName) == 0)) - { - /* Get the Driver's Location */ - ValueSize = sizeof(TempImagePath); - rc = RegQueryValue(hDriverKey, L"ImagePath", NULL, (PUCHAR)TempImagePath, &ValueSize); - - /* Write the whole path if it succeeded, else prepare to fail */ - if (rc != ERROR_SUCCESS) - { - TRACE_CH(REACTOS, "ImagePath: not found\n"); - TempImagePath[0] = 0; - RtlStringCbPrintfA(ImagePath, sizeof(ImagePath), "%s\system32\drivers\%S.sys", SystemRoot, ServiceName); - } - else if (TempImagePath[0] != L'\') - { - RtlStringCbPrintfA(ImagePath, sizeof(ImagePath), "%s%S", SystemRoot, TempImagePath); - } - else - { - RtlStringCbPrintfA(ImagePath, sizeof(ImagePath), "%S", TempImagePath); - TRACE_CH(REACTOS, "ImagePath: '%s'\n", ImagePath); - } - - TRACE("Adding boot driver: '%s'\n", ImagePath); - - Success = WinLdrAddDriverToList(BootDriverListHead, - L"\Registry\Machine\System\CurrentControlSet\Services\", - TempImagePath, - ServiceName); - if (!Success) - ERR("Failed to add boot driver\n"); - } - else - { - //TRACE(" Skipping driver '%S' with Start %d, Tag %d and Group '%S' (Current Tag %d, current group '%S')\n", - // ServiceName, StartValue, TagValue, DriverGroup, OrderList[TagIndex], GroupName); - } - - RegCloseKey(hDriverKey); - } - } - - for (Index = 0; TRUE; Index++) - { - /* Get the Driver's Name */ - ValueSize = sizeof(ServiceName); - rc = RegEnumKey(hServiceKey, Index, ServiceName, &ValueSize, &hDriverKey); - - //TRACE_CH(REACTOS, "RegEnumKey(): rc %d\n", (int)rc); - if (rc == ERROR_NO_MORE_ITEMS) - break; - if (rc != ERROR_SUCCESS) - goto Quit; - TRACE("Service %d: '%S'\n", (int)Index, ServiceName); - - /* Read the Start Value */ - ValueSize = sizeof(ULONG); - rc = RegQueryValue(hDriverKey, L"Start", &ValueType, (PUCHAR)&StartValue, &ValueSize); - if (rc != ERROR_SUCCESS) StartValue = (ULONG)-1; - //TRACE_CH(REACTOS, " Start: %x\n", (int)StartValue); - - /* Read the Tag */ - ValueSize = sizeof(ULONG); - rc = RegQueryValue(hDriverKey, L"Tag", &ValueType, (PUCHAR)&TagValue, &ValueSize); - if (rc != ERROR_SUCCESS) TagValue = (ULONG)-1; - //TRACE_CH(REACTOS, " Tag: %x\n", (int)TagValue); - - /* Read the driver's group */ - DriverGroupSize = sizeof(DriverGroup); - rc = RegQueryValue(hDriverKey, L"Group", NULL, (PUCHAR)DriverGroup, &DriverGroupSize); - //TRACE_CH(REACTOS, " Group: '%S'\n", DriverGroup); - - for (TagIndex = 1; TagIndex <= OrderList[0]; TagIndex++) - { - if (TagValue == OrderList[TagIndex]) break; - } - - if ((StartValue == 0) && - (TagIndex > OrderList[0]) && - (_wcsicmp(DriverGroup, GroupName) == 0)) - { - ValueSize = sizeof(TempImagePath); - rc = RegQueryValue(hDriverKey, L"ImagePath", NULL, (PUCHAR)TempImagePath, &ValueSize); - if (rc != ERROR_SUCCESS) - { - TRACE_CH(REACTOS, "ImagePath: not found\n"); - TempImagePath[0] = 0; - RtlStringCbPrintfA(ImagePath, sizeof(ImagePath), "%ssystem32\drivers\%S.sys", SystemRoot, ServiceName); - } - else if (TempImagePath[0] != L'\') - { - RtlStringCbPrintfA(ImagePath, sizeof(ImagePath), "%s%S", SystemRoot, TempImagePath); - } - else - { - RtlStringCbPrintfA(ImagePath, sizeof(ImagePath), "%S", TempImagePath); - TRACE_CH(REACTOS, "ImagePath: '%s'\n", ImagePath); - } - TRACE(" Adding boot driver: '%s'\n", ImagePath); - - Success = WinLdrAddDriverToList(BootDriverListHead, - L"\Registry\Machine\System\CurrentControlSet\Services\", - TempImagePath, - ServiceName); - if (!Success) - ERR(" Failed to add boot driver\n"); - } - else - { - //TRACE(" Skipping driver '%S' with Start %d, Tag %d and Group '%S' (Current group '%S')\n", - // ServiceName, StartValue, TagValue, DriverGroup, GroupName); - } - - RegCloseKey(hDriverKey); - } - - /* Move to the next group name */ - GroupName = GroupName + wcslen(GroupName) + 1; - }
Quit: - /* Free allocated memory */ - if (GroupNameBuffer) - FrLdrHeapFree(GroupNameBuffer, TAG_WLDR_NAME); + /* In case of failure, free the boot driver list */ + if (!Success) + CmpFreeDriverList(SystemHive, BootDriverListHead);
- /* Close the registry key handles */ - RegCloseKey(hServiceKey); - RegCloseKey(hOrderKey); + return Success; }
-static +/** + * @brief + * Inserts the specified driver entry into the driver list, or updates + * an existing entry with new ImagePath, ErrorControl, Group and Tag values. + * + * @param[in,out] DriverListHead + * The driver list where to insert the driver entry. + * + * @param[in] InsertAtHead + * Whether to insert the driver at the head (TRUE) or at the tail (FALSE) + * of the driver list. + * + * @param[in] DriverName + * The driver's name. + * + * @param[in] ImagePath + * Optional path the the driver's image. If none is specified, + * a default path is constructed out of the driver's name. + * + * @param[in] GroupName + * Optional driver group name. + * + * @param[in] ErrorControl + * @param[in] Tag + * The ErrorControl and group Tag values for the driver. + * + * @return + * TRUE if the driver has been inserted into the list or updated, FALSE if not. + **/ BOOLEAN -InsertInBootDriverList( - PLIST_ENTRY BootDriverListHead, - PBOOT_DRIVER_LIST_ENTRY BootDriverEntry) +WinLdrAddDriverToList( + _Inout_ PLIST_ENTRY DriverListHead, + _In_ BOOLEAN InsertAtHead, + _In_ PCWSTR DriverName, + _In_opt_ PCWSTR ImagePath, + _In_opt_ PCWSTR GroupName, + _In_ ULONG ErrorControl, + _In_ ULONG Tag) { + PBOOT_DRIVER_NODE DriverNode; PBOOT_DRIVER_LIST_ENTRY DriverEntry; - PLIST_ENTRY ListEntry; - - ASSERT(BootDriverEntry->FilePath.Buffer != NULL); - ASSERT(BootDriverEntry->RegistryPath.Buffer != NULL); - - for (ListEntry = BootDriverListHead->Flink; - ListEntry != BootDriverListHead; - ListEntry = ListEntry->Flink) - { - DriverEntry = CONTAINING_RECORD(ListEntry, - BOOT_DRIVER_LIST_ENTRY, - Link); - if ((DriverEntry->FilePath.Buffer != NULL) && - RtlEqualUnicodeString(&BootDriverEntry->FilePath, - &DriverEntry->FilePath, - TRUE)) - { - return FALSE; - } - - if ((DriverEntry->RegistryPath.Buffer != NULL) && - RtlEqualUnicodeString(&BootDriverEntry->RegistryPath, - &DriverEntry->RegistryPath, - TRUE)) - { - return FALSE; - } + BOOLEAN AlreadyInserted; + USHORT PathLength; + UNICODE_STRING DriverNameU; + UNICODE_STRING RegistryPath; + UNICODE_STRING FilePath = {0}; + UNICODE_STRING RegistryString = {0}; + UNICODE_STRING GroupString = {0}; + + /* Check whether the driver is already in the list */ + RtlInitUnicodeString(&DriverNameU, DriverName); + AlreadyInserted = CmpIsDriverInList(DriverListHead, + &DriverNameU, + &DriverNode); + if (AlreadyInserted) + { + /* If so, we have obtained its node */ + ASSERT(DriverNode); + DriverEntry = &DriverNode->ListEntry; } + else + { + /* Allocate a driver node and initialize it */ + DriverNode = CmpAllocate(sizeof(BOOT_DRIVER_NODE), FALSE, TAG_CM); + if (!DriverNode) + return FALSE;
- InsertTailList(BootDriverListHead, &BootDriverEntry->Link); - return TRUE; -} - -BOOLEAN -WinLdrAddDriverToList(LIST_ENTRY *BootDriverListHead, - PWSTR RegistryPath, - PWSTR ImagePath, - PWSTR ServiceName) -{ - PBOOT_DRIVER_LIST_ENTRY BootDriverEntry; - NTSTATUS Status; - USHORT PathLength; + RtlZeroMemory(DriverNode, sizeof(BOOT_DRIVER_NODE)); + DriverEntry = &DriverNode->ListEntry;
- BootDriverEntry = FrLdrHeapAlloc(sizeof(BOOT_DRIVER_LIST_ENTRY), TAG_WLDR_BDE); - if (!BootDriverEntry) - return FALSE; + /* Driver Name */ + RtlInitEmptyUnicodeString(&DriverNode->Name, + CmpAllocate(DriverNameU.Length, FALSE, TAG_CM), + DriverNameU.Length); + if (!DriverNode->Name.Buffer) + goto Failure;
- // DTE will be filled during actual load of the driver - BootDriverEntry->LdrEntry = NULL; + if (!NT_SUCCESS(RtlAppendUnicodeStringToString(&DriverNode->Name, &DriverNameU))) + goto Failure; + }
- // Check - if we have a valid ImagePath, if not - we need to build it - // like "System32\Drivers\blah.sys" - if (ImagePath && (ImagePath[0] != 0)) + /* Check whether we have a valid ImagePath. If not, we need + * to build it like "System32\Drivers\blah.sys" */ + if (ImagePath && *ImagePath) { - // Just copy ImagePath to the corresponding field in the structure - PathLength = (USHORT)wcslen(ImagePath) * sizeof(WCHAR) + sizeof(UNICODE_NULL); + /* Just copy ImagePath to the corresponding field in the structure */ + PathLength = (USHORT)(wcslen(ImagePath)) * sizeof(WCHAR); + RtlInitEmptyUnicodeString(&FilePath, + CmpAllocate(PathLength, FALSE, TAG_WLDR_NAME), + PathLength); + if (!FilePath.Buffer) + goto Failure;
- BootDriverEntry->FilePath.Length = 0; - BootDriverEntry->FilePath.MaximumLength = PathLength; - BootDriverEntry->FilePath.Buffer = FrLdrHeapAlloc(PathLength, TAG_WLDR_NAME); - if (!BootDriverEntry->FilePath.Buffer) - { - FrLdrHeapFree(BootDriverEntry, TAG_WLDR_BDE); - return FALSE; - } - - Status = RtlAppendUnicodeToString(&BootDriverEntry->FilePath, ImagePath); - if (!NT_SUCCESS(Status)) - { - FrLdrHeapFree(BootDriverEntry->FilePath.Buffer, TAG_WLDR_NAME); - FrLdrHeapFree(BootDriverEntry, TAG_WLDR_BDE); - return FALSE; - } + if (!NT_SUCCESS(RtlAppendUnicodeToString(&FilePath, ImagePath))) + goto Failure; } else { - // we have to construct ImagePath ourselves - PathLength = (USHORT)wcslen(ServiceName)*sizeof(WCHAR) + sizeof(L"system32\drivers\.sys"); - BootDriverEntry->FilePath.Length = 0; - BootDriverEntry->FilePath.MaximumLength = PathLength; - BootDriverEntry->FilePath.Buffer = FrLdrHeapAlloc(PathLength, TAG_WLDR_NAME); - if (!BootDriverEntry->FilePath.Buffer) + /* We have to construct ImagePath ourselves */ + PathLength = DriverNode->Name.Length + sizeof(L"system32\drivers\.sys"); + RtlInitEmptyUnicodeString(&FilePath, + CmpAllocate(PathLength, FALSE, TAG_WLDR_NAME), + PathLength); + if (!FilePath.Buffer) + goto Failure; + + if (!NT_SUCCESS(RtlAppendUnicodeToString(&FilePath, L"system32\drivers\")) || + !NT_SUCCESS(RtlAppendUnicodeStringToString(&FilePath, &DriverNode->Name)) || + !NT_SUCCESS(RtlAppendUnicodeToString(&FilePath, L".sys"))) { - FrLdrHeapFree(BootDriverEntry, TAG_WLDR_BDE); - return FALSE; + goto Failure; } + }
- Status = RtlAppendUnicodeToString(&BootDriverEntry->FilePath, L"system32\drivers\"); - if (!NT_SUCCESS(Status)) - { - FrLdrHeapFree(BootDriverEntry->FilePath.Buffer, TAG_WLDR_NAME); - FrLdrHeapFree(BootDriverEntry, TAG_WLDR_BDE); - return FALSE; - } + /* Registry path */ + RtlInitUnicodeString(&RegistryPath, + L"\Registry\Machine\System\CurrentControlSet\Services\"); + PathLength = RegistryPath.Length + DriverNode->Name.Length; + RtlInitEmptyUnicodeString(&RegistryString, + CmpAllocate(PathLength, FALSE, TAG_WLDR_NAME), + PathLength); + if (!RegistryString.Buffer) + goto Failure;
- Status = RtlAppendUnicodeToString(&BootDriverEntry->FilePath, ServiceName); - if (!NT_SUCCESS(Status)) - { - FrLdrHeapFree(BootDriverEntry->FilePath.Buffer, TAG_WLDR_NAME); - FrLdrHeapFree(BootDriverEntry, TAG_WLDR_BDE); - return FALSE; - } + if (!NT_SUCCESS(RtlAppendUnicodeStringToString(&RegistryString, &RegistryPath)) || + !NT_SUCCESS(RtlAppendUnicodeStringToString(&RegistryString, &DriverNode->Name))) + { + goto Failure; + }
- Status = RtlAppendUnicodeToString(&BootDriverEntry->FilePath, L".sys"); - if (!NT_SUCCESS(Status)) - { - FrLdrHeapFree(BootDriverEntry->FilePath.Buffer, TAG_WLDR_NAME); - FrLdrHeapFree(BootDriverEntry, TAG_WLDR_BDE); - return FALSE; - } + /* Group */ + if (GroupName && *GroupName) + { + /* + * NOTE: Here we can use our own allocator as we alone maintain the + * group string. This is different from the other allocated strings, + * where we instead need to use the same (hive) allocator as the + * one used by CmpAddDriverToList(), for interoperability purposes. + */ + RtlCreateUnicodeString(&GroupString, GroupName); + if (!GroupString.Buffer) + goto Failure; + } + else + { + RtlInitEmptyUnicodeString(&GroupString, NULL, 0); }
- // Add registry path - PathLength = (USHORT)(wcslen(RegistryPath) + wcslen(ServiceName))*sizeof(WCHAR) + sizeof(UNICODE_NULL); - BootDriverEntry->RegistryPath.Length = 0; - BootDriverEntry->RegistryPath.MaximumLength = PathLength; - BootDriverEntry->RegistryPath.Buffer = FrLdrHeapAlloc(PathLength, TAG_WLDR_NAME); - if (!BootDriverEntry->RegistryPath.Buffer) + /* Set or replace the driver node's file path */ + if (DriverEntry->FilePath.Buffer) { - FrLdrHeapFree(BootDriverEntry->FilePath.Buffer, TAG_WLDR_NAME); - FrLdrHeapFree(BootDriverEntry, TAG_WLDR_BDE); - return FALSE; + CmpFree(DriverEntry->FilePath.Buffer, + DriverEntry->FilePath.MaximumLength); } + DriverEntry->FilePath = FilePath; + FilePath.Buffer = NULL;
- Status = RtlAppendUnicodeToString(&BootDriverEntry->RegistryPath, RegistryPath); - if (!NT_SUCCESS(Status)) + /* Set or replace the driver node's registry path */ + if (DriverEntry->RegistryPath.Buffer) { - FrLdrHeapFree(BootDriverEntry->RegistryPath.Buffer, TAG_WLDR_NAME); - FrLdrHeapFree(BootDriverEntry->FilePath.Buffer, TAG_WLDR_NAME); - FrLdrHeapFree(BootDriverEntry, TAG_WLDR_BDE); - return FALSE; + CmpFree(DriverEntry->RegistryPath.Buffer, + DriverEntry->RegistryPath.MaximumLength); } + DriverEntry->RegistryPath = RegistryString; + RegistryString.Buffer = NULL;
- Status = RtlAppendUnicodeToString(&BootDriverEntry->RegistryPath, ServiceName); - if (!NT_SUCCESS(Status)) + /* Set or replace the driver node's group */ + if (DriverNode->Group.Buffer) { - FrLdrHeapFree(BootDriverEntry->RegistryPath.Buffer, TAG_WLDR_NAME); - FrLdrHeapFree(BootDriverEntry->FilePath.Buffer, TAG_WLDR_NAME); - FrLdrHeapFree(BootDriverEntry, TAG_WLDR_BDE); - return FALSE; + /* + * If the buffer is inside the registry hive's memory, this means that + * it has been set by CmpAddDriverToList() to point to some data within + * the hive; thus we should not free the buffer but just replace it. + * Otherwise, this is a buffer previously allocated by ourselves, that + * we can free. + * + * NOTE: This function does not have an explicit LoaderBlock input + * parameter pointer, since it does not need it, except for this + * very place. So instead, use the global WinLdrSystemBlock pointer. + */ + PLOADER_PARAMETER_BLOCK LoaderBlock = + (WinLdrSystemBlock ? &WinLdrSystemBlock->LoaderBlock : NULL); + + if (!LoaderBlock || !LoaderBlock->RegistryBase || !LoaderBlock->RegistryLength || + ((ULONG_PTR)DriverNode->Group.Buffer < + (ULONG_PTR)VaToPa(LoaderBlock->RegistryBase)) || + ((ULONG_PTR)DriverNode->Group.Buffer >= + (ULONG_PTR)VaToPa(LoaderBlock->RegistryBase) + LoaderBlock->RegistryLength)) + { + RtlFreeUnicodeString(&DriverNode->Group); + } } + DriverNode->Group = GroupString; + GroupString.Buffer = NULL; + + /* ErrorControl and Tag */ + DriverNode->ErrorControl = ErrorControl; + DriverNode->Tag = Tag;
- // Insert entry into the list - if (!InsertInBootDriverList(BootDriverListHead, BootDriverEntry)) + /* Insert the entry into the list if it does not exist there already */ + if (!AlreadyInserted) { - // It was already there, so delete our entry - FrLdrHeapFree(BootDriverEntry->RegistryPath.Buffer, TAG_WLDR_NAME); - FrLdrHeapFree(BootDriverEntry->FilePath.Buffer, TAG_WLDR_NAME); - FrLdrHeapFree(BootDriverEntry, TAG_WLDR_BDE); + if (InsertAtHead) + InsertHeadList(DriverListHead, &DriverEntry->Link); + else + InsertTailList(DriverListHead, &DriverEntry->Link); }
return TRUE; + +Failure: + if (GroupString.Buffer) + RtlFreeUnicodeString(&GroupString); + if (RegistryString.Buffer) + CmpFree(RegistryString.Buffer, RegistryString.MaximumLength); + if (FilePath.Buffer) + CmpFree(FilePath.Buffer, FilePath.MaximumLength); + + /* If it does not exist in the list already, free the allocated + * driver node, otherwise keep the original one in place. */ + if (!AlreadyInserted) + { + if (DriverEntry->RegistryPath.Buffer) + { + CmpFree(DriverEntry->RegistryPath.Buffer, + DriverEntry->RegistryPath.MaximumLength); + } + if (DriverEntry->FilePath.Buffer) + { + CmpFree(DriverEntry->FilePath.Buffer, + DriverEntry->FilePath.MaximumLength); + } + if (DriverNode->Name.Buffer) + { + CmpFree(DriverNode->Name.Buffer, + DriverNode->Name.MaximumLength); + } + CmpFree(DriverNode, sizeof(BOOT_DRIVER_NODE)); + } + + return FALSE; }