https://git.reactos.org/?p=reactos.git;a=commitdiff;h=94874baf198fb86536ee4…
commit 94874baf198fb86536ee41a71e016a47e37799b4
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Tue Mar 22 04:14:35 2022 +0100
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)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;
}