3 * Copyright (C) 2003 ReactOS Team
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.
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.
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.
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
27 /* INCLUDES *****************************************************************/
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)
53 /* FUNCTIONS ****************************************************************/
56 GetRootKey (PCHAR Name)
58 if (!strcasecmp (Name, "HKCR"))
60 strcpy (Name, "\\Registry\\Machine\\SOFTWARE\\Classes\\");
64 if (!strcasecmp (Name, "HKCU"))
66 strcpy (Name, "\\Registry\\User\\.DEFAULT\\");
70 if (!strcasecmp (Name, "HKLM"))
72 strcpy (Name, "\\Registry\\Machine\\");
76 if (!strcasecmp (Name, "HKU"))
78 strcpy (Name, "\\Registry\\User\\");
83 if (!strcasecmp (Name, "HKR"))
91 /***********************************************************************
92 * append_multi_sz_value
94 * Append a multisz string to a multisz registry value.
98 append_multi_sz_value (HANDLE hkey,
100 const WCHAR *strings,
103 DWORD size, type, total;
106 if (RegQueryValueExW( hkey, value, NULL, &type, NULL, &size )) return;
107 if (type != REG_MULTI_SZ) return;
109 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (size + str_size) * sizeof(WCHAR) ))) return;
110 if (RegQueryValueExW( hkey, value, NULL, NULL, (BYTE *)buffer, &size )) goto done;
112 /* compare each string against all the existing ones */
116 int len = strlenW(strings) + 1;
118 for (p = buffer; *p; p += strlenW(p) + 1)
119 if (!strcmpiW( p, strings )) break;
121 if (!*p) /* not found, need to append it */
123 memcpy( p, strings, len * sizeof(WCHAR) );
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 );
135 HeapFree( GetProcessHeap(), 0, buffer );
139 /***********************************************************************
140 * delete_multi_sz_value
142 * Remove a string from a multisz registry value.
145 static void delete_multi_sz_value( HKEY hkey, const WCHAR *value, const WCHAR *string )
148 WCHAR *buffer, *src, *dst;
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;
159 int len = strlenW(src) + 1;
160 if (strcmpiW( src, string ))
162 memcpy( dst, src, len * sizeof(WCHAR) );
168 if (dst != buffer + 2*size) /* did we remove something? */
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) );
175 HeapFree( GetProcessHeap(), 0, buffer );
179 /***********************************************************************
182 * Perform an add/delete registry operation depending on the flags.
185 do_reg_operation(HKEY KeyHandle,
190 CHAR EmptyStr = (CHAR)0;
195 if (Flags & FLG_ADDREG_DELVAL) /* deletion */
200 RegDeleteValueW( hkey, value );
204 RegDeleteKeyW( hkey, NULL );
210 if (Flags & FLG_ADDREG_KEYONLY)
214 if (Flags & (FLG_ADDREG_NOCLOBBER | FLG_ADDREG_OVERWRITEONLY))
216 BOOL exists = !RegQueryValueExW( hkey, value, NULL, NULL, NULL, NULL );
217 if (exists && (flags & FLG_ADDREG_NOCLOBBER))
219 if (!exists & (flags & FLG_ADDREG_OVERWRITEONLY))
224 switch (Flags & FLG_ADDREG_TYPE_MASK)
226 case FLG_ADDREG_TYPE_SZ:
230 case FLG_ADDREG_TYPE_MULTI_SZ:
234 case FLG_ADDREG_TYPE_EXPAND_SZ:
235 Type = REG_EXPAND_SZ;
238 case FLG_ADDREG_TYPE_BINARY:
242 case FLG_ADDREG_TYPE_DWORD:
246 case FLG_ADDREG_TYPE_NONE:
255 if (!(Flags & FLG_ADDREG_BINVALUETYPE) ||
256 (Type == REG_DWORD && InfGetFieldCount (Context) == 5))
260 if (Type == REG_MULTI_SZ)
262 if (!InfGetMultiSzField (Context, 5, NULL, 0, &Size))
271 InfGetMultiSzField (Context, 5, Str, Size, NULL);
274 if (Flags & FLG_ADDREG_APPEND)
279 // append_multi_sz_value( hkey, value, str, size );
284 /* else fall through to normal string handling */
288 if (!InfGetStringField (Context, 5, NULL, 0, &Size))
297 InfGetStringField (Context, 5, Str, Size, NULL);
301 if (Type == REG_DWORD)
303 ULONG dw = Str ? strtol (Str, NULL, 0) : 0;
305 DPRINT("setting dword %s to %lx\n", ValueName, dw);
307 RegSetValue (KeyHandle,
315 DPRINT ("setting value %wZ to %S\n", ValueName, Str);
319 RegSetValue (KeyHandle,
327 RegSetValue (KeyHandle,
336 else /* get the binary data */
340 if (!InfGetBinaryField (Context, 5, NULL, 0, &Size))
345 Data = malloc (Size);
349 DPRINT("setting binary data %s len %lu\n", ValueName, Size);
350 InfGetBinaryField (Context, 5, Data, Size, NULL);
353 RegSetValue (KeyHandle,
366 /***********************************************************************
369 * Called once for each AddReg and DelReg entry in a given section.
372 registry_callback (HINF hInf, PCHAR Section, BOOL Delete)
374 CHAR Buffer[MAX_INF_STRING_LENGTH];
384 Ok = InfFindFirstLine (hInf, Section, NULL, &Context);
386 for (;Ok; Ok = InfFindNextLine (&Context, &Context))
389 if (!InfGetStringField (&Context, 1, Buffer, MAX_INF_STRING_LENGTH, NULL))
391 if (!GetRootKey (Buffer))
395 Length = strlen (Buffer);
396 if (!InfGetStringField (&Context, 2, Buffer + Length, MAX_INF_STRING_LENGTH - Length, NULL))
399 DPRINT("KeyName: <%s>\n", Buffer);
402 if (!InfGetIntField (&Context, 4, (PLONG)&Flags))
405 DPRINT("Flags: %lx\n", Flags);
407 if (Delete || (Flags & FLG_ADDREG_OVERWRITEONLY))
409 if (RegOpenKey (NULL, Buffer, &KeyHandle) != ERROR_SUCCESS)
411 DPRINT("RegOpenKey(%s) failed\n", Buffer);
412 continue; /* ignore if it doesn't exist */
417 if (RegCreateKey (NULL, Buffer, &KeyHandle) != ERROR_SUCCESS)
419 DPRINT("RegCreateKey(%s) failed\n", Buffer);
425 if (InfGetStringField (&Context, 3, Buffer, MAX_INF_STRING_LENGTH, NULL))
435 if (!do_reg_operation (KeyHandle, ValuePtr, &Context, Flags))
446 ImportRegistryFile(PCHAR FileName,
453 /* Load inf file from install media. */
454 if (!InfOpenFile(&hInf, FileName, &ErrorLine))
456 DPRINT1 ("InfOpenFile() failed\n");
460 if (!registry_callback (hInf, "AddReg", FALSE))
462 DPRINT1 ("registry_callback() failed\n");