mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 07:32:57 +00:00
[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:
parent
b20908acc8
commit
7fedeb7db3
4 changed files with 194 additions and 103 deletions
|
@ -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)
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -524,7 +524,12 @@ Default = "XT-, AT- or extended keyboard (83-105 keys)"
|
||||||
0000048F = kbdeo.dll
|
0000048F = kbdeo.dll
|
||||||
|
|
||||||
[HiveInfs.Install]
|
[HiveInfs.Install]
|
||||||
|
; Called "HiveInfs.Fresh" on Windows
|
||||||
AddReg = caroots.inf,AddReg
|
AddReg = caroots.inf,AddReg
|
||||||
AddReg = registry.inf,AddReg
|
AddReg = registry.inf,AddReg
|
||||||
|
|
||||||
|
[HiveInfs.Upgrade]
|
||||||
|
DelReg = registry.inf,DelReg
|
||||||
|
AddReg = registry.inf,AddReg
|
||||||
|
|
||||||
; EOF
|
; EOF
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue