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
15 #include <ddk/ntddk.h>
17 #include <internal/ob.h>
20 #include <internal/pool.h>
21 #include <internal/registry.h>
24 #include <internal/debug.h>
30 checkAndSkipMagic (PCHAR regChunk)
32 if (strncmp (regChunk,
34 strlen (REGISTRY_FILE_MAGIC)) != 0)
36 CPRINT ("incorrect magic number in registry chunk. expected: %s got:%.*s\n",
38 strlen (REGISTRY_FILE_MAGIC),
42 regChunk += strlen (REGISTRY_FILE_MAGIC);
43 DPRINT ("Found regsitry chunk magic value\n");
49 skipWhitespaceInChunk (PCHAR regChunk)
51 while (*regChunk && isspace (*regChunk))
54 return *regChunk ? regChunk : 0;
58 computeKeyNameSize (PCHAR regChunk)
62 while (*regChunk != 0 && *regChunk != ']')
72 allocateKeyName (PUNICODE_STRING newKeyName, int newKeySize)
74 if (newKeyName->MaximumLength < (newKeySize + 1) * sizeof (WCHAR))
76 if (newKeyName->Buffer != 0)
77 ExFreePool (newKeyName->Buffer);
78 newKeyName->Length = 0;
79 newKeyName->MaximumLength = (newKeySize + 1) * sizeof (WCHAR);
80 newKeyName->Buffer = ExAllocatePool (NonPagedPool, newKeyName->MaximumLength);
81 if (newKeyName->Buffer == 0)
83 CPRINT ("Could not allocate space for key name\n");
86 newKeyName->Buffer [0] = 0;
90 newKeyName->Length = 0;
91 newKeyName->Buffer [0] = 0;
98 skipToNextKeyInChunk (PCHAR regChunk)
100 while (*regChunk != 0 && *regChunk != '[')
102 while (*regChunk != 0 && *regChunk != '\n')
109 return *regChunk ? regChunk : 0;
113 getKeyNameFromChunk (PCHAR regChunk, PUNICODE_STRING newKeyName)
117 while (*regChunk != 0 && *regChunk != ']')
119 newKeyName->Buffer [index++] = *regChunk++;
121 newKeyName->Buffer [index] = '\0';
122 newKeyName->Length = index * sizeof (WCHAR);
124 return *regChunk ? regChunk : 0;
128 createNewKey (PUNICODE_STRING newKeyName)
131 OBJECT_ATTRIBUTES attributes;
132 HANDLE handleToReturn;
134 DPRINT ("Creating key (%wZ)\n", newKeyName);
135 InitializeObjectAttributes (&attributes,
140 status = NtCreateKey (&handleToReturn,
147 if (!NT_SUCCESS(status))
149 CPRINT ("Could not crete key (%wZ)\n", newKeyName);
150 return INVALID_HANDLE_VALUE;
153 return handleToReturn;
157 skipToNextKeyValueInChunk (PCHAR regChunk)
159 while (*regChunk != 0 && *regChunk != '\n')
161 regChunk = skipWhitespaceInChunk (regChunk);
167 computeKeyValueNameSize (PCHAR regChunk)
171 if (*regChunk != '\"')
174 while (*regChunk != 0 && *regChunk != '\"')
180 return regChunk ? size : 0;
184 getKeyValueNameFromChunk (PCHAR regChunk, PUNICODE_STRING newKeyName)
189 while (*regChunk != 0 && *regChunk != '\"')
191 newKeyName->Buffer [index++] = *regChunk++;
193 newKeyName->Buffer [index] = '\0';
194 newKeyName->Length = index * sizeof (WCHAR);
197 return *regChunk ? regChunk : 0;
201 getKeyValueTypeFromChunk (PCHAR regChunk, PCHAR dataFormat, int *keyValueType)
203 if (*regChunk == '\"')
205 strcpy (dataFormat, "string");
206 *keyValueType = REG_SZ;
208 else if (strncmp (regChunk, "hex", 3) == 0)
210 strcpy (dataFormat, "hex");
212 if (*regChunk == '(')
215 *keyValueType = atoi (regChunk);
216 while (*regChunk != 0 && *regChunk != ')')
221 *keyValueType = REG_BINARY;
222 if (*regChunk == ':')
225 else if (strncmp (regChunk, "dword", 5) == 0)
227 strcpy (dataFormat, "dword");
228 *keyValueType = REG_DWORD;
230 if (*regChunk == ':')
233 else if (strncmp (regChunk, "multi", 5) == 0)
235 strcpy (dataFormat, "multi");
236 *keyValueType = REG_MULTI_SZ;
238 if (*regChunk == ':')
241 else if (strncmp (regChunk, "expand", 6) == 0)
243 strcpy (dataFormat, "expand");
244 *keyValueType = REG_EXPAND_SZ;
246 if (*regChunk == ':')
254 return *regChunk ? regChunk : 0;
258 computeKeyValueDataSize (PCHAR regChunk, PCHAR dataFormat)
262 if (strcmp (dataFormat, "string") == 0)
265 while (*regChunk != 0 && *regChunk != '\"')
274 else if (strcmp (dataFormat, "hex") == 0)
276 while (*regChunk != 0 && isxdigit(*regChunk))
281 if (*regChunk == ',')
284 if (*regChunk == '\\')
287 regChunk = skipWhitespaceInChunk (regChunk);
292 else if (strcmp (dataFormat, "dword") == 0)
294 dataSize = sizeof(DWORD);
295 while (*regChunk != 0 && isxdigit(*regChunk))
300 else if (strcmp (dataFormat, "multi") == 0)
302 while (*regChunk == '\"')
305 while (*regChunk != 0 && *regChunk != '\"')
314 if (*regChunk == ',')
317 regChunk = skipWhitespaceInChunk (regChunk);
318 if (*regChunk == '\\')
321 regChunk = skipWhitespaceInChunk (regChunk);
330 else if (strcmp (dataFormat, "expand") == 0)
333 while (*regChunk != 0 && *regChunk != '\"')
351 allocateDataBuffer (PVOID * data, int * dataBufferSize, int dataSize)
353 if (*dataBufferSize < dataSize)
355 if (*dataBufferSize > 0)
357 *data = ExAllocatePool (NonPagedPool, dataSize);
358 *dataBufferSize = dataSize;
365 getKeyValueDataFromChunk (PCHAR regChunk, PCHAR dataFormat, PCHAR data)
371 if (strcmp (dataFormat, "string") == 0)
373 /* convert quoted string to zero-terminated Unicode string */
376 while (*regChunk != 0 && *regChunk != '\"')
378 *ptr++ = (WCHAR)*regChunk++;
383 else if (strcmp (dataFormat, "hex") == 0)
385 while (*regChunk != 0 && isxdigit (*regChunk))
387 dataValue = (isdigit (*regChunk) ? *regChunk - '0' :
388 tolower(*regChunk) - 'a' + 10) << 4;
390 dataValue += (isdigit (*regChunk) ? *regChunk - '0' :
391 tolower(*regChunk) - 'a' + 10);
394 if (*regChunk == ',')
397 if (*regChunk == '\\')
400 regChunk = skipWhitespaceInChunk (regChunk);
405 else if (strcmp (dataFormat, "dword") == 0)
408 while (*regChunk != 0 && isxdigit(*regChunk))
410 dataValue = (isdigit (*regChunk) ? *regChunk - '0' :
411 tolower(*regChunk) - 'a' + 10);
412 ulValue = (ulValue << 4) + dataValue;
415 memcpy(data, &ulValue, sizeof(ULONG));
417 else if (strcmp (dataFormat, "multi") == 0)
420 while (*regChunk == '\"')
423 while (*regChunk != 0 && *regChunk != '\"')
425 *ptr++ = (WCHAR)*regChunk++;
429 if (*regChunk == ',')
432 regChunk = skipWhitespaceInChunk (regChunk);
433 if (*regChunk == '\\')
436 regChunk = skipWhitespaceInChunk (regChunk);
444 else if (strcmp (dataFormat, "expand") == 0)
446 /* convert quoted string to zero-terminated Unicode string */
449 while (*regChunk != 0 && *regChunk != '\"')
451 *ptr++ = (WCHAR)*regChunk++;
461 return *regChunk ? regChunk : 0;
465 setKeyValue (HANDLE currentKey,
466 PUNICODE_STRING newValueName,
473 DPRINT ("Adding value (%wZ) to current key, with data type %d size %d\n",
477 status = NtSetValueKey (currentKey,
483 if (!NT_SUCCESS(status))
485 CPRINT ("could not set key value, rc:%08x\n", status);
493 CmImportHive(PCHAR ChunkBase,
496 HANDLE currentKey = INVALID_HANDLE_VALUE;
498 UNICODE_STRING newKeyName = {0, 0, 0};
499 char dataFormat [10];
502 int dataBufferSize = 0;
506 DPRINT("ChunkBase %p ChunkSize %lx\n", ChunkBase, ChunkSize);
508 regChunk = checkAndSkipMagic (ChunkBase);
512 while (regChunk != 0 && *regChunk != 0 && (((ULONG)regChunk-(ULONG)ChunkBase) < ChunkSize))
514 regChunk = skipWhitespaceInChunk (regChunk);
518 if (*regChunk == '[')
520 if (currentKey != INVALID_HANDLE_VALUE)
522 DPRINT("Closing current key: 0x%lx\n", currentKey);
523 NtClose (currentKey);
524 currentKey = INVALID_HANDLE_VALUE;
529 newKeySize = computeKeyNameSize (regChunk);
530 if (!allocateKeyName (&newKeyName, newKeySize))
536 regChunk = getKeyNameFromChunk (regChunk, &newKeyName);
540 currentKey = createNewKey (&newKeyName);
541 if (currentKey == INVALID_HANDLE_VALUE)
543 regChunk = skipToNextKeyInChunk (regChunk);
551 if (currentKey == INVALID_HANDLE_VALUE)
553 regChunk = skipToNextKeyInChunk (regChunk);
557 newKeySize = computeKeyValueNameSize (regChunk);
558 if (!allocateKeyName (&newKeyName, newKeySize))
564 regChunk = getKeyValueNameFromChunk (regChunk, &newKeyName);
568 if (*regChunk != '=')
570 regChunk = skipToNextKeyValueInChunk (regChunk);
575 regChunk = getKeyValueTypeFromChunk (regChunk, dataFormat, &keyValueType);
579 dataSize = computeKeyValueDataSize (regChunk, dataFormat);
580 if (!allocateDataBuffer (&data, &dataBufferSize, dataSize))
586 regChunk = getKeyValueDataFromChunk (regChunk, dataFormat, data);
590 if (!setKeyValue (currentKey, &newKeyName, keyValueType, data, dataSize))
598 if (currentKey != INVALID_HANDLE_VALUE)
600 NtClose (currentKey);
602 if (newKeyName.Buffer != 0)
604 ExFreePool (newKeyName.Buffer);