Treat DWORD values as unsigned - Patch by vizzini
[reactos.git] / reactos / tools / mkhive / reginf.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id: reginf.c,v 1.4 2003/07/27 22:00:26 sedwards Exp $
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS hive maker
22 * FILE: tools/mkhive/reginf.h
23 * PURPOSE: Inf file import code
24 * PROGRAMMER: Eric Kohl
25 */
26
27 /* INCLUDES *****************************************************************/
28
29 #include <string.h>
30 #include <stdlib.h>
31
32 #include "mkhive.h"
33 #include "registry.h"
34 #include "infcache.h"
35
36
37
38 #define FLG_ADDREG_BINVALUETYPE 0x00000001
39 #define FLG_ADDREG_NOCLOBBER 0x00000002
40 #define FLG_ADDREG_DELVAL 0x00000004
41 #define FLG_ADDREG_APPEND 0x00000008
42 #define FLG_ADDREG_KEYONLY 0x00000010
43 #define FLG_ADDREG_OVERWRITEONLY 0x00000020
44 #define FLG_ADDREG_TYPE_SZ 0x00000000
45 #define FLG_ADDREG_TYPE_MULTI_SZ 0x00010000
46 #define FLG_ADDREG_TYPE_EXPAND_SZ 0x00020000
47 #define FLG_ADDREG_TYPE_BINARY (0x00000000 | FLG_ADDREG_BINVALUETYPE)
48 #define FLG_ADDREG_TYPE_DWORD (0x00010000 | FLG_ADDREG_BINVALUETYPE)
49 #define FLG_ADDREG_TYPE_NONE (0x00020000 | FLG_ADDREG_BINVALUETYPE)
50 #define FLG_ADDREG_TYPE_MASK (0xFFFF0000 | FLG_ADDREG_BINVALUETYPE)
51
52
53 /* FUNCTIONS ****************************************************************/
54
55 static BOOL
56 GetRootKey (PCHAR Name)
57 {
58 if (!strcasecmp (Name, "HKCR"))
59 {
60 strcpy (Name, "\\Registry\\Machine\\SOFTWARE\\Classes\\");
61 return TRUE;
62 }
63
64 if (!strcasecmp (Name, "HKCU"))
65 {
66 strcpy (Name, "\\Registry\\User\\.DEFAULT\\");
67 return TRUE;
68 }
69
70 if (!strcasecmp (Name, "HKLM"))
71 {
72 strcpy (Name, "\\Registry\\Machine\\");
73 return TRUE;
74 }
75
76 if (!strcasecmp (Name, "HKU"))
77 {
78 strcpy (Name, "\\Registry\\User\\");
79 return TRUE;
80 }
81
82 #if 0
83 if (!strcasecmp (Name, "HKR"))
84 return FALSE;
85 #endif
86
87 return FALSE;
88 }
89
90
91 /***********************************************************************
92 * append_multi_sz_value
93 *
94 * Append a multisz string to a multisz registry value.
95 */
96 #if 0
97 static void
98 append_multi_sz_value (HANDLE hkey,
99 const WCHAR *value,
100 const WCHAR *strings,
101 DWORD str_size )
102 {
103 DWORD size, type, total;
104 WCHAR *buffer, *p;
105
106 if (RegQueryValueExW( hkey, value, NULL, &type, NULL, &size )) return;
107 if (type != REG_MULTI_SZ) return;
108
109 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (size + str_size) * sizeof(WCHAR) ))) return;
110 if (RegQueryValueExW( hkey, value, NULL, NULL, (BYTE *)buffer, &size )) goto done;
111
112 /* compare each string against all the existing ones */
113 total = size;
114 while (*strings)
115 {
116 int len = strlenW(strings) + 1;
117
118 for (p = buffer; *p; p += strlenW(p) + 1)
119 if (!strcmpiW( p, strings )) break;
120
121 if (!*p) /* not found, need to append it */
122 {
123 memcpy( p, strings, len * sizeof(WCHAR) );
124 p[len] = 0;
125 total += len;
126 }
127 strings += len;
128 }
129 if (total != size)
130 {
131 TRACE( "setting value %s to %s\n", debugstr_w(value), debugstr_w(buffer) );
132 RegSetValueExW( hkey, value, 0, REG_MULTI_SZ, (BYTE *)buffer, total );
133 }
134 done:
135 HeapFree( GetProcessHeap(), 0, buffer );
136 }
137 #endif
138
139 /***********************************************************************
140 * delete_multi_sz_value
141 *
142 * Remove a string from a multisz registry value.
143 */
144 #if 0
145 static void delete_multi_sz_value( HKEY hkey, const WCHAR *value, const WCHAR *string )
146 {
147 DWORD size, type;
148 WCHAR *buffer, *src, *dst;
149
150 if (RegQueryValueExW( hkey, value, NULL, &type, NULL, &size )) return;
151 if (type != REG_MULTI_SZ) return;
152 /* allocate double the size, one for value before and one for after */
153 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size * 2 * sizeof(WCHAR) ))) return;
154 if (RegQueryValueExW( hkey, value, NULL, NULL, (BYTE *)buffer, &size )) goto done;
155 src = buffer;
156 dst = buffer + size;
157 while (*src)
158 {
159 int len = strlenW(src) + 1;
160 if (strcmpiW( src, string ))
161 {
162 memcpy( dst, src, len * sizeof(WCHAR) );
163 dst += len;
164 }
165 src += len;
166 }
167 *dst++ = 0;
168 if (dst != buffer + 2*size) /* did we remove something? */
169 {
170 TRACE( "setting value %s to %s\n", debugstr_w(value), debugstr_w(buffer + size) );
171 RegSetValueExW( hkey, value, 0, REG_MULTI_SZ,
172 (BYTE *)(buffer + size), dst - (buffer + size) );
173 }
174 done:
175 HeapFree( GetProcessHeap(), 0, buffer );
176 }
177 #endif
178
179 /***********************************************************************
180 * do_reg_operation
181 *
182 * Perform an add/delete registry operation depending on the flags.
183 */
184 static BOOL
185 do_reg_operation(HKEY KeyHandle,
186 PCHAR ValueName,
187 PINFCONTEXT Context,
188 ULONG Flags)
189 {
190 CHAR EmptyStr = (CHAR)0;
191 ULONG Type;
192 ULONG Size;
193 // NTSTATUS Status;
194
195 if (Flags & FLG_ADDREG_DELVAL) /* deletion */
196 {
197 #if 0
198 if (ValueName)
199 {
200 RegDeleteValueW( hkey, value );
201 }
202 else
203 {
204 RegDeleteKeyW( hkey, NULL );
205 }
206 #endif
207 return TRUE;
208 }
209
210 if (Flags & FLG_ADDREG_KEYONLY)
211 return TRUE;
212
213 #if 0
214 if (Flags & (FLG_ADDREG_NOCLOBBER | FLG_ADDREG_OVERWRITEONLY))
215 {
216 BOOL exists = !RegQueryValueExW( hkey, value, NULL, NULL, NULL, NULL );
217 if (exists && (flags & FLG_ADDREG_NOCLOBBER))
218 return TRUE;
219 if (!exists & (flags & FLG_ADDREG_OVERWRITEONLY))
220 return TRUE;
221 }
222 #endif
223
224 switch (Flags & FLG_ADDREG_TYPE_MASK)
225 {
226 case FLG_ADDREG_TYPE_SZ:
227 Type = REG_SZ;
228 break;
229
230 case FLG_ADDREG_TYPE_MULTI_SZ:
231 Type = REG_MULTI_SZ;
232 break;
233
234 case FLG_ADDREG_TYPE_EXPAND_SZ:
235 Type = REG_EXPAND_SZ;
236 break;
237
238 case FLG_ADDREG_TYPE_BINARY:
239 Type = REG_BINARY;
240 break;
241
242 case FLG_ADDREG_TYPE_DWORD:
243 Type = REG_DWORD;
244 break;
245
246 case FLG_ADDREG_TYPE_NONE:
247 Type = REG_NONE;
248 break;
249
250 default:
251 Type = Flags >> 16;
252 break;
253 }
254
255 if (!(Flags & FLG_ADDREG_BINVALUETYPE) ||
256 (Type == REG_DWORD && InfGetFieldCount (Context) == 5))
257 {
258 PCHAR Str = NULL;
259
260 if (Type == REG_MULTI_SZ)
261 {
262 if (!InfGetMultiSzField (Context, 5, NULL, 0, &Size))
263 Size = 0;
264
265 if (Size)
266 {
267 Str = malloc (Size);
268 if (Str == NULL)
269 return FALSE;
270
271 InfGetMultiSzField (Context, 5, Str, Size, NULL);
272 }
273
274 if (Flags & FLG_ADDREG_APPEND)
275 {
276 if (Str == NULL)
277 return TRUE;
278
279 // append_multi_sz_value( hkey, value, str, size );
280
281 free (Str);
282 return TRUE;
283 }
284 /* else fall through to normal string handling */
285 }
286 else
287 {
288 if (!InfGetStringField (Context, 5, NULL, 0, &Size))
289 Size = 0;
290
291 if (Size)
292 {
293 Str = malloc (Size);
294 if (Str == NULL)
295 return FALSE;
296
297 InfGetStringField (Context, 5, Str, Size, NULL);
298 }
299 }
300
301 if (Type == REG_DWORD)
302 {
303 ULONG dw = Str ? strtoul (Str, NULL, 0) : 0;
304
305 DPRINT("setting dword %s to %lx\n", ValueName, dw);
306
307 RegSetValue (KeyHandle,
308 ValueName,
309 Type,
310 (PVOID)&dw,
311 sizeof(ULONG));
312 }
313 else
314 {
315 DPRINT ("setting value %wZ to %S\n", ValueName, Str);
316
317 if (Str)
318 {
319 RegSetValue (KeyHandle,
320 ValueName,
321 Type,
322 (PVOID)Str,
323 Size);
324 }
325 else
326 {
327 RegSetValue (KeyHandle,
328 ValueName,
329 Type,
330 (PVOID)&EmptyStr,
331 sizeof(CHAR));
332 }
333 }
334 free (Str);
335 }
336 else /* get the binary data */
337 {
338 PUCHAR Data = NULL;
339
340 if (!InfGetBinaryField (Context, 5, NULL, 0, &Size))
341 Size = 0;
342
343 if (Size)
344 {
345 Data = malloc (Size);
346 if (Data == NULL)
347 return FALSE;
348
349 DPRINT("setting binary data %s len %lu\n", ValueName, Size);
350 InfGetBinaryField (Context, 5, Data, Size, NULL);
351 }
352
353 RegSetValue (KeyHandle,
354 ValueName,
355 Type,
356 (PVOID)Data,
357 Size);
358
359 free (Data);
360 }
361
362 return TRUE;
363 }
364
365
366 /***********************************************************************
367 * registry_callback
368 *
369 * Called once for each AddReg and DelReg entry in a given section.
370 */
371 static BOOL
372 registry_callback (HINF hInf, PCHAR Section, BOOL Delete)
373 {
374 CHAR Buffer[MAX_INF_STRING_LENGTH];
375 PCHAR ValuePtr;
376 ULONG Flags;
377 ULONG Length;
378
379 INFCONTEXT Context;
380 HKEY KeyHandle;
381 BOOL Ok;
382
383
384 Ok = InfFindFirstLine (hInf, Section, NULL, &Context);
385 if (!Ok)
386 return FALSE;
387
388 for (;Ok; Ok = InfFindNextLine (&Context, &Context))
389 {
390 /* get root */
391 if (!InfGetStringField (&Context, 1, Buffer, MAX_INF_STRING_LENGTH, NULL))
392 continue;
393 if (!GetRootKey (Buffer))
394 continue;
395
396 /* get key */
397 Length = strlen (Buffer);
398 if (!InfGetStringField (&Context, 2, Buffer + Length, MAX_INF_STRING_LENGTH - Length, NULL))
399 *Buffer = 0;
400
401 DPRINT("KeyName: <%s>\n", Buffer);
402
403 /* get flags */
404 if (!InfGetIntField (&Context, 4, (PLONG)&Flags))
405 Flags = 0;
406
407 DPRINT("Flags: %lx\n", Flags);
408
409 if (Delete || (Flags & FLG_ADDREG_OVERWRITEONLY))
410 {
411 if (RegOpenKey (NULL, Buffer, &KeyHandle) != ERROR_SUCCESS)
412 {
413 DPRINT("RegOpenKey(%s) failed\n", Buffer);
414 continue; /* ignore if it doesn't exist */
415 }
416 }
417 else
418 {
419 if (RegCreateKey (NULL, Buffer, &KeyHandle) != ERROR_SUCCESS)
420 {
421 DPRINT("RegCreateKey(%s) failed\n", Buffer);
422 continue;
423 }
424 }
425
426 /* get value name */
427 if (InfGetStringField (&Context, 3, Buffer, MAX_INF_STRING_LENGTH, NULL))
428 {
429 ValuePtr = Buffer;
430 }
431 else
432 {
433 ValuePtr = NULL;
434 }
435
436 /* and now do it */
437 if (!do_reg_operation (KeyHandle, ValuePtr, &Context, Flags))
438 {
439 return FALSE;
440 }
441 }
442
443 return TRUE;
444 }
445
446
447 BOOL
448 ImportRegistryFile(PCHAR FileName,
449 PCHAR Section,
450 BOOL Delete)
451 {
452 HINF hInf;
453 ULONG ErrorLine;
454
455 /* Load inf file from install media. */
456 if (!InfOpenFile(&hInf, FileName, &ErrorLine))
457 {
458 DPRINT1 ("InfOpenFile() failed\n");
459 return FALSE;
460 }
461
462 if (!registry_callback (hInf, "AddReg", FALSE))
463 {
464 DPRINT1 ("registry_callback() failed\n");
465 }
466
467 InfCloseFile (hInf);
468
469 return TRUE;
470 }
471
472 /* EOF */