3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/cm/import.c
6 * PURPOSE: Registry functions
7 * PROGRAMMERS: Rex Jolliff
12 #include <ddk/ntddk.h>
14 #include <internal/ob.h>
17 #include <internal/pool.h>
18 #include <internal/registry.h>
21 #include <internal/debug.h>
26 checkAndSkipMagic (PCHAR regChunk)
28 if (strncmp (regChunk,
30 strlen (REGISTRY_FILE_MAGIC)) != 0)
32 CPRINT ("incorrect magic number in registry chunk. expected: %s got:%.*s\n",
34 strlen (REGISTRY_FILE_MAGIC),
38 regChunk += strlen (REGISTRY_FILE_MAGIC);
39 DPRINT ("Found regsitry chunk magic value\n");
45 skipWhitespaceInChunk (PCHAR regChunk)
47 while (*regChunk && isspace (*regChunk))
50 return *regChunk ? regChunk : 0;
54 computeKeyNameSize (PCHAR regChunk)
58 while (*regChunk != 0 && *regChunk != ']')
68 allocateKeyName (PUNICODE_STRING newKeyName, int newKeySize)
70 if (newKeyName->MaximumLength < (newKeySize + 1) * sizeof (WCHAR))
72 if (newKeyName->Buffer != 0)
73 ExFreePool (newKeyName->Buffer);
74 newKeyName->Length = 0;
75 newKeyName->MaximumLength = (newKeySize + 1) * sizeof (WCHAR);
76 newKeyName->Buffer = ExAllocatePool (NonPagedPool, newKeyName->MaximumLength);
77 if (newKeyName->Buffer == 0)
79 CPRINT ("Could not allocate space for key name\n");
82 newKeyName->Buffer [0] = 0;
86 newKeyName->Length = 0;
87 newKeyName->Buffer [0] = 0;
94 skipToNextKeyInChunk (PCHAR regChunk)
96 while (*regChunk != 0 && *regChunk != '[')
98 while (*regChunk != 0 && *regChunk != '\n')
105 return *regChunk ? regChunk : 0;
109 getKeyNameFromChunk (PCHAR regChunk, PUNICODE_STRING newKeyName)
113 while (*regChunk != 0 && *regChunk != ']')
115 newKeyName->Buffer [index++] = *regChunk++;
117 newKeyName->Buffer [index] = '\0';
118 newKeyName->Length = index * sizeof (WCHAR);
120 return *regChunk ? regChunk : 0;
124 createNewKey (PUNICODE_STRING newKeyName)
127 OBJECT_ATTRIBUTES attributes;
128 HANDLE handleToReturn;
130 DPRINT ("Creating key (%wZ)\n", newKeyName);
131 InitializeObjectAttributes (&attributes,
136 status = NtCreateKey (&handleToReturn,
143 if (!NT_SUCCESS(status))
145 CPRINT ("Could not crete key (%wZ)\n", newKeyName);
146 return INVALID_HANDLE_VALUE;
149 return handleToReturn;
153 skipToNextKeyValueInChunk (PCHAR regChunk)
155 while (*regChunk != 0 && *regChunk != '\n')
157 regChunk = skipWhitespaceInChunk (regChunk);
163 computeKeyValueNameSize (PCHAR regChunk)
167 if (*regChunk != '\"')
170 while (*regChunk != 0 && *regChunk != '\"')
176 return regChunk ? size : 0;
180 getKeyValueNameFromChunk (PCHAR regChunk, PUNICODE_STRING newKeyName)
185 while (*regChunk != 0 && *regChunk != '\"')
187 newKeyName->Buffer [index++] = *regChunk++;
189 newKeyName->Buffer [index] = '\0';
190 newKeyName->Length = index * sizeof (WCHAR);
193 return *regChunk ? regChunk : 0;
197 getKeyValueTypeFromChunk (PCHAR regChunk, PCHAR dataFormat, int *keyValueType)
199 if (*regChunk == '\"')
201 strcpy (dataFormat, "string");
202 *keyValueType = REG_SZ;
204 else if (strncmp (regChunk, "hex", 3) == 0)
206 strcpy (dataFormat, "hex");
208 if (*regChunk == '(')
211 *keyValueType = atoi (regChunk);
212 while (*regChunk != 0 && *regChunk != ')')
217 *keyValueType = REG_BINARY;
218 if (*regChunk == ':')
221 else if (strncmp (regChunk, "dword", 5) == 0)
223 strcpy (dataFormat, "dword");
224 *keyValueType = REG_DWORD;
226 if (*regChunk == ':')
229 else if (strncmp (regChunk, "multi", 5) == 0)
231 strcpy (dataFormat, "multi");
232 *keyValueType = REG_MULTI_SZ;
234 if (*regChunk == ':')
237 else if (strncmp (regChunk, "expand", 6) == 0)
239 strcpy (dataFormat, "expand");
240 *keyValueType = REG_EXPAND_SZ;
242 if (*regChunk == ':')
250 return *regChunk ? regChunk : 0;
254 computeKeyValueDataSize (PCHAR regChunk, PCHAR dataFormat)
258 if (strcmp (dataFormat, "string") == 0)
261 while (*regChunk != 0 && *regChunk != '\"')
270 else if (strcmp (dataFormat, "hex") == 0)
272 while (*regChunk != 0 && isxdigit(*regChunk))
277 if (*regChunk == ',')
280 if (*regChunk == '\\')
283 regChunk = skipWhitespaceInChunk (regChunk);
288 else if (strcmp (dataFormat, "dword") == 0)
290 dataSize = sizeof(DWORD);
291 while (*regChunk != 0 && isxdigit(*regChunk))
296 else if (strcmp (dataFormat, "multi") == 0)
298 while (*regChunk == '\"')
301 while (*regChunk != 0 && *regChunk != '\"')
310 if (*regChunk == ',')
313 regChunk = skipWhitespaceInChunk (regChunk);
314 if (*regChunk == '\\')
317 regChunk = skipWhitespaceInChunk (regChunk);
326 else if (strcmp (dataFormat, "expand") == 0)
329 while (*regChunk != 0 && *regChunk != '\"')
347 allocateDataBuffer (PVOID * data, int * dataBufferSize, int dataSize)
349 if (*dataBufferSize < dataSize)
351 if (*dataBufferSize > 0)
353 *data = ExAllocatePool (NonPagedPool, dataSize);
354 *dataBufferSize = dataSize;
361 getKeyValueDataFromChunk (PCHAR regChunk, PCHAR dataFormat, PCHAR data)
367 if (strcmp (dataFormat, "string") == 0)
369 /* convert quoted string to zero-terminated Unicode string */
372 while (*regChunk != 0 && *regChunk != '\"')
374 *ptr++ = (WCHAR)*regChunk++;
379 else if (strcmp (dataFormat, "hex") == 0)
381 while (*regChunk != 0 && isxdigit (*regChunk))
383 dataValue = (isdigit (*regChunk) ? *regChunk - '0' :
384 tolower(*regChunk) - 'a' + 10) << 4;
386 dataValue += (isdigit (*regChunk) ? *regChunk - '0' :
387 tolower(*regChunk) - 'a' + 10);
390 if (*regChunk == ',')
393 if (*regChunk == '\\')
396 regChunk = skipWhitespaceInChunk (regChunk);
401 else if (strcmp (dataFormat, "dword") == 0)
404 while (*regChunk != 0 && isxdigit(*regChunk))
406 dataValue = (isdigit (*regChunk) ? *regChunk - '0' :
407 tolower(*regChunk) - 'a' + 10);
408 ulValue = (ulValue << 4) + dataValue;
411 memcpy(data, &ulValue, sizeof(ULONG));
413 else if (strcmp (dataFormat, "multi") == 0)
416 while (*regChunk == '\"')
419 while (*regChunk != 0 && *regChunk != '\"')
421 *ptr++ = (WCHAR)*regChunk++;
425 if (*regChunk == ',')
428 regChunk = skipWhitespaceInChunk (regChunk);
429 if (*regChunk == '\\')
432 regChunk = skipWhitespaceInChunk (regChunk);
440 else if (strcmp (dataFormat, "expand") == 0)
442 /* convert quoted string to zero-terminated Unicode string */
445 while (*regChunk != 0 && *regChunk != '\"')
447 *ptr++ = (WCHAR)*regChunk++;
457 return *regChunk ? regChunk : 0;
461 setKeyValue (HANDLE currentKey,
462 PUNICODE_STRING newValueName,
469 DPRINT ("Adding value (%wZ) to current key, with data type %d size %d\n",
473 status = NtSetValueKey (currentKey,
479 if (!NT_SUCCESS(status))
481 CPRINT ("could not set key value, rc:%08x\n", status);
489 CmImportHive(PCHAR ChunkBase,
492 HANDLE currentKey = INVALID_HANDLE_VALUE;
494 UNICODE_STRING newKeyName = {0, 0, 0};
495 char dataFormat [10];
498 int dataBufferSize = 0;
502 DPRINT("ChunkBase %p ChunkSize %lx\n", ChunkBase, ChunkSize);
504 regChunk = checkAndSkipMagic (ChunkBase);
508 while (regChunk != 0 && *regChunk != 0 && (((ULONG)regChunk-(ULONG)ChunkBase) < ChunkSize))
510 regChunk = skipWhitespaceInChunk (regChunk);
514 if (*regChunk == '[')
516 if (currentKey != INVALID_HANDLE_VALUE)
518 DPRINT("Closing current key: 0x%lx\n", currentKey);
519 NtClose (currentKey);
520 currentKey = INVALID_HANDLE_VALUE;
525 newKeySize = computeKeyNameSize (regChunk);
526 if (!allocateKeyName (&newKeyName, newKeySize))
532 regChunk = getKeyNameFromChunk (regChunk, &newKeyName);
536 currentKey = createNewKey (&newKeyName);
537 if (currentKey == INVALID_HANDLE_VALUE)
539 regChunk = skipToNextKeyInChunk (regChunk);
547 if (currentKey == INVALID_HANDLE_VALUE)
549 regChunk = skipToNextKeyInChunk (regChunk);
553 newKeySize = computeKeyValueNameSize (regChunk);
554 if (!allocateKeyName (&newKeyName, newKeySize))
560 regChunk = getKeyValueNameFromChunk (regChunk, &newKeyName);
564 if (*regChunk != '=')
566 regChunk = skipToNextKeyValueInChunk (regChunk);
571 regChunk = getKeyValueTypeFromChunk (regChunk, dataFormat, &keyValueType);
575 dataSize = computeKeyValueDataSize (regChunk, dataFormat);
576 if (!allocateDataBuffer (&data, &dataBufferSize, dataSize))
582 regChunk = getKeyValueDataFromChunk (regChunk, dataFormat, data);
586 if (!setKeyValue (currentKey, &newKeyName, keyValueType, data, dataSize))
594 if (currentKey != INVALID_HANDLE_VALUE)
596 NtClose (currentKey);
598 if (newKeyName.Buffer != 0)
600 ExFreePool (newKeyName.Buffer);