ReactOS  0.4.14-dev-606-g14ebc0b
reginf.c
Go to the documentation of this file.
1 /*
2  * ReactOS kernel
3  * Copyright (C) 2003, 2006 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 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.
18  */
19 /*
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
25  * Hervé Poussineau
26  */
27 
28 /* INCLUDES *****************************************************************/
29 
30 #include <string.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33 
34 #define NDEBUG
35 #include "mkhive.h"
36 
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
46 
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)
54 
55 
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};
62 
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};
68 
69 static const WCHAR AddReg[] = {'A','d','d','R','e','g',0};
70 static const WCHAR DelReg[] = {'D','e','l','R','e','g',0};
71 
72 /* FUNCTIONS ****************************************************************/
73 
74 static BOOL
76 {
77  if (!strcmpiW(Name, HKCR))
78  {
80  return TRUE;
81  }
82 
83  if (!strcmpiW(Name, HKCU))
84  {
86  return TRUE;
87  }
88 
89  if (!strcmpiW(Name, HKLM))
90  {
92  return TRUE;
93  }
94 
95  if (!strcmpiW(Name, HKU))
96  {
98  return TRUE;
99  }
100 
101  if (!strcmpiW(Name, BCD))
102  {
103  strcpyW(Name, BCDPath);
104  return TRUE;
105  }
106 
107 #if 0
108  if (!strcmpiW(Name, HKR))
109  return FALSE;
110 #endif
111 
112  return FALSE;
113 }
114 
115 
116 /***********************************************************************
117  * append_multi_sz_value
118  *
119  * Append a multisz string to a multisz registry value.
120  */
121 // NOTE: Synced with setupapi/install.c ; see also usetup/registry.c
122 static VOID
124  IN HKEY KeyHandle,
126  IN PCWSTR Strings,
127  IN ULONG StringSize) // In characters
128 {
129  ULONG Size, Total; // In bytes
130  ULONG Type;
131  PWCHAR Buffer;
132  PWCHAR p;
133  size_t len;
134  LONG Error;
135 
137  ValueName,
138  NULL,
139  &Type,
140  NULL,
141  &Size);
142  if ((Error != ERROR_SUCCESS) || (Type != REG_MULTI_SZ))
143  return;
144 
145  Buffer = malloc(Size + StringSize * sizeof(WCHAR));
146  if (Buffer == NULL)
147  return;
148 
150  ValueName,
151  NULL,
152  NULL,
153  (PUCHAR)Buffer,
154  &Size);
155  if (Error != ERROR_SUCCESS)
156  goto done;
157 
158  /* compare each string against all the existing ones */
159  Total = Size;
160  while (*Strings != 0)
161  {
162  len = strlenW(Strings) + 1;
163 
164  for (p = Buffer; *p != 0; p += strlenW(p) + 1)
165  if (!strcmpiW(p, Strings))
166  break;
167 
168  if (*p == 0) /* not found, need to append it */
169  {
170  memcpy(p, Strings, len * sizeof(WCHAR));
171  p[len] = 0;
172  Total += len * sizeof(WCHAR);
173  }
174  Strings += len;
175  }
176 
177  if (Total != Size)
178  {
179  DPRINT("setting value '%S' to '%S'\n", ValueName, Buffer);
181  ValueName,
182  0,
183  REG_MULTI_SZ,
184  (PUCHAR)Buffer,
185  Total + sizeof(WCHAR));
186  }
187 
188 done:
189  free(Buffer);
190 }
191 
192 
193 /***********************************************************************
194  * do_reg_operation
195  *
196  * Perform an add/delete registry operation depending on the flags.
197  */
198 static BOOL
200  IN HKEY KeyHandle,
203  IN ULONG Flags)
204 {
205  WCHAR EmptyStr = 0;
206  ULONG Type;
207  ULONG Size;
208  LONG Error;
209 
210  if (Flags & (FLG_ADDREG_DELREG_BIT | FLG_ADDREG_DELVAL)) /* deletion */
211  {
213  {
214  // NOTE: We don't currently handle deleting sub-values inside multi-strings.
216  }
217  else
218  {
220  }
221  return TRUE;
222  }
223 
225  return TRUE;
226 
228  {
230  ValueName,
231  NULL,
232  NULL,
233  NULL,
234  NULL);
235 
237  return TRUE;
238 
240  return TRUE;
241  }
242 
243  switch (Flags & FLG_ADDREG_TYPE_MASK)
244  {
245  case FLG_ADDREG_TYPE_SZ:
246  Type = REG_SZ;
247  break;
248 
250  Type = REG_MULTI_SZ;
251  break;
252 
255  break;
256 
258  Type = REG_BINARY;
259  break;
260 
262  Type = REG_DWORD;
263  break;
264 
266  Type = REG_NONE;
267  break;
268 
269  default:
270  Type = Flags >> 16;
271  break;
272  }
273 
274  if (!(Flags & FLG_ADDREG_BINVALUETYPE) ||
276  {
277  PWCHAR Str = NULL;
278 
279  if (Type == REG_MULTI_SZ)
280  {
281  if (InfHostGetMultiSzField(Context, 5, NULL, 0, &Size) != 0)
282  Size = 0;
283 
284  if (Size)
285  {
286  Str = malloc(Size * sizeof(WCHAR));
287  if (Str == NULL)
288  return FALSE;
289 
291  }
292 
293  if (Flags & FLG_ADDREG_APPEND)
294  {
295  if (Str == NULL)
296  return TRUE;
297 
298  DPRINT("append_multi_sz_value(ValueName = '%S')\n", ValueName);
300  ValueName,
301  Str,
302  Size);
303 
304  free(Str);
305  return TRUE;
306  }
307  /* else fall through to normal string handling */
308  }
309  else
310  {
311  if (InfHostGetStringField(Context, 5, NULL, 0, &Size) != 0)
312  Size = 0;
313 
314  if (Size)
315  {
316  Str = malloc(Size * sizeof(WCHAR));
317  if (Str == NULL)
318  return FALSE;
319 
321  }
322  }
323 
324  if (Type == REG_DWORD)
325  {
326  ULONG dw = Str ? strtoulW(Str, NULL, 0) : 0;
327 
328  DPRINT("setting dword '%S' to %x\n", ValueName, dw);
329 
331  ValueName,
332  0,
333  Type,
334  (const PUCHAR)&dw,
335  sizeof(ULONG));
336  }
337  else
338  {
339  DPRINT("setting value '%S' to '%S'\n", ValueName, Str);
340 
341  if (Str)
342  {
344  ValueName,
345  0,
346  Type,
347  (PVOID)Str,
348  (ULONG)(Size * sizeof(WCHAR)));
349  }
350  else
351  {
353  ValueName,
354  0,
355  Type,
356  (PVOID)&EmptyStr,
357  sizeof(WCHAR));
358  }
359  }
360  free(Str);
361  }
362  else /* get the binary data */
363  {
364  PUCHAR Data = NULL;
365 
366  if (InfHostGetBinaryField(Context, 5, NULL, 0, &Size) != 0)
367  Size = 0;
368 
369  if (Size)
370  {
371  Data = malloc(Size);
372  if (Data == NULL)
373  return FALSE;
374 
375  DPRINT("setting binary data '%S' len %d\n", ValueName, (ULONG)Size);
377  }
378 
380  ValueName,
381  0,
382  Type,
383  (PVOID)Data,
384  (ULONG)Size);
385 
386  free(Data);
387  }
388 
389  return TRUE;
390 }
391 
392 /***********************************************************************
393  * registry_callback
394  *
395  * Called once for each AddReg and DelReg entry in a given section.
396  */
397 static BOOL
399 {
401  PWCHAR ValuePtr;
402  ULONG Flags;
403  size_t Length;
404 
406  HKEY KeyHandle;
407  BOOL Ok;
408 
409  Ok = InfHostFindFirstLine(hInf, Section, NULL, &Context) == 0;
410  if (!Ok)
411  return TRUE; /* Don't fail if the section isn't present */
412 
413  for (Ok = TRUE; Ok; Ok = (InfHostFindNextLine(Context, Context) == 0))
414  {
415  /* Get root */
416  if (InfHostGetStringField(Context, 1, Buffer, sizeof(Buffer)/sizeof(WCHAR), NULL) != 0)
417  continue;
418  if (!get_root_key(Buffer))
419  continue;
420 
421  /* Get key */
422  Length = strlenW(Buffer);
423  if (InfHostGetStringField(Context, 2, Buffer + Length, sizeof(Buffer)/sizeof(WCHAR) - (ULONG)Length, NULL) != 0)
424  *Buffer = 0;
425 
426  DPRINT("KeyName: <%S>\n", Buffer);
427 
428  /* Get flags */
429  if (InfHostGetIntField(Context, 4, (INT*)&Flags) != 0)
430  Flags = 0;
431 
432  if (Delete)
433  {
434  if (!Flags)
436  else if (!(Flags & FLG_ADDREG_DELREG_BIT))
437  continue; /* ignore this entry */
438  }
439  else
440  {
442  continue; /* ignore this entry */
443  }
444 
445  DPRINT("Flags: 0x%x\n", Flags);
446 
448  {
450  {
451  DPRINT("RegOpenKey(%S) failed\n", Buffer);
452  continue; /* ignore if it doesn't exist */
453  }
454  }
455  else
456  {
458  {
459  DPRINT("RegCreateKey(%S) failed\n", Buffer);
460  continue;
461  }
462  }
463 
464  /* Get value name */
465  if (InfHostGetStringField(Context, 3, Buffer, sizeof(Buffer)/sizeof(WCHAR), NULL) == 0)
466  {
467  ValuePtr = Buffer;
468  }
469  else
470  {
471  ValuePtr = NULL;
472  }
473 
474  /* And now do it */
475  if (!do_reg_operation(KeyHandle, ValuePtr, Context, Flags))
476  {
478  return FALSE;
479  }
480 
482  }
483 
485 
486  return TRUE;
487 }
488 
489 
490 BOOL
492 {
493  HINF hInf;
494  ULONG ErrorLine;
495 
496  /* Load inf file from install media. */
497  if (InfHostOpenFile(&hInf, FileName, 0, &ErrorLine) != 0)
498  {
499  DPRINT1("InfHostOpenFile(%s) failed\n", FileName);
500  return FALSE;
501  }
502 
503  if (!registry_callback(hInf, (PWCHAR)DelReg, TRUE))
504  {
505  DPRINT1("registry_callback() for DelReg failed\n");
506  InfHostCloseFile(hInf);
507  return FALSE;
508  }
509 
510  if (!registry_callback(hInf, (PWCHAR)AddReg, FALSE))
511  {
512  DPRINT1("registry_callback() for AddReg failed\n");
513  InfHostCloseFile(hInf);
514  return FALSE;
515  }
516 
517  InfHostCloseFile(hInf);
518  return TRUE;
519 }
520 
521 /* EOF */
static const WCHAR HKCR[]
Definition: reginf.c:56
signed char * PCHAR
Definition: retypes.h:7
int InfHostFindFirstLine(HINF InfHandle, const WCHAR *Section, const WCHAR *Key, PINFCONTEXT *Context)
Definition: infhostget.c:18
const uint16_t * PCWSTR
Definition: typedefs.h:55
#define IN
Definition: typedefs.h:38
static const WCHAR BCDPath[]
Definition: reginf.c:67
#define FLG_ADDREG_NOCLOBBER
Definition: reginf.c:38
#define FLG_ADDREG_KEYONLY
Definition: reginf.c:41
#define TRUE
Definition: types.h:120
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
static const WCHAR HKCUPath[]
Definition: reginf.c:64
Type
Definition: Type.h:6
static const WCHAR BCD[]
Definition: reginf.c:61
#define ERROR_SUCCESS
Definition: deptool.c:10
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4711
#define REG_BINARY
Definition: nt_native.h:1496
void InfHostCloseFile(HINF InfHandle)
Definition: infhostgen.c:283
unsigned char * PUCHAR
Definition: retypes.h:3
#define free
Definition: debug_ros.c:5
int InfHostGetIntField(PINFCONTEXT Context, ULONG FieldIndex, INT *IntegerValue)
Definition: infhostget.c:139
LONG WINAPI RegDeleteKeyW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey)
Definition: reg.c:1237
#define FLG_ADDREG_TYPE_EXPAND_SZ
Definition: reginf.c:49
#define FLG_ADDREG_KEYONLY_COMMON
Definition: reginf.c:43
uint16_t * PWCHAR
Definition: typedefs.h:54
static const WCHAR HKU[]
Definition: reginf.c:59
int32_t INT
Definition: typedefs.h:56
#define FLG_ADDREG_TYPE_MASK
Definition: reginf.c:53
_In_ PUNICODE_STRING ValueName
Definition: cmfuncs.h:264
#define FLG_ADDREG_BINVALUETYPE
Definition: reginf.c:37
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define FLG_ADDREG_TYPE_DWORD
Definition: reginf.c:51
#define FLG_DELREG_KEYONLY_COMMON
Definition: reginf.c:44
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
static VOID append_multi_sz_value(IN HKEY KeyHandle, IN PCWSTR ValueName, IN PCWSTR Strings, IN ULONG StringSize)
Definition: reginf.c:123
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
static BOOL do_reg_operation(IN HKEY KeyHandle, IN PCWSTR ValueName, IN PINFCONTEXT Context, IN ULONG Flags)
Definition: reginf.c:199
LONG WINAPI RegOpenKeyW(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3296
#define REG_MULTI_SZ
Definition: nt_native.h:1501
#define FLG_ADDREG_APPEND
Definition: reginf.c:40
static const WCHAR HKLMPath[]
Definition: reginf.c:65
smooth NULL
Definition: ftsmooth.c:416
#define FLG_ADDREG_OVERWRITEONLY
Definition: reginf.c:42
void DPRINT(...)
Definition: polytest.cpp:61
int InfHostFindNextLine(PINFCONTEXT ContextIn, PINFCONTEXT ContextOut)
Definition: infhostget.c:39
Definition: bufpool.h:45
static const WCHAR HKLM[]
Definition: reginf.c:58
static const WCHAR HKR[]
Definition: reginf.c:60
LONG WINAPI RegSetValueExW(_In_ HKEY hKey, _In_ LPCWSTR lpValueName, _In_ DWORD Reserved, _In_ DWORD dwType, _In_ CONST BYTE *lpData, _In_ DWORD cbData)
Definition: reg.c:4895
#define MAX_INF_STRING_LENGTH
Definition: infsupp.h:34
#define FLG_ADDREG_TYPE_NONE
Definition: reginf.c:52
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4116
static const WCHAR HKUPath[]
Definition: reginf.c:66
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define FLG_ADDREG_TYPE_SZ
Definition: reginf.c:47
int InfHostGetMultiSzField(PINFCONTEXT Context, ULONG FieldIndex, WCHAR *ReturnBuffer, ULONG ReturnBufferSize, ULONG *RequiredSize)
Definition: infhostget.c:159
BOOL Error
Definition: chkdsk.c:66
REFIID LPVOID DWORD dw
Definition: atlbase.h:40
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
static const WCHAR Strings[]
Definition: reg.c:35
#define FLG_ADDREG_TYPE_MULTI_SZ
Definition: reginf.c:48
int InfHostGetStringField(PINFCONTEXT Context, ULONG FieldIndex, WCHAR *ReturnBuffer, ULONG ReturnBufferSize, ULONG *RequiredSize)
Definition: infhostget.c:182
static const WCHAR DelReg[]
Definition: reginf.c:70
BOOL ImportRegistryFile(PCHAR FileName)
Definition: reginf.c:491
#define FLG_ADDREG_TYPE_BINARY
Definition: reginf.c:50
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
LONG WINAPI RegCreateKeyW(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:1199
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
#define strcmpiW(s1, s2)
Definition: unicode.h:39
static const WCHAR HKCU[]
Definition: reginf.c:57
WINE_UNICODE_INLINE WCHAR * strcpyW(WCHAR *dst, const WCHAR *src)
Definition: unicode.h:219
LONG WINAPI RegDeleteValueW(HKEY hKey, LPCWSTR lpValueName)
Definition: reg.c:2355
static const WCHAR AddReg[]
Definition: reginf.c:69
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
void InfHostFreeContext(PINFCONTEXT Context)
Definition: infhostget.c:244
static BOOL registry_callback(HINF hInf, PCWSTR Section, BOOL Delete)
Definition: reginf.c:398
LONG InfHostGetFieldCount(PINFCONTEXT Context)
Definition: infhostget.c:109
#define DPRINT1
Definition: precomp.h:8
static const WCHAR HKCRPath[]
Definition: reginf.c:63
#define FLG_ADDREG_DELREG_BIT
Definition: reginf.c:45
unsigned int ULONG
Definition: retypes.h:1
#define malloc
Definition: debug_ros.c:4
#define strtoulW(s1, s2, b)
Definition: unicode.h:41
#define REG_NONE
Definition: nt_native.h:1492
GLfloat GLfloat p
Definition: glext.h:8902
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
#define REG_DWORD
Definition: sdbapi.c:596
BOOL Delete(LPCTSTR ServiceName)
Definition: delete.c:12
int InfHostOpenFile(PHINF InfHandle, const CHAR *FileName, LANGID LanguageId, ULONG *ErrorLine)
Definition: infhostgen.c:128
static BOOL get_root_key(PWCHAR Name)
Definition: reginf.c:75
#define FLG_ADDREG_DELVAL
Definition: reginf.c:39
int InfHostGetBinaryField(PINFCONTEXT Context, ULONG FieldIndex, UCHAR *ReturnBuffer, ULONG ReturnBufferSize, ULONG *RequiredSize)
Definition: infhostget.c:116
#define REG_SZ
Definition: layer.c:22