xref: /reactos/sdk/lib/cmlib/cmname.c (revision d8738659)
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