Commit 31a33e1b authored by Greg Thompson's avatar Greg Thompson Committed by Commit Bot

Report finer-grained errors for failures to launch setup.exe.

Specifically, this replaces exit code 106 (COULD_NOT_CREATE_PROCESS)
with six new codes to help diagnose these failures.

BUG=672813

Change-Id: I6a482761c34ae06c4f438aa2a30d7bd69afdf819
Reviewed-on: https://chromium-review.googlesource.com/601987Reviewed-by: default avatarSigurður Ásgeirsson <siggi@chromium.org>
Commit-Queue: Greg Thompson <grt@chromium.org>
Cr-Commit-Position: refs/heads/master@{#492009}
parent 042810ea
...@@ -20,7 +20,7 @@ enum ExitCode { ...@@ -20,7 +20,7 @@ enum ExitCode {
// DEPRECATED_SETUP_FAILURE = 103, // DEPRECATED_SETUP_FAILURE = 103,
// NO_PREVIOUS_SETUP_PATH = 104, // NO_PREVIOUS_SETUP_PATH = 104,
COMMAND_STRING_OVERFLOW = 105, COMMAND_STRING_OVERFLOW = 105,
COULD_NOT_CREATE_PROCESS = 106, // COULD_NOT_CREATE_PROCESS = 106,
WAIT_FOR_PROCESS_FAILED = 107, WAIT_FOR_PROCESS_FAILED = 107,
PATH_STRING_OVERFLOW = 108, PATH_STRING_OVERFLOW = 108,
UNABLE_TO_GET_WORK_DIRECTORY = 109, UNABLE_TO_GET_WORK_DIRECTORY = 109,
...@@ -33,6 +33,15 @@ enum ExitCode { ...@@ -33,6 +33,15 @@ enum ExitCode {
UNABLE_TO_EXTRACT_SETUP = 116, UNABLE_TO_EXTRACT_SETUP = 116,
UNABLE_TO_SET_DIRECTORY_ACL = 117, UNABLE_TO_SET_DIRECTORY_ACL = 117,
INVALID_OPTION = 118, INVALID_OPTION = 118,
// These next codes specifically mean that the attempt to launch the previous
// setup.exe to patch it failed.
SETUP_PATCH_FAILED_FILE_NOT_FOUND = 119, // ERROR_FILE_NOT_FOUND.
SETUP_PATCH_FAILED_PATH_NOT_FOUND = 120, // ERROR_PATH_NOT_FOUND.
SETUP_PATCH_FAILED_COULD_NOT_CREATE_PROCESS = 121, // All other errors.
// As above, but for running the new setup.exe to handle an install.
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.
}; };
} // namespace mini_installer } // namespace mini_installer
......
...@@ -193,14 +193,40 @@ ProcessExitResult GetPreviousSetupExePath(const Configuration& configuration, ...@@ -193,14 +193,40 @@ ProcessExitResult GetPreviousSetupExePath(const Configuration& configuration,
} }
// Calls CreateProcess with good default parameters and waits for the process to // Calls CreateProcess with good default parameters and waits for the process to
// terminate returning the process exit code. |exit_code|, if non-NULL, is // terminate returning the process exit code. In case of CreateProcess failure,
// populated with the process exit code. // returns a results object with the provided codes as follows:
ProcessExitResult RunProcessAndWait(const wchar_t* exe_path, wchar_t* cmdline) { // - ERROR_FILE_NOT_FOUND: (file_not_found_code, attributes of setup.exe).
// - ERROR_PATH_NOT_FOUND: (path_not_found_code, attributes of setup.exe).
// - Otherwise: (generic_failure_code, CreateProcess error code).
// In case of error waiting for the process to exit, returns a results object
// with (WAIT_FOR_PROCESS_FAILED, last error code). Otherwise, returns a results
// object with the subprocess's exit code.
ProcessExitResult RunProcessAndWait(const wchar_t* exe_path,
wchar_t* cmdline,
DWORD file_not_found_code,
DWORD path_not_found_code,
DWORD generic_failure_code) {
STARTUPINFOW si = {sizeof(si)}; STARTUPINFOW si = {sizeof(si)};
PROCESS_INFORMATION pi = {0}; PROCESS_INFORMATION pi = {0};
if (!::CreateProcess(exe_path, cmdline, NULL, NULL, FALSE, CREATE_NO_WINDOW, if (!::CreateProcess(exe_path, cmdline, NULL, NULL, FALSE, CREATE_NO_WINDOW,
NULL, NULL, &si, &pi)) { NULL, NULL, &si, &pi)) {
return ProcessExitResult(COULD_NOT_CREATE_PROCESS, ::GetLastError()); // Split specific failure modes. If setup.exe couldn't be launched because
// its file/path couldn't be found, report its attributes in ExtraCode1.
// This will help diagnose the prevalence of launch failures due to Image
// File Execution Options tampering. See https://crbug.com/672813 for more
// details.
const DWORD last_error = ::GetLastError();
const DWORD attributes = ::GetFileAttributes(exe_path);
switch (last_error) {
case ERROR_FILE_NOT_FOUND:
return ProcessExitResult(file_not_found_code, attributes);
case ERROR_PATH_NOT_FOUND:
return ProcessExitResult(path_not_found_code, attributes);
default:
break;
}
// Lump all other errors into a distinct failure bucket.
return ProcessExitResult(generic_failure_code, last_error);
} }
::CloseHandle(pi.hThread); ::CloseHandle(pi.hThread);
...@@ -387,8 +413,12 @@ ProcessExitResult UnpackBinaryResources(const Configuration& configuration, ...@@ -387,8 +413,12 @@ ProcessExitResult UnpackBinaryResources(const Configuration& configuration,
// on to setup.exe. // on to setup.exe.
AppendCommandLineFlags(configuration.command_line(), &cmd_line); AppendCommandLineFlags(configuration.command_line(), &cmd_line);
if (exit_code.IsSuccess()) if (exit_code.IsSuccess()) {
exit_code = RunProcessAndWait(exe_path.get(), cmd_line.get()); exit_code = RunProcessAndWait(
exe_path.get(), cmd_line.get(), SETUP_PATCH_FAILED_FILE_NOT_FOUND,
SETUP_PATCH_FAILED_PATH_NOT_FOUND,
SETUP_PATCH_FAILED_COULD_NOT_CREATE_PROCESS);
}
if (!exit_code.IsSuccess()) if (!exit_code.IsSuccess())
DeleteFile(setup_path->get()); DeleteFile(setup_path->get());
...@@ -486,7 +516,10 @@ ProcessExitResult RunSetup(const Configuration& configuration, ...@@ -486,7 +516,10 @@ ProcessExitResult RunSetup(const Configuration& configuration,
// on to setup.exe // on to setup.exe
AppendCommandLineFlags(configuration.command_line(), &cmd_line); AppendCommandLineFlags(configuration.command_line(), &cmd_line);
return RunProcessAndWait(NULL, cmd_line.get()); return RunProcessAndWait(NULL, cmd_line.get(),
RUN_SETUP_FAILED_FILE_NOT_FOUND,
RUN_SETUP_FAILED_PATH_NOT_FOUND,
RUN_SETUP_FAILED_COULD_NOT_CREATE_PROCESS);
} }
// Deletes given files and working dir. // Deletes given files and working dir.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment