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 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 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 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 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 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 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