mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 17:05:46 +00:00
[NTOS]: Rewrite boot driver loading code (not the driver code itself) to use the boot loader's BootDriverListHead, instead of parsing InOrderListHead and cherry-picking ".sys" files. This is the last incompatibility with Windows.
[NTOS]: Use group prioritiy, tag numbers, and tag priority to determine the correct loading order for boot drivers, instead of just parsing the linked list. Dependencies work now! [NTOS]: Load any DLLs that are driver-dependent with MmCallDllInitialize. Previously, these .DLLS were ignored and drivers could lose dependencies. svn path=/trunk/; revision=46690
This commit is contained in:
parent
74e30b9093
commit
6075ae9a8f
6 changed files with 595 additions and 13 deletions
|
@ -395,6 +395,33 @@ typedef struct _LOAD_UNLOAD_PARAMS
|
|||
PDRIVER_OBJECT DriverObject;
|
||||
} LOAD_UNLOAD_PARAMS, *PLOAD_UNLOAD_PARAMS;
|
||||
|
||||
//
|
||||
// Boot Driver List Entry
|
||||
//
|
||||
typedef struct _DRIVER_INFORMATION
|
||||
{
|
||||
LIST_ENTRY Link;
|
||||
PDRIVER_OBJECT DriverObject;
|
||||
PBOOT_DRIVER_LIST_ENTRY DataTableEntry;
|
||||
HANDLE ServiceHandle;
|
||||
USHORT TagPosition;
|
||||
ULONG Failed;
|
||||
ULONG Processed;
|
||||
NTSTATUS Status;
|
||||
} DRIVER_INFORMATION, *PDRIVER_INFORMATION;
|
||||
|
||||
//
|
||||
// Boot Driver Node
|
||||
//
|
||||
typedef struct _BOOT_DRIVER_NODE
|
||||
{
|
||||
BOOT_DRIVER_LIST_ENTRY ListEntry;
|
||||
UNICODE_STRING Group;
|
||||
UNICODE_STRING Name;
|
||||
ULONG Tag;
|
||||
ULONG ErrorControl;
|
||||
} BOOT_DRIVER_NODE, *PBOOT_DRIVER_NODE;
|
||||
|
||||
//
|
||||
// List of Bus Type GUIDs
|
||||
//
|
||||
|
@ -605,6 +632,43 @@ IopGetRegistryValue(IN HANDLE Handle,
|
|||
OUT PKEY_VALUE_FULL_INFORMATION *Information);
|
||||
|
||||
|
||||
//
|
||||
// PnP Routines
|
||||
//
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PiInitCacheGroupInformation(
|
||||
VOID
|
||||
);
|
||||
|
||||
USHORT
|
||||
NTAPI
|
||||
PpInitGetGroupOrderIndex(
|
||||
IN HANDLE ServiceHandle
|
||||
);
|
||||
|
||||
USHORT
|
||||
NTAPI
|
||||
PipGetDriverTagPriority(
|
||||
IN HANDLE ServiceHandle
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PnpRegMultiSzToUnicodeStrings(
|
||||
IN PKEY_VALUE_FULL_INFORMATION KeyValueInformation,
|
||||
OUT PUNICODE_STRING *UnicodeStringList,
|
||||
OUT PULONG UnicodeStringCount
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
PnpRegSzToString(
|
||||
IN PWCHAR RegSzData,
|
||||
IN ULONG RegSzLength,
|
||||
OUT PUSHORT StringLength OPTIONAL
|
||||
);
|
||||
|
||||
//
|
||||
// Initialization Routines
|
||||
//
|
||||
|
|
|
@ -34,6 +34,9 @@ POBJECT_TYPE IoDriverObjectType = NULL;
|
|||
extern BOOLEAN ExpInTextModeSetup;
|
||||
extern BOOLEAN PnpSystemInit;
|
||||
|
||||
USHORT IopGroupIndex;
|
||||
PLIST_ENTRY IopGroupTable;
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
NTSTATUS NTAPI
|
||||
|
@ -880,14 +883,17 @@ VOID
|
|||
FASTCALL
|
||||
IopInitializeBootDrivers(VOID)
|
||||
{
|
||||
PLIST_ENTRY ListHead, NextEntry;
|
||||
PLIST_ENTRY ListHead, NextEntry, NextEntry2;
|
||||
PLDR_DATA_TABLE_ENTRY LdrEntry;
|
||||
PDEVICE_NODE DeviceNode;
|
||||
PDRIVER_OBJECT DriverObject;
|
||||
LDR_DATA_TABLE_ENTRY ModuleObject;
|
||||
NTSTATUS Status;
|
||||
UNICODE_STRING DriverName;
|
||||
|
||||
ULONG i, Index;
|
||||
PDRIVER_INFORMATION DriverInfo, DriverInfoTag;
|
||||
HANDLE KeyHandle;
|
||||
PBOOT_DRIVER_LIST_ENTRY BootEntry;
|
||||
DPRINT("IopInitializeBootDrivers()\n");
|
||||
|
||||
/* Use IopRootDeviceNode for now */
|
||||
|
@ -931,6 +937,19 @@ IopInitializeBootDrivers(VOID)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Get highest group order index */
|
||||
IopGroupIndex = PpInitGetGroupOrderIndex(NULL);
|
||||
if (IopGroupIndex == 0xFFFF) ASSERT(FALSE);
|
||||
|
||||
/* Allocate the group table */
|
||||
IopGroupTable = ExAllocatePoolWithTag(PagedPool,
|
||||
IopGroupIndex * sizeof(LIST_ENTRY),
|
||||
TAG_IO);
|
||||
if (IopGroupTable == NULL) ASSERT(FALSE);
|
||||
|
||||
/* Initialize the group table lists */
|
||||
for (i = 0; i < IopGroupIndex; i++) InitializeListHead(&IopGroupTable[i]);
|
||||
|
||||
/* Loop the boot modules */
|
||||
ListHead = &KeLoaderBlock->LoadOrderListHead;
|
||||
NextEntry = ListHead->Flink;
|
||||
|
@ -940,19 +959,83 @@ IopInitializeBootDrivers(VOID)
|
|||
LdrEntry = CONTAINING_RECORD(NextEntry,
|
||||
LDR_DATA_TABLE_ENTRY,
|
||||
InLoadOrderLinks);
|
||||
|
||||
/*
|
||||
* HACK: Make sure we're loading a driver
|
||||
* (we should be using BootDriverListHead!)
|
||||
*/
|
||||
if (wcsstr(_wcsupr(LdrEntry->BaseDllName.Buffer), L".SYS"))
|
||||
|
||||
/* Check if the DLL needs to be initialized */
|
||||
if (LdrEntry->Flags & LDRP_DRIVER_DEPENDENT_DLL)
|
||||
{
|
||||
/* Make sure we didn't load this driver already */
|
||||
if (!(LdrEntry->Flags & LDRP_ENTRY_INSERTED))
|
||||
/* Call its entrypoint */
|
||||
MmCallDllInitialize(LdrEntry, NULL);
|
||||
}
|
||||
|
||||
/* Go to the next driver */
|
||||
NextEntry = NextEntry->Flink;
|
||||
}
|
||||
|
||||
/* Loop the boot drivers */
|
||||
ListHead = &KeLoaderBlock->BootDriverListHead;
|
||||
NextEntry = ListHead->Flink;
|
||||
while (ListHead != NextEntry)
|
||||
{
|
||||
/* Get the entry */
|
||||
BootEntry = CONTAINING_RECORD(NextEntry,
|
||||
BOOT_DRIVER_LIST_ENTRY,
|
||||
Link);
|
||||
|
||||
/* Get the driver loader entry */
|
||||
LdrEntry = BootEntry->LdrEntry;
|
||||
|
||||
/* Allocate our internal accounting structure */
|
||||
DriverInfo = ExAllocatePoolWithTag(PagedPool,
|
||||
sizeof(DRIVER_INFORMATION),
|
||||
TAG_IO);
|
||||
if (DriverInfo)
|
||||
{
|
||||
/* Zero it and initialize it */
|
||||
RtlZeroMemory(DriverInfo, sizeof(DRIVER_INFORMATION));
|
||||
InitializeListHead(&DriverInfo->Link);
|
||||
DriverInfo->DataTableEntry = BootEntry;
|
||||
|
||||
/* Open the registry key */
|
||||
Status = IopOpenRegistryKeyEx(&KeyHandle,
|
||||
NULL,
|
||||
&BootEntry->RegistryPath,
|
||||
KEY_READ);
|
||||
if ((NT_SUCCESS(Status)) || /* ReactOS HACK for SETUPLDR */
|
||||
((KeLoaderBlock->SetupLdrBlock) && (KeyHandle = (PVOID)1)))
|
||||
{
|
||||
DPRINT("Initializing bootdriver %wZ\n", &LdrEntry->BaseDllName);
|
||||
/* Initialize it */
|
||||
IopInitializeBuiltinDriver(LdrEntry);
|
||||
/* Save the handle */
|
||||
DriverInfo->ServiceHandle = KeyHandle;
|
||||
|
||||
/* Get the group oder index */
|
||||
Index = PpInitGetGroupOrderIndex(KeyHandle);
|
||||
|
||||
/* Get the tag position */
|
||||
DriverInfo->TagPosition = PipGetDriverTagPriority(KeyHandle);
|
||||
|
||||
/* Insert it into the list, at the right place */
|
||||
ASSERT(Index < IopGroupIndex);
|
||||
NextEntry2 = IopGroupTable[Index].Flink;
|
||||
while (NextEntry2 != &IopGroupTable[Index])
|
||||
{
|
||||
/* Get the driver info */
|
||||
DriverInfoTag = CONTAINING_RECORD(NextEntry2,
|
||||
DRIVER_INFORMATION,
|
||||
Link);
|
||||
|
||||
/* Check if we found the right tag position */
|
||||
if (DriverInfoTag->TagPosition > DriverInfo->TagPosition)
|
||||
{
|
||||
/* We're done */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Next entry */
|
||||
NextEntry2 = NextEntry2->Flink;
|
||||
}
|
||||
|
||||
/* Insert us right before the next entry */
|
||||
NextEntry2 = NextEntry2->Blink;
|
||||
InsertHeadList(NextEntry2, &DriverInfo->Link);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -960,6 +1043,29 @@ IopInitializeBootDrivers(VOID)
|
|||
NextEntry = NextEntry->Flink;
|
||||
}
|
||||
|
||||
/* Loop each group index */
|
||||
for (i = 0; i < IopGroupIndex; i++)
|
||||
{
|
||||
/* Loop each group table */
|
||||
NextEntry = IopGroupTable[i].Flink;
|
||||
while (NextEntry != &IopGroupTable[i])
|
||||
{
|
||||
/* Get the entry */
|
||||
DriverInfo = CONTAINING_RECORD(NextEntry,
|
||||
DRIVER_INFORMATION,
|
||||
Link);
|
||||
|
||||
/* Get the driver loader entry */
|
||||
LdrEntry = DriverInfo->DataTableEntry->LdrEntry;
|
||||
|
||||
/* Initialize it */
|
||||
IopInitializeBuiltinDriver(LdrEntry);
|
||||
|
||||
/* Next entry */
|
||||
NextEntry = NextEntry->Flink;
|
||||
}
|
||||
}
|
||||
|
||||
/* In old ROS, the loader list became empty after this point. Simulate. */
|
||||
InitializeListHead(&KeLoaderBlock->LoadOrderListHead);
|
||||
}
|
||||
|
|
|
@ -489,6 +489,9 @@ IoInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
|||
|
||||
/* Initialize PnP manager */
|
||||
PnpInit();
|
||||
|
||||
/* Setup the group cache */
|
||||
if (!NT_SUCCESS(PiInitCacheGroupInformation())) return FALSE;
|
||||
|
||||
/* Create the group driver list */
|
||||
IoCreateDriverList();
|
||||
|
|
222
reactos/ntoskrnl/io/pnpmgr/pnpinit.c
Normal file
222
reactos/ntoskrnl/io/pnpmgr/pnpinit.c
Normal file
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: ntoskrnl/io/pnpmgr/pnpinit.c
|
||||
* PURPOSE: PnP Initialization Code
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
PUNICODE_STRING PiInitGroupOrderTable;
|
||||
ULONG PiInitGroupOrderTableCount;
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PiInitCacheGroupInformation(VOID)
|
||||
{
|
||||
HANDLE KeyHandle;
|
||||
NTSTATUS Status;
|
||||
PKEY_VALUE_FULL_INFORMATION KeyValueInformation;
|
||||
PUNICODE_STRING GroupTable;
|
||||
ULONG Count;
|
||||
UNICODE_STRING GroupString =
|
||||
RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet"
|
||||
L"\\Control\\ServiceGroupOrder");
|
||||
|
||||
/* ReactOS HACK for SETUPLDR */
|
||||
if (KeLoaderBlock->SetupLdrBlock)
|
||||
{
|
||||
/* Bogus data */
|
||||
PiInitGroupOrderTableCount = 0;
|
||||
PiInitGroupOrderTable = (PVOID)0xBABEB00B;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Open the registry key */
|
||||
Status = IopOpenRegistryKeyEx(&KeyHandle,
|
||||
NULL,
|
||||
&GroupString,
|
||||
KEY_READ);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Get the list */
|
||||
Status = IopGetRegistryValue(KeyHandle, L"List", &KeyValueInformation);
|
||||
ZwClose(KeyHandle);
|
||||
|
||||
/* Make sure we got it */
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Make sure it's valid */
|
||||
if ((KeyValueInformation->Type == REG_MULTI_SZ) &&
|
||||
(KeyValueInformation->DataLength))
|
||||
{
|
||||
/* Convert it to unicode strings */
|
||||
Status = PnpRegMultiSzToUnicodeStrings(KeyValueInformation,
|
||||
&GroupTable,
|
||||
&Count);
|
||||
|
||||
/* Cache it for later */
|
||||
PiInitGroupOrderTable = GroupTable;
|
||||
PiInitGroupOrderTableCount = Count;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Fail */
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* Free the information */
|
||||
ExFreePool(KeyValueInformation);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
USHORT
|
||||
NTAPI
|
||||
PpInitGetGroupOrderIndex(IN HANDLE ServiceHandle)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PKEY_VALUE_FULL_INFORMATION KeyValueInformation;
|
||||
ULONG i;
|
||||
PVOID Buffer;
|
||||
UNICODE_STRING Group;
|
||||
PAGED_CODE();
|
||||
|
||||
/* Make sure we have a cache */
|
||||
if (!PiInitGroupOrderTable) return -1;
|
||||
|
||||
/* If we don't have a handle, the rest is easy -- return the count */
|
||||
if (!ServiceHandle) return PiInitGroupOrderTableCount + 1;
|
||||
|
||||
/* Otherwise, get the group value */
|
||||
Status = IopGetRegistryValue(ServiceHandle, L"Group", &KeyValueInformation);
|
||||
if (!NT_SUCCESS(Status)) return PiInitGroupOrderTableCount;
|
||||
|
||||
/* Make sure we have a valid string */
|
||||
ASSERT(KeyValueInformation->Type == REG_SZ);
|
||||
ASSERT(KeyValueInformation->DataLength);
|
||||
|
||||
/* Convert to unicode string */
|
||||
Buffer = (PVOID)((ULONG_PTR)KeyValueInformation + KeyValueInformation->DataOffset);
|
||||
PnpRegSzToString(Buffer, KeyValueInformation->DataLength, &Group.Length);
|
||||
Group.MaximumLength = KeyValueInformation->DataLength;
|
||||
Group.Buffer = Buffer;
|
||||
|
||||
/* Loop the groups */
|
||||
for (i = 0; i < PiInitGroupOrderTableCount; i++)
|
||||
{
|
||||
/* Try to find a match */
|
||||
if (RtlEqualUnicodeString(&Group, &PiInitGroupOrderTable[i], TRUE)) break;
|
||||
}
|
||||
|
||||
/* We're done */
|
||||
ExFreePool(KeyValueInformation);
|
||||
return i;
|
||||
}
|
||||
|
||||
USHORT
|
||||
NTAPI
|
||||
PipGetDriverTagPriority(IN HANDLE ServiceHandle)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
HANDLE KeyHandle = NULL;
|
||||
PKEY_VALUE_FULL_INFORMATION KeyValueInformation = NULL;
|
||||
PKEY_VALUE_FULL_INFORMATION KeyValueInformationTag;
|
||||
PKEY_VALUE_FULL_INFORMATION KeyValueInformationGroupOrderList;
|
||||
PVOID Buffer;
|
||||
UNICODE_STRING Group;
|
||||
PULONG GroupOrder;
|
||||
ULONG i = -1, Count, Tag = 0;
|
||||
UNICODE_STRING GroupString =
|
||||
RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet"
|
||||
L"\\Control\\ServiceGroupOrder");
|
||||
|
||||
/* Open the key */
|
||||
Status = IopOpenRegistryKeyEx(&KeyHandle, NULL, &GroupString, KEY_READ);
|
||||
if (!NT_SUCCESS(Status)) goto Quickie;
|
||||
|
||||
/* Read the group */
|
||||
Status = IopGetRegistryValue(ServiceHandle, L"Group", &KeyValueInformation);
|
||||
if (!NT_SUCCESS(Status)) goto Quickie;
|
||||
|
||||
/* Make sure we have a group */
|
||||
if ((KeyValueInformation->Type == REG_SZ) &&
|
||||
(KeyValueInformation->DataLength))
|
||||
{
|
||||
/* Convert to unicode string */
|
||||
Buffer = (PVOID)((ULONG_PTR)KeyValueInformation + KeyValueInformation->DataOffset);
|
||||
PnpRegSzToString(Buffer, KeyValueInformation->DataLength, &Group.Length);
|
||||
Group.MaximumLength = KeyValueInformation->DataLength;
|
||||
Group.Buffer = Buffer;
|
||||
}
|
||||
|
||||
/* Now read the tag */
|
||||
Status = IopGetRegistryValue(ServiceHandle, L"Tag", &KeyValueInformationTag);
|
||||
if (!NT_SUCCESS(Status)) goto Quickie;
|
||||
|
||||
/* Make sure we have a tag */
|
||||
if ((KeyValueInformationTag->Type == REG_DWORD) &&
|
||||
(KeyValueInformationTag->DataLength))
|
||||
{
|
||||
/* Read it */
|
||||
Tag = *(PULONG)((ULONG_PTR)KeyValueInformationTag +
|
||||
KeyValueInformationTag->DataOffset);
|
||||
}
|
||||
|
||||
/* We can get rid of this now */
|
||||
ExFreePool(KeyValueInformationTag);
|
||||
|
||||
/* Now let's read the group's tag order */
|
||||
Status = IopGetRegistryValue(KeyHandle,
|
||||
Group.Buffer,
|
||||
&KeyValueInformationGroupOrderList);
|
||||
|
||||
/* We can get rid of this now */
|
||||
Quickie:
|
||||
if (KeyValueInformation) ExFreePool(KeyValueInformation);
|
||||
if (KeyHandle) NtClose(KeyHandle);
|
||||
if (!NT_SUCCESS(Status)) return -1;
|
||||
|
||||
/* We're on the success path -- validate the tag order*/
|
||||
if ((KeyValueInformationGroupOrderList->Type == REG_BINARY) &&
|
||||
(KeyValueInformationGroupOrderList->DataLength))
|
||||
{
|
||||
/* Get the order array */
|
||||
GroupOrder = (PULONG)((ULONG_PTR)KeyValueInformationGroupOrderList +
|
||||
KeyValueInformationGroupOrderList->DataOffset);
|
||||
|
||||
/* Get the count */
|
||||
Count = *GroupOrder;
|
||||
ASSERT(((Count + 1) * sizeof(ULONG)) <=
|
||||
KeyValueInformationGroupOrderList->DataLength);
|
||||
|
||||
/* Now loop each tag */
|
||||
GroupOrder++;
|
||||
for (i = 1; i <= Count; i++)
|
||||
{
|
||||
/* If we found it, we're out */
|
||||
if (Tag == *GroupOrder) break;
|
||||
|
||||
/* Try the next one */
|
||||
GroupOrder++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Last buffer to free */
|
||||
ExFreePool(KeyValueInformationGroupOrderList);
|
||||
return i;
|
||||
}
|
||||
|
||||
/* EOF */
|
185
reactos/ntoskrnl/io/pnpmgr/pnputil.c
Normal file
185
reactos/ntoskrnl/io/pnpmgr/pnputil.c
Normal file
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: ntoskrnl/io/pnpmgr/pnputil.c
|
||||
* PURPOSE: PnP Utility Code
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
PnpFreeUnicodeStringList(IN PUNICODE_STRING UnicodeStringList,
|
||||
IN ULONG StringCount)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
/* Go through the list */
|
||||
if (UnicodeStringList)
|
||||
{
|
||||
/* Go through each string */
|
||||
for (i = 0; i < StringCount; i++)
|
||||
{
|
||||
/* Check if it exists */
|
||||
if (UnicodeStringList[i].Buffer)
|
||||
{
|
||||
/* Free it */
|
||||
ExFreePool(UnicodeStringList[i].Buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the whole list */
|
||||
ExFreePool(UnicodeStringList);
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PnpRegMultiSzToUnicodeStrings(IN PKEY_VALUE_FULL_INFORMATION KeyValueInformation,
|
||||
OUT PUNICODE_STRING *UnicodeStringList,
|
||||
OUT PULONG UnicodeStringCount)
|
||||
{
|
||||
PWCHAR p, pp, ps;
|
||||
ULONG i = 0, n;
|
||||
ULONG Count = 0;
|
||||
|
||||
/* Validate the key information */
|
||||
if (KeyValueInformation->Type != REG_MULTI_SZ) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* Set the pointers */
|
||||
p = (PWCHAR)((ULONG_PTR)KeyValueInformation +
|
||||
KeyValueInformation->DataOffset);
|
||||
pp = (PWCHAR)((ULONG_PTR)p + KeyValueInformation->DataLength);
|
||||
|
||||
/* Loop the data */
|
||||
while (p != pp)
|
||||
{
|
||||
/* If we find a NULL, that means one string is done */
|
||||
if (!*p)
|
||||
{
|
||||
/* Add to our string count */
|
||||
Count++;
|
||||
|
||||
/* Check for a double-NULL, which means we're done */
|
||||
if (((p + 1) == pp) || !(*(p + 1))) break;
|
||||
}
|
||||
|
||||
/* Go to the next character */
|
||||
p++;
|
||||
}
|
||||
|
||||
/* If we looped the whole list over, we missed increment a string, do it */
|
||||
if (p == pp) Count++;
|
||||
|
||||
/* Allocate the list now that we know how big it is */
|
||||
*UnicodeStringList = ExAllocatePoolWithTag(PagedPool,
|
||||
sizeof(UNICODE_STRING) * Count,
|
||||
'sUpP');
|
||||
if (!(*UnicodeStringList)) return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
/* Set pointers for second loop */
|
||||
ps = p = (PWCHAR)((ULONG_PTR)KeyValueInformation +
|
||||
KeyValueInformation->DataOffset);
|
||||
|
||||
/* Loop again, to do the copy this time */
|
||||
while (p != pp)
|
||||
{
|
||||
/* If we find a NULL, that means one string is done */
|
||||
if (!*p)
|
||||
{
|
||||
/* Check how long this string is */
|
||||
n = (ULONG_PTR)p - (ULONG_PTR)ps + sizeof(UNICODE_NULL);
|
||||
|
||||
/* Allocate the buffer */
|
||||
(*UnicodeStringList)[i].Buffer = ExAllocatePoolWithTag(PagedPool,
|
||||
n,
|
||||
'sUpP');
|
||||
if (!(*UnicodeStringList)[i].Buffer)
|
||||
{
|
||||
/* Back out of everything */
|
||||
PnpFreeUnicodeStringList(*UnicodeStringList, i);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* Copy the string into the buffer */
|
||||
RtlCopyMemory((*UnicodeStringList)[i].Buffer, ps, n);
|
||||
|
||||
/* Set the lengths */
|
||||
(*UnicodeStringList)[i].MaximumLength = n;
|
||||
(*UnicodeStringList)[i].Length = n - sizeof(UNICODE_NULL);
|
||||
|
||||
/* One more entry done */
|
||||
i++;
|
||||
|
||||
/* Check for a double-NULL, which means we're done */
|
||||
if (((p + 1) == pp) || !(*(p + 1))) break;
|
||||
|
||||
/* New string */
|
||||
ps = p + 1;
|
||||
}
|
||||
|
||||
/* New string */
|
||||
p++;
|
||||
}
|
||||
|
||||
/* Check if we've reached the last string */
|
||||
if (p == pp)
|
||||
{
|
||||
/* Calculate the string length */
|
||||
n = (ULONG_PTR)p - (ULONG_PTR)ps;
|
||||
|
||||
/* Allocate the buffer for it */
|
||||
(*UnicodeStringList)[i].Buffer = ExAllocatePoolWithTag(PagedPool,
|
||||
n +
|
||||
sizeof(UNICODE_NULL),
|
||||
'sUpP');
|
||||
if (!(*UnicodeStringList)[i].Buffer)
|
||||
{
|
||||
/* Back out of everything */
|
||||
PnpFreeUnicodeStringList(*UnicodeStringList, i);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* Make sure there's an actual string here */
|
||||
if (n) RtlCopyMemory((*UnicodeStringList)[i].Buffer, ps, n);
|
||||
|
||||
/* Null-terminate the string ourselves */
|
||||
(*UnicodeStringList)[i].Buffer[n / sizeof(WCHAR)] = UNICODE_NULL;
|
||||
|
||||
/* Set the lenghts */
|
||||
(*UnicodeStringList)[i].Length = n;
|
||||
(*UnicodeStringList)[i].MaximumLength = n + sizeof(UNICODE_NULL);
|
||||
}
|
||||
|
||||
/* And we're done */
|
||||
*UnicodeStringCount = Count;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
PnpRegSzToString(IN PWCHAR RegSzData,
|
||||
IN ULONG RegSzLength,
|
||||
OUT PUSHORT StringLength OPTIONAL)
|
||||
{
|
||||
PWCHAR p, pp;
|
||||
|
||||
/* Find the end */
|
||||
pp = RegSzData + RegSzLength;
|
||||
for (p = RegSzData; p < pp; p++) if (!*p) break;
|
||||
|
||||
/* Return it */
|
||||
if (StringLength) *StringLength = p - RegSzData;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* EOF */
|
|
@ -267,10 +267,12 @@
|
|||
<directory name="pnpmgr">
|
||||
<file>plugplay.c</file>
|
||||
<file>pnpdma.c</file>
|
||||
<file>pnpinit.c</file>
|
||||
<file>pnpmgr.c</file>
|
||||
<file>pnpnotify.c</file>
|
||||
<file>pnpreport.c</file>
|
||||
<file>pnproot.c</file>
|
||||
<file>pnputil.c</file>
|
||||
</directory>
|
||||
</directory>
|
||||
<if property="_WINKD_" value="0">
|
||||
|
|
Loading…
Reference in a new issue