f23f243f6e6d5d34645879717f9640112a634b5f
[reactos.git] / freeldr / freeldr / reactos / reghive.c
1 /*
2 * FreeLoader
3 *
4 * Copyright (C) 2001 Rex Jolliff
5 * Copyright (C) 2001 Eric Kohl
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "../freeldr.h"
23 #include "../stdlib.h"
24 #include "../memory.h"
25
26 #include "registry.h"
27
28 #define NDEBUG
29
30
31 #define REGISTRY_FILE_MAGIC "REGEDIT4"
32
33 #define INVALID_HANDLE_VALUE NULL
34
35
36 static PCHAR
37 checkAndSkipMagic (PCHAR regChunk)
38 {
39 if (strncmp (regChunk,
40 REGISTRY_FILE_MAGIC,
41 strlen (REGISTRY_FILE_MAGIC)) != 0)
42 {
43 #ifndef NDEBUG
44 printf("incorrect magic number in registry chunk. expected: %s got:%.*s\n",
45 REGISTRY_FILE_MAGIC,
46 strlen (REGISTRY_FILE_MAGIC),
47 regChunk);
48 #endif
49 return 0;
50 }
51 regChunk += strlen (REGISTRY_FILE_MAGIC);
52 #ifndef NDEBUG
53 printf("Found registry chunk magic value\n");
54 #endif
55
56 return regChunk;
57 }
58
59 static PCHAR
60 skipWhitespaceInChunk (PCHAR regChunk)
61 {
62 while (*regChunk && isspace (*regChunk))
63 regChunk++;
64
65 return *regChunk ? regChunk : 0;
66 }
67
68 static int
69 computeKeyNameSize (PCHAR regChunk)
70 {
71 int copyCount = 0;
72
73 while (*regChunk != 0 && *regChunk != ']')
74 {
75 copyCount++;
76 regChunk++;
77 }
78
79 return copyCount;
80 }
81
82 static BOOL
83 allocateKeyName(PCHAR *newKeyName, int newKeySize)
84 {
85 if (*newKeyName != NULL)
86 FreeMemory(*newKeyName);
87
88 *newKeyName = AllocateMemory(newKeySize + 1);
89 if (*newKeyName == NULL)
90 return(FALSE);
91
92 memset(*newKeyName, 0, newKeySize + 1);
93
94 return(TRUE);
95 }
96
97 static PCHAR
98 skipToNextKeyInChunk (PCHAR regChunk)
99 {
100 while (*regChunk != 0 && *regChunk != '[')
101 {
102 while (*regChunk != 0 && *regChunk != '\n')
103 {
104 regChunk++;
105 }
106 regChunk++;
107 }
108
109 return *regChunk ? regChunk : 0;
110 }
111
112 static PCHAR
113 getKeyNameFromChunk (PCHAR regChunk, PCHAR newKeyName)
114 {
115 int index = 0;
116
117 while (*regChunk != 0 && *regChunk != ']')
118 {
119 newKeyName[index++] = *regChunk++;
120 }
121 newKeyName[index] = '\0';
122
123 return *regChunk ? regChunk : 0;
124 }
125
126 static HKEY
127 createNewKey (PCHAR newKeyName)
128 {
129 HKEY handleToReturn = NULL;
130
131 #ifndef NDEBUG
132 printf("Adding new key '%s'\n", newKeyName);
133 #endif
134
135 RegCreateKey(NULL,
136 newKeyName,
137 &handleToReturn);
138
139 #ifndef NDEBUG
140 printf(" returned handle: 0x%x\n", handleToReturn);
141 #endif
142
143 return handleToReturn;
144 }
145
146 static PCHAR
147 skipToNextKeyValueInChunk (PCHAR regChunk)
148 {
149 while (*regChunk != 0 && *regChunk != '\n')
150 regChunk++;
151 regChunk = skipWhitespaceInChunk (regChunk);
152
153 return regChunk;
154 }
155
156 static int
157 computeKeyValueNameSize (PCHAR regChunk)
158 {
159 int size = 0;
160
161 if (*regChunk != '\"')
162 return 0;
163 regChunk++;
164 while (*regChunk != 0 && *regChunk != '\"')
165 {
166 size++;
167 regChunk++;
168 }
169
170 return regChunk ? size : 0;
171 }
172
173 static PCHAR
174 getKeyValueNameFromChunk (PCHAR regChunk, PCHAR newKeyName)
175 {
176 int index = 0;
177
178 regChunk++;
179 while (*regChunk != 0 && *regChunk != '\"')
180 {
181 newKeyName[index++] = *regChunk++;
182 }
183 newKeyName[index] = '\0';
184 regChunk++;
185
186 return *regChunk ? regChunk : 0;
187 }
188
189 static PCHAR
190 getKeyValueTypeFromChunk (PCHAR regChunk, PCHAR dataFormat, int *keyValueType)
191 {
192 if (*regChunk == '\"')
193 {
194 strcpy (dataFormat, "string");
195 *keyValueType = REG_SZ;
196 }
197 else if (strncmp (regChunk, "hex", 3) == 0)
198 {
199 strcpy (dataFormat, "hex");
200 regChunk += 3;
201 if (*regChunk == '(')
202 {
203 regChunk++;
204 *keyValueType = atoi (regChunk);
205 while (*regChunk != 0 && *regChunk != ')')
206 regChunk++;
207 regChunk++;
208 }
209 else
210 *keyValueType = REG_BINARY;
211 if (*regChunk == ':')
212 regChunk++;
213 }
214 else if (strncmp (regChunk, "dword", 5) == 0)
215 {
216 strcpy (dataFormat, "dword");
217 *keyValueType = REG_DWORD;
218 regChunk += 5;
219 if (*regChunk == ':')
220 regChunk++;
221 }
222 else
223 {
224 // UNIMPLEMENTED;
225 }
226
227 return *regChunk ? regChunk : 0;
228 }
229
230 static int
231 computeKeyValueDataSize (PCHAR regChunk, PCHAR dataFormat)
232 {
233 int dataSize = 0;
234
235 if (strcmp (dataFormat, "string") == 0)
236 {
237 regChunk++;
238 while (*regChunk != 0 && *regChunk != '\"')
239 {
240 dataSize++;
241 regChunk++;
242 }
243 dataSize++;
244 }
245 else if (strcmp (dataFormat, "hex") == 0)
246 {
247 while (*regChunk != 0 && isxdigit(*regChunk))
248 {
249 regChunk++;
250 regChunk++;
251 dataSize++;
252 if (*regChunk == ',')
253 {
254 regChunk++;
255 if (*regChunk == '\\')
256 {
257 regChunk++;
258 regChunk = skipWhitespaceInChunk (regChunk);
259 }
260 }
261 }
262 }
263 else if (strcmp (dataFormat, "dword") == 0)
264 {
265 dataSize = sizeof(DWORD);
266 while (*regChunk != 0 && isxdigit(*regChunk))
267 {
268 regChunk++;
269 }
270 }
271 else
272 {
273 // UNIMPLEMENTED;
274 }
275
276 return dataSize;
277 }
278
279 static BOOL
280 allocateDataBuffer (PVOID * data, int * dataBufferSize, int dataSize)
281 {
282 if (*dataBufferSize < dataSize)
283 {
284 if (*dataBufferSize > 0)
285 FreeMemory(*data);
286 *data = AllocateMemory(dataSize);
287 *dataBufferSize = dataSize;
288 }
289
290 return TRUE;
291 }
292
293 static PCHAR
294 getKeyValueDataFromChunk (PCHAR regChunk, PCHAR dataFormat, PCHAR data)
295 {
296 char dataValue;
297 ULONG ulValue;
298 PCHAR ptr;
299
300 if (strcmp (dataFormat, "string") == 0)
301 {
302 /* convert quoted string to zero-terminated Unicode string */
303 ptr = (PCHAR)data;
304 regChunk++;
305 while (*regChunk != 0 && *regChunk != '\"')
306 {
307 *ptr++ = (CHAR)*regChunk++;
308 }
309 *ptr = 0;
310 regChunk++;
311 }
312 else if (strcmp (dataFormat, "hex") == 0)
313 {
314 while (*regChunk != 0 && isxdigit (*regChunk))
315 {
316 dataValue = (isdigit (*regChunk) ? *regChunk - '0' :
317 tolower(*regChunk) - 'a') << 4;
318 regChunk++;
319 dataValue += (isdigit (*regChunk) ? *regChunk - '0' :
320 tolower(*regChunk) - 'a');
321 regChunk++;
322 *data++ = dataValue;
323 if (*regChunk == ',')
324 {
325 regChunk++;
326 if (*regChunk == '\\')
327 {
328 regChunk++;
329 regChunk = skipWhitespaceInChunk (regChunk);
330 }
331 }
332 }
333 }
334 else if (strcmp (dataFormat, "dword") == 0)
335 {
336 ulValue = 0;
337 while (*regChunk != 0 && isxdigit(*regChunk))
338 {
339 dataValue = (isdigit (*regChunk) ? *regChunk - '0' :
340 tolower(*regChunk) - 'a');
341 ulValue = (ulValue << 4) + dataValue;
342 regChunk++;
343 }
344 memcpy(data, &ulValue, sizeof(ULONG));
345 }
346 else
347 {
348 // UNIMPLEMENTED;
349 }
350
351 return *regChunk ? regChunk : 0;
352 }
353
354 static BOOL
355 setKeyValue (HKEY currentKey,
356 PCHAR newValueName,
357 ULONG keyValueType,
358 PVOID data,
359 ULONG dataSize)
360 {
361 LONG status;
362
363 #ifndef NDEBUG
364 printf("Adding value (%s) to current key, with data type %d size %d\n",
365 newValueName,
366 (int)keyValueType,
367 (int)dataSize);
368 #endif
369 status = RegSetValue(currentKey,
370 newValueName,
371 keyValueType,
372 data,
373 dataSize);
374 if (status != ERROR_SUCCESS)
375 {
376 #ifndef NDEBUG
377 printf("could not set key value, rc:%d\n", status);
378 #endif
379 return FALSE;
380 }
381
382 return TRUE;
383 }
384
385
386 VOID
387 RegImportHive(PCHAR ChunkBase,
388 ULONG ChunkSize)
389 {
390 HKEY currentKey = NULL;
391 int newKeySize = 0;
392 char *newKeyName = NULL;
393 char dataFormat [10];
394 int keyValueType;
395 int dataSize = 0;
396 int dataBufferSize = 0;
397 PVOID data = 0;
398 PCHAR regChunk;
399
400 #ifndef NDEBUG
401 printf("ChunkBase 0x%x ChunkSize %x\n", ChunkBase, ChunkSize);
402 #endif
403
404 regChunk = checkAndSkipMagic (ChunkBase);
405 if (regChunk == 0)
406 return;
407
408 while (regChunk != 0 && *regChunk != 0 && (((ULONG)regChunk-(ULONG)ChunkBase) < ChunkSize))
409 {
410 regChunk = skipWhitespaceInChunk (regChunk);
411 if (regChunk == 0)
412 continue;
413
414 if (*regChunk == '[')
415 {
416 #ifndef NDEBUG
417 printf("Line: %s\n", regChunk);
418 #endif
419 if (currentKey != NULL)
420 {
421 #ifndef NDEBUG
422 printf("Closing current key: 0x%lx\n", currentKey);
423 #endif
424 currentKey = NULL;
425 }
426
427 regChunk++;
428
429 newKeySize = computeKeyNameSize (regChunk);
430 if (!allocateKeyName (&newKeyName, newKeySize))
431 {
432 regChunk = 0;
433 continue;
434 }
435
436 regChunk = getKeyNameFromChunk (regChunk, newKeyName);
437 if (regChunk == 0)
438 continue;
439
440 currentKey = createNewKey (newKeyName);
441 if (currentKey == NULL)
442 {
443 regChunk = skipToNextKeyInChunk (regChunk);
444 continue;
445 }
446
447 regChunk++;
448 }
449 else
450 {
451 if (currentKey == NULL)
452 {
453 regChunk = skipToNextKeyInChunk (regChunk);
454 continue;
455 }
456
457 newKeySize = computeKeyValueNameSize(regChunk);
458 if (!allocateKeyName (&newKeyName, newKeySize))
459 {
460 regChunk = 0;
461 continue;
462 }
463
464 regChunk = getKeyValueNameFromChunk (regChunk, newKeyName);
465 if (regChunk == 0)
466 continue;
467
468 if (*regChunk != '=')
469 {
470 regChunk = skipToNextKeyValueInChunk (regChunk);
471 continue;
472 }
473 regChunk++;
474
475 regChunk = getKeyValueTypeFromChunk (regChunk, dataFormat, &keyValueType);
476 if (regChunk == 0)
477 continue;
478
479 dataSize = computeKeyValueDataSize (regChunk, dataFormat);
480 if (!allocateDataBuffer (&data, &dataBufferSize, dataSize))
481 {
482 regChunk = 0;
483 continue;
484 }
485
486 regChunk = getKeyValueDataFromChunk (regChunk, dataFormat, data);
487 if (regChunk == 0)
488 continue;
489
490 if (!setKeyValue (currentKey, newKeyName, keyValueType, data, dataSize))
491 {
492 regChunk = 0;
493 continue;
494 }
495 }
496 }
497
498 if (newKeyName != NULL)
499 {
500 FreeMemory(newKeyName);
501 }
502 if (data != NULL)
503 {
504 FreeMemory(data);
505 }
506
507 return;
508 }
509
510
511
512
513 static PCHAR
514 bprintf(char *buffer, char *format, ... )
515 {
516 int *dataptr = (int *) &format;
517 char c, *ptr, str[16];
518 char *p = buffer;
519
520 dataptr++;
521
522 while ((c = *(format++)))
523 {
524 if (c != '%')
525 {
526 *p = c;
527 p++;
528 }
529 else
530 switch (c = *(format++))
531 {
532 case 'd': case 'u': case 'x':
533 *convert_to_ascii(str, c, *((unsigned long *) dataptr++)) = 0;
534
535 ptr = str;
536
537 while (*ptr)
538 {
539 *p = *(ptr++);
540 p++;
541 }
542 break;
543
544 case 'c':
545 *p = (*(dataptr++))&0xff;
546 p++;
547 break;
548
549 case 's':
550 ptr = (char *)(*(dataptr++));
551
552 while ((c = *(ptr++)))
553 {
554 *p = c;
555 p++;
556 }
557 break;
558 }
559 }
560 return(p);
561 }
562
563
564 BOOL
565 RegExportHive(PCHAR ChunkBase, PULONG ChunkSize)
566 {
567
568 return(TRUE);
569 }
570
571 /* EOF */