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.
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
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
? strtoul (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
);
388 for (;Ok
; Ok
= InfFindNextLine (&Context
, &Context
))
391 if (!InfGetStringField (&Context
, 1, Buffer
, MAX_INF_STRING_LENGTH
, NULL
))
393 if (!GetRootKey (Buffer
))
397 Length
= strlen (Buffer
);
398 if (!InfGetStringField (&Context
, 2, Buffer
+ Length
, MAX_INF_STRING_LENGTH
- Length
, NULL
))
401 DPRINT("KeyName: <%s>\n", Buffer
);
404 if (!InfGetIntField (&Context
, 4, (PLONG
)&Flags
))
407 DPRINT("Flags: %lx\n", Flags
);
409 if (Delete
|| (Flags
& FLG_ADDREG_OVERWRITEONLY
))
411 if (RegOpenKey (NULL
, Buffer
, &KeyHandle
) != ERROR_SUCCESS
)
413 DPRINT("RegOpenKey(%s) failed\n", Buffer
);
414 continue; /* ignore if it doesn't exist */
419 if (RegCreateKey (NULL
, Buffer
, &KeyHandle
) != ERROR_SUCCESS
)
421 DPRINT("RegCreateKey(%s) failed\n", Buffer
);
427 if (InfGetStringField (&Context
, 3, Buffer
, MAX_INF_STRING_LENGTH
, NULL
))
437 if (!do_reg_operation (KeyHandle
, ValuePtr
, &Context
, Flags
))
448 ImportRegistryFile(PCHAR FileName
,
455 /* Load inf file from install media. */
456 if (!InfOpenFile(&hInf
, FileName
, &ErrorLine
))
458 DPRINT1 ("InfOpenFile() failed\n");
462 if (!registry_callback (hInf
, "AddReg", FALSE
))
464 DPRINT1 ("registry_callback() failed\n");