Author: sir_richard
Date: Fri Apr 2 19:57:33 2010
New Revision: 46690
URL:
http://svn.reactos.org/svn/reactos?rev=46690&view=rev
Log:
[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.
Added:
trunk/reactos/ntoskrnl/io/pnpmgr/pnpinit.c (with props)
trunk/reactos/ntoskrnl/io/pnpmgr/pnputil.c (with props)
Modified:
trunk/reactos/ntoskrnl/include/internal/io.h
trunk/reactos/ntoskrnl/io/iomgr/driver.c
trunk/reactos/ntoskrnl/io/iomgr/iomgr.c
trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild
Modified: trunk/reactos/ntoskrnl/include/internal/io.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/io.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/io.h [iso-8859-1] Fri Apr 2 19:57:33 2010
@@ -396,6 +396,33 @@
} 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
//
typedef struct _IO_BUS_TYPE_GUID_LIST
@@ -605,6 +632,43 @@
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
//
Modified: trunk/reactos/ntoskrnl/io/iomgr/driver.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/driver.c…
==============================================================================
--- trunk/reactos/ntoskrnl/io/iomgr/driver.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/io/iomgr/driver.c [iso-8859-1] Fri Apr 2 19:57:33 2010
@@ -33,6 +33,9 @@
extern BOOLEAN ExpInTextModeSetup;
extern BOOLEAN PnpSystemInit;
+
+USHORT IopGroupIndex;
+PLIST_ENTRY IopGroupTable;
/* PRIVATE FUNCTIONS **********************************************************/
@@ -880,14 +883,17 @@
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 @@
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 @@
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 @@
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);
}
Modified: trunk/reactos/ntoskrnl/io/iomgr/iomgr.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/iomgr.c?…
==============================================================================
--- trunk/reactos/ntoskrnl/io/iomgr/iomgr.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/io/iomgr/iomgr.c [iso-8859-1] Fri Apr 2 19:57:33 2010
@@ -489,6 +489,9 @@
/* Initialize PnP manager */
PnpInit();
+
+ /* Setup the group cache */
+ if (!NT_SUCCESS(PiInitCacheGroupInformation())) return FALSE;
/* Create the group driver list */
IoCreateDriverList();
Added: trunk/reactos/ntoskrnl/io/pnpmgr/pnpinit.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/pnpmgr/pnpinit…
==============================================================================
--- trunk/reactos/ntoskrnl/io/pnpmgr/pnpinit.c (added)
+++ trunk/reactos/ntoskrnl/io/pnpmgr/pnpinit.c [iso-8859-1] Fri Apr 2 19:57:33 2010
@@ -1,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 */
Propchange: trunk/reactos/ntoskrnl/io/pnpmgr/pnpinit.c
------------------------------------------------------------------------------
svn:eol-stlye = native
Propchange: trunk/reactos/ntoskrnl/io/pnpmgr/pnpinit.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/reactos/ntoskrnl/io/pnpmgr/pnputil.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/pnpmgr/pnputil…
==============================================================================
--- trunk/reactos/ntoskrnl/io/pnpmgr/pnputil.c (added)
+++ trunk/reactos/ntoskrnl/io/pnpmgr/pnputil.c [iso-8859-1] Fri Apr 2 19:57:33 2010
@@ -1,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 */
Propchange: trunk/reactos/ntoskrnl/io/pnpmgr/pnputil.c
------------------------------------------------------------------------------
svn:eol-stlye = native
Propchange: trunk/reactos/ntoskrnl/io/pnpmgr/pnputil.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ntoskrnl-generic.…
==============================================================================
--- trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild [iso-8859-1] Fri Apr 2 19:57:33 2010
@@ -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">