3 * Copyright (C) 2003, 2006 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 along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS hive maker
22 * FILE: tools/mkhive/reginf.c
23 * PURPOSE: Inf file import code
24 * PROGRAMMERS: Eric Kohl
28 /* INCLUDES *****************************************************************/
37 #define FLG_ADDREG_BINVALUETYPE 0x00000001
38 #define FLG_ADDREG_NOCLOBBER 0x00000002
39 #define FLG_ADDREG_DELVAL 0x00000004
40 #define FLG_ADDREG_APPEND 0x00000008
41 #define FLG_ADDREG_KEYONLY 0x00000010
42 #define FLG_ADDREG_OVERWRITEONLY 0x00000020
43 #define FLG_ADDREG_KEYONLY_COMMON 0x00002000
44 #define FLG_DELREG_KEYONLY_COMMON FLG_ADDREG_KEYONLY_COMMON
45 #define FLG_ADDREG_DELREG_BIT 0x00008000
47 #define FLG_ADDREG_TYPE_SZ 0x00000000
48 #define FLG_ADDREG_TYPE_MULTI_SZ 0x00010000
49 #define FLG_ADDREG_TYPE_EXPAND_SZ 0x00020000
50 #define FLG_ADDREG_TYPE_BINARY (0x00000000 | FLG_ADDREG_BINVALUETYPE)
51 #define FLG_ADDREG_TYPE_DWORD (0x00010000 | FLG_ADDREG_BINVALUETYPE)
52 #define FLG_ADDREG_TYPE_NONE (0x00020000 | FLG_ADDREG_BINVALUETYPE)
53 #define FLG_ADDREG_TYPE_MASK (0xFFFF0000 | FLG_ADDREG_BINVALUETYPE)
56 static const WCHAR HKCR
[] = {'H','K','C','R',0};
57 static const WCHAR HKCU
[] = {'H','K','C','U',0};
58 static const WCHAR HKLM
[] = {'H','K','L','M',0};
59 static const WCHAR HKU
[] = {'H','K','U',0};
60 static const WCHAR HKR
[] = {'H','K','R',0};
61 static const WCHAR BCD
[] = {'B','C','D',0};
63 static const WCHAR HKCRPath
[] = {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\','S','O','F','T','W','A','R','E','\\','C','l','a','s','s','e','s','\\',0};
64 static const WCHAR HKCUPath
[] = {'\\','R','e','g','i','s','t','r','y','\\','U','s','e','r','\\','.','D','E','F','A','U','L','T','\\',0};
65 static const WCHAR HKLMPath
[] = {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\',0};
66 static const WCHAR HKUPath
[] = {'\\','R','e','g','i','s','t','r','y','\\','U','s','e','r','\\',0};
67 static const WCHAR BCDPath
[] = {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\',0};
69 static const WCHAR AddReg
[] = {'A','d','d','R','e','g',0};
70 static const WCHAR DelReg
[] = {'D','e','l','R','e','g',0};
72 /* FUNCTIONS ****************************************************************/
75 get_root_key(PWCHAR Name
)
77 if (!strcmpiW(Name
, HKCR
))
79 strcpyW(Name
, HKCRPath
);
83 if (!strcmpiW(Name
, HKCU
))
85 strcpyW(Name
, HKCUPath
);
89 if (!strcmpiW(Name
, HKLM
))
91 strcpyW(Name
, HKLMPath
);
95 if (!strcmpiW(Name
, HKU
))
97 strcpyW(Name
, HKUPath
);
101 if (!strcmpiW(Name
, BCD
))
103 strcpyW(Name
, BCDPath
);
108 if (!strcmpiW(Name
, HKR
))
116 /***********************************************************************
117 * append_multi_sz_value
119 * Append a multisz string to a multisz registry value.
121 // NOTE: Synced with setupapi/install.c ; see also usetup/registry.c
123 append_multi_sz_value(
127 IN ULONG StringSize
) // In characters
129 ULONG Size
, Total
; // In bytes
136 Error
= RegQueryValueExW(KeyHandle
,
142 if ((Error
!= ERROR_SUCCESS
) || (Type
!= REG_MULTI_SZ
))
145 Buffer
= malloc(Size
+ StringSize
* sizeof(WCHAR
));
149 Error
= RegQueryValueExW(KeyHandle
,
155 if (Error
!= ERROR_SUCCESS
)
158 /* compare each string against all the existing ones */
160 while (*Strings
!= 0)
162 len
= strlenW(Strings
) + 1;
164 for (p
= Buffer
; *p
!= 0; p
+= strlenW(p
) + 1)
165 if (!strcmpiW(p
, Strings
))
168 if (*p
== 0) /* not found, need to append it */
170 memcpy(p
, Strings
, len
* sizeof(WCHAR
));
172 Total
+= len
* sizeof(WCHAR
);
179 DPRINT("setting value '%S' to '%S'\n", ValueName
, Buffer
);
180 RegSetValueExW(KeyHandle
,
185 Total
+ sizeof(WCHAR
));
193 /***********************************************************************
196 * Perform an add/delete registry operation depending on the flags.
202 IN PINFCONTEXT Context
,
210 if (Flags
& (FLG_ADDREG_DELREG_BIT
| FLG_ADDREG_DELVAL
)) /* deletion */
212 if (ValueName
&& *ValueName
&& !(Flags
& FLG_DELREG_KEYONLY_COMMON
))
214 // NOTE: We don't currently handle deleting sub-values inside multi-strings.
215 RegDeleteValueW(KeyHandle
, ValueName
);
219 RegDeleteKeyW(KeyHandle
, NULL
);
224 if (Flags
& (FLG_ADDREG_KEYONLY
| FLG_ADDREG_KEYONLY_COMMON
))
227 if (Flags
& (FLG_ADDREG_NOCLOBBER
| FLG_ADDREG_OVERWRITEONLY
))
229 Error
= RegQueryValueExW(KeyHandle
,
236 if ((Error
== ERROR_SUCCESS
) && (Flags
& FLG_ADDREG_NOCLOBBER
))
239 if ((Error
!= ERROR_SUCCESS
) && (Flags
& FLG_ADDREG_OVERWRITEONLY
))
243 switch (Flags
& FLG_ADDREG_TYPE_MASK
)
245 case FLG_ADDREG_TYPE_SZ
:
249 case FLG_ADDREG_TYPE_MULTI_SZ
:
253 case FLG_ADDREG_TYPE_EXPAND_SZ
:
254 Type
= REG_EXPAND_SZ
;
257 case FLG_ADDREG_TYPE_BINARY
:
261 case FLG_ADDREG_TYPE_DWORD
:
265 case FLG_ADDREG_TYPE_NONE
:
274 if (!(Flags
& FLG_ADDREG_BINVALUETYPE
) ||
275 (Type
== REG_DWORD
&& InfHostGetFieldCount(Context
) == 5))
279 if (Type
== REG_MULTI_SZ
)
281 if (InfHostGetMultiSzField(Context
, 5, NULL
, 0, &Size
) != 0)
286 Str
= malloc(Size
* sizeof(WCHAR
));
290 InfHostGetMultiSzField(Context
, 5, Str
, Size
, NULL
);
293 if (Flags
& FLG_ADDREG_APPEND
)
298 DPRINT("append_multi_sz_value(ValueName = '%S')\n", ValueName
);
299 append_multi_sz_value(KeyHandle
,
307 /* else fall through to normal string handling */
311 if (InfHostGetStringField(Context
, 5, NULL
, 0, &Size
) != 0)
316 Str
= malloc(Size
* sizeof(WCHAR
));
320 InfHostGetStringField(Context
, 5, Str
, Size
, NULL
);
324 if (Type
== REG_DWORD
)
326 ULONG dw
= Str
? strtoulW(Str
, NULL
, 0) : 0;
328 DPRINT("setting dword '%S' to %x\n", ValueName
, dw
);
330 RegSetValueExW(KeyHandle
,
339 DPRINT("setting value '%S' to '%S'\n", ValueName
, Str
);
343 RegSetValueExW(KeyHandle
,
348 (ULONG
)(Size
* sizeof(WCHAR
)));
352 RegSetValueExW(KeyHandle
,
362 else /* get the binary data */
366 if (InfHostGetBinaryField(Context
, 5, NULL
, 0, &Size
) != 0)
375 DPRINT("setting binary data '%S' len %d\n", ValueName
, (ULONG
)Size
);
376 InfHostGetBinaryField(Context
, 5, Data
, Size
, NULL
);
379 RegSetValueExW(KeyHandle
,
392 /***********************************************************************
395 * Called once for each AddReg and DelReg entry in a given section.
398 registry_callback(HINF hInf
, PCWSTR Section
, BOOL Delete
)
400 WCHAR Buffer
[MAX_INF_STRING_LENGTH
];
405 PINFCONTEXT Context
= NULL
;
409 Ok
= InfHostFindFirstLine(hInf
, Section
, NULL
, &Context
) == 0;
411 return TRUE
; /* Don't fail if the section isn't present */
413 for (Ok
= TRUE
; Ok
; Ok
= (InfHostFindNextLine(Context
, Context
) == 0))
416 if (InfHostGetStringField(Context
, 1, Buffer
, sizeof(Buffer
)/sizeof(WCHAR
), NULL
) != 0)
418 if (!get_root_key(Buffer
))
422 Length
= strlenW(Buffer
);
423 if (InfHostGetStringField(Context
, 2, Buffer
+ Length
, sizeof(Buffer
)/sizeof(WCHAR
) - (ULONG
)Length
, NULL
) != 0)
426 DPRINT("KeyName: <%S>\n", Buffer
);
429 if (InfHostGetIntField(Context
, 4, (INT
*)&Flags
) != 0)
435 Flags
= FLG_ADDREG_DELREG_BIT
;
436 else if (!(Flags
& FLG_ADDREG_DELREG_BIT
))
437 continue; /* ignore this entry */
441 if (Flags
& FLG_ADDREG_DELREG_BIT
)
442 continue; /* ignore this entry */
445 DPRINT("Flags: 0x%x\n", Flags
);
447 if (Delete
|| (Flags
& FLG_ADDREG_OVERWRITEONLY
))
449 if (RegOpenKeyW(NULL
, Buffer
, &KeyHandle
) != ERROR_SUCCESS
)
451 DPRINT("RegOpenKey(%S) failed\n", Buffer
);
452 continue; /* ignore if it doesn't exist */
457 if (RegCreateKeyW(NULL
, Buffer
, &KeyHandle
) != ERROR_SUCCESS
)
459 DPRINT("RegCreateKey(%S) failed\n", Buffer
);
465 if (InfHostGetStringField(Context
, 3, Buffer
, sizeof(Buffer
)/sizeof(WCHAR
), NULL
) == 0)
475 if (!do_reg_operation(KeyHandle
, ValuePtr
, Context
, Flags
))
477 RegCloseKey(KeyHandle
);
481 RegCloseKey(KeyHandle
);
484 InfHostFreeContext(Context
);
491 ImportRegistryFile(PCHAR FileName
)
496 /* Load inf file from install media. */
497 if (InfHostOpenFile(&hInf
, FileName
, 0, &ErrorLine
) != 0)
499 DPRINT1("InfHostOpenFile(%s) failed\n", FileName
);
503 if (!registry_callback(hInf
, (PWCHAR
)DelReg
, TRUE
))
505 DPRINT1("registry_callback() for DelReg failed\n");
506 InfHostCloseFile(hInf
);
510 if (!registry_callback(hInf
, (PWCHAR
)AddReg
, FALSE
))
512 DPRINT1("registry_callback() for AddReg failed\n");
513 InfHostCloseFile(hInf
);
517 InfHostCloseFile(hInf
);