1 /*
2 * PROJECT: ReactOS Registry Library
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: lib/cmlib/cmname.c
5 * PURPOSE: Configuration Manager - Name Management
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include "cmlib.h"
12 #define NDEBUG
13 #include <debug.h>
14
15 /* GLOBALS *******************************************************************/
16
17 /* FUNCTIONS *****************************************************************/
18
19 USHORT
20 NTAPI
CmpCopyName(IN PHHIVE Hive,OUT PWCHAR Destination,IN PCUNICODE_STRING Source)21 CmpCopyName(IN PHHIVE Hive,
22 OUT PWCHAR Destination,
23 IN PCUNICODE_STRING Source)
24 {
25 ULONG i;
26
27 /* Check for old hives */
28 if (Hive->Version == 1)
29 {
30 /* Just copy the source directly */
31 RtlCopyMemory(Destination, Source->Buffer, Source->Length);
32 return Source->Length;
33 }
34
35 /* For new versions, check for compressed name */
36 for (i = 0; i < (Source->Length / sizeof(WCHAR)); i++)
37 {
38 /* Check if the name is non compressed */
39 if (Source->Buffer[i] > (UCHAR)-1)
40 {
41 /* Do the copy */
42 RtlCopyMemory(Destination, Source->Buffer, Source->Length);
43 return Source->Length;
44 }
45
46 /* Copy this character */
47 ((PCHAR)Destination)[i] = (CHAR)(Source->Buffer[i]);
48 }
49
50 /* Compressed name, return length */
51 return Source->Length / sizeof(WCHAR);
52 }
53
54 VOID
55 NTAPI
CmpCopyCompressedName(OUT PWCHAR Destination,IN ULONG DestinationLength,IN PWCHAR Source,IN ULONG SourceLength)56 CmpCopyCompressedName(OUT PWCHAR Destination,
57 IN ULONG DestinationLength,
58 IN PWCHAR Source,
59 IN ULONG SourceLength)
60 {
61 ULONG i, Length;
62
63 /* Get the actual length to copy */
64 Length = min(DestinationLength / sizeof(WCHAR), SourceLength);
65 for (i = 0; i < Length; i++)
66 {
67 /* Copy each character */
68 Destination[i] = (WCHAR)((PUCHAR)Source)[i];
69 }
70 }
71
72 USHORT
73 NTAPI
CmpNameSize(IN PHHIVE Hive,IN PCUNICODE_STRING Name)74 CmpNameSize(IN PHHIVE Hive,
75 IN PCUNICODE_STRING Name)
76 {
77 ULONG i;
78
79 /* For old hives, just return the length */
80 if (Hive->Version == 1) return Name->Length;
81
82 /* For new versions, check for compressed name */
83 for (i = 0; i < (Name->Length / sizeof(WCHAR)); i++)
84 {
85 /* Check if the name is non compressed */
86 if (Name->Buffer[i] > (UCHAR)-1) return Name->Length;
87 }
88
89 /* Compressed name, return length */
90 return Name->Length / sizeof(WCHAR);
91 }
92
93 USHORT
94 NTAPI
CmpCompressedNameSize(IN PWCHAR Name,IN ULONG Length)95 CmpCompressedNameSize(IN PWCHAR Name,
96 IN ULONG Length)
97 {
98 /*
99 * Don't remove this: compressed names are "opaque" and just because
100 * the current implementation turns them into ansi-names doesn't mean
101 * that it will remain that way forever, so -never- assume this code
102 * below internally!
103 */
104 return (USHORT)Length * sizeof(WCHAR);
105 }
106
107 LONG
108 NTAPI
CmpCompareCompressedName(IN PCUNICODE_STRING SearchName,IN PWCHAR CompressedName,IN ULONG NameLength)109 CmpCompareCompressedName(IN PCUNICODE_STRING SearchName,
110 IN PWCHAR CompressedName,
111 IN ULONG NameLength)
112 {
113 WCHAR* p;
114 UCHAR* pp;
115 WCHAR chr1, chr2;
116 USHORT SearchLength;
117 LONG Result;
118
119 /* Set the pointers and length and then loop */
120 p = SearchName->Buffer;
121 pp = (PUCHAR)CompressedName;
122 SearchLength = (SearchName->Length / sizeof(WCHAR));
123 while (SearchLength > 0 && NameLength > 0)
124 {
125 /* Get the characters */
126 chr1 = *p++;
127 chr2 = (WCHAR)(*pp++);
128
129 /* Check if we have a direct match */
130 if (chr1 != chr2)
131 {
132 /* See if they match and return result if they don't */
133 Result = (LONG)RtlUpcaseUnicodeChar(chr1) -
134 (LONG)RtlUpcaseUnicodeChar(chr2);
135 if (Result) return Result;
136 }
137
138 /* Next chars */
139 SearchLength--;
140 NameLength--;
141 }
142
143 /* Return the difference directly */
144 return SearchLength - NameLength;
145 }
146
147 BOOLEAN
148 NTAPI
CmpFindNameInList(IN PHHIVE Hive,IN PCHILD_LIST ChildList,IN PCUNICODE_STRING Name,OUT PULONG ChildIndex OPTIONAL,OUT PHCELL_INDEX CellIndex)149 CmpFindNameInList(IN PHHIVE Hive,
150 IN PCHILD_LIST ChildList,
151 IN PCUNICODE_STRING Name,
152 OUT PULONG ChildIndex OPTIONAL,
153 OUT PHCELL_INDEX CellIndex)
154 {
155 PCELL_DATA CellData;
156 HCELL_INDEX CellToRelease = HCELL_NIL;
157 ULONG i;
158 PCM_KEY_VALUE KeyValue;
159 LONG Result;
160 UNICODE_STRING SearchName;
161 BOOLEAN Success;
162
163 /* Make sure there's actually something on the list */
164 if (ChildList->Count != 0)
165 {
166 /* Get the cell data */
167 CellData = (PCELL_DATA)HvGetCell(Hive, ChildList->List);
168 if (!CellData)
169 {
170 /* Couldn't get the cell... tell the caller */
171 *CellIndex = HCELL_NIL;
172 return FALSE;
173 }
174
175 /* Now loop every entry */
176 for (i = 0; i < ChildList->Count; i++)
177 {
178 /* Check if we have a cell to release */
179 if (CellToRelease != HCELL_NIL)
180 {
181 /* Release it */
182 HvReleaseCell(Hive, CellToRelease);
183 CellToRelease = HCELL_NIL;
184 }
185
186 /* Get this value */
187 KeyValue = (PCM_KEY_VALUE)HvGetCell(Hive, CellData->u.KeyList[i]);
188 if (!KeyValue)
189 {
190 /* Return with no data found */
191 *CellIndex = HCELL_NIL;
192 Success = FALSE;
193 goto Return;
194 }
195
196 /* Save the cell to release */
197 CellToRelease = CellData->u.KeyList[i];
198
199 /* Check if it's a compressed value name */
200 if (KeyValue->Flags & VALUE_COMP_NAME)
201 {
202 /* Compare compressed names */
203 Result = CmpCompareCompressedName(Name,
204 KeyValue->Name,
205 KeyValue->NameLength);
206 }
207 else
208 {
209 /* Compare the Unicode name directly */
210 SearchName.Length = KeyValue->NameLength;
211 SearchName.MaximumLength = SearchName.Length;
212 SearchName.Buffer = KeyValue->Name;
213 Result = RtlCompareUnicodeString(Name, &SearchName, TRUE);
214 }
215
216 /* Check if we found it */
217 if (!Result)
218 {
219 /* We did... return info to caller */
220 if (ChildIndex) *ChildIndex = i;
221 *CellIndex = CellData->u.KeyList[i];
222
223 /* Set success state */
224 Success = TRUE;
225 goto Return;
226 }
227 }
228
229 /* Got to the end of the list */
230 if (ChildIndex) *ChildIndex = i;
231 *CellIndex = HCELL_NIL;
232
233 /* Nothing found if we got here */
234 Success = TRUE;
235 goto Return;
236 }
237
238 /* Nothing found... check if the caller wanted more info */
239 ASSERT(ChildList->Count == 0);
240 if (ChildIndex) *ChildIndex = 0;
241 *CellIndex = HCELL_NIL;
242
243 /* Nothing found if we got here */
244 return TRUE;
245
246 Return:
247 /* Release the first cell we got */
248 if (CellData) HvReleaseCell(Hive, ChildList->List);
249
250 /* Release the secondary one, if we have one */
251 if (CellToRelease) HvReleaseCell(Hive, CellToRelease);
252 return Success;
253 }
254