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.
19 /* COPYRIGHT: See COPYING in the top level directory
20 * PROJECT: ReactOS hive maker
21 * FILE: tools/mkhive/reginf.h
22 * PURPOSE: Inf file import code
23 * PROGRAMMER: Eric Kohl
27 /* INCLUDES *****************************************************************/
36 #define FLG_ADDREG_BINVALUETYPE 0x00000001
37 #define FLG_ADDREG_NOCLOBBER 0x00000002
38 #define FLG_ADDREG_DELVAL 0x00000004
39 #define FLG_ADDREG_APPEND 0x00000008
40 #define FLG_ADDREG_KEYONLY 0x00000010
41 #define FLG_ADDREG_OVERWRITEONLY 0x00000020
42 #define FLG_ADDREG_TYPE_SZ 0x00000000
43 #define FLG_ADDREG_TYPE_MULTI_SZ 0x00010000
44 #define FLG_ADDREG_TYPE_EXPAND_SZ 0x00020000
45 #define FLG_ADDREG_TYPE_BINARY (0x00000000 | FLG_ADDREG_BINVALUETYPE)
46 #define FLG_ADDREG_TYPE_DWORD (0x00010000 | FLG_ADDREG_BINVALUETYPE)
47 #define FLG_ADDREG_TYPE_NONE (0x00020000 | FLG_ADDREG_BINVALUETYPE)
48 #define FLG_ADDREG_TYPE_MASK (0xFFFF0000 | FLG_ADDREG_BINVALUETYPE)
51 static const WCHAR HKCR
[] = {'H','K','C','R',0};
52 static const WCHAR HKCU
[] = {'H','K','C','U',0};
53 static const WCHAR HKLM
[] = {'H','K','L','M',0};
54 static const WCHAR HKU
[] = {'H','K','U',0};
55 static const WCHAR HKR
[] = {'H','K','R',0};
57 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};
58 static const WCHAR HKCUPath
[] = {'\\','R','e','g','i','s','t','r','y','\\','U','s','e','r','\\','.','D','E','F','A','U','L','T','\\',0};
59 static const WCHAR HKLMPath
[] = {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\',0};
60 static const WCHAR HKUPath
[] = {'\\','R','e','g','i','s','t','r','y','\\','U','s','e','r','\\',0};
62 static const WCHAR AddReg
[] = {'A','d','d','R','e','g',0};
63 static const WCHAR DelReg
[] = {'D','e','l','R','e','g',0};
65 /* FUNCTIONS ****************************************************************/
68 GetRootKey (PWCHAR Name
)
70 if (!strcmpiW (Name
, HKCR
))
72 strcpyW (Name
, HKCRPath
);
76 if (!strcmpiW (Name
, HKCU
))
78 strcpyW (Name
, HKCUPath
);
82 if (!strcmpiW (Name
, HKLM
))
84 strcpyW (Name
, HKLMPath
);
88 if (!strcmpiW (Name
, HKU
))
90 strcpyW (Name
, HKUPath
);
95 if (!strcmpiW (Name
, HKR
))
103 /***********************************************************************
106 * Append a multisz string to a multisz registry value.
113 IN SIZE_T StringSize
)
123 Error
= RegQueryValueExW (
130 if ((Error
!= ERROR_SUCCESS
) ||
131 (Type
!= REG_MULTI_SZ
))
134 Buffer
= malloc ((Size
+ StringSize
) * sizeof(WCHAR
));
138 Error
= RegQueryValueExW (
145 if (Error
!= ERROR_SUCCESS
)
148 /* compare each string against all the existing ones */
150 while (*Strings
!= 0)
152 len
= strlenW(Strings
) + 1;
154 for (p
= Buffer
; *p
!= 0; p
+= strlenW(p
) + 1)
155 if (!strcmpiW(p
, Strings
))
158 if (*p
== 0) /* not found, need to append it */
160 memcpy (p
, Strings
, len
);
169 DPRINT ("setting value %S to %S\n", ValueName
, Buffer
);
176 (ULONG
)Total
* sizeof(WCHAR
));
184 /***********************************************************************
187 * Perform an add/delete registry operation depending on the flags.
193 IN PINFCONTEXT Context
,
196 WCHAR EmptyStr
= (CHAR
)0;
201 if (Flags
& FLG_ADDREG_DELVAL
) /* deletion */
205 RegDeleteValueW (KeyHandle
, ValueName
);
209 RegDeleteKeyW (KeyHandle
, NULL
);
215 if (Flags
& FLG_ADDREG_KEYONLY
)
218 if (Flags
& (FLG_ADDREG_NOCLOBBER
| FLG_ADDREG_OVERWRITEONLY
))
220 Error
= RegQueryValueExW (
227 if ((Error
== ERROR_SUCCESS
) &&
228 (Flags
& FLG_ADDREG_NOCLOBBER
))
231 if ((Error
!= ERROR_SUCCESS
) &&
232 (Flags
& FLG_ADDREG_OVERWRITEONLY
))
236 switch (Flags
& FLG_ADDREG_TYPE_MASK
)
238 case FLG_ADDREG_TYPE_SZ
:
242 case FLG_ADDREG_TYPE_MULTI_SZ
:
246 case FLG_ADDREG_TYPE_EXPAND_SZ
:
247 Type
= REG_EXPAND_SZ
;
250 case FLG_ADDREG_TYPE_BINARY
:
254 case FLG_ADDREG_TYPE_DWORD
:
258 case FLG_ADDREG_TYPE_NONE
:
267 if (!(Flags
& FLG_ADDREG_BINVALUETYPE
) ||
268 (Type
== REG_DWORD
&& InfHostGetFieldCount (Context
) == 5))
272 if (Type
== REG_MULTI_SZ
)
274 if (InfHostGetMultiSzField (Context
, 5, NULL
, 0, &Size
) != 0)
279 Str
= malloc (Size
* sizeof(WCHAR
));
283 InfHostGetMultiSzField (Context
, 5, Str
, (ULONG
)Size
, NULL
);
286 if (Flags
& FLG_ADDREG_APPEND
)
300 /* else fall through to normal string handling */
304 if (InfHostGetStringField (Context
, 5, NULL
, 0, &Size
) != 0)
309 Str
= malloc (Size
* sizeof(WCHAR
));
313 InfHostGetStringField (Context
, 5, Str
, (ULONG
)Size
, NULL
);
317 if (Type
== REG_DWORD
)
319 ULONG dw
= Str
? strtoulW (Str
, NULL
, 0) : 0;
321 DPRINT("setting dword %S to %x\n", ValueName
, dw
);
333 DPRINT("setting value %S to %S\n", ValueName
, Str
);
343 (ULONG
)Size
* sizeof(WCHAR
));
353 (ULONG
)sizeof(WCHAR
));
358 else /* get the binary data */
362 if (InfHostGetBinaryField (Context
, 5, NULL
, 0, &Size
) != 0)
367 Data
= malloc (Size
);
371 DPRINT("setting binary data %S len %d\n", ValueName
, Size
);
372 InfHostGetBinaryField (Context
, 5, Data
, Size
, NULL
);
389 /***********************************************************************
392 * Called once for each AddReg and DelReg entry in a given section.
395 registry_callback (HINF hInf
, PWCHAR Section
, BOOL Delete
)
397 WCHAR Buffer
[MAX_INF_STRING_LENGTH
];
402 PINFCONTEXT Context
= NULL
;
407 Ok
= InfHostFindFirstLine (hInf
, Section
, NULL
, &Context
) == 0;
409 return TRUE
; /* Don't fail if the section isn't present */
411 for (;Ok
; Ok
= (InfHostFindNextLine (Context
, Context
) == 0))
414 if (InfHostGetStringField (Context
, 1, Buffer
, MAX_INF_STRING_LENGTH
, NULL
) != 0)
416 if (!GetRootKey (Buffer
))
420 Length
= strlenW (Buffer
);
421 if (InfHostGetStringField (Context
, 2, Buffer
+ Length
, MAX_INF_STRING_LENGTH
- (ULONG
)Length
, NULL
) != 0)
424 DPRINT("KeyName: <%S>\n", Buffer
);
428 Flags
= FLG_ADDREG_DELVAL
;
433 if (InfHostGetIntField (Context
, 4, (INT
*)&Flags
) != 0)
437 DPRINT("Flags: 0x%x\n", Flags
);
439 if (Delete
|| (Flags
& FLG_ADDREG_OVERWRITEONLY
))
441 if (RegOpenKeyW (NULL
, Buffer
, &KeyHandle
) != ERROR_SUCCESS
)
443 DPRINT("RegOpenKey(%S) failed\n", Buffer
);
444 continue; /* ignore if it doesn't exist */
449 if (RegCreateKeyW (NULL
, Buffer
, &KeyHandle
) != ERROR_SUCCESS
)
451 DPRINT("RegCreateKey(%S) failed\n", Buffer
);
457 if (InfHostGetStringField (Context
, 3, Buffer
, MAX_INF_STRING_LENGTH
, NULL
) == 0)
467 if (!do_reg_operation (KeyHandle
, ValuePtr
, Context
, Flags
))
473 InfHostFreeContext(Context
);
480 ImportRegistryFile(PCHAR FileName
)
485 /* Load inf file from install media. */
486 if (InfHostOpenFile(&hInf
, FileName
, 0, &ErrorLine
) != 0)
488 DPRINT1 ("InfHostOpenFile(%s) failed\n", FileName
);
492 if (!registry_callback (hInf
, (PWCHAR
)DelReg
, TRUE
))
494 DPRINT1 ("registry_callback() for DelReg failed\n");
497 if (!registry_callback (hInf
, (PWCHAR
)AddReg
, FALSE
))
499 DPRINT1 ("registry_callback() for AddReg failed\n");
502 InfHostCloseFile (hInf
);