/*
* ReactOS kernel
- * Copyright (C) 2003 ReactOS Team
+ * Copyright (C) 2003, 2006 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-/* $Id: reginf.c,v 1.3 2003/05/18 12:12:07 ekohl Exp $
- * COPYRIGHT: See COPYING in the top level directory
+/* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS hive maker
* FILE: tools/mkhive/reginf.h
* PURPOSE: Inf file import code
* PROGRAMMER: Eric Kohl
+ * Hervé Poussineau
*/
/* INCLUDES *****************************************************************/
#include <string.h>
#include <stdlib.h>
+#include <stdio.h>
+#define NDEBUG
#include "mkhive.h"
-#include "registry.h"
-#include "infcache.h"
-
-
#define FLG_ADDREG_BINVALUETYPE 0x00000001
#define FLG_ADDREG_NOCLOBBER 0x00000002
/* FUNCTIONS ****************************************************************/
static BOOL
-GetRootKey (PCHAR Name)
+GetRootKey (PWCHAR Name)
{
- if (!strcasecmp (Name, "HKCR"))
- {
- strcpy (Name, "\\Registry\\Machine\\SOFTWARE\\Classes\\");
- return TRUE;
- }
-
- if (!strcasecmp (Name, "HKCU"))
- {
- strcpy (Name, "\\Registry\\User\\.DEFAULT\\");
- return TRUE;
- }
-
- if (!strcasecmp (Name, "HKLM"))
- {
- strcpy (Name, "\\Registry\\Machine\\");
- return TRUE;
- }
-
- if (!strcasecmp (Name, "HKU"))
- {
- strcpy (Name, "\\Registry\\User\\");
- return TRUE;
- }
+ if (!wcsicmp (Name, L"HKCR"))
+ {
+ wcscpy (Name, L"\\Registry\\Machine\\SOFTWARE\\Classes\\");
+ return TRUE;
+ }
+
+ if (!wcsicmp (Name, L"HKCU"))
+ {
+ wcscpy (Name, L"\\Registry\\User\\.DEFAULT\\");
+ return TRUE;
+ }
+
+ if (!wcsicmp (Name, L"HKLM"))
+ {
+ wcscpy (Name, L"\\Registry\\Machine\\");
+ return TRUE;
+ }
+
+ if (!wcsicmp (Name, L"HKU"))
+ {
+ wcscpy (Name, L"\\Registry\\User\\");
+ return TRUE;
+ }
#if 0
- if (!strcasecmp (Name, "HKR"))
- return FALSE;
+ if (!wcsicmp (Name, L"HKR"))
+ return FALSE;
#endif
return FALSE;
/***********************************************************************
- * append_multi_sz_value
+ * AppendMultiSzValue
*
* Append a multisz string to a multisz registry value.
*/
-#if 0
-static void
-append_multi_sz_value (HANDLE hkey,
- const WCHAR *value,
- const WCHAR *strings,
- DWORD str_size )
+static VOID
+AppendMultiSzValue (
+ IN HKEY KeyHandle,
+ IN PWCHAR ValueName,
+ IN PWCHAR Strings,
+ IN SIZE_T StringSize)
{
- DWORD size, type, total;
- WCHAR *buffer, *p;
-
- if (RegQueryValueExW( hkey, value, NULL, &type, NULL, &size )) return;
- if (type != REG_MULTI_SZ) return;
-
- if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (size + str_size) * sizeof(WCHAR) ))) return;
- if (RegQueryValueExW( hkey, value, NULL, NULL, (BYTE *)buffer, &size )) goto done;
-
- /* compare each string against all the existing ones */
- total = size;
- while (*strings)
- {
- int len = strlenW(strings) + 1;
-
- for (p = buffer; *p; p += strlenW(p) + 1)
- if (!strcmpiW( p, strings )) break;
-
- if (!*p) /* not found, need to append it */
- {
- memcpy( p, strings, len * sizeof(WCHAR) );
- p[len] = 0;
- total += len;
- }
- strings += len;
- }
- if (total != size)
- {
- TRACE( "setting value %s to %s\n", debugstr_w(value), debugstr_w(buffer) );
- RegSetValueExW( hkey, value, 0, REG_MULTI_SZ, (BYTE *)buffer, total );
- }
- done:
- HeapFree( GetProcessHeap(), 0, buffer );
-}
-#endif
+ SIZE_T Size;
+ ULONG Type;
+ size_t Total;
+ PWCHAR Buffer;
+ PWCHAR p;
+ size_t len;
+ LONG Error;
+
+ Error = RegQueryValueExW (
+ KeyHandle,
+ ValueName,
+ NULL,
+ &Type,
+ NULL,
+ &Size);
+ if ((Error != ERROR_SUCCESS) ||
+ (Type != REG_MULTI_SZ))
+ return;
+
+ Buffer = malloc (Size + (StringSize * sizeof(WCHAR)));
+ if (Buffer == NULL)
+ return;
+
+ Error = RegQueryValueExW (
+ KeyHandle,
+ ValueName,
+ NULL,
+ NULL,
+ (PUCHAR)Buffer,
+ &Size);
+ if (Error != ERROR_SUCCESS)
+ goto done;
+
+ /* compare each string against all the existing ones */
+ Total = Size;
+ while (*Strings != 0)
+ {
+ len = wcslen (Strings) + 1;
+
+ for (p = Buffer; *p != 0; p += wcslen (p) + 1)
+ if (!wcsicmp (p, Strings))
+ break;
+
+ if (*p == 0) /* not found, need to append it */
+ {
+ memcpy (p, Strings, len * sizeof(WCHAR));
+ p[len] = 0;
+ Total += len * sizeof(WCHAR);
+ }
+ Strings += len;
+ }
-/***********************************************************************
- * delete_multi_sz_value
- *
- * Remove a string from a multisz registry value.
- */
-#if 0
-static void delete_multi_sz_value( HKEY hkey, const WCHAR *value, const WCHAR *string )
-{
- DWORD size, type;
- WCHAR *buffer, *src, *dst;
-
- if (RegQueryValueExW( hkey, value, NULL, &type, NULL, &size )) return;
- if (type != REG_MULTI_SZ) return;
- /* allocate double the size, one for value before and one for after */
- if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size * 2 * sizeof(WCHAR) ))) return;
- if (RegQueryValueExW( hkey, value, NULL, NULL, (BYTE *)buffer, &size )) goto done;
- src = buffer;
- dst = buffer + size;
- while (*src)
- {
- int len = strlenW(src) + 1;
- if (strcmpiW( src, string ))
- {
- memcpy( dst, src, len * sizeof(WCHAR) );
- dst += len;
- }
- src += len;
- }
- *dst++ = 0;
- if (dst != buffer + 2*size) /* did we remove something? */
- {
- TRACE( "setting value %s to %s\n", debugstr_w(value), debugstr_w(buffer + size) );
- RegSetValueExW( hkey, value, 0, REG_MULTI_SZ,
- (BYTE *)(buffer + size), dst - (buffer + size) );
- }
- done:
- HeapFree( GetProcessHeap(), 0, buffer );
+ if (Total != Size)
+ {
+ DPRINT ("setting value %S to %S\n", ValueName, Buffer);
+ RegSetValueExW (
+ KeyHandle,
+ ValueName,
+ 0,
+ REG_MULTI_SZ,
+ (PUCHAR)Buffer,
+ (ULONG)Total);
+ }
+
+done:
+ free (Buffer);
}
-#endif
+
/***********************************************************************
* do_reg_operation
* Perform an add/delete registry operation depending on the flags.
*/
static BOOL
-do_reg_operation(HKEY KeyHandle,
- PCHAR ValueName,
- PINFCONTEXT Context,
- ULONG Flags)
+do_reg_operation(
+ IN HKEY KeyHandle,
+ IN PWCHAR ValueName,
+ IN PINFCONTEXT Context,
+ IN ULONG Flags)
{
- CHAR EmptyStr = (CHAR)0;
- ULONG Type;
- ULONG Size;
-// NTSTATUS Status;
+ WCHAR EmptyStr = (WCHAR)0;
+ ULONG Type;
+ ULONG Size;
+ LONG Error;
- if (Flags & FLG_ADDREG_DELVAL) /* deletion */
- {
-#if 0
- if (ValueName)
+ if (Flags & FLG_ADDREG_DELVAL) /* deletion */
{
- RegDeleteValueW( hkey, value );
- }
- else
- {
- RegDeleteKeyW( hkey, NULL );
- }
-#endif
- return TRUE;
- }
-
- if (Flags & FLG_ADDREG_KEYONLY)
- return TRUE;
-
-#if 0
- if (Flags & (FLG_ADDREG_NOCLOBBER | FLG_ADDREG_OVERWRITEONLY))
- {
- BOOL exists = !RegQueryValueExW( hkey, value, NULL, NULL, NULL, NULL );
- if (exists && (flags & FLG_ADDREG_NOCLOBBER))
- return TRUE;
- if (!exists & (flags & FLG_ADDREG_OVERWRITEONLY))
- return TRUE;
- }
-#endif
-
- switch (Flags & FLG_ADDREG_TYPE_MASK)
- {
- case FLG_ADDREG_TYPE_SZ:
- Type = REG_SZ;
- break;
-
- case FLG_ADDREG_TYPE_MULTI_SZ:
- Type = REG_MULTI_SZ;
- break;
+ if (ValueName)
+ {
+ RegDeleteValueW (KeyHandle, ValueName);
+ }
+ else
+ {
+ RegDeleteKeyW (KeyHandle, NULL);
+ }
- case FLG_ADDREG_TYPE_EXPAND_SZ:
- Type = REG_EXPAND_SZ;
- break;
-
- case FLG_ADDREG_TYPE_BINARY:
- Type = REG_BINARY;
- break;
-
- case FLG_ADDREG_TYPE_DWORD:
- Type = REG_DWORD;
- break;
-
- case FLG_ADDREG_TYPE_NONE:
- Type = REG_NONE;
- break;
+ return TRUE;
+ }
- default:
- Type = Flags >> 16;
- break;
- }
+ if (Flags & FLG_ADDREG_KEYONLY)
+ return TRUE;
- if (!(Flags & FLG_ADDREG_BINVALUETYPE) ||
- (Type == REG_DWORD && InfGetFieldCount (Context) == 5))
- {
- PCHAR Str = NULL;
+ if (Flags & (FLG_ADDREG_NOCLOBBER | FLG_ADDREG_OVERWRITEONLY))
+ {
+ Error = RegQueryValueExW (
+ KeyHandle,
+ ValueName,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if ((Error == ERROR_SUCCESS) &&
+ (Flags & FLG_ADDREG_NOCLOBBER))
+ return TRUE;
+
+ if ((Error != ERROR_SUCCESS) &&
+ (Flags & FLG_ADDREG_OVERWRITEONLY))
+ return TRUE;
+ }
- if (Type == REG_MULTI_SZ)
+ switch (Flags & FLG_ADDREG_TYPE_MASK)
{
- if (!InfGetMultiSzField (Context, 5, NULL, 0, &Size))
- Size = 0;
+ case FLG_ADDREG_TYPE_SZ:
+ Type = REG_SZ;
+ break;
- if (Size)
- {
- Str = malloc (Size);
- if (Str == NULL)
- return FALSE;
+ case FLG_ADDREG_TYPE_MULTI_SZ:
+ Type = REG_MULTI_SZ;
+ break;
- InfGetMultiSzField (Context, 5, Str, Size, NULL);
- }
+ case FLG_ADDREG_TYPE_EXPAND_SZ:
+ Type = REG_EXPAND_SZ;
+ break;
- if (Flags & FLG_ADDREG_APPEND)
- {
- if (Str == NULL)
- return TRUE;
+ case FLG_ADDREG_TYPE_BINARY:
+ Type = REG_BINARY;
+ break;
-// append_multi_sz_value( hkey, value, str, size );
+ case FLG_ADDREG_TYPE_DWORD:
+ Type = REG_DWORD;
+ break;
- free (Str);
- return TRUE;
- }
- /* else fall through to normal string handling */
- }
- else
- {
- if (!InfGetStringField (Context, 5, NULL, 0, &Size))
- Size = 0;
+ case FLG_ADDREG_TYPE_NONE:
+ Type = REG_NONE;
+ break;
- if (Size)
- {
- Str = malloc (Size);
- if (Str == NULL)
- return FALSE;
-
- InfGetStringField (Context, 5, Str, Size, NULL);
- }
+ default:
+ Type = Flags >> 16;
+ break;
}
- if (Type == REG_DWORD)
+ if (!(Flags & FLG_ADDREG_BINVALUETYPE) ||
+ (Type == REG_DWORD && InfHostGetFieldCount (Context) == 5))
{
- ULONG dw = Str ? strtol (Str, NULL, 0) : 0;
-
- DPRINT("setting dword %s to %lx\n", ValueName, dw);
-
- RegSetValue (KeyHandle,
- ValueName,
- Type,
- (PVOID)&dw,
- sizeof(ULONG));
+ WCHAR *Str = NULL;
+
+ if (Type == REG_MULTI_SZ)
+ {
+ if (InfHostGetMultiSzField (Context, 5, NULL, 0, &Size) != 0)
+ Size = 0;
+
+ if (Size)
+ {
+ Str = malloc (Size * sizeof(WCHAR));
+ if (Str == NULL)
+ return FALSE;
+
+ InfHostGetMultiSzField (Context, 5, Str, (ULONG)Size, NULL);
+ }
+
+ if (Flags & FLG_ADDREG_APPEND)
+ {
+ if (Str == NULL)
+ return TRUE;
+
+ AppendMultiSzValue (
+ KeyHandle,
+ ValueName,
+ Str,
+ Size);
+
+ free (Str);
+ return TRUE;
+ }
+ /* else fall through to normal string handling */
+ }
+ else
+ {
+ if (InfHostGetStringField (Context, 5, NULL, 0, &Size) != 0)
+ Size = 0;
+
+ if (Size)
+ {
+ Str = malloc (Size * sizeof(WCHAR));
+ if (Str == NULL)
+ return FALSE;
+
+ InfHostGetStringField (Context, 5, Str, (ULONG)Size, NULL);
+ }
+ }
+
+ if (Type == REG_DWORD)
+ {
+ ULONG dw = Str ? wcstoul (Str, NULL, 0) : 0;
+
+ DPRINT("setting dword %S to %x\n", ValueName, dw);
+
+ RegSetValueExW (
+ KeyHandle,
+ ValueName,
+ 0,
+ Type,
+ (const PUCHAR)&dw,
+ sizeof(ULONG));
+ }
+ else
+ {
+ DPRINT("setting value %S to %S\n", ValueName, Str);
+
+ if (Str)
+ {
+ RegSetValueExW (
+ KeyHandle,
+ ValueName,
+ 0,
+ Type,
+ (PVOID)Str,
+ (ULONG)Size * sizeof(WCHAR));
+ }
+ else
+ {
+ RegSetValueExW (
+ KeyHandle,
+ ValueName,
+ 0,
+ Type,
+ (PVOID)&EmptyStr,
+ (ULONG)sizeof(WCHAR));
+ }
+ }
+ free (Str);
}
- else
+ else /* get the binary data */
{
- DPRINT ("setting value %wZ to %S\n", ValueName, Str);
-
- if (Str)
- {
- RegSetValue (KeyHandle,
- ValueName,
- Type,
- (PVOID)Str,
- Size);
- }
- else
- {
- RegSetValue (KeyHandle,
- ValueName,
- Type,
- (PVOID)&EmptyStr,
- sizeof(CHAR));
- }
+ PUCHAR Data = NULL;
+
+ if (InfHostGetBinaryField (Context, 5, NULL, 0, &Size) != 0)
+ Size = 0;
+
+ if (Size)
+ {
+ Data = malloc (Size);
+ if (Data == NULL)
+ return FALSE;
+
+ DPRINT("setting binary data %s len %d\n", ValueName, Size);
+ InfHostGetBinaryField (Context, 5, Data, Size, NULL);
+ }
+
+ RegSetValueExW (
+ KeyHandle,
+ ValueName,
+ 0,
+ Type,
+ (PVOID)Data,
+ (ULONG)Size);
+
+ free (Data);
}
- free (Str);
- }
- else /* get the binary data */
- {
- PUCHAR Data = NULL;
-
- if (!InfGetBinaryField (Context, 5, NULL, 0, &Size))
- Size = 0;
-
- if (Size)
- {
- Data = malloc (Size);
- if (Data == NULL)
- return FALSE;
-
- DPRINT("setting binary data %s len %lu\n", ValueName, Size);
- InfGetBinaryField (Context, 5, Data, Size, NULL);
- }
-
- RegSetValue (KeyHandle,
- ValueName,
- Type,
- (PVOID)Data,
- Size);
-
- free (Data);
- }
- return TRUE;
+ return TRUE;
}
-
/***********************************************************************
* registry_callback
*
* Called once for each AddReg and DelReg entry in a given section.
*/
static BOOL
-registry_callback (HINF hInf, PCHAR Section, BOOL Delete)
+registry_callback (HINF hInf, PWCHAR Section, BOOL Delete)
{
- CHAR Buffer[MAX_INF_STRING_LENGTH];
- PCHAR ValuePtr;
- ULONG Flags;
- ULONG Length;
+ WCHAR Buffer[MAX_INF_STRING_LENGTH];
+ PWCHAR ValuePtr;
+ ULONG Flags;
+ size_t Length;
- INFCONTEXT Context;
- HKEY KeyHandle;
- BOOL Ok;
+ PINFCONTEXT Context = NULL;
+ HKEY KeyHandle;
+ BOOL Ok;
- Ok = InfFindFirstLine (hInf, Section, NULL, &Context);
- if (!Ok)
- return FALSE;
+ Ok = InfHostFindFirstLine (hInf, Section, NULL, &Context) == 0;
+ if (!Ok)
+ return TRUE; /* Don't fail if the section isn't present */
- for (;Ok; Ok = InfFindNextLine (&Context, &Context))
- {
- /* get root */
- if (!InfGetStringField (&Context, 1, Buffer, MAX_INF_STRING_LENGTH, NULL))
- continue;
- if (!GetRootKey (Buffer))
- continue;
+ for (;Ok; Ok = (InfHostFindNextLine (Context, Context) == 0))
+ {
+ /* get root */
+ if (InfHostGetStringField (Context, 1, Buffer, MAX_INF_STRING_LENGTH, NULL) != 0)
+ continue;
+ if (!GetRootKey (Buffer))
+ continue;
+
+ /* get key */
+ Length = wcslen (Buffer);
+ if (InfHostGetStringField (Context, 2, Buffer + Length, MAX_INF_STRING_LENGTH - (ULONG)Length, NULL) != 0)
+ *Buffer = 0;
+
+ DPRINT("KeyName: <%S>\n", Buffer);
+
+ if (Delete)
+ {
+ Flags = FLG_ADDREG_DELVAL;
+ }
+ else
+ {
+ /* get flags */
+ if (InfHostGetIntField (Context, 4, &Flags) != 0)
+ Flags = 0;
+ }
+
+ DPRINT("Flags: 0x%x\n", Flags);
+
+ if (Delete || (Flags & FLG_ADDREG_OVERWRITEONLY))
+ {
+ if (RegOpenKeyW (NULL, Buffer, &KeyHandle) != ERROR_SUCCESS)
+ {
+ DPRINT("RegOpenKey(%S) failed\n", Buffer);
+ continue; /* ignore if it doesn't exist */
+ }
+ }
+ else
+ {
+ if (RegCreateKeyW (NULL, Buffer, &KeyHandle) != ERROR_SUCCESS)
+ {
+ DPRINT("RegCreateKey(%S) failed\n", Buffer);
+ continue;
+ }
+ }
+
+ /* get value name */
+ if (InfHostGetStringField (Context, 3, Buffer, MAX_INF_STRING_LENGTH, NULL) == 0)
+ {
+ ValuePtr = Buffer;
+ }
+ else
+ {
+ ValuePtr = NULL;
+ }
+
+ /* and now do it */
+ if (!do_reg_operation (KeyHandle, ValuePtr, Context, Flags))
+ {
+ return FALSE;
+ }
+ }
- /* get key */
- Length = strlen (Buffer);
- if (!InfGetStringField (&Context, 2, Buffer + Length, MAX_INF_STRING_LENGTH - Length, NULL))
- *Buffer = 0;
+ InfHostFreeContext(Context);
- DPRINT("KeyName: <%s>\n", Buffer);
+ return TRUE;
+}
- /* get flags */
- if (!InfGetIntField (&Context, 4, (PLONG)&Flags))
- Flags = 0;
- DPRINT("Flags: %lx\n", Flags);
+BOOL
+ImportRegistryFile(PCHAR FileName)
+{
+ HINF hInf;
+ ULONG ErrorLine;
- if (Delete || (Flags & FLG_ADDREG_OVERWRITEONLY))
+ /* Load inf file from install media. */
+ if (InfHostOpenFile(&hInf, FileName, 0, &ErrorLine) != 0)
{
- if (RegOpenKey (NULL, Buffer, &KeyHandle) != ERROR_SUCCESS)
- {
- DPRINT("RegOpenKey(%s) failed\n", Buffer);
- continue; /* ignore if it doesn't exist */
- }
- }
- else
- {
- if (RegCreateKey (NULL, Buffer, &KeyHandle) != ERROR_SUCCESS)
- {
- DPRINT("RegCreateKey(%s) failed\n", Buffer);
- continue;
- }
+ DPRINT1 ("InfHostOpenFile(%s) failed\n", FileName);
+ return FALSE;
}
- /* get value name */
- if (InfGetStringField (&Context, 3, Buffer, MAX_INF_STRING_LENGTH, NULL))
+ if (!registry_callback (hInf, L"DelReg", TRUE))
{
- ValuePtr = Buffer;
- }
- else
- {
- ValuePtr = NULL;
+ DPRINT1 ("registry_callback() for DelReg failed\n");
}
- /* and now do it */
- if (!do_reg_operation (KeyHandle, ValuePtr, &Context, Flags))
+ if (!registry_callback (hInf, L"AddReg", FALSE))
{
- return FALSE;
+ DPRINT1 ("registry_callback() for AddReg failed\n");
}
- }
-
- return TRUE;
-}
+ InfHostCloseFile (hInf);
-BOOL
-ImportRegistryFile(PCHAR FileName,
- PCHAR Section,
- BOOL Delete)
-{
- HINF hInf;
- ULONG ErrorLine;
-
- /* Load inf file from install media. */
- if (!InfOpenFile(&hInf, FileName, &ErrorLine))
- {
- DPRINT1 ("InfOpenFile() failed\n");
- return FALSE;
- }
-
- if (!registry_callback (hInf, "AddReg", FALSE))
- {
- DPRINT1 ("registry_callback() failed\n");
- }
-
- InfCloseFile (hInf);
-
- return TRUE;
+ return TRUE;
}
/* EOF */