0

updater: reduce installer error overlaps with Windows/other error codes

To allow for the metainstaller process exit code to be meaningful, this
CL moves all metainstaller/updater error codes above 0xFFFF (65535) for
Windows only, which is the range of Windows error codes.

With this CL:
* Metainstaller error codes are in the 73000 range.
* Error codes funnelled through `update_client` are in the 74000 range.
* updater error codes are in the 75000 range.

Low-Coverage-Reason: HARD_TO_TEST
Fixed: b/40863154,b/352650305
Change-Id: I26c232b4cf19d15e52a8de444a0b8a6a8fc2c753
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5704279
Commit-Queue: Sorin Jianu <sorin@chromium.org>
Reviewed-by: Sorin Jianu <sorin@chromium.org>
Auto-Submit: S Ganesh <ganesh@chromium.org>
Commit-Queue: S Ganesh <ganesh@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1327087}
This commit is contained in:
S. Ganesh
2024-07-13 00:40:17 +00:00
committed by Chromium LUCI CQ
parent d3f53264ff
commit dba3f73715
10 changed files with 146 additions and 120 deletions

@ -172,7 +172,7 @@ TEST_F(AppServerTestCase, SelfPromoteFails) {
EXPECT_CALL(*app, ActiveDuty).Times(0);
EXPECT_CALL(*app, SwapInNewVersion).WillOnce(Return(false));
EXPECT_CALL(*app, UninstallSelf).Times(0);
EXPECT_EQ(app->Run(), 2);
EXPECT_EQ(app->Run(), kErrorFailedToSwap);
}
scoped_refptr<GlobalPrefs> global_prefs =
CreateGlobalPrefs(GetUpdaterScopeForTesting());
@ -253,7 +253,7 @@ TEST_F(AppServerTestCase, StateDirtySwapFails) {
EXPECT_CALL(*app, ActiveDuty).Times(0);
EXPECT_CALL(*app, SwapInNewVersion).WillOnce(Return(false));
EXPECT_CALL(*app, UninstallSelf).Times(0);
EXPECT_EQ(app->Run(), 2);
EXPECT_EQ(app->Run(), kErrorFailedToSwap);
}
scoped_refptr<GlobalPrefs> global_prefs =
CreateGlobalPrefs(GetUpdaterScopeForTesting());

@ -203,7 +203,7 @@ TEST_F(LegacyAppCommandWebImplTest, FailedToLaunchStatus) {
EXPECT_EQ(command_id, base::WideToASCII(kCmdId1));
EXPECT_EQ(error_params.error_code,
HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
EXPECT_EQ(error_params.extra_code1, 105);
EXPECT_EQ(error_params.extra_code1, kErrorAppCommandLaunchFailed);
}),
app_command_web));

@ -271,11 +271,17 @@ extern const char kUserDefaultsSuiteName[];
// Install Errors.
//
// Specific install errors for the updater are reported in such a way that
// their range does not conflict with the range of generic errors defined by
// the |update_client| module.
// Specific errors for the updater that are passed through `update_client` are
// reported in such a way that their range does not conflict with the range of
// generic errors defined by the metainstaller, the `update_client` module, or
// Windows.
#if BUILDFLAG(IS_WIN)
inline constexpr int kCustomInstallErrorBase =
static_cast<int>(update_client::InstallError::CUSTOM_ERROR_BASE) + 74000;
#else
inline constexpr int kCustomInstallErrorBase =
static_cast<int>(update_client::InstallError::CUSTOM_ERROR_BASE);
#endif
// Running the application installer failed.
inline constexpr int kErrorApplicationInstallerFailed =
@ -310,148 +316,167 @@ inline constexpr int kErrorAppCommandLaunchFailed = kCustomInstallErrorBase + 5;
// `error`.
inline constexpr int kErrorAppCommandTimedOut = kCustomInstallErrorBase + 6;
// Specific error codes for the updater are reported in such a way that their
// range does not conflict with the range of generic errors defined by the
// metainstaller, the `update_client` module, or Windows.
#if BUILDFLAG(IS_WIN)
inline constexpr int kUpdaterErrorBase = 75000;
#else
inline constexpr int kUpdaterErrorBase = 0;
#endif
// Error codes.
//
// The server process may exit with any of these exit codes.
inline constexpr int kErrorOk = 0;
// The server could not acquire the lock needed to run.
inline constexpr int kErrorFailedToLockPrefsMutex = 1;
inline constexpr int kErrorFailedToLockPrefsMutex = kUpdaterErrorBase + 1;
// The server candidate failed to promote itself to active.
inline constexpr int kErrorFailedToSwap = 2;
inline constexpr int kErrorFailedToSwap = kUpdaterErrorBase + 2;
inline constexpr int kErrorRegistrationFailed = 3;
inline constexpr int kErrorPermissionDenied = 4;
inline constexpr int kErrorWaitFailedUninstall = 5;
inline constexpr int kErrorWaitFailedInstall = 6;
inline constexpr int kErrorPathServiceFailed = 7;
inline constexpr int kErrorComInitializationFailed = 8;
inline constexpr int kErrorUnknownCommandLine = 9;
inline constexpr int kErrorNoVersionedDirectory = 11;
inline constexpr int kErrorNoBaseDirectory = 12;
inline constexpr int kErrorPathTooLong = 13;
inline constexpr int kErrorProcessLaunchFailed = 14;
inline constexpr int kErrorRegistrationFailed = kUpdaterErrorBase + 3;
inline constexpr int kErrorPermissionDenied = kUpdaterErrorBase + 4;
inline constexpr int kErrorWaitFailedUninstall = kUpdaterErrorBase + 5;
inline constexpr int kErrorWaitFailedInstall = kUpdaterErrorBase + 6;
inline constexpr int kErrorPathServiceFailed = kUpdaterErrorBase + 7;
inline constexpr int kErrorComInitializationFailed = kUpdaterErrorBase + 8;
inline constexpr int kErrorUnknownCommandLine = kUpdaterErrorBase + 9;
inline constexpr int kErrorNoVersionedDirectory = kUpdaterErrorBase + 11;
inline constexpr int kErrorNoBaseDirectory = kUpdaterErrorBase + 12;
inline constexpr int kErrorPathTooLong = kUpdaterErrorBase + 13;
inline constexpr int kErrorProcessLaunchFailed = kUpdaterErrorBase + 14;
// Failed to copy the updater's bundle.
inline constexpr int kErrorFailedToCopyBundle = 15;
inline constexpr int kErrorFailedToCopyBundle = kUpdaterErrorBase + 15;
// Failed to delete the updater's install folder.
inline constexpr int kErrorFailedToDeleteFolder = 16;
inline constexpr int kErrorFailedToDeleteFolder = kUpdaterErrorBase + 16;
// Failed to delete the updater's data folder.
inline constexpr int kErrorFailedToDeleteDataFolder = 17;
inline constexpr int kErrorFailedToDeleteDataFolder = kUpdaterErrorBase + 17;
// Failed to get versioned updater folder path.
inline constexpr int kErrorFailedToGetVersionedInstallDirectory = 18;
inline constexpr int kErrorFailedToGetVersionedInstallDirectory =
kUpdaterErrorBase + 18;
// Failed to get the install directory.
inline constexpr int kErrorFailedToGetInstallDir = 19;
inline constexpr int kErrorFailedToGetInstallDir = kUpdaterErrorBase + 19;
// Failed to remove the active(unversioned) update service job from Launchd.
inline constexpr int kErrorFailedToRemoveActiveUpdateServiceJobFromLaunchd = 20;
inline constexpr int kErrorFailedToRemoveActiveUpdateServiceJobFromLaunchd =
kUpdaterErrorBase + 20;
// Failed to remove versioned update service job from Launchd.
inline constexpr int kErrorFailedToRemoveCandidateUpdateServiceJobFromLaunchd =
21;
kUpdaterErrorBase + 21;
// Failed to remove versioned update service internal job from Launchd.
inline constexpr int kErrorFailedToRemoveUpdateServiceInternalJobFromLaunchd =
22;
kUpdaterErrorBase + 22;
// Failed to remove versioned wake job from Launchd.
inline constexpr int kErrorFailedToRemoveWakeJobFromLaunchd = 23;
inline constexpr int kErrorFailedToRemoveWakeJobFromLaunchd =
kUpdaterErrorBase + 23;
// Failed to create the active(unversioned) update service Launchd plist.
inline constexpr int kErrorFailedToCreateUpdateServiceLaunchdJobPlist = 24;
inline constexpr int kErrorFailedToCreateUpdateServiceLaunchdJobPlist =
kUpdaterErrorBase + 24;
// Failed to create the versioned update service Launchd plist.
inline constexpr int kErrorFailedToCreateVersionedUpdateServiceLaunchdJobPlist =
25;
kUpdaterErrorBase + 25;
// Failed to create the versioned update service internal Launchd plist.
inline constexpr int kErrorFailedToCreateUpdateServiceInternalLaunchdJobPlist =
26;
kUpdaterErrorBase + 26;
// Failed to create the versioned wake Launchd plist.
inline constexpr int kErrorFailedToCreateWakeLaunchdJobPlist = 27;
inline constexpr int kErrorFailedToCreateWakeLaunchdJobPlist =
kUpdaterErrorBase + 27;
// Failed to start the active(unversioned) update service job.
inline constexpr int kErrorFailedToStartLaunchdActiveServiceJob = 28;
inline constexpr int kErrorFailedToStartLaunchdActiveServiceJob =
kUpdaterErrorBase + 28;
// Failed to start the versioned update service job.
inline constexpr int kErrorFailedToStartLaunchdVersionedServiceJob = 29;
inline constexpr int kErrorFailedToStartLaunchdVersionedServiceJob =
kUpdaterErrorBase + 29;
// Failed to start the update service internal job.
inline constexpr int kErrorFailedToStartLaunchdUpdateServiceInternalJob = 30;
inline constexpr int kErrorFailedToStartLaunchdUpdateServiceInternalJob =
kUpdaterErrorBase + 30;
// Failed to start the wake job.
inline constexpr int kErrorFailedToStartLaunchdWakeJob = 31;
inline constexpr int kErrorFailedToStartLaunchdWakeJob = kUpdaterErrorBase + 31;
// Timed out while awaiting launchctl to become aware of the update service
// internal job.
inline constexpr int kErrorFailedAwaitingLaunchdUpdateServiceInternalJob = 32;
inline constexpr int kErrorFailedAwaitingLaunchdUpdateServiceInternalJob =
kUpdaterErrorBase + 32;
// DM registration failure with mandatory enrollment.
inline constexpr int kErrorDMRegistrationFailed = 33;
inline constexpr int kErrorDMRegistrationFailed = kUpdaterErrorBase + 33;
inline constexpr int kErrorFailedToInstallLegacyUpdater = 34;
inline constexpr int kErrorFailedToInstallLegacyUpdater =
kUpdaterErrorBase + 34;
// A Mojo remote was unexpectedly disconnected.
inline constexpr int kErrorIpcDisconnect = 35;
inline constexpr int kErrorIpcDisconnect = kUpdaterErrorBase + 35;
// Failed to copy the updater binary.
inline constexpr int kErrorFailedToCopyBinary = 36;
inline constexpr int kErrorFailedToCopyBinary = kUpdaterErrorBase + 36;
// Failed to delete a socket file.
inline constexpr int kErrorFailedToDeleteSocket = 37;
inline constexpr int kErrorFailedToDeleteSocket = kUpdaterErrorBase + 37;
// Failed to create a symlink to the current version.
inline constexpr int kErrorFailedToLinkCurrent = 38;
inline constexpr int kErrorFailedToLinkCurrent = kUpdaterErrorBase + 38;
// Failed to rename the current symlink during activation.
inline constexpr int kErrorFailedToRenameCurrent = 39;
inline constexpr int kErrorFailedToRenameCurrent = kUpdaterErrorBase + 39;
// Failed to install one or more Systemd units.
inline constexpr int kErrorFailedToInstallSystemdUnit = 40;
inline constexpr int kErrorFailedToInstallSystemdUnit = kUpdaterErrorBase + 40;
// Failed to remove one or more Systemd units during uninstallation.
inline constexpr int kErrorFailedToRemoveSystemdUnit = 41;
inline constexpr int kErrorFailedToRemoveSystemdUnit = kUpdaterErrorBase + 41;
// Running as the wrong user for the provided UpdaterScope.
inline constexpr int kErrorWrongUser = 42;
inline constexpr int kErrorWrongUser = kUpdaterErrorBase + 42;
// Failed to get the setup files.
inline constexpr int kErrorFailedToGetSetupFiles = 43;
inline constexpr int kErrorFailedToGetSetupFiles = kUpdaterErrorBase + 43;
// Failed to run install list.
inline constexpr int kErrorFailedToRunInstallList = 44;
inline constexpr int kErrorFailedToRunInstallList = kUpdaterErrorBase + 44;
// The server was running but had no tasks to do.
inline constexpr int kErrorIdle = 45;
inline constexpr int kErrorIdle = kUpdaterErrorBase + 45;
// The call was rejected because the user needs to accept the EULA / Terms of
// service.
inline constexpr int kErrorEulaRequired = 46;
inline constexpr int kErrorEulaRequired = kUpdaterErrorBase + 46;
// The current operating system is not supported.
inline constexpr int kErrorUnsupportedOperatingSystem = 47;
inline constexpr int kErrorUnsupportedOperatingSystem = kUpdaterErrorBase + 47;
inline constexpr int kErrorTagParsing = 50;
inline constexpr int kErrorTagParsing = kUpdaterErrorBase + 50;
// Metainstaller errors.
inline constexpr int kErrorCreatingTempDir = 60;
inline constexpr int kErrorUnpackingResource = 61;
inline constexpr int kErrorInitializingBackupDir = 62;
inline constexpr int kErrorCreatingTempDir = kUpdaterErrorBase + 60;
inline constexpr int kErrorUnpackingResource = kUpdaterErrorBase + 61;
inline constexpr int kErrorInitializingBackupDir = kUpdaterErrorBase + 62;
// Launcher errors.
constexpr int kErrorGettingUpdaterPath = 71;
constexpr int kErrorStattingPath = 72;
constexpr int kErrorLaunchingProcess = 73;
constexpr int kErrorPathOwnershipMismatch = 74;
inline constexpr int kErrorGettingUpdaterPath = kUpdaterErrorBase + 71;
inline constexpr int kErrorStattingPath = kUpdaterErrorBase + 72;
inline constexpr int kErrorLaunchingProcess = kUpdaterErrorBase + 73;
inline constexpr int kErrorPathOwnershipMismatch = kUpdaterErrorBase + 74;
// A setup process could not acquire the lock needed to run.
inline constexpr int kErrorFailedToLockSetupMutex = 75;
inline constexpr int kErrorFailedToLockSetupMutex = kUpdaterErrorBase + 75;
// Policy Management constants.
// The maximum value allowed for policy AutoUpdateCheckPeriodMinutes.

@ -10,26 +10,27 @@ namespace updater {
// Installer process exit codes (the underlying type is uint32_t).
enum ExitCode {
SUCCESS_EXIT_CODE = 0,
TEMP_DIR_FAILED = 11, // Unable to get Temp directory.
UNPACKING_FAILED = 57, // Unpacking the uncompressed archive failed.
GENERIC_INITIALIZATION_FAILURE = 101,
COMMAND_STRING_OVERFLOW = 105,
WAIT_FOR_PROCESS_FAILED = 107,
PATH_STRING_OVERFLOW = 108,
UNABLE_TO_GET_WORK_DIRECTORY = 109,
UNABLE_TO_EXTRACT_ARCHIVE = 112,
UNEXPECTED_ELEVATION_LOOP = 113,
UNEXPECTED_DE_ELEVATION_LOOP = 114,
UNEXPECTED_ELEVATION_LOOP_SILENT = 115,
UNABLE_TO_SET_DIRECTORY_ACL = 117,
INVALID_OPTION = 118,
FAILED_TO_ELEVATE_METAINSTALLER = 119,
FAILED_TO_DE_ELEVATE_METAINSTALLER = 120,
RUN_SETUP_FAILED_FILE_NOT_FOUND = 122, // ERROR_FILE_NOT_FOUND.
RUN_SETUP_FAILED_PATH_NOT_FOUND = 123, // ERROR_PATH_NOT_FOUND.
RUN_SETUP_FAILED_COULD_NOT_CREATE_PROCESS = 124, // All other errors.
UNSUPPORTED_WINDOWS_VERSION = 125,
UNABLE_TO_GET_EXE_PATH = 126,
TEMP_DIR_FAILED = 73011, // Unable to get Temp directory.
UNPACKING_FAILED = 73057, // Unpacking the uncompressed archive failed.
GENERIC_INITIALIZATION_FAILURE = 73101,
COMMAND_STRING_OVERFLOW = 73105,
WAIT_FOR_PROCESS_FAILED = 73107,
PATH_STRING_OVERFLOW = 73108,
UNABLE_TO_GET_WORK_DIRECTORY = 73109,
UNABLE_TO_EXTRACT_ARCHIVE = 73112,
UNEXPECTED_ELEVATION_LOOP = 73113,
UNEXPECTED_DE_ELEVATION_LOOP = 73114,
UNEXPECTED_ELEVATION_LOOP_SILENT = 73115,
UNABLE_TO_SET_DIRECTORY_ACL = 73117,
INVALID_OPTION = 73118,
FAILED_TO_ELEVATE_METAINSTALLER = 73119,
FAILED_TO_DE_ELEVATE_METAINSTALLER = 73120,
RUN_SETUP_FAILED_FILE_NOT_FOUND = 73122, // ERROR_FILE_NOT_FOUND.
RUN_SETUP_FAILED_PATH_NOT_FOUND = 73123, // ERROR_PATH_NOT_FOUND.
RUN_SETUP_FAILED_COULD_NOT_CREATE_PROCESS = 73124, // All other errors.
UNSUPPORTED_WINDOWS_VERSION = 73125,
UNABLE_TO_GET_EXE_PATH = 73126,
UPDATER_EXIT_CODE = 73500,
};
} // namespace updater

@ -45,6 +45,7 @@
#include "chrome/updater/win/installer/configuration.h"
#include "chrome/updater/win/installer/installer_constants.h"
#include "chrome/updater/win/installer/pe_resource.h"
#include "chrome/updater/win/ui/l10n_util.h"
namespace updater {
@ -110,10 +111,11 @@ ProcessExitResult RunProcessAndWait(const wchar_t* exe_path, wchar_t* cmdline) {
::CloseHandle(pi.hThread);
DWORD exit_code = SUCCESS_EXIT_CODE;
DWORD updater_exit_code = 0;
DWORD wr = ::WaitForSingleObject(pi.hProcess, INFINITE);
if (WAIT_OBJECT_0 != wr || !::GetExitCodeProcess(pi.hProcess, &exit_code)) {
// Note: We've assumed that WAIT_OBJCT_0 != wr means a failure. The call
if (WAIT_OBJECT_0 != wr ||
!::GetExitCodeProcess(pi.hProcess, &updater_exit_code)) {
// Note: We've assumed that WAIT_OBJECT_0 != wr means a failure. The call
// could return a different object but since we never spawn more than one
// sub-process at a time that case should never happen.
return ProcessExitResult(WAIT_FOR_PROCESS_FAILED, ::GetLastError());
@ -121,7 +123,7 @@ ProcessExitResult RunProcessAndWait(const wchar_t* exe_path, wchar_t* cmdline) {
::CloseHandle(pi.hProcess);
return ProcessExitResult(exit_code);
return ProcessExitResult(UPDATER_EXIT_CODE, updater_exit_code);
}
// Windows defined callback used in the EnumResourceNames call. For each
@ -485,11 +487,25 @@ ProcessExitResult InstallerMain(HMODULE module) {
return exit_code;
}
ProcessExitResult WMain(HMODULE module) {
const updater::ProcessExitResult result = InstallerMain(module);
int WMain(HMODULE module) {
const ProcessExitResult result = InstallerMain(module);
VLOG(1) << "Metainstaller WMain returned: " << result.exit_code
<< ", Windows error: " << result.windows_error;
return result;
// Display UI only for metainstaller errors.
if (result.exit_code != SUCCESS_EXIT_CODE &&
result.exit_code != UPDATER_EXIT_CODE &&
!GetCommandLineLegacyCompatible().HasSwitch(kSilentSwitch)) {
base::FilePath exe_path;
base::PathService::Get(base::FILE_EXE, &exe_path);
::MessageBoxEx(nullptr,
GetLocalizedMetainstallerErrorString(result.exit_code,
result.windows_error)
.c_str(),
exe_path.BaseName().value().c_str(), 0, 0);
}
return result.exit_code == UPDATER_EXIT_CODE ? result.windows_error
: result.exit_code;
}
} // namespace updater

@ -50,7 +50,7 @@ ProcessExitResult BuildInstallerCommandLineArguments(
ProcessExitResult HandleRunElevated(const base::CommandLine& command_line);
// Main function for the installer.
ProcessExitResult WMain(HMODULE module);
int WMain(HMODULE module);
} // namespace updater

@ -9,13 +9,7 @@
#include <string>
#include "base/at_exit.h"
#include "base/base_paths.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/updater/updater_branding.h"
#include "chrome/updater/win/installer/installer.h"
#include "chrome/updater/win/ui/l10n_util.h"
// http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx
extern "C" IMAGE_DOS_HEADER __ImageBase;
@ -25,23 +19,5 @@ int WINAPI wWinMain(HINSTANCE /* instance */,
LPWSTR command_line,
int /* command_show */) {
base::AtExitManager exit_manager;
updater::ProcessExitResult result =
updater::WMain(reinterpret_cast<HMODULE>(&__ImageBase));
// If errors occur, display UI only for metainstaller errors, and also only
// when the metainstaller runs without command line arguments.
if (result.exit_code != updater::SUCCESS_EXIT_CODE &&
wcslen(command_line) == 0) {
const std::wstring metainstaller_error_string =
updater::GetLocalizedMetainstallerErrorString(result.exit_code,
result.windows_error);
if (!metainstaller_error_string.empty()) {
base::FilePath exe_path;
base::PathService::Get(base::FILE_EXE, &exe_path);
::MessageBoxEx(nullptr, metainstaller_error_string.c_str(),
exe_path.BaseName().value().c_str(), 0, 0);
}
}
return result.exit_code;
return updater::WMain(reinterpret_cast<HMODULE>(&__ImageBase));
}

@ -109,7 +109,9 @@ std::wstring GetLocalizedMetainstallerErrorString(DWORD exit_code,
case FAILED_TO_ELEVATE_METAINSTALLER:
return GetLocalizedStringF(IDS_FAILED_TO_ELEVATE_METAINSTALLER_BASE,
GetTextForSystemError(windows_error));
case UPDATER_EXIT_CODE:
default:
NOTREACHED_IN_MIGRATION();
return {};
}
#undef METAINSTALLER_ERROR_SWITCH_ENTRY

@ -288,9 +288,6 @@ INSTANTIATE_TEST_SUITE_P(
{FAILED_TO_ELEVATE_METAINSTALLER, ERROR_CANCELLED,
GetLocalizedStringF(IDS_FAILED_TO_ELEVATE_METAINSTALLER_BASE,
GetTextForSystemError(ERROR_CANCELLED))},
// This is an `updater.exe` error, not a metainstaller error.
{kErrorTagParsing, 0, {}},
}));
TEST_P(GetLocalizedMetainstallerErrorStringTest, TestCases) {

@ -135,9 +135,18 @@ Command line arguments for the updater client are documented in the [functional
## Error codes
The updater setup process can exit with the following error codes:
* UNEXPECTED_ELEVATION_LOOP = 113: This error code indicates that the
updater setup failed to elevate itself when trying to install a system app.
To allow for the updater metainstaller process exit codes to be meaningful, all
metainstaller and updater error codes are in a range above 0xFFFF (65535) for
Windows only, which is the range of Windows error codes.
Specifically:
* [Metainstaller error codes](https://source.chromium.org/chromium/chromium/src/+/main:chrome/updater/win/installer/exit_code.h)
are in the 73000 range.
* Error codes
[funnelled through `update_client`](https://source.chromium.org/search?q=kCustomInstallErrorBase&sq=&ss=chromium%2Fchromium%2Fsrc:chrome%2Fupdater%2F)
are in the 74000 range.
* [updater error codes](https://source.chromium.org/chromium/chromium/src/+/main:chrome/updater/constants.h?q=%22%2F%2F%20Error%20codes.%22&ss=chromium%2Fchromium%2Fsrc:chrome%2Fupdater%2F)
are in the 75000 range.
## Dynamic Install Parameters