[USETUP] More code for updating/repairing the registry. Fix the name of the txtsetup.sif section to look for when performing a registry upgrade.

[BOOTDATA] Add needed entries in txtsetup.sif for registry upgrade.

svn path=/branches/setup_improvements/; revision=75162
svn path=/branches/setup_improvements/; revision=75226
This commit is contained in:
Hermès Bélusca-Maïto 2017-06-22 00:38:32 +00:00
parent b20908acc8
commit 7fedeb7db3
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
4 changed files with 194 additions and 103 deletions

View file

@ -750,7 +750,7 @@ CreateRegistryFile(
InitializeObjectAttributes(&ObjectAttributes, InitializeObjectAttributes(&ObjectAttributes,
&FileName, &FileName,
OBJ_CASE_INSENSITIVE, OBJ_CASE_INSENSITIVE,
NULL, // Could have been installpath, etc... NULL, // Could have been InstallPath, etc...
NULL); // Descriptor NULL); // Descriptor
Status = NtCreateFile(&FileHandle, Status = NtCreateFile(&FileHandle,
@ -902,7 +902,7 @@ VerifyRegistryHive(
{ {
NTSTATUS Status; NTSTATUS Status;
UNICODE_STRING KeyName; UNICODE_STRING KeyName;
OBJECT_ATTRIBUTES KeyObjectAttributes; OBJECT_ATTRIBUTES ObjectAttributes;
/* Try to mount the specified registry hive */ /* Try to mount the specified registry hive */
Status = ConnectRegistry(NULL, Status = ConnectRegistry(NULL,
@ -937,14 +937,14 @@ VerifyRegistryHive(
DPRINT1("VerifyRegistryHive: Registry hive %S succeeded recovered (Status 0x%08lx)\n", RegistryKey, Status); DPRINT1("VerifyRegistryHive: Registry hive %S succeeded recovered (Status 0x%08lx)\n", RegistryKey, Status);
/* Unmount the hive */ /* Unmount the hive */
InitializeObjectAttributes(&KeyObjectAttributes, InitializeObjectAttributes(&ObjectAttributes,
&KeyName, &KeyName,
OBJ_CASE_INSENSITIVE, OBJ_CASE_INSENSITIVE,
NULL, NULL,
NULL); NULL);
RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\USetup_VerifyHive"); RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\USetup_VerifyHive");
Status = NtUnloadKey(&KeyObjectAttributes); Status = NtUnloadKey(&ObjectAttributes);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("NtUnloadKey(%S, %wZ) failed, Status 0x%08lx\n", RegistryKey, &KeyName, Status); DPRINT1("NtUnloadKey(%S, %wZ) failed, Status 0x%08lx\n", RegistryKey, &KeyName, Status);
@ -998,14 +998,14 @@ C_ASSERT(_countof(SecurityRegistryHives) == NUMBER_OF_SECURITY_REGISTRY_HIVES);
NTSTATUS NTSTATUS
VerifyRegistryHives( VerifyRegistryHives(
IN PUNICODE_STRING InstallPath, IN PUNICODE_STRING InstallPath,
OUT PBOOLEAN ShouldUpdateRegistry) OUT PBOOLEAN ShouldRepairRegistry)
{ {
NTSTATUS Status; NTSTATUS Status;
BOOLEAN PrivilegeSet[2] = {FALSE, FALSE}; BOOLEAN PrivilegeSet[2] = {FALSE, FALSE};
UINT i; UINT i;
/* Suppose first the registry hives do not have to be updated/recreated */ /* Suppose first the registry hives do not have to be fully recreated */
*ShouldUpdateRegistry = FALSE; *ShouldRepairRegistry = FALSE;
/* Acquire restore privilege */ /* Acquire restore privilege */
Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, FALSE, &PrivilegeSet[0]); Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, FALSE, &PrivilegeSet[0]);
@ -1033,7 +1033,7 @@ VerifyRegistryHives(
{ {
DPRINT1("Registry hive '%S' needs repair!\n", RegistryHives[i].HiveName); DPRINT1("Registry hive '%S' needs repair!\n", RegistryHives[i].HiveName);
RegistryHives[i].State = Repair; RegistryHives[i].State = Repair;
*ShouldUpdateRegistry = TRUE; *ShouldRepairRegistry = TRUE;
} }
else else
{ {
@ -1145,14 +1145,14 @@ RegInitializeRegistry(
{ {
DPRINT1("CreateRegistryFile(%S) failed, Status 0x%08lx\n", RegistryHives[i].HiveName, Status); DPRINT1("CreateRegistryFile(%S) failed, Status 0x%08lx\n", RegistryHives[i].HiveName, Status);
/* Exit prematurely here.... */ /* Exit prematurely here.... */
/* That is now done, clean everything up! */ /* That is now done, remove the proto-hive */
NtDeleteKey(KeyHandle); NtDeleteKey(KeyHandle);
NtClose(KeyHandle); NtClose(KeyHandle);
goto Quit; goto Quit;
} }
} }
/* That is now done, clean everything up! */ /* That is now done, remove the proto-hive */
NtDeleteKey(KeyHandle); NtDeleteKey(KeyHandle);
NtClose(KeyHandle); NtClose(KeyHandle);
@ -1238,7 +1238,7 @@ RegInitializeRegistry(
} }
else else
{ {
/* Create *DUMMY* volatile hives just to make the update procedure work */ /* Create *DUMMY* volatile hives just to make the update procedure working */
RtlInitUnicodeString(&KeyName, RegistryHives[i].RegSymLink); RtlInitUnicodeString(&KeyName, RegistryHives[i].RegSymLink);
InitializeObjectAttributes(&ObjectAttributes, InitializeObjectAttributes(&ObjectAttributes,
@ -1385,23 +1385,14 @@ RegCleanupRegistry(
IN PUNICODE_STRING InstallPath) IN PUNICODE_STRING InstallPath)
{ {
NTSTATUS Status; NTSTATUS Status;
HANDLE KeyHandle;
UNICODE_STRING KeyName; UNICODE_STRING KeyName;
OBJECT_ATTRIBUTES KeyObjectAttributes; OBJECT_ATTRIBUTES ObjectAttributes;
BOOLEAN PrivilegeSet[2] = {FALSE, FALSE}; BOOLEAN PrivilegeSet[2] = {FALSE, FALSE};
UINT i; UINT i;
WCHAR SrcPath[MAX_PATH]; WCHAR SrcPath[MAX_PATH];
WCHAR DstPath[MAX_PATH]; WCHAR DstPath[MAX_PATH];
for (i = 0; i < ARRAYSIZE(RootKeys); ++i)
{
if (RootKeys[i].Handle)
{
NtFlushKey(RootKeys[i].Handle);
NtClose(RootKeys[i].Handle);
RootKeys[i].Handle = NULL;
}
}
/* Acquire restore privilege */ /* Acquire restore privilege */
Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, FALSE, &PrivilegeSet[0]); Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, FALSE, &PrivilegeSet[0]);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
@ -1421,20 +1412,68 @@ RegCleanupRegistry(
return; return;
} }
InitializeObjectAttributes(&KeyObjectAttributes, /*
&KeyName, * Note that we don't need to explicitly remove the symlinks we have created
OBJ_CASE_INSENSITIVE, * since they are created volatile, inside registry keys that will be however
NULL, * removed explictly in the following.
NULL); */
for (i = 0; i < ARRAYSIZE(RegistryHives); ++i) for (i = 0; i < ARRAYSIZE(RegistryHives); ++i)
{ {
if (RegistryHives[i].State != Create && RegistryHives[i].State != Repair) if (RegistryHives[i].State != Create && RegistryHives[i].State != Repair)
continue; {
RtlInitUnicodeString(&KeyName, RegistryHives[i].RegSymLink);
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
RootKeys[GetPredefKeyIndex(RegistryHives[i].PredefKeyHandle)].Handle,
NULL);
KeyHandle = NULL;
Status = NtOpenKey(&KeyHandle,
DELETE,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtOpenKey(%wZ) failed, Status 0x%08lx\n", &KeyName, Status);
// return;
}
NtDeleteKey(KeyHandle);
NtClose(KeyHandle);
}
else
{
RtlInitUnicodeString(&KeyName, RegistryHives[i].HiveRegistryPath); RtlInitUnicodeString(&KeyName, RegistryHives[i].HiveRegistryPath);
Status = NtUnloadKey(&KeyObjectAttributes); InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
// Status = NtUnloadKey(&ObjectAttributes);
Status = NtUnloadKey2(&ObjectAttributes, 1 /* REG_FORCE_UNLOAD */);
DPRINT1("Unmounting '%S' %s\n", RegistryHives[i].HiveRegistryPath, NT_SUCCESS(Status) ? "succeeded" : "failed"); DPRINT1("Unmounting '%S' %s\n", RegistryHives[i].HiveRegistryPath, NT_SUCCESS(Status) ? "succeeded" : "failed");
/* Switch the hive state to 'Update' */
RegistryHives[i].State = Update;
}
}
/*
* FIXME: Once force-unloading keys is correctly fixed, I'll fix
* this code that closes some of the registry keys that were opened
* inside the hives we've just unmounted above...
*/
/* Remove the registry root keys */
for (i = 0; i < ARRAYSIZE(RootKeys); ++i)
{
if (RootKeys[i].Handle)
{
/**/NtFlushKey(RootKeys[i].Handle);/**/ // FIXME: Why does it hang? Answer: because we have some problems in CMAPI!
NtDeleteKey(RootKeys[i].Handle);
NtClose(RootKeys[i].Handle);
RootKeys[i].Handle = NULL;
}
} }
// //
@ -1465,6 +1504,7 @@ RegCleanupRegistry(
RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, PrivilegeSet[0], FALSE, &PrivilegeSet[0]); RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, PrivilegeSet[0], FALSE, &PrivilegeSet[0]);
} }
VOID VOID
SetDefaultPagefile( SetDefaultPagefile(
WCHAR Drive) WCHAR Drive)

View file

@ -46,7 +46,7 @@ ImportRegistryFile(
NTSTATUS NTSTATUS
VerifyRegistryHives( VerifyRegistryHives(
IN PUNICODE_STRING InstallPath, IN PUNICODE_STRING InstallPath,
OUT PBOOLEAN ShouldUpdateRegistry); OUT PBOOLEAN ShouldRepairRegistry);
NTSTATUS NTSTATUS
RegInitializeRegistry( RegInitializeRegistry(

View file

@ -4079,32 +4079,32 @@ RegistryPage(PINPUT_RECORD Ir)
PWSTR Action; PWSTR Action;
PWSTR File; PWSTR File;
PWSTR Section; PWSTR Section;
BOOLEAN Success;
BOOLEAN ShouldRepairRegistry = FALSE;
BOOLEAN Delete; BOOLEAN Delete;
MUIDisplayPage(REGISTRY_PAGE); MUIDisplayPage(REGISTRY_PAGE);
if (RepairUpdateFlag) if (RepairUpdateFlag)
{ {
BOOLEAN ShouldUpdateRegistry = FALSE;
DPRINT1("TODO: Updating / repairing the registry is not completely implemented yet!\n"); DPRINT1("TODO: Updating / repairing the registry is not completely implemented yet!\n");
/* Verify the registry hives and check whether we need to update or repair any of them */ /* Verify the registry hives and check whether we need to update or repair any of them */
Status = VerifyRegistryHives(&DestinationPath, &ShouldUpdateRegistry); Status = VerifyRegistryHives(&DestinationPath, &ShouldRepairRegistry);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("VerifyRegistryHives failed, Status 0x%08lx\n", Status); DPRINT1("VerifyRegistryHives failed, Status 0x%08lx\n", Status);
ShouldUpdateRegistry = FALSE; ShouldRepairRegistry = FALSE;
}
if (!ShouldUpdateRegistry)
{
DPRINT1("No need to update the registry\n");
// return SUCCESS_PAGE;
goto Quit;
} }
if (!ShouldRepairRegistry)
DPRINT1("No need to repair the registry\n");
} }
/* Initialize the registry and setup the default installation hives */ DoUpdate:
/* Update the registry */
CONSOLE_SetStatusText(MUIGetString(STRING_REGHIVEUPDATE));
/* Initialize the registry and setup the registry hives */
Status = RegInitializeRegistry(&DestinationPath); Status = RegInitializeRegistry(&DestinationPath);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
@ -4124,15 +4124,42 @@ RegistryPage(PINPUT_RECORD Ir)
return QUIT_PAGE; return QUIT_PAGE;
} }
/* Update registry */ if (!RepairUpdateFlag || ShouldRepairRegistry)
CONSOLE_SetStatusText(MUIGetString(STRING_REGHIVEUPDATE)); {
/*
* We fully setup the hives, in case we are doing a fresh installation
* (RepairUpdateFlag == FALSE), or in case we are doing an update
* (RepairUpdateFlag == TRUE) BUT we have some registry hives to
* "repair" (aka. recreate: ShouldRepairRegistry == TRUE).
*/
if (!SetupFindFirstLineW(SetupInf, L"HiveInfs.Install", NULL, &InfContext)) Success = SetupFindFirstLineW(SetupInf, L"HiveInfs.Fresh", NULL, &InfContext); // Windows-compatible
if (!Success)
Success = SetupFindFirstLineW(SetupInf, L"HiveInfs.Install", NULL, &InfContext); // ReactOS-specific
if (!Success)
{ {
DPRINT1("SetupFindFirstLine() failed\n"); DPRINT1("SetupFindFirstLine() failed\n");
MUIDisplayError(ERROR_FIND_REGISTRY, Ir, POPUP_WAIT_ENTER); MUIDisplayError(ERROR_FIND_REGISTRY, Ir, POPUP_WAIT_ENTER);
goto Cleanup; goto Cleanup;
} }
}
else // if (RepairUpdateFlag && !ShouldRepairRegistry)
{
/*
* In case we are doing an update (RepairUpdateFlag == TRUE) and
* NO registry hives need a repair (ShouldRepairRegistry == FALSE),
* we only update the hives.
*/
Success = SetupFindFirstLineW(SetupInf, L"HiveInfs.Upgrade", NULL, &InfContext);
if (!Success)
{
/* Nothing to do for update! */
DPRINT1("No update needed for the registry!\n");
goto Cleanup;
}
}
do do
{ {
@ -4150,7 +4177,10 @@ RegistryPage(PINPUT_RECORD Ir)
else if (!_wcsicmp(Action, L"DelReg")) else if (!_wcsicmp(Action, L"DelReg"))
Delete = TRUE; Delete = TRUE;
else else
{
DPRINT1("Unrecognized registry INF action '%S'\n", Action);
continue; continue;
}
CONSOLE_SetStatusText(MUIGetString(STRING_IMPORTFILE), File); CONSOLE_SetStatusText(MUIGetString(STRING_IMPORTFILE), File);
@ -4162,6 +4192,10 @@ RegistryPage(PINPUT_RECORD Ir)
} }
} while (SetupFindNextLine(&InfContext, &InfContext)); } while (SetupFindNextLine(&InfContext, &InfContext));
if (!RepairUpdateFlag || ShouldRepairRegistry)
{
/* See the explanation for this test above */
/* Update display registry settings */ /* Update display registry settings */
CONSOLE_SetStatusText(MUIGetString(STRING_DISPLAYETTINGSUPDATE)); CONSOLE_SetStatusText(MUIGetString(STRING_DISPLAYETTINGSUPDATE));
if (!ProcessDisplayRegistry(SetupInf, DisplayList)) if (!ProcessDisplayRegistry(SetupInf, DisplayList))
@ -4218,6 +4252,7 @@ RegistryPage(PINPUT_RECORD Ir)
/* Update the mounted devices list */ /* Update the mounted devices list */
// FIXME: This should technically be done by mountmgr (if AutoMount is enabled)! // FIXME: This should technically be done by mountmgr (if AutoMount is enabled)!
SetMountedDeviceValues(PartitionList); SetMountedDeviceValues(PartitionList);
}
Cleanup: Cleanup:
// //
@ -4226,7 +4261,18 @@ Cleanup:
// //
RegCleanupRegistry(&DestinationPath); RegCleanupRegistry(&DestinationPath);
Quit: /*
* Check whether we were in update/repair mode but we were actually
* repairing the registry hives. If so, we have finished repairing them,
* and we now reset the flag and run the proper registry update.
* Otherwise we have finished the registry update!
*/
if (RepairUpdateFlag && ShouldRepairRegistry)
{
ShouldRepairRegistry = FALSE;
goto DoUpdate;
}
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
CONSOLE_SetStatusText(MUIGetString(STRING_DONE)); CONSOLE_SetStatusText(MUIGetString(STRING_DONE));

View file

@ -524,7 +524,12 @@ Default = "XT-, AT- or extended keyboard (83-105 keys)"
0000048F = kbdeo.dll 0000048F = kbdeo.dll
[HiveInfs.Install] [HiveInfs.Install]
AddReg=caroots.inf,AddReg ; Called "HiveInfs.Fresh" on Windows
AddReg=registry.inf,AddReg AddReg = caroots.inf,AddReg
AddReg = registry.inf,AddReg
[HiveInfs.Upgrade]
DelReg = registry.inf,DelReg
AddReg = registry.inf,AddReg
; EOF ; EOF