#include <freeldr.h>
#include "winldr.h"
#include "registry.h"
+#include <internal/cmboot.h>
#include <debug.h>
DBG_DEFAULT_CHANNEL(WINDOWS);
_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 **************************************************************/
PVOID HiveDataPhysical;
PVOID HiveDataVirtual;
ULONG BytesRead;
- PCWSTR FsService;
/* Concatenate path and filename to get the full name */
RtlStringCbCopyA(FullHiveName, sizeof(FullHiveName), DirectoryPath);
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;
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,
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;
}