[NTOS]: Rewrite boot driver loading code (not the driver code itself) to use the...
[reactos.git] / reactos / ntoskrnl / io / pnpmgr / pnputil.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/io/pnpmgr/pnputil.c
5 * PURPOSE: PnP Utility Code
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* GLOBALS ********************************************************************/
16
17 /* FUNCTIONS ******************************************************************/
18
19 VOID
20 NTAPI
21 PnpFreeUnicodeStringList(IN PUNICODE_STRING UnicodeStringList,
22 IN ULONG StringCount)
23 {
24 ULONG i;
25
26 /* Go through the list */
27 if (UnicodeStringList)
28 {
29 /* Go through each string */
30 for (i = 0; i < StringCount; i++)
31 {
32 /* Check if it exists */
33 if (UnicodeStringList[i].Buffer)
34 {
35 /* Free it */
36 ExFreePool(UnicodeStringList[i].Buffer);
37 }
38 }
39
40 /* Free the whole list */
41 ExFreePool(UnicodeStringList);
42 }
43 }
44
45 NTSTATUS
46 NTAPI
47 PnpRegMultiSzToUnicodeStrings(IN PKEY_VALUE_FULL_INFORMATION KeyValueInformation,
48 OUT PUNICODE_STRING *UnicodeStringList,
49 OUT PULONG UnicodeStringCount)
50 {
51 PWCHAR p, pp, ps;
52 ULONG i = 0, n;
53 ULONG Count = 0;
54
55 /* Validate the key information */
56 if (KeyValueInformation->Type != REG_MULTI_SZ) return STATUS_INVALID_PARAMETER;
57
58 /* Set the pointers */
59 p = (PWCHAR)((ULONG_PTR)KeyValueInformation +
60 KeyValueInformation->DataOffset);
61 pp = (PWCHAR)((ULONG_PTR)p + KeyValueInformation->DataLength);
62
63 /* Loop the data */
64 while (p != pp)
65 {
66 /* If we find a NULL, that means one string is done */
67 if (!*p)
68 {
69 /* Add to our string count */
70 Count++;
71
72 /* Check for a double-NULL, which means we're done */
73 if (((p + 1) == pp) || !(*(p + 1))) break;
74 }
75
76 /* Go to the next character */
77 p++;
78 }
79
80 /* If we looped the whole list over, we missed increment a string, do it */
81 if (p == pp) Count++;
82
83 /* Allocate the list now that we know how big it is */
84 *UnicodeStringList = ExAllocatePoolWithTag(PagedPool,
85 sizeof(UNICODE_STRING) * Count,
86 'sUpP');
87 if (!(*UnicodeStringList)) return STATUS_INSUFFICIENT_RESOURCES;
88
89 /* Set pointers for second loop */
90 ps = p = (PWCHAR)((ULONG_PTR)KeyValueInformation +
91 KeyValueInformation->DataOffset);
92
93 /* Loop again, to do the copy this time */
94 while (p != pp)
95 {
96 /* If we find a NULL, that means one string is done */
97 if (!*p)
98 {
99 /* Check how long this string is */
100 n = (ULONG_PTR)p - (ULONG_PTR)ps + sizeof(UNICODE_NULL);
101
102 /* Allocate the buffer */
103 (*UnicodeStringList)[i].Buffer = ExAllocatePoolWithTag(PagedPool,
104 n,
105 'sUpP');
106 if (!(*UnicodeStringList)[i].Buffer)
107 {
108 /* Back out of everything */
109 PnpFreeUnicodeStringList(*UnicodeStringList, i);
110 return STATUS_INSUFFICIENT_RESOURCES;
111 }
112
113 /* Copy the string into the buffer */
114 RtlCopyMemory((*UnicodeStringList)[i].Buffer, ps, n);
115
116 /* Set the lengths */
117 (*UnicodeStringList)[i].MaximumLength = n;
118 (*UnicodeStringList)[i].Length = n - sizeof(UNICODE_NULL);
119
120 /* One more entry done */
121 i++;
122
123 /* Check for a double-NULL, which means we're done */
124 if (((p + 1) == pp) || !(*(p + 1))) break;
125
126 /* New string */
127 ps = p + 1;
128 }
129
130 /* New string */
131 p++;
132 }
133
134 /* Check if we've reached the last string */
135 if (p == pp)
136 {
137 /* Calculate the string length */
138 n = (ULONG_PTR)p - (ULONG_PTR)ps;
139
140 /* Allocate the buffer for it */
141 (*UnicodeStringList)[i].Buffer = ExAllocatePoolWithTag(PagedPool,
142 n +
143 sizeof(UNICODE_NULL),
144 'sUpP');
145 if (!(*UnicodeStringList)[i].Buffer)
146 {
147 /* Back out of everything */
148 PnpFreeUnicodeStringList(*UnicodeStringList, i);
149 return STATUS_INSUFFICIENT_RESOURCES;
150 }
151
152 /* Make sure there's an actual string here */
153 if (n) RtlCopyMemory((*UnicodeStringList)[i].Buffer, ps, n);
154
155 /* Null-terminate the string ourselves */
156 (*UnicodeStringList)[i].Buffer[n / sizeof(WCHAR)] = UNICODE_NULL;
157
158 /* Set the lenghts */
159 (*UnicodeStringList)[i].Length = n;
160 (*UnicodeStringList)[i].MaximumLength = n + sizeof(UNICODE_NULL);
161 }
162
163 /* And we're done */
164 *UnicodeStringCount = Count;
165 return STATUS_SUCCESS;
166 }
167
168 BOOLEAN
169 NTAPI
170 PnpRegSzToString(IN PWCHAR RegSzData,
171 IN ULONG RegSzLength,
172 OUT PUSHORT StringLength OPTIONAL)
173 {
174 PWCHAR p, pp;
175
176 /* Find the end */
177 pp = RegSzData + RegSzLength;
178 for (p = RegSzData; p < pp; p++) if (!*p) break;
179
180 /* Return it */
181 if (StringLength) *StringLength = p - RegSzData;
182 return TRUE;
183 }
184
185 /* EOF */