[USETUP][SETUPLIB] Split the registry helper code.

Split the registry helper code into registry utility functions
(create/mount/unmount/verify hives) and registry creation code
(the rest: initializing the system hives) and move it in the
setup library.

svn path=/branches/setup_improvements/; revision=75247

[USETUP][SETUPLIB] Improve how the Setup* INF APIs are interfaced in the code.

Define prototypes compatible (including their calling convention)
with the ones defined by setupapi (.h/.dll) so that it can be possible
to either use an internal implementation of these functions (via the
INFLIB library) as currently being done, or using imported setupapi
functions, as would be done by the future 1st-stage GUI installer.

[SETUPLIB] Cleanup the registry.c file and use the infsupp.h header.

svn path=/branches/setup_improvements/; revision=75345
svn path=/branches/setup_improvements/; revision=75346

[USETUP][SETUPLIB] Move some INF-related code from usetup to the setuplib.

- Move the generic INF_GetDataField() and INF_GetData() helpers to
  setuplib, and rework them a bit so that they explicitly call setupapi
  functions (or implementations thereof when being used in usetup);

- Rework the headers in accordance;
- Fix compilation in lib/registry.c .

- Fix compilation when these headers are used withing usetup (who
  doesn't use setupapi.dll) and "reactos" (the 1st-stage GUI installer
  that uses setupapi.dll).

svn path=/branches/setup_improvements/; revision=75515
svn path=/branches/setup_improvements/; revision=75537
svn path=/branches/setup_improvements/; revision=75538
This commit is contained in:
Hermès Bélusca-Maïto 2017-06-30 19:07:02 +00:00
parent ed41bd71dd
commit 60d9ea76d1
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
14 changed files with 2164 additions and 1603 deletions

View file

@ -5,10 +5,13 @@ list(APPEND SOURCE
filesup.c
fsutil.c
genlist.c
infsupp.c
inicache.c
ntverrsrc.c
osdetect.c
partlist.c
registry.c
regutil.c
precomp.h)
add_library(setuplib ${SOURCE})

View file

@ -7,7 +7,12 @@
#pragma once
typedef enum
/* setupapi.h defines ERROR_NOT_INSTALLED with another meaning */
#ifdef ERROR_NOT_INSTALLED
#undef ERROR_NOT_INSTALLED
#endif
typedef enum _ERROR_NUMBER
{
NOT_AN_ERROR = 0, // ERROR_SUCCESS,
ERROR_NOT_INSTALLED,

119
base/setup/lib/infsupp.c Normal file
View file

@ -0,0 +1,119 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Setup Library
* FILE: base/setup/lib/infsupp.c
* PURPOSE: Interfacing with Setup* API .inf files support functions
* PROGRAMMERS: Hervé Poussineau
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
/* INCLUDES *****************************************************************/
#include "precomp.h"
#include "infsupp.h"
#define NDEBUG
#include <debug.h>
/* HELPER FUNCTIONS **********************************************************/
BOOLEAN
INF_GetDataField(
IN PINFCONTEXT Context,
IN ULONG FieldIndex,
OUT PWCHAR *Data)
{
#if 0
BOOL Success;
PWCHAR InfData;
DWORD dwSize;
*Data = NULL;
Success = SetupGetStringFieldW(Context,
FieldIndex,
NULL,
0,
&dwSize);
if (!Success)
return FALSE;
InfData = RtlAllocateHeap(ProcessHeap, 0, dwSize * sizeof(WCHAR));
if (!InfData)
return FALSE;
Success = SetupGetStringFieldW(Context,
FieldIndex,
InfData,
dwSize,
NULL);
if (!Success)
{
RtlFreeHeap(ProcessHeap, 0, InfData);
return FALSE;
}
*Data = InfData;
return TRUE;
#else
*Data = (PWCHAR)pSetupGetField(Context, FieldIndex);
return !!*Data;
#endif
}
BOOLEAN
INF_GetData(
IN PINFCONTEXT Context,
OUT PWCHAR *Key,
OUT PWCHAR *Data)
{
BOOL Success;
PWCHAR InfData[2] = {NULL, NULL};
if (Key)
*Key = NULL;
if (Data)
*Data = NULL;
/*
* Verify that the INF file has only one value field, in addition to its key name.
* Note that SetupGetFieldCount() does not count the key name as a field.
*/
if (SetupGetFieldCount(Context) != 1)
{
DPRINT1("SetupGetFieldCount != 1\n");
return FALSE;
}
if (Key)
{
Success = INF_GetDataField(Context, 0, &InfData[0]);
if (!Success)
return FALSE;
}
if (Data)
{
Success = INF_GetDataField(Context, 1, &InfData[1]);
if (!Success)
{
INF_FreeData(InfData[0]);
return FALSE;
}
}
if (Key)
*Key = InfData[0];
if (Data)
*Data = InfData[1];
return TRUE;
}
/* EOF */

164
base/setup/lib/infsupp.h Normal file
View file

@ -0,0 +1,164 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Setup Library
* FILE: base/setup/lib/infsupp.h
* PURPOSE: Interfacing with Setup* API .inf files support functions
* PROGRAMMER: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
#pragma once
/* Make setupapi.h to not define the API as exports to the DLL */
#ifdef __REACTOS__
#define _SETUPAPI_
#endif
// FIXME: Temporary measure until all the users of this header
// (usetup...) use or define SetupAPI-conforming APIs.
#if defined(_SETUPAPI_H_) || defined(_INC_SETUPAPI)
#include <setupapi.h>
#else
typedef PVOID HINF;
typedef struct _INFCONTEXT
{
HINF Inf;
HINF CurrentInf;
UINT Section;
UINT Line;
} INFCONTEXT, *PINFCONTEXT;
// #define SetupCloseInfFile InfCloseFile
VOID
WINAPI
SetupCloseInfFile(HINF InfHandle);
// #define SetupFindFirstLineW InfpFindFirstLineW
BOOL
WINAPI
SetupFindFirstLineW(
IN HINF InfHandle,
IN PCWSTR Section,
IN PCWSTR Key,
IN OUT PINFCONTEXT Context);
// #define SetupFindNextLine InfFindNextLine
BOOL
WINAPI
SetupFindNextLine(PINFCONTEXT ContextIn,
PINFCONTEXT ContextOut);
// #define SetupGetFieldCount InfGetFieldCount
LONG
WINAPI
SetupGetFieldCount(PINFCONTEXT Context);
// #define SetupGetBinaryField InfGetBinaryField
BOOL
WINAPI
SetupGetBinaryField(PINFCONTEXT Context,
ULONG FieldIndex,
PUCHAR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize);
// #define SetupGetIntField InfGetIntField
BOOL
WINAPI
SetupGetIntField(PINFCONTEXT Context,
ULONG FieldIndex,
INT *IntegerValue); // PINT
// #define SetupGetMultiSzFieldW InfGetMultiSzField
BOOL
WINAPI
SetupGetMultiSzFieldW(PINFCONTEXT Context,
ULONG FieldIndex,
PWSTR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize);
// #define SetupGetStringFieldW InfGetStringField
BOOL
WINAPI
SetupGetStringFieldW(PINFCONTEXT Context,
ULONG FieldIndex,
PWSTR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize);
#endif
/* Lower the MAX_INF_STRING_LENGTH value in order to avoid too much stack usage */
#undef MAX_INF_STRING_LENGTH
#define MAX_INF_STRING_LENGTH 1024 // Still larger than in infcommon.h
#ifndef INF_STYLE_WIN4
#define INF_STYLE_WIN4 0x00000002
#endif
#if 0
typedef PVOID HINF;
typedef struct _INFCONTEXT
{
HINF Inf;
HINF CurrentInf;
UINT Section;
UINT Line;
} INFCONTEXT, *PINFCONTEXT;
#endif
C_ASSERT(sizeof(INFCONTEXT) == 2 * sizeof(HINF) + 2 * sizeof(UINT));
/*
* This function corresponds to an undocumented but exported SetupAPI function
* that exists since WinNT4 and is still present in Win10.
* The returned string pointer is a read-only pointer to a string in the
* maintained INF cache, and is always in UNICODE (on NT systems).
*/
PCWSTR
WINAPI
pSetupGetField(PINFCONTEXT Context,
ULONG FieldIndex);
/* A version of SetupOpenInfFileW with support for a user-provided LCID */
// #define SetupOpenInfFileExW InfpOpenInfFileW
HINF
WINAPI
SetupOpenInfFileExW(
IN PCWSTR FileName,
IN PCWSTR InfClass,
IN DWORD InfStyle,
IN LCID LocaleId,
OUT PUINT ErrorLine);
/* HELPER FUNCTIONS **********************************************************/
FORCEINLINE VOID
INF_FreeData(IN PWCHAR InfData)
{
#if 0
if (InfData)
RtlFreeHeap(ProcessHeap, 0, InfData);
#else
UNREFERENCED_PARAMETER(InfData);
#endif
}
BOOLEAN
INF_GetDataField(
IN PINFCONTEXT Context,
IN ULONG FieldIndex,
OUT PWCHAR *Data);
BOOLEAN
INF_GetData(
IN PINFCONTEXT Context,
OUT PWCHAR *Key,
OUT PWCHAR *Data);
/* EOF */

1118
base/setup/lib/registry.c Normal file

File diff suppressed because it is too large Load diff

61
base/setup/lib/registry.h Normal file
View file

@ -0,0 +1,61 @@
/*
* ReactOS kernel
* Copyright (C) 2003 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Setup Library
* FILE: base/setup/lib/registry.h
* PURPOSE: Registry creation functions
* PROGRAMMERS: ...
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
#pragma once
HANDLE
GetRootKeyByPredefKey(
IN HANDLE KeyHandle,
OUT PCWSTR* RootKeyMountPoint OPTIONAL);
HANDLE
GetRootKeyByName(
IN PCWSTR RootKeyName,
OUT PCWSTR* RootKeyMountPoint OPTIONAL);
BOOLEAN
ImportRegistryFile(
IN PCWSTR SourcePath,
IN PCWSTR FileName,
IN PCWSTR Section,
IN LCID LocaleId,
IN BOOLEAN Delete);
NTSTATUS
VerifyRegistryHives(
IN PUNICODE_STRING InstallPath,
OUT PBOOLEAN ShouldRepairRegistry);
NTSTATUS
RegInitializeRegistry(
IN PUNICODE_STRING InstallPath);
VOID
RegCleanupRegistry(
IN PUNICODE_STRING InstallPath);
/* EOF */

457
base/setup/lib/regutil.c Normal file
View file

@ -0,0 +1,457 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Setup Library
* FILE: base/setup/lib/regutil.c
* PURPOSE: Registry utility functions
* PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
/* INCLUDES *****************************************************************/
#include "precomp.h"
#include "filesup.h"
#include "regutil.h"
// HACK!
#include <strsafe.h>
#define NDEBUG
#include <debug.h>
// HACK!! These functions should actually be moved in the setup lib!
// For the moment, see usetup/filesup.c (or .h)
#if 1
NTSTATUS
SetupCopyFile(
IN PCWSTR SourceFileName,
IN PCWSTR DestinationFileName,
IN BOOLEAN FailIfExists);
#define MOVEFILE_REPLACE_EXISTING 1
NTSTATUS
SetupMoveFile(
IN PCWSTR ExistingFileName,
IN PCWSTR NewFileName,
IN ULONG Flags);
#endif
/* FUNCTIONS ****************************************************************/
/*
* This function is similar to the one in dlls/win32/advapi32/reg/reg.c
* TODO: I should review both of them very carefully, because they may need
* some adjustments in their NtCreateKey calls, especially for CreateOptions
* stuff etc...
*/
NTSTATUS
CreateNestedKey(PHANDLE KeyHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
ULONG CreateOptions)
{
OBJECT_ATTRIBUTES LocalObjectAttributes;
UNICODE_STRING LocalKeyName;
ULONG Disposition;
NTSTATUS Status;
USHORT FullNameLength;
PWCHAR Ptr;
HANDLE LocalKeyHandle;
Status = NtCreateKey(KeyHandle,
KEY_ALL_ACCESS,
ObjectAttributes,
0,
NULL,
CreateOptions,
&Disposition);
DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", ObjectAttributes->ObjectName, Status);
if (Status != STATUS_OBJECT_NAME_NOT_FOUND)
{
if (!NT_SUCCESS(Status))
DPRINT1("CreateNestedKey: NtCreateKey(%wZ) failed (Status %lx)\n", ObjectAttributes->ObjectName, Status);
return Status;
}
/* Copy object attributes */
RtlCopyMemory(&LocalObjectAttributes,
ObjectAttributes,
sizeof(OBJECT_ATTRIBUTES));
RtlCreateUnicodeString(&LocalKeyName,
ObjectAttributes->ObjectName->Buffer);
LocalObjectAttributes.ObjectName = &LocalKeyName;
FullNameLength = LocalKeyName.Length;
/* Remove the last part of the key name and try to create the key again. */
while (Status == STATUS_OBJECT_NAME_NOT_FOUND)
{
Ptr = wcsrchr(LocalKeyName.Buffer, '\\');
if (Ptr == NULL || Ptr == LocalKeyName.Buffer)
{
Status = STATUS_UNSUCCESSFUL;
break;
}
*Ptr = (WCHAR)0;
LocalKeyName.Length = wcslen(LocalKeyName.Buffer) * sizeof(WCHAR);
Status = NtCreateKey(&LocalKeyHandle,
KEY_CREATE_SUB_KEY,
&LocalObjectAttributes,
0,
NULL,
REG_OPTION_NON_VOLATILE,
&Disposition);
DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName, Status);
if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
DPRINT1("CreateNestedKey: NtCreateKey(%wZ) failed (Status %lx)\n", LocalObjectAttributes.ObjectName, Status);
}
if (!NT_SUCCESS(Status))
{
RtlFreeUnicodeString(&LocalKeyName);
return Status;
}
/* Add removed parts of the key name and create them too. */
while (TRUE)
{
if (LocalKeyName.Length == FullNameLength)
{
Status = STATUS_SUCCESS;
*KeyHandle = LocalKeyHandle;
break;
}
NtClose(LocalKeyHandle);
LocalKeyName.Buffer[LocalKeyName.Length / sizeof(WCHAR)] = L'\\';
LocalKeyName.Length = wcslen(LocalKeyName.Buffer) * sizeof(WCHAR);
Status = NtCreateKey(&LocalKeyHandle,
KEY_ALL_ACCESS,
&LocalObjectAttributes,
0,
NULL,
CreateOptions,
&Disposition);
DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName, Status);
if (!NT_SUCCESS(Status))
{
DPRINT1("CreateNestedKey: NtCreateKey(%wZ) failed (Status %lx)\n", LocalObjectAttributes.ObjectName, Status);
break;
}
}
RtlFreeUnicodeString(&LocalKeyName);
return Status;
}
/*
* Should be called under SE_BACKUP_PRIVILEGE privilege
*/
NTSTATUS
CreateRegistryFile(
IN PUNICODE_STRING InstallPath,
IN PCWSTR RegistryKey,
IN BOOLEAN IsHiveNew,
IN HANDLE ProtoKeyHandle
/*
IN PUCHAR Descriptor,
IN ULONG DescriptorLength
*/
)
{
/* '.old' is for old valid hives, while '.brk' is for old broken hives */
static PCWSTR Extensions[] = {L"old", L"brk"};
NTSTATUS Status;
HANDLE FileHandle;
UNICODE_STRING FileName;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
PCWSTR Extension;
WCHAR PathBuffer[MAX_PATH];
WCHAR PathBuffer2[MAX_PATH];
CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 3,
InstallPath->Buffer, L"System32\\config", RegistryKey);
Extension = Extensions[IsHiveNew ? 0 : 1];
//
// FIXME: The best, actually, would be to rename (move) the existing
// System32\config\RegistryKey file to System32\config\RegistryKey.old,
// and if it already existed some System32\config\RegistryKey.old, we should
// first rename this one into System32\config\RegistryKey_N.old before
// performing the original rename.
//
/* Check whether the registry hive file already existed, and if so, rename it */
if (DoesFileExist(NULL, PathBuffer))
{
// UINT i;
DPRINT1("Registry hive '%S' already exists, rename it\n", PathBuffer);
// i = 1;
/* Try first by just appending the '.old' extension */
StringCchPrintfW(PathBuffer2, ARRAYSIZE(PathBuffer2), L"%s.%s", PathBuffer, Extension);
#if 0
while (DoesFileExist(NULL, PathBuffer2))
{
/* An old file already exists, increments its index, but not too much */
if (i <= 0xFFFF)
{
/* Append '_N.old' extension */
StringCchPrintfW(PathBuffer2, ARRAYSIZE(PathBuffer2), L"%s_%lu.%s", PathBuffer, i, Extension);
++i;
}
else
{
/*
* Too many old files exist, we will rename the file
* using the name of the oldest one.
*/
StringCchPrintfW(PathBuffer2, ARRAYSIZE(PathBuffer2), L"%s.%s", PathBuffer, Extension);
break;
}
}
#endif
/* Now rename the file (force the move) */
Status = SetupMoveFile(PathBuffer, PathBuffer2, MOVEFILE_REPLACE_EXISTING);
}
/* Create the file */
RtlInitUnicodeString(&FileName, PathBuffer);
InitializeObjectAttributes(&ObjectAttributes,
&FileName,
OBJ_CASE_INSENSITIVE,
NULL, // Could have been InstallPath, etc...
NULL); // Descriptor
Status = NtCreateFile(&FileHandle,
FILE_GENERIC_WRITE,
&ObjectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OVERWRITE_IF,
FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE,
NULL,
0);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtCreateFile(%wZ) failed, Status 0x%08lx\n", &FileName, Status);
return Status;
}
/* Save the selected hive into the file */
Status = NtSaveKeyEx(ProtoKeyHandle, FileHandle, REG_LATEST_FORMAT);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtSaveKeyEx(%wZ) failed, Status 0x%08lx\n", &FileName, Status);
}
/* Close the file and return */
NtClose(FileHandle);
return Status;
}
BOOLEAN
CmpLinkKeyToHive(
IN HANDLE RootLinkKeyHandle OPTIONAL,
IN PCWSTR LinkKeyName,
IN PCWSTR TargetKeyName)
{
static UNICODE_STRING CmSymbolicLinkValueName =
RTL_CONSTANT_STRING(L"SymbolicLinkValue");
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName;
HANDLE TargetKeyHandle;
ULONG Disposition;
/* Initialize the object attributes */
RtlInitUnicodeString(&KeyName, LinkKeyName);
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
RootLinkKeyHandle,
NULL);
/* Create the link key */
Status = NtCreateKey(&TargetKeyHandle,
KEY_SET_VALUE | KEY_CREATE_LINK,
&ObjectAttributes,
0,
NULL,
REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK,
&Disposition);
if (!NT_SUCCESS(Status))
{
DPRINT1("CmpLinkKeyToHive: couldn't create %S, Status = 0x%08lx\n",
LinkKeyName, Status);
return FALSE;
}
/* Check if the new key was actually created */
if (Disposition != REG_CREATED_NEW_KEY)
{
DPRINT1("CmpLinkKeyToHive: %S already exists!\n", LinkKeyName);
NtClose(TargetKeyHandle);
return FALSE;
}
/* Set the target key name as link target */
RtlInitUnicodeString(&KeyName, TargetKeyName);
Status = NtSetValueKey(TargetKeyHandle,
&CmSymbolicLinkValueName,
0,
REG_LINK,
KeyName.Buffer,
KeyName.Length);
/* Close the link key handle */
NtClose(TargetKeyHandle);
if (!NT_SUCCESS(Status))
{
DPRINT1("CmpLinkKeyToHive: couldn't create symbolic link for %S, Status = 0x%08lx\n",
TargetKeyName, Status);
return FALSE;
}
return TRUE;
}
/*
* Should be called under SE_RESTORE_PRIVILEGE privilege
*/
NTSTATUS
ConnectRegistry(
IN HKEY RootKey OPTIONAL,
IN PCWSTR RegMountPoint,
// IN HANDLE RootDirectory OPTIONAL,
IN PUNICODE_STRING InstallPath,
IN PCWSTR RegistryKey
/*
IN PUCHAR Descriptor,
IN ULONG DescriptorLength
*/
)
{
UNICODE_STRING KeyName, FileName;
OBJECT_ATTRIBUTES KeyObjectAttributes;
OBJECT_ATTRIBUTES FileObjectAttributes;
WCHAR PathBuffer[MAX_PATH];
RtlInitUnicodeString(&KeyName, RegMountPoint);
InitializeObjectAttributes(&KeyObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
RootKey,
NULL); // Descriptor
CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 3,
InstallPath->Buffer, L"System32\\config", RegistryKey);
RtlInitUnicodeString(&FileName, PathBuffer);
InitializeObjectAttributes(&FileObjectAttributes,
&FileName,
OBJ_CASE_INSENSITIVE,
NULL, // RootDirectory,
NULL);
/* Mount the registry hive in the registry namespace */
return NtLoadKey(&KeyObjectAttributes, &FileObjectAttributes);
}
/*
* Should be called under SE_RESTORE_PRIVILEGE privilege
*/
NTSTATUS
DisconnectRegistry(
IN HKEY RootKey OPTIONAL,
IN PCWSTR RegMountPoint,
IN ULONG Flags)
{
UNICODE_STRING KeyName;
OBJECT_ATTRIBUTES ObjectAttributes;
RtlInitUnicodeString(&KeyName, RegMountPoint);
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
RootKey,
NULL);
// NOTE: NtUnloadKey == NtUnloadKey2 with Flags == 0.
return NtUnloadKey2(&ObjectAttributes, Flags);
}
/*
* Should be called under SE_RESTORE_PRIVILEGE privilege
*/
NTSTATUS
VerifyRegistryHive(
// IN HKEY RootKey OPTIONAL,
// // IN HANDLE RootDirectory OPTIONAL,
IN PUNICODE_STRING InstallPath,
IN PCWSTR RegistryKey /* ,
IN PCWSTR RegMountPoint */)
{
NTSTATUS Status;
/* Try to mount the specified registry hive */
Status = ConnectRegistry(NULL,
L"\\Registry\\Machine\\USetup_VerifyHive",
InstallPath,
RegistryKey
/* NULL, 0 */);
if (!NT_SUCCESS(Status))
{
DPRINT1("ConnectRegistry(%S) failed, Status 0x%08lx\n", RegistryKey, Status);
}
DPRINT1("VerifyRegistryHive: ConnectRegistry(%S) returns Status 0x%08lx\n", RegistryKey, Status);
//
// TODO: Check the Status error codes: STATUS_SUCCESS, STATUS_REGISTRY_RECOVERED,
// STATUS_REGISTRY_HIVE_RECOVERED, STATUS_REGISTRY_CORRUPT, STATUS_REGISTRY_IO_FAILED,
// STATUS_NOT_REGISTRY_FILE, STATUS_CANNOT_LOAD_REGISTRY_FILE ;
//(STATUS_HIVE_UNLOADED) ; STATUS_SYSTEM_HIVE_TOO_LARGE
//
if (Status == STATUS_REGISTRY_HIVE_RECOVERED) // NT_SUCCESS is still FALSE in this case!
DPRINT1("VerifyRegistryHive: Registry hive %S was recovered but some data may be lost (Status 0x%08lx)\n", RegistryKey, Status);
if (!NT_SUCCESS(Status))
{
DPRINT1("VerifyRegistryHive: Registry hive %S is corrupted (Status 0x%08lx)\n", RegistryKey, Status);
return Status;
}
if (Status == STATUS_REGISTRY_RECOVERED)
DPRINT1("VerifyRegistryHive: Registry hive %S succeeded recovered (Status 0x%08lx)\n", RegistryKey, Status);
/* Unmount the hive */
Status = DisconnectRegistry(NULL,
L"\\Registry\\Machine\\USetup_VerifyHive",
0);
if (!NT_SUCCESS(Status))
{
DPRINT1("DisconnectRegistry(%S) failed, Status 0x%08lx\n", RegistryKey, Status);
}
return Status;
}
/* EOF */

80
base/setup/lib/regutil.h Normal file
View file

@ -0,0 +1,80 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Setup Library
* FILE: base/setup/lib/regutil.h
* PURPOSE: Registry utility functions
* PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
#pragma once
/*
* This function is similar to the one in dlls/win32/advapi32/reg/reg.c
* TODO: I should review both of them very carefully, because they may need
* some adjustments in their NtCreateKey calls, especially for CreateOptions
* stuff etc...
*/
NTSTATUS
CreateNestedKey(PHANDLE KeyHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
ULONG CreateOptions);
/*
* Should be called under SE_BACKUP_PRIVILEGE privilege
*/
NTSTATUS
CreateRegistryFile(
IN PUNICODE_STRING InstallPath,
IN PCWSTR RegistryKey,
IN BOOLEAN IsHiveNew,
IN HANDLE ProtoKeyHandle
/*
IN PUCHAR Descriptor,
IN ULONG DescriptorLength
*/
);
BOOLEAN
CmpLinkKeyToHive(
IN HANDLE RootLinkKeyHandle OPTIONAL,
IN PCWSTR LinkKeyName,
IN PCWSTR TargetKeyName);
/*
* Should be called under SE_RESTORE_PRIVILEGE privilege
*/
NTSTATUS
ConnectRegistry(
IN HKEY RootKey OPTIONAL,
IN PCWSTR RegMountPoint,
// IN HANDLE RootDirectory OPTIONAL,
IN PUNICODE_STRING InstallPath,
IN PCWSTR RegistryKey
/*
IN PUCHAR Descriptor,
IN ULONG DescriptorLength
*/
);
/*
* Should be called under SE_RESTORE_PRIVILEGE privilege
*/
NTSTATUS
DisconnectRegistry(
IN HKEY RootKey OPTIONAL,
IN PCWSTR RegMountPoint,
IN ULONG Flags);
/*
* Should be called under SE_RESTORE_PRIVILEGE privilege
*/
NTSTATUS
VerifyRegistryHive(
// IN HKEY RootKey OPTIONAL,
// // IN HANDLE RootDirectory OPTIONAL,
IN PUNICODE_STRING InstallPath,
IN PCWSTR RegistryKey /* ,
IN PCWSTR RegMountPoint */);
/* EOF */

View file

@ -34,5 +34,7 @@ extern HANDLE ProcessHeap;
#include "partlist.h"
#include "arcname.h"
#include "osdetect.h"
#include "regutil.h"
#include "registry.h"
/* EOF */

View file

@ -21,7 +21,8 @@
* PROJECT: ReactOS text-mode setup
* FILE: base/setup/usetup/inffile.c
* PURPOSE: .inf files support functions
* PROGRAMMER: Hervé Poussineau
* PROGRAMMERS: Hervé Poussineau
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
/* INCLUDES ******************************************************************/
@ -31,11 +32,23 @@
#define NDEBUG
#include <debug.h>
/* FUNCTIONS *****************************************************************/
/* SETUP* API COMPATIBILITY FUNCTIONS ****************************************/
/* Functions from the INFLIB library */
extern VOID InfCloseFile(HINF InfHandle);
// #define SetupCloseInfFile InfCloseFile
VOID
WINAPI
SetupCloseInfFile(HINF InfHandle)
{
InfCloseFile(InfHandle);
}
// #define SetupFindFirstLineW InfpFindFirstLineW
BOOL
WINAPI
InfpFindFirstLineW(
SetupFindFirstLineW(
IN HINF InfHandle,
IN PCWSTR Section,
IN PCWSTR Key,
@ -53,10 +66,128 @@ InfpFindFirstLineW(
return TRUE;
}
extern BOOLEAN InfFindNextLine(PINFCONTEXT ContextIn,
PINFCONTEXT ContextOut);
// #define SetupFindNextLine InfFindNextLine
BOOL
WINAPI
SetupFindNextLine(PINFCONTEXT ContextIn,
PINFCONTEXT ContextOut)
{
return !!InfFindNextLine(ContextIn, ContextOut);
}
extern LONG InfGetFieldCount(PINFCONTEXT Context);
// #define SetupGetFieldCount InfGetFieldCount
LONG
WINAPI
SetupGetFieldCount(PINFCONTEXT Context)
{
return InfGetFieldCount(Context);
}
/*
* This function corresponds to an undocumented but exported setupapi API
* that exists since WinNT4 and is still present in Win10.
* The returned string pointer is a read-only pointer to a string in the
* maintained INF cache, and is always in UNICODE (on NT systems).
*/
extern BOOLEAN InfGetDataField(PINFCONTEXT Context,
ULONG FieldIndex,
PWCHAR *Data);
PCWSTR
WINAPI
pSetupGetField(PINFCONTEXT Context,
ULONG FieldIndex)
{
PWCHAR Data = NULL;
if (!InfGetDataField(Context, FieldIndex, &Data))
return NULL;
return Data;
}
extern BOOLEAN InfGetBinaryField(PINFCONTEXT Context,
ULONG FieldIndex,
PUCHAR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize);
// #define SetupGetBinaryField InfGetBinaryField
BOOL
WINAPI
SetupGetBinaryField(PINFCONTEXT Context,
ULONG FieldIndex,
PUCHAR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize)
{
return !!InfGetBinaryField(Context,
FieldIndex,
ReturnBuffer,
ReturnBufferSize,
RequiredSize);
}
extern BOOLEAN InfGetIntField(PINFCONTEXT Context,
ULONG FieldIndex,
INT *IntegerValue);
// #define SetupGetIntField InfGetIntField
BOOL
WINAPI
SetupGetIntField(PINFCONTEXT Context,
ULONG FieldIndex,
INT *IntegerValue) // PINT
{
return !!InfGetIntField(Context, FieldIndex, IntegerValue);
}
extern BOOLEAN InfGetMultiSzField(PINFCONTEXT Context,
ULONG FieldIndex,
PWSTR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize);
// #define SetupGetMultiSzFieldW InfGetMultiSzField
BOOL
WINAPI
SetupGetMultiSzFieldW(PINFCONTEXT Context,
ULONG FieldIndex,
PWSTR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize)
{
return !!InfGetMultiSzField(Context,
FieldIndex,
ReturnBuffer,
ReturnBufferSize,
RequiredSize);
}
extern BOOLEAN InfGetStringField(PINFCONTEXT Context,
ULONG FieldIndex,
PWSTR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize);
// #define SetupGetStringFieldW InfGetStringField
BOOL
WINAPI
SetupGetStringFieldW(PINFCONTEXT Context,
ULONG FieldIndex,
PWSTR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize)
{
return !!InfGetStringField(Context,
FieldIndex,
ReturnBuffer,
ReturnBufferSize,
RequiredSize);
}
/* SetupOpenInfFileW with support for a user-provided LCID */
// #define SetupOpenInfFileExW InfpOpenInfFileW
HINF
WINAPI
InfpOpenInfFileW(
SetupOpenInfFileExW(
IN PCWSTR FileName,
IN PCWSTR InfClass,
IN DWORD InfStyle,
@ -81,25 +212,7 @@ InfpOpenInfFileW(
}
BOOLEAN
INF_GetData(
IN PINFCONTEXT Context,
OUT PWCHAR *Key,
OUT PWCHAR *Data)
{
return InfGetData(Context, Key, Data);
}
BOOLEAN
INF_GetDataField(
IN PINFCONTEXT Context,
IN ULONG FieldIndex,
OUT PWCHAR *Data)
{
return InfGetDataField(Context, FieldIndex, Data);
}
/* HELPER FUNCTIONS **********************************************************/
HINF WINAPI
INF_OpenBufferedFileA(

View file

@ -21,88 +21,32 @@
* PROJECT: ReactOS text-mode setup
* FILE: base/setup/usetup/inffile.h
* PURPOSE: .inf files support functions
* PROGRAMMER: Hervé Poussineau
* PROGRAMMERS: Hervé Poussineau
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
#pragma once
#include <infcommon.h>
#ifdef __REACTOS__
// HACK around the fact INFLIB unconditionally defines MAX_INF_STRING_LENGTH.
#undef MAX_INF_STRING_LENGTH
/* Functions from the INFLIB library */
// #include <infcommon.h>
#include <infros.h>
#undef MAX_INF_STRING_LENGTH
#define MAX_INF_STRING_LENGTH 1024
extern VOID InfSetHeap(PVOID Heap);
extern VOID InfCloseFile(HINF InfHandle);
extern BOOLEAN InfFindNextLine(PINFCONTEXT ContextIn,
PINFCONTEXT ContextOut);
extern BOOLEAN InfGetBinaryField(PINFCONTEXT Context,
ULONG FieldIndex,
PUCHAR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize);
extern BOOLEAN InfGetMultiSzField(PINFCONTEXT Context,
ULONG FieldIndex,
PWSTR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize);
extern BOOLEAN InfGetStringField(PINFCONTEXT Context,
ULONG FieldIndex,
PWSTR ReturnBuffer,
ULONG ReturnBufferSize,
PULONG RequiredSize);
#define SetupCloseInfFile InfCloseFile
#define SetupFindNextLine InfFindNextLine
#define SetupGetBinaryField InfGetBinaryField
#define SetupGetMultiSzFieldW InfGetMultiSzField
#define SetupGetStringFieldW InfGetStringField
#endif /* __REACTOS__ */
#include <../lib/infsupp.h>
#define SetupFindFirstLineW InfpFindFirstLineW
#define SetupGetFieldCount InfGetFieldCount
#define SetupGetIntField InfGetIntField
// SetupOpenInfFileW with support for a user-provided LCID
#define SetupOpenInfFileExW InfpOpenInfFileW
#define INF_STYLE_WIN4 0x00000002
/* FIXME: this structure is the one used in inflib, not in setupapi
* Delete it once we don't use inflib anymore */
typedef struct _INFCONTEXT
{
HINF Inf;
HINF CurrentInf;
UINT Section;
UINT Line;
} INFCONTEXT;
C_ASSERT(sizeof(INFCONTEXT) == 2 * sizeof(PVOID) + 2 * sizeof(UINT));
BOOL
WINAPI
InfpFindFirstLineW(
IN HINF InfHandle,
IN PCWSTR Section,
IN PCWSTR Key,
IN OUT PINFCONTEXT Context);
HINF
WINAPI
InfpOpenInfFileW(
IN PCWSTR FileName,
IN PCWSTR InfClass,
IN DWORD InfStyle,
IN LCID LocaleId,
OUT PUINT ErrorLine);
BOOLEAN
INF_GetData(
IN PINFCONTEXT Context,
OUT PWCHAR *Key,
OUT PWCHAR *Data);
BOOLEAN
INF_GetDataField(
IN PINFCONTEXT Context,
IN ULONG FieldIndex,
OUT PWCHAR *Data);
/* HELPER FUNCTIONS **********************************************************/
HINF WINAPI
INF_OpenBufferedFileA(

File diff suppressed because it is too large Load diff

View file

@ -26,37 +26,6 @@
#pragma once
HANDLE
GetRootKeyByPredefKey(
IN HANDLE KeyHandle,
OUT PCWSTR* RootKeyMountPoint OPTIONAL);
HANDLE
GetRootKeyByName(
IN PCWSTR RootKeyName,
OUT PCWSTR* RootKeyMountPoint OPTIONAL);
BOOLEAN
ImportRegistryFile(
PCWSTR SourcePath,
PWSTR Filename,
PWSTR Section,
LCID LocaleId,
BOOLEAN Delete);
NTSTATUS
VerifyRegistryHives(
IN PUNICODE_STRING InstallPath,
OUT PBOOLEAN ShouldRepairRegistry);
NTSTATUS
RegInitializeRegistry(
IN PUNICODE_STRING InstallPath);
VOID
RegCleanupRegistry(
IN PUNICODE_STRING InstallPath);
VOID
SetDefaultPagefile(
WCHAR Drive);

View file

@ -61,7 +61,6 @@
#include "consup.h"
#include "inffile.h"
#include "progress.h"
#include "infros.h"
#include "filequeue.h"
#include "registry.h"
#include "fslist.h"