Sync with trunk r63174.
[reactos.git] / 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;
53 SIZE_T n;
54 ULONG Count = 0;
55
56 /* Validate the key information */
57 if (KeyValueInformation->Type != REG_MULTI_SZ) return STATUS_INVALID_PARAMETER;
58
59 /* Set the pointers */
60 p = (PWCHAR)((ULONG_PTR)KeyValueInformation +
61 KeyValueInformation->DataOffset);
62 pp = (PWCHAR)((ULONG_PTR)p + KeyValueInformation->DataLength);
63
64 /* Loop the data */
65 while (p != pp)
66 {
67 /* If we find a NULL, that means one string is done */
68 if (!*p)
69 {
70 /* Add to our string count */
71 Count++;
72
73 /* Check for a double-NULL, which means we're done */
74 if (((p + 1) == pp) || !(*(p + 1))) break;
75 }
76
77 /* Go to the next character */
78 p++;
79 }
80
81 /* If we looped the whole list over, we missed increment a string, do it */
82 if (p == pp) Count++;
83
84 /* Allocate the list now that we know how big it is */
85 *UnicodeStringList = ExAllocatePoolWithTag(PagedPool,
86 sizeof(UNICODE_STRING) * Count,
87 'sUpP');
88 if (!(*UnicodeStringList)) return STATUS_INSUFFICIENT_RESOURCES;
89
90 /* Set pointers for second loop */
91 ps = p = (PWCHAR)((ULONG_PTR)KeyValueInformation +
92 KeyValueInformation->DataOffset);
93
94 /* Loop again, to do the copy this time */
95 while (p != pp)
96 {
97 /* If we find a NULL, that means one string is done */
98 if (!*p)
99 {
100 /* Check how long this string is */
101 n = (ULONG_PTR)p - (ULONG_PTR)ps + sizeof(UNICODE_NULL);
102
103 /* Allocate the buffer */
104 (*UnicodeStringList)[i].Buffer = ExAllocatePoolWithTag(PagedPool,
105 n,
106 'sUpP');
107 if (!(*UnicodeStringList)[i].Buffer)
108 {
109 /* Back out of everything */
110 PnpFreeUnicodeStringList(*UnicodeStringList, i);
111 return STATUS_INSUFFICIENT_RESOURCES;
112 }
113
114 /* Copy the string into the buffer */
115 RtlCopyMemory((*UnicodeStringList)[i].Buffer, ps, n);
116
117 /* Set the lengths */
118 (*UnicodeStringList)[i].MaximumLength = (USHORT)n;
119 (*UnicodeStringList)[i].Length = (USHORT)(n - sizeof(UNICODE_NULL));
120
121 /* One more entry done */
122 i++;
123
124 /* Check for a double-NULL, which means we're done */
125 if (((p + 1) == pp) || !(*(p + 1))) break;
126
127 /* New string */
128 ps = p + 1;
129 }
130
131 /* New string */
132 p++;
133 }
134
135 /* Check if we've reached the last string */
136 if (p == pp)
137 {
138 /* Calculate the string length */
139 n = (ULONG_PTR)p - (ULONG_PTR)ps;
140
141 /* Allocate the buffer for it */
142 (*UnicodeStringList)[i].Buffer = ExAllocatePoolWithTag(PagedPool,
143 n +
144 sizeof(UNICODE_NULL),
145 'sUpP');
146 if (!(*UnicodeStringList)[i].Buffer)
147 {
148 /* Back out of everything */
149 PnpFreeUnicodeStringList(*UnicodeStringList, i);
150 return STATUS_INSUFFICIENT_RESOURCES;
151 }
152
153 /* Make sure there's an actual string here */
154 if (n) RtlCopyMemory((*UnicodeStringList)[i].Buffer, ps, n);
155
156 /* Null-terminate the string ourselves */
157 (*UnicodeStringList)[i].Buffer[n / sizeof(WCHAR)] = UNICODE_NULL;
158
159 /* Set the lengths */
160 (*UnicodeStringList)[i].Length = (USHORT)n;
161 (*UnicodeStringList)[i].MaximumLength = (USHORT)(n + sizeof(UNICODE_NULL));
162 }
163
164 /* And we're done */
165 *UnicodeStringCount = Count;
166 return STATUS_SUCCESS;
167 }
168
169 BOOLEAN
170 NTAPI
171 PnpRegSzToString(IN PWCHAR RegSzData,
172 IN ULONG RegSzLength,
173 OUT PUSHORT StringLength OPTIONAL)
174 {
175 PWCHAR p, pp;
176
177 /* Find the end */
178 pp = RegSzData + RegSzLength;
179 for (p = RegSzData; p < pp; p++) if (!*p) break;
180
181 /* Return it */
182 if (StringLength) *StringLength = (USHORT)(p - RegSzData) * sizeof(WCHAR);
183 return TRUE;
184 }
185
186 /* EOF */