Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(660)

Unified Diff: goopdate/goopdate.cc

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « goopdate/goopdate.h ('k') | goopdate/goopdate.def » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: goopdate/goopdate.cc
diff --git a/goopdate/goopdate.cc b/goopdate/goopdate.cc
deleted file mode 100644
index aeda0aad554816c2bd3be877f4678364b108e607..0000000000000000000000000000000000000000
--- a/goopdate/goopdate.cc
+++ /dev/null
@@ -1,1618 +0,0 @@
-// Copyright 2007-2010 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-// ========================================================================
-//
-// For interactive instances, do not access the network before displaying the
-// UI. This provides a better user experience - quick UI - when the network is
-// slow. It is also required to ensure that UI displayed event is signaled
-// before potentially waiting on a firewall prompt.
-//
-// Debugging notes:
-// * Omaha initial install:
-// /install "appguid={8A69D345-D564-463C-AFF1-A69D9E530F96}&appname=Google%20Chrome&needsadmin=False&lang=en" // NOLINT
-// /install "appguid={283EAF47-8817-4c2b-A801-AD1FADFB7BAA}&appname=Gears&needsadmin=True&lang=en" // NOLINT
-// * App install:
-// /handoff "appguid={8A69D345-D564-463C-AFF1-A69D9E530F96}&appname=Google%20Chrome&needsadmin=False&lang=en" // NOLINT
-// /handoff "appguid={283EAF47-8817-4c2b-A801-AD1FADFB7BAA}&appname=Gears&needsadmin=True&lang=en" // NOLINT
-// * Silent install:
-// * Add "/silent" to any of the above command lines (not to the tag).
-// * Google Update self-update:
-// /update
-// * Update check for apps that need it:
-// /ua
-// * Core:
-// /c
-// * Cod Red check:
-// /cr
-// * Cod Red repair:
-// /recover [/machine]
-// * OneClick:
-// /pi "http://www.google.com/" "/install%20%22appguid=%7B8A69D345-D564-463C-AFF1-A69D9E530F96%7D%26lang=en%26appname=Google%2520Chrome%26needsadmin=false" /installsource oneclick // NOLINT
-// * COM server:
-// -Embedding
-
-#include "omaha/goopdate/goopdate.h"
-
-#include <atlstr.h>
-#include <new>
-#include "base/scoped_ptr.h"
-#include "omaha/base/app_util.h"
-#include "omaha/base/const_object_names.h"
-#include "omaha/base/crash_if_specific_error.h"
-#include "omaha/base/debug.h"
-#include "omaha/base/error.h"
-#include "omaha/base/file.h"
-#include "omaha/base/logging.h"
-#include "omaha/base/module_utils.h"
-#include "omaha/base/omaha_version.h"
-#include "omaha/base/proc_utils.h"
-#include "omaha/base/reg_key.h"
-#include "omaha/base/safe_format.h"
-#include "omaha/base/scoped_any.h"
-#include "omaha/base/scoped_ptr_address.h"
-#include "omaha/base/system_info.h"
-#include "omaha/base/utils.h"
-#include "omaha/base/vistautil.h"
-#include "omaha/client/client_utils.h"
-#include "omaha/client/install.h"
-#include "omaha/client/install_apps.h"
-#include "omaha/client/install_self.h"
-#include "omaha/client/resource.h" // IDS_* are used in client modes only.
-#include "omaha/client/ua.h"
-#include "omaha/common/app_registry_utils.h"
-#include "omaha/common/command_line.h"
-#include "omaha/common/config_manager.h"
-#include "omaha/common/const_cmd_line.h"
-#include "omaha/common/const_goopdate.h"
-#include "omaha/common/goopdate_utils.h"
-#include "omaha/common/ping.h"
-#include "omaha/common/lang.h"
-#include "omaha/common/oem_install_utils.h"
-#include "omaha/common/stats_uploader.h"
-#include "omaha/common/webplugin_utils.h"
-#include "omaha/core/core.h"
-#include "omaha/core/crash_handler.h"
-#include "omaha/goopdate/code_red_check.h"
-#include "omaha/goopdate/crash.h"
-#include "omaha/goopdate/google_update.h"
-#include "omaha/goopdate/goopdate_internal.h"
-#include "omaha/goopdate/goopdate_metrics.h"
-#include "omaha/goopdate/resource_manager.h"
-#include "omaha/net/net_diags.h"
-#include "omaha/service/service_main.h"
-#include "omaha/setup/setup_service.h"
-#include "third_party/breakpad/src/client/windows/sender/crash_report_sender.h"
-#include "third_party/breakpad/src/client/windows/handler/exception_handler.h"
-
-// TODO(omaha3): Where should we put this? In Omaha 2, it was in worker.cc.
-// TODO(omaha): fix this clunkiness and require explicit registration of the
-// http creators with the factory. Not ideal but better then linker options.
-#pragma comment(linker, "/INCLUDE:_kRegisterWinHttp")
-
-namespace omaha {
-
-namespace {
-
-#if DEBUG
-const TCHAR* const kBuildType = _T("dbg");
-#else
-const TCHAR* const kBuildType = _T("opt");
-#endif
-
-#if OFFICIAL_BUILD
-const TCHAR* const kOfficialBuild = _T("official");
-#else
-const TCHAR* const kOfficialBuild = _T("dev");
-#endif
-
-#if DEBUG
-// Returns true if the binary's version matches the installed version or this
-// mode does not require the versions to match.
-bool CheckRegisteredVersion(const CString& version,
- bool is_machine,
- CommandLineMode mode) {
- switch (mode) {
- // Modes that may run before or during installation or otherwise do not
- // need to match the installed version.
- case COMMANDLINE_MODE_UNKNOWN:
- case COMMANDLINE_MODE_NOARGS:
- case COMMANDLINE_MODE_REGSERVER:
- case COMMANDLINE_MODE_UNREGSERVER:
- case COMMANDLINE_MODE_NETDIAGS:
- case COMMANDLINE_MODE_CRASH:
- case COMMANDLINE_MODE_REPORTCRASH:
- case COMMANDLINE_MODE_INSTALL:
- case COMMANDLINE_MODE_UPDATE:
- case COMMANDLINE_MODE_RECOVER:
- case COMMANDLINE_MODE_WEBPLUGIN:
- case COMMANDLINE_MODE_REGISTER_PRODUCT:
- case COMMANDLINE_MODE_UNREGISTER_PRODUCT:
- case COMMANDLINE_MODE_SERVICE_REGISTER:
- case COMMANDLINE_MODE_SERVICE_UNREGISTER:
- case COMMANDLINE_MODE_PING:
- return true;
-
- // COM servers and services that should only run after installation.
- case COMMANDLINE_MODE_CORE:
- case COMMANDLINE_MODE_SERVICE:
- case COMMANDLINE_MODE_CODE_RED_CHECK:
- case COMMANDLINE_MODE_COMSERVER:
- case COMMANDLINE_MODE_CRASH_HANDLER:
- case COMMANDLINE_MODE_COMBROKER:
- case COMMANDLINE_MODE_ONDEMAND:
- case COMMANDLINE_MODE_MEDIUM_SERVICE:
-
- // Clients that should only run after installation and should match the
- // installed version.
- case COMMANDLINE_MODE_HANDOFF_INSTALL:
- case COMMANDLINE_MODE_UA:
- case COMMANDLINE_MODE_UNINSTALL:
-
- default:
- // This binary's version should be the installed version.
- CString installed_version;
- VERIFY1(SUCCEEDED(RegKey::GetValue(
- ConfigManager::Instance()->registry_update(is_machine),
- kRegValueInstalledVersion,
- &installed_version)));
- return version == installed_version;
- }
-}
-#endif
-
-} // namespace
-
-namespace detail {
-
-class GoopdateImpl {
- public:
- GoopdateImpl(Goopdate* goopdate, bool is_local_system);
- ~GoopdateImpl();
-
- HRESULT Main(HINSTANCE instance, const TCHAR* cmd_line, int cmd_show);
-
- HRESULT QueueUserWorkItem(UserWorkItem* work_item, uint32 flags);
-
- void Stop();
-
- bool is_local_system() const { return is_local_system_; }
-
- private:
- HRESULT DoMain(HINSTANCE instance, const TCHAR* cmd_line, int cmd_show);
-
- // Performs initialization that must be done as soon as the command line has
- // been parsed and loads the resources. If this method succeeds, we can use
- // the resources - for example, to display error messagse.
- HRESULT InitializeGoopdateAndLoadResources();
-
- // Executes the mode determined by DoMain().
- HRESULT ExecuteMode(bool* has_ui_been_displayed);
-
- // Returns whether a process is a machine process.
- // Does not determine whether the process has the appropriate privileges.
- bool IsMachineProcess();
-
- bool ShouldCheckShutdownEvent(CommandLineMode mode);
- bool IsShutdownEventSet();
-
- HRESULT LoadResourceDllIfNecessary(CommandLineMode mode,
- const CString& resource_dir);
-
- HRESULT SetUsageStatsEnable();
-
- // Handles error conditions by showing UI if appropriate.
- void HandleError(HRESULT hr, bool has_ui_been_displayed);
-
- // Handles response to /pi command.
- HRESULT HandleWebPlugin();
-
- // Handles responses to /cr command.
- HRESULT HandleCodeRedCheck();
-
- // Handles /report command.
- HRESULT HandleReportCrash();
-
- // Installs apps for the /handoff instance.
- HRESULT DoHandoff(bool* has_ui_been_displayed);
-
- // Updates all registered apps for the /ua instance.
- HRESULT DoUpdateAllApps(bool* has_ui_been_displayed);
-
- // Generates a divide by zero to trigger breakpad dump.
- // Is only enabled in debug builds.
- HRESULT DoCrash();
-
- // Install Omaha.
- HRESULT DoInstall(bool* has_ui_been_displayed);
-
- // Silently update Omaha.
- HRESULT DoSelfUpdate();
-
- // Handles the recover command in Google Update.
- HRESULT DoRecover();
-
- // Uninstalls Omaha if appropriate.
- HRESULT HandleUninstall();
-
- // Pings the Omaha server with a string.
- HRESULT HandlePing();
-
- // TODO(omaha): Reconcile the two uninstall functions and paths.
- void MaybeUninstallGoogleUpdate();
-
- // Uninstalls Google Update if a /install process failed to install itself
- // or the app and there are no other apps registered.
- HRESULT UninstallIfNecessary();
-
- // Called by operator new or operator new[] when they cannot satisfy
- // a request for additional storage.
- static void OutOfMemoryHandler();
-
- static HRESULT CaptureOSMetrics();
-
- HINSTANCE module_instance_; // Current module instance.
- CString cmd_line_; // Command line, as provided by the OS.
- int cmd_show_;
-
- CommandLineArgs args_; // Command line options and flags.
-
- // True if the process belongs to a machine Omaha "session".
- bool is_machine_;
- bool is_local_system_; // True if running as LOCAL_SYSTEM.
- CString this_version_; // Version of this Goopdate DLL.
-
- // True if Omaha has been uninstalled by the Worker.
- bool has_uninstalled_;
-
- // Language identifier for the current user locale.
- CString user_default_language_id_;
-
- scoped_ptr<ThreadPool> thread_pool_;
-
- Goopdate* goopdate_;
-
- DISALLOW_EVIL_CONSTRUCTORS(GoopdateImpl);
-};
-
-GoopdateImpl::GoopdateImpl(Goopdate* goopdate, bool is_local_system)
- : module_instance_(NULL),
- cmd_show_(0),
- is_local_system_(is_local_system),
- has_uninstalled_(false),
- goopdate_(goopdate) {
- ASSERT1(goopdate);
-
- ++metric_goopdate_constructor;
-
- // The command line needs to be parsed to accurately determine if the current
- // process is a machine process or not. Take an upfront guess before that.
- is_machine_ = vista_util::IsUserAdmin() &&
- goopdate_utils::IsRunningFromOfficialGoopdateDir(true);
-
- // Install an error-handling mechanism which gets called when new operator
- // fails to allocate memory.
- VERIFY1(set_new_handler(&GoopdateImpl::OutOfMemoryHandler) == 0);
-
- // Install the exception handler.
- VERIFY1(SUCCEEDED(Crash::InstallCrashHandler(is_machine_)));
-
- // Hints network configure manager how to create its singleton.
- NetworkConfigManager::set_is_machine(is_machine_);
-
- // Initialize the global metrics collection.
- stats_report::g_global_metrics.Initialize();
-
- // TODO(omaha): Support multiple HRESULT codes to crash on.
- // TODO(omaha): Support passing in HRESULT codes via the command line,
- // especially for "/update".
- DWORD crash_specific_error = 0;
- if (SUCCEEDED(RegKey::GetValue(MACHINE_REG_UPDATE_DEV,
- kRegValueNameCrashIfSpecificError,
- &crash_specific_error))) {
- omaha::g_crash_specific_error = static_cast<HRESULT>(crash_specific_error);
- }
-
- static const int kThreadPoolShutdownDelayMs = 60000;
- thread_pool_.reset(new ThreadPool);
- HRESULT hr = thread_pool_->Initialize(kThreadPoolShutdownDelayMs);
- if (FAILED(hr)) {
- CORE_LOG(LE, (_T("[thread_pool_->Initialize failed][0x%08x]"), hr));
- }
-}
-
-GoopdateImpl::~GoopdateImpl() {
- CORE_LOG(L2, (_T("[GoopdateImpl::~GoopdateImpl]")));
-
- ++metric_goopdate_destructor;
-
- Stop();
-
- // Bug 994348 does not repro anymore.
- // If the assert fires, clean up the key, and fix the code if we have unit
- // tests or application code that create the key.
- ASSERT(!RegKey::HasKey(_T("HKEY_USERS\\.DEFAULT\\Software\\Google\\Update")),
- (_T("This assert has fired because it has found the registry key at ")
- _T("'HKEY_USERS\\.DEFAULT\\Software\\Google\\Update'. ")
- _T("Please delete the key and report to omaha-core team if ")
- _T("the assert fires again.")));
-
- // The global metrics collection must be uninitialized before the metrics
- // destructors are called.
- stats_report::g_global_metrics.Uninitialize();
-
- // Uninstall the exception handler. Program crashes are handled by Windows
- // Error Reporting (WER) beyond this point.
- Crash::UninstallCrashHandler();
-
- // Reset the new handler.
- set_new_handler(NULL);
-}
-
-HRESULT GoopdateImpl::QueueUserWorkItem(UserWorkItem* work_item, uint32 flags) {
- CORE_LOG(L3, (_T("[GoopdateImpl::QueueUserWorkItem]")));
- ASSERT1(work_item);
-
- ASSERT1(thread_pool_.get());
-
- return thread_pool_->QueueUserWorkItem(work_item, flags);
-}
-
-void GoopdateImpl::Stop() {
- // The thread pool destructor waits for any remaining jobs to complete.
- thread_pool_.reset();
-}
-
-// Assumes the resources are loaded and members are initialized.
-void GoopdateImpl::HandleError(HRESULT hr, bool has_ui_been_displayed) {
- CORE_LOG(L3, (_T("[GoopdateImpl::HandleError][0x%x][%u]"),
- hr, has_ui_been_displayed));
-
- if (has_ui_been_displayed ||
- !internal::CanDisplayUi(args_.mode, args_.is_silent_set)) {
- return;
- }
-
- const CString& bundle_name = args_.extra.bundle_name;
- CString primary_app_guid;
- if (!args_.extra.apps.empty()) {
- primary_app_guid = GuidToString(args_.extra.apps[0].app_guid);
- }
-
- CString error_text;
- switch (hr) {
- case GOOPDATE_E_UA_ALREADY_RUNNING:
- error_text.FormatMessage(IDS_APPLICATION_ALREADY_INSTALLING,
- client_utils::GetUpdateAllAppsBundleName());
- break;
- case OMAHA_NET_E_WINHTTP_NOT_AVAILABLE:
- ASSERT1(!bundle_name.IsEmpty());
- error_text.FormatMessage(IDS_WINDOWS_IS_NOT_UP_TO_DATE,
- bundle_name);
- break;
- default:
- // TODO(omaha3): This currently assumes that any error returned here is
- // related to Setup.
- CString product_name;
- VERIFY1(product_name.LoadString(IDS_PRODUCT_DISPLAY_NAME));
- error_text.FormatMessage(IDS_SETUP_FAILED, product_name, hr);
- break;
- }
-
- VERIFY1(client_utils::DisplayError(is_machine_,
- bundle_name,
- hr,
- 0,
- error_text,
- primary_app_guid,
- args_.extra.language,
- args_.extra.installation_id,
- args_.extra.brand_code));
-}
-
-HRESULT GoopdateImpl::Main(HINSTANCE instance,
- const TCHAR* cmd_line,
- int cmd_show) {
- ++metric_goopdate_main;
-
- HRESULT hr = DoMain(instance, cmd_line, cmd_show);
-
- CORE_LOG(L2, (_T("[has_uninstalled_ is %d]"), has_uninstalled_));
-
- // For install processes, verify the Google Update EULA has been accepted and
- // we can use the network unless a) the command line specifies EULA is
- // required or b) in OEM installing mode, which also prevents network use.
- if ((COMMANDLINE_MODE_INSTALL == args_.mode ||
- COMMANDLINE_MODE_HANDOFF_INSTALL == args_.mode) &&
- SUCCEEDED(hr)) {
- ASSERT1(args_.is_eula_required_set ||
- ConfigManager::Instance()->CanUseNetwork(is_machine_) ||
- oem_install_utils::IsOemInstalling(is_machine_));
- }
-
- // In the /install case, clean up if Google Update and/or app install did not
- // complete successfully.
- // Only aggregate the metrics if there is no chance that Google Update has
- // or may be uninstalled and the process has the appropriate permissions.
- // Uninstall will aggregate and report the metrics as appropriate.
- bool did_install_uninstall_fail = false;
- if (COMMANDLINE_MODE_INSTALL == args_.mode) {
- did_install_uninstall_fail = FAILED(UninstallIfNecessary());
- } else if (!has_uninstalled_) {
- if (args_.mode == COMMANDLINE_MODE_UA) {
- VERIFY1(SUCCEEDED(AggregateAndReportMetrics(is_machine_, false)));
- } else if (!is_machine_ || vista_util::IsUserAdmin()) {
- VERIFY1(SUCCEEDED(AggregateMetrics(is_machine_)));
- }
- }
-
- Worker::DeleteInstance();
-
- // Uninitializing the network configuration must happen after reporting the
- // metrics. The call succeeds even if the network has not been initialized
- // due to errors up the execution path.
- NetworkConfigManager::DeleteInstance();
-
- if (COMMANDLINE_MODE_INSTALL == args_.mode &&
- args_.is_oem_set &&
- SUCCEEDED(hr) &&
- !oem_install_utils::IsOemInstalling(is_machine_)) {
- ASSERT1(false);
- hr = GOOPDATE_E_OEM_INSTALL_SUCCEEDED_BUT_NOT_IN_OEM_INSTALLING_MODE;
- }
-
- // Verify that Google Update is either completely installed or uninstalled.
- // Do not check in the following cases:
- // * Modes that may exit during Setup, during uninstall, or while Omaha
- // is partially installed.
- // * The mode is unknown, which means the args were not be parsed.
- // * /cr instance, which may exit after Omaha is uninstalled.
- // * /install instance that would not have called Setup.Uninstall().
- // * /install instance when Uninstall failed for some reason since the
- // the consistency check may expect the wrong state.
- // * /update instance that failed due to an install/uninstall in progress.
- if (COMMANDLINE_MODE_REGSERVER != args_.mode &&
- COMMANDLINE_MODE_UNREGSERVER != args_.mode &&
- COMMANDLINE_MODE_COMSERVER != args_.mode &&
- COMMANDLINE_MODE_CODE_RED_CHECK != args_.mode &&
- COMMANDLINE_MODE_SERVICE_REGISTER != args_.mode &&
- COMMANDLINE_MODE_SERVICE_UNREGISTER != args_.mode &&
- COMMANDLINE_MODE_UNKNOWN != args_.mode &&
- !(COMMANDLINE_MODE_INSTALL == args_.mode &&
- is_machine_ &&
- !vista_util::IsUserAdmin()) &&
- !(COMMANDLINE_MODE_UPDATE == args_.mode &&
- GOOPDATE_E_FAILED_TO_GET_LOCK == hr) &&
- !did_install_uninstall_fail) {
- install_self::CheckInstallStateConsistency(is_machine_);
- }
-
- ResourceManager::Delete();
-
- return hr;
-}
-
-HRESULT GoopdateImpl::DoMain(HINSTANCE instance,
- const TCHAR* cmd_line,
- int cmd_show) {
- module_instance_ = instance;
- cmd_line_ = cmd_line;
- cmd_show_ = cmd_show;
-
- // The system terminates the process without displaying a retry dialog box
- // for the user. GoogleUpdate has no user state to be saved, therefore
- // prompting the user for input is meaningless.
- VERIFY1(SUCCEEDED(SetProcessSilentShutdown()));
-
- VERIFY1(SUCCEEDED(CaptureOSMetrics()));
-
- InitializeVersionFromModule(module_instance_);
- this_version_ = GetVersionString();
-
- TCHAR path[MAX_PATH] = {0};
- VERIFY1(::GetModuleFileName(module_instance_, path, MAX_PATH));
- OPT_LOG(L1, (_T("[%s][version %s][%s][%s]"),
- path, this_version_, kBuildType, kOfficialBuild));
-
- CORE_LOG(L2, (_T("[is system %d]")
- _T("[elevated admin %d]")
- _T("[non-elevated admin %d]")
- _T("[testsource %s]"),
- is_local_system_,
- vista_util::IsUserAdmin(),
- vista_util::IsUserNonElevatedAdmin(),
- ConfigManager::Instance()->GetTestSource()));
-
- HRESULT parse_hr = omaha::ParseCommandLine(cmd_line_, &args_);
- if (FAILED(parse_hr)) {
- CORE_LOG(LE, (_T("[Parse cmd line failed][0x%08x]"), parse_hr));
- args_.mode = COMMANDLINE_MODE_UNKNOWN;
- // Continue because we want to load the resources and display an error.
- }
-
- // TODO(omaha3): Interactive updates might be useful for debugging or even
- // on-demand updates of all apps. Figure out how to expose this. For now, no
- // install source, which should not happen normally, is used as the trigger.
- // The simplest way to make this work is to set args_.is_silent_set
- // accordingly. However, we also need a way for this to work for per-machine
- // instances since IsMachineProcess() relies on being Local System. When we
- // settle on a mechanism, we should update the parser and remove this.
- if (args_.mode == COMMANDLINE_MODE_UA) {
- args_.is_silent_set = !args_.install_source.IsEmpty();
- }
-
- HRESULT hr = InitializeGoopdateAndLoadResources();
- if (FAILED(hr)) {
- CORE_LOG(LE,
- (_T("[InitializeGoopdateAndLoadResources failed][0x%08x]"), hr));
- if (internal::CanDisplayUi(args_.mode, args_.is_silent_set)) {
- // The resources are unavaliable, so we must use hard-coded text.
- const TCHAR* const kMsgBoxTitle = _T("Google Installer");
- CString message;
- message.Format(_T("Installation failed with error 0x%08x."), hr);
- VERIFY1(IDOK == ::MessageBox(NULL, message, kMsgBoxTitle, MB_OK));
- }
- return hr;
- }
- // The resources are now loaded and available if applicable for this instance.
- // If there was no bundle name specified on the command line, we take the
- // bundle name from the first app's name; if that has no name (or if there is
- // no apps, as in a runtime-only install) it will be an empty string.
- // Replace it with the localized installer name.
- if (args_.extra.bundle_name.IsEmpty()) {
- args_.extra.bundle_name.LoadString(IDS_PRODUCT_DISPLAY_NAME);
- }
-
- CORE_LOG(L2, (_T("[can use network %d]")
- _T("[can collect stats %d]"),
- ConfigManager::Instance()->CanUseNetwork(is_machine_),
- ConfigManager::Instance()->CanCollectStats(is_machine_)));
-
- bool has_ui_been_displayed = false;
-
- if (!is_machine_ && vista_util::IsElevatedWithUACMaybeOn()) {
- CORE_LOG(LW, (_T("User GoogleUpdate is possibly running in an unsupported ")
- _T("way, at High integrity with UAC possibly enabled.")));
- }
-
- if (FAILED(parse_hr)) {
- ASSERT1(args_.mode == COMMANDLINE_MODE_UNKNOWN);
- hr = parse_hr;
- } else {
- ASSERT1(args_.mode != COMMANDLINE_MODE_UNKNOWN);
- // TODO(omaha): I would like to pass the mode as an argument, but there
- // are so many uses for args_.mode and they could easily creep in. Consider
- // eliminating the args_ member.
- hr = ExecuteMode(&has_ui_been_displayed);
- if (FAILED(hr)) {
- CORE_LOG(LE, (_T("[ExecuteMode failed][0x%08x]"), hr));
- // Continue and display error.
- }
- }
-
- if (FAILED(hr)) {
- HandleError(hr, has_ui_been_displayed);
- return hr;
- }
-
- return S_OK;
-}
-
-// Assumes the command line has been parsed.
-HRESULT GoopdateImpl::InitializeGoopdateAndLoadResources() {
- // IsMachineProcess requires the command line be parsed first.
- is_machine_ = IsMachineProcess();
- OPT_LOG(L1, (_T("[is machine: %d]"), is_machine_));
-
- if (!::SetEnvironmentVariable(kEnvVariableIsMachine,
- is_machine_ ? _T("1") : _T("0"))) {
- HRESULT hr = HRESULTFromLastError();
- CORE_LOG(LW, (_T("[::SetEnvironmentVariable failed][%s][0x%x]"),
- kEnvVariableIsMachine, hr));
- }
-
- // After parsing the command line, reinstall the crash handler to match the
- // state of the process.
- if (is_machine_ != Crash::is_machine()) {
- VERIFY1(SUCCEEDED(Crash::InstallCrashHandler(is_machine_)));
- }
-
- // We have parsed the command line, and we are now resetting is_machine.
- NetworkConfigManager::set_is_machine(
- is_machine_ && vista_util::IsUserAdmin());
-
- // Set the current directory to be the one that the DLL was launched from.
- TCHAR module_directory[MAX_PATH] = {0};
- if (!GetModuleDirectory(module_instance_, module_directory)) {
- return HRESULTFromLastError();
- }
- if (!::SetCurrentDirectory(module_directory)) {
- return HRESULTFromLastError();
- }
- OPT_LOG(L3, (_T("[Current dir][%s]"), module_directory));
-
- // Set the usage stats as soon as possible, which is after the command line
- // has been parsed, so that we can report crashes and other stats.
- VERIFY1(SUCCEEDED(SetUsageStatsEnable()));
-
- VERIFY1(SUCCEEDED(internal::PromoteAppEulaAccepted(is_machine_)));
-
- if (ShouldCheckShutdownEvent(args_.mode) && IsShutdownEventSet()) {
- return GOOPDATE_E_SHUTDOWN_SIGNALED;
- }
-
- HRESULT hr = LoadResourceDllIfNecessary(args_.mode, module_directory);
- if (FAILED(hr)) {
- CORE_LOG(LE, (_T("[LoadResourceDllIfNecessary failed][0x%08x]"), hr));
- return hr;
- }
-
- return S_OK;
-}
-
-// Assumes Goopdate is initialized and resources are loaded.
-HRESULT GoopdateImpl::ExecuteMode(bool* has_ui_been_displayed) {
- ASSERT1(has_ui_been_displayed);
-
- // Save the mode on the stack for post-mortem debugging purposes.
- volatile CommandLineMode mode = args_.mode;
-
- user_default_language_id_ = lang::GetDefaultLanguage(is_local_system_);
-
- ASSERT1(CheckRegisteredVersion(GetVersionString(), is_machine_, mode));
-
-#pragma warning(push)
-// C4061: enumerator 'xxx' in switch of enum 'yyy' is not explicitly handled by
-// a case label.
-#pragma warning(disable : 4061)
- switch (mode) {
- // Delegate to the service or the core. Both have reliability requirements
- // and resource constraints. Generally speaking, they do not use COM nor
- // networking code.
- case COMMANDLINE_MODE_SERVICE:
- return omaha::Update3ServiceModule().Main(SW_HIDE);
-
- case COMMANDLINE_MODE_MEDIUM_SERVICE:
- return omaha::UpdateMediumServiceModule().Main(SW_HIDE);
-
- case COMMANDLINE_MODE_SERVICE_REGISTER: {
- HRESULT hr = SetupUpdate3Service::InstallService(
- app_util::GetModulePath(NULL));
- if (FAILED(hr)) {
- return hr;
- }
- return SetupUpdateMediumService::InstallService(
- app_util::GetModulePath(NULL));
- }
-
- case COMMANDLINE_MODE_SERVICE_UNREGISTER: {
- HRESULT hr = SetupUpdate3Service::UninstallService();
- if (FAILED(hr)) {
- return hr;
- }
- return SetupUpdateMediumService::UninstallService();
- }
-
- default: {
- scoped_co_init init_com_apt(COINIT_MULTITHREADED);
- HRESULT hr = init_com_apt.hresult();
- if (FAILED(hr)) {
- return hr;
- }
-
- switch (mode) {
- case COMMANDLINE_MODE_CORE:
- return omaha::Core().Main(is_local_system_,
- !args_.is_crash_handler_disabled);
-
- case COMMANDLINE_MODE_CRASH_HANDLER:
- return omaha::CrashHandler().Main(is_local_system_);
-
- case COMMANDLINE_MODE_NOARGS:
- return GOOPDATE_E_NO_ARGS;
-
- case COMMANDLINE_MODE_UNREGISTER_PRODUCT:
- // TODO(omaha3): Eliminate the need for this mode.
- return E_FAIL;
-
- case COMMANDLINE_MODE_COMBROKER:
- return omaha::GoogleUpdate(is_machine_,
- omaha::GoogleUpdate::kBrokerMode).Main();
-
- case COMMANDLINE_MODE_ONDEMAND:
- return omaha::GoogleUpdate(
- is_machine_,
- omaha::GoogleUpdate::kOnDemandMode).Main();
-
- default: {
- // Reference the network instance here so the singleton can be
- // created before possible impersonation.
- NetworkConfigManager::Instance();
-
- switch (mode) {
- case COMMANDLINE_MODE_WEBPLUGIN:
- return HandleWebPlugin();
-
- case COMMANDLINE_MODE_CODE_RED_CHECK:
- return HandleCodeRedCheck();
-
- case COMMANDLINE_MODE_NETDIAGS:
- return NetDiags().Main();
-
- case COMMANDLINE_MODE_REGISTER_PRODUCT:
- // TODO(omaha3): Eliminate the need for this mode.
- return E_FAIL;
-
- case COMMANDLINE_MODE_INSTALL:
- return DoInstall(has_ui_been_displayed);
-
- case COMMANDLINE_MODE_UPDATE:
- return DoSelfUpdate();
-
- case COMMANDLINE_MODE_RECOVER:
- return DoRecover();
-
- case COMMANDLINE_MODE_HANDOFF_INSTALL:
- return DoHandoff(has_ui_been_displayed);
-
- case COMMANDLINE_MODE_UA:
- return DoUpdateAllApps(has_ui_been_displayed);
-
- case COMMANDLINE_MODE_CRASH:
- return DoCrash();
-
- case COMMANDLINE_MODE_REPORTCRASH:
- return HandleReportCrash();
-
- case COMMANDLINE_MODE_REGSERVER:
- case COMMANDLINE_MODE_UNREGSERVER: {
- hr = omaha::GoogleUpdate(
- is_machine_, omaha::GoogleUpdate::kUpdate3Mode).Main();
- if (FAILED(hr)) {
- return hr;
- }
- hr = omaha::GoogleUpdate(
- is_machine_, omaha::GoogleUpdate::kBrokerMode).Main();
- if (FAILED(hr)) {
- return hr;
- }
- return omaha::GoogleUpdate(
- is_machine_, omaha::GoogleUpdate::kOnDemandMode).Main();
- }
-
- case COMMANDLINE_MODE_COMSERVER:
- return omaha::GoogleUpdate(
- is_machine_, omaha::GoogleUpdate::kUpdate3Mode).Main();
-
- case COMMANDLINE_MODE_UNINSTALL:
- return HandleUninstall();
-
- case COMMANDLINE_MODE_PING:
- return HandlePing();
-
- default:
- // We have a COMMANDLINE_MODE_ that isn't being handled.
- ASSERT1(false);
- OPT_LOG(LE, (_T("[Command line has unhandled mode]")));
- return E_UNEXPECTED;
- }
- }
- }
- }
- }
-#pragma warning(pop)
-}
-
-bool GoopdateImpl::IsMachineProcess() {
- Tristate needs_admin(TRISTATE_NONE);
- if (!args_.extra.apps.empty()) {
- needs_admin = args_.extra.apps[0].needs_admin != NEEDS_ADMIN_NO ?
- TRISTATE_TRUE : TRISTATE_FALSE;
- }
-
- return internal::IsMachineProcess(
- args_.mode,
- goopdate_utils::IsRunningFromOfficialGoopdateDir(true),
- is_local_system_,
- args_.is_machine_set,
- needs_admin);
-}
-
-
-HRESULT GoopdateImpl::HandleReportCrash() {
- ++metric_goopdate_handle_report_crash;
- VERIFY1(SUCCEEDED(AggregateMetrics(is_machine_)));
-
- // Catch exceptions to avoid reporting crashes when handling a crash.
- // TODO(omaha): maybe let Windows handle the crashes when reporting crashes
- // in certain interactive modes.
- HRESULT hr = S_OK;
- __try {
- // Crashes are uploaded always in the out-of-process case.
- //
- // Google Update internal crashes are handled in-process. They are uploaded
- // only for the users that have opted in sending usage stats and when
- // network use is allowed, and from systems that are not development
- // nor test.
- // This default behavior can be overriden by an UpdatedDev parameter that
- // allows crashes to be uploaded always.
- //
- // All GoogleUpdate crashes are logged in the Windows event log for
- // applications, unless the logging is disabled by the administrator.
- ConfigManager* cm = ConfigManager::Instance();
- const bool can_upload_in_process = cm->AlwaysAllowCrashUploads() ||
- (cm->CanCollectStats(is_machine_) &&
- cm->CanUseNetwork(is_machine_) &&
- !goopdate_utils::IsTestSource());
- hr = Crash::Report(can_upload_in_process,
- args_.crash_filename,
- args_.custom_info_filename,
- user_default_language_id_);
- }
- __except(EXCEPTION_EXECUTE_HANDLER) {
- hr = E_FAIL;
- }
- return hr;
-}
-
-bool GoopdateImpl::ShouldCheckShutdownEvent(CommandLineMode mode) {
- switch (mode) {
- // Modes that may run before or during installation or otherwise do not
- // need to listen to shutdown.
- case COMMANDLINE_MODE_UNKNOWN:
- case COMMANDLINE_MODE_NOARGS:
- case COMMANDLINE_MODE_REGSERVER:
- case COMMANDLINE_MODE_UNREGSERVER:
- case COMMANDLINE_MODE_NETDIAGS:
- case COMMANDLINE_MODE_CRASH:
- case COMMANDLINE_MODE_REPORTCRASH:
- case COMMANDLINE_MODE_RECOVER:
- case COMMANDLINE_MODE_SERVICE_REGISTER:
- case COMMANDLINE_MODE_SERVICE_UNREGISTER:
-
- case COMMANDLINE_MODE_INSTALL:
- case COMMANDLINE_MODE_UPDATE:
- case COMMANDLINE_MODE_WEBPLUGIN:
- case COMMANDLINE_MODE_CODE_RED_CHECK:
- case COMMANDLINE_MODE_REGISTER_PRODUCT:
- case COMMANDLINE_MODE_UNREGISTER_PRODUCT:
- case COMMANDLINE_MODE_PING:
- return false;
-
- // Modes that should honor shutdown.
- case COMMANDLINE_MODE_CORE:
- case COMMANDLINE_MODE_SERVICE:
- case COMMANDLINE_MODE_COMSERVER:
- case COMMANDLINE_MODE_CRASH_HANDLER:
- case COMMANDLINE_MODE_COMBROKER:
- case COMMANDLINE_MODE_ONDEMAND:
- case COMMANDLINE_MODE_MEDIUM_SERVICE:
-
- case COMMANDLINE_MODE_HANDOFF_INSTALL:
- case COMMANDLINE_MODE_UA:
- case COMMANDLINE_MODE_UNINSTALL:
- return true;
-
- default:
- ASSERT1(false);
- return true;
- }
-}
-
-bool GoopdateImpl::IsShutdownEventSet() {
- NamedObjectAttributes attr;
- GetNamedObjectAttributes(kShutdownEvent, is_machine_, &attr);
- scoped_event shutdown_event(::OpenEvent(SYNCHRONIZE, false, attr.name));
- if (!shutdown_event) {
- return false;
- }
-
- return WAIT_OBJECT_0 == ::WaitForSingleObject(get(shutdown_event), 0);
-}
-
-// The resource dll is loaded only in the following cases:
-// 1. Initial setup: /install
-// 2. Handoff install: /handoff
-// 3. App update worker: /ua
-// 4. Various registrations.
-// 5. Modes where an error message needs to be displayed.
-HRESULT GoopdateImpl::LoadResourceDllIfNecessary(CommandLineMode mode,
- const CString& resource_dir) {
- switch (mode) {
- case COMMANDLINE_MODE_UNKNOWN: // Displays an error using UI.
- case COMMANDLINE_MODE_NOARGS: // Displays an error using UI.
- case COMMANDLINE_MODE_INSTALL: // Has UI on errors.
- case COMMANDLINE_MODE_UPDATE: // Task and Service descriptions.
- case COMMANDLINE_MODE_RECOVER: // Writes strings to registry.
- case COMMANDLINE_MODE_HANDOFF_INSTALL: // Has optional UI.
- case COMMANDLINE_MODE_UA: // Has optional UI.
- case COMMANDLINE_MODE_COMSERVER: // Returns strings to caller.
- case COMMANDLINE_MODE_SERVICE: // Returns strings to caller.
- case COMMANDLINE_MODE_MEDIUM_SERVICE: // TODO(omaha): Check & explain.
- case COMMANDLINE_MODE_SERVICE_REGISTER: // Requires the RGS resources.
- case COMMANDLINE_MODE_SERVICE_UNREGISTER: // Requires the RGS resources.
- case COMMANDLINE_MODE_ONDEMAND: // Worker, etc. load strings.
- // Load the resource DLL for these modes.
- break;
-
- // For the Core, the resource DLL needs to be loaded when the Core is
- // servicing IGoogleUpdate3. The Core loads the resource DLL after the Code
- // Red kickoff, from within core.cc.
- case COMMANDLINE_MODE_CORE:
- case COMMANDLINE_MODE_REGSERVER:
- case COMMANDLINE_MODE_UNREGSERVER:
- case COMMANDLINE_MODE_NETDIAGS:
- case COMMANDLINE_MODE_CRASH:
- case COMMANDLINE_MODE_REPORTCRASH:
- case COMMANDLINE_MODE_WEBPLUGIN:
- case COMMANDLINE_MODE_CODE_RED_CHECK:
- case COMMANDLINE_MODE_REGISTER_PRODUCT:
- case COMMANDLINE_MODE_UNREGISTER_PRODUCT:
- case COMMANDLINE_MODE_CRASH_HANDLER:
- case COMMANDLINE_MODE_COMBROKER:
- case COMMANDLINE_MODE_UNINSTALL:
- case COMMANDLINE_MODE_PING:
- default:
- // These modes do not need the resource DLL.
- ASSERT1(!internal::CanDisplayUi(mode, false));
- return S_OK;
- }
-
- // TODO(omaha3): Consider not using ResourceManager in this file.
- HRESULT hr = ResourceManager::Create(
- is_machine_,
- resource_dir,
- lang::GetLanguageForProcess(args_.extra.language));
- if (FAILED(hr)) {
- ASSERT(false, (_T("ResourceManager::Create failed with 0x%08x"), hr));
- return hr;
- }
-
- return S_OK;
-}
-
-// Writes the information for the primary app to enable Omaha to send usage
-// stats now. It will be set for each app in the args when they are installed.
-HRESULT GoopdateImpl::SetUsageStatsEnable() {
- if (args_.extra.apps.empty()) {
- return S_OK;
- }
-
- HRESULT hr = app_registry_utils::SetUsageStatsEnable(
- args_.extra.apps[0].needs_admin != NEEDS_ADMIN_NO,
- GuidToString(args_.extra.apps[0].app_guid),
- args_.extra.usage_stats_enable);
- if (FAILED(hr)) {
- CORE_LOG(LW, (_T("[SetUsageStatsEnable failed][0x%08x]"), hr));
-
- if ((HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) == hr) &&
- args_.extra.apps[0].needs_admin &&
- !vista_util::IsUserAdmin()) {
- CORE_LOG(L3, (_T("[Process does not have permission to HKLM]")));
- return S_OK;
- }
- return hr;
- }
-
- return S_OK;
-}
-
-HRESULT GoopdateImpl::HandleCodeRedCheck() {
- CORE_LOG(L2, (_T("[GoopdateImpl::HandleCodeRedCheck]")));
- ++metric_cr_process_total;
-
- // Call the utils method instead of member method because we want to execute
- // as little code as possible.
- bool is_machine = internal::IsMachineProcess(args_.mode,
- false, // machine dir
- is_local_system_,
- args_.is_machine_set,
- TRISTATE_NONE);
- ASSERT1(IsMachineProcess() == is_machine);
-
- if (!ConfigManager::Instance()->CanUseNetwork(is_machine)) {
- CORE_LOG(L1,
- (_T("[Code Red check not sent because network use prohibited]")));
- return GOOPDATE_E_CANNOT_USE_NETWORK;
- }
-
- CheckForCodeRed(is_machine, this_version_);
- return S_OK;
-}
-
-// Even though http://b/1135173 is fixed, there is still a possibility that only
-// some of the files will be copied if Setup is currently running.
-// TODO(omaha3): If we save and use the metainstaller for OneClick, that may
-// address this.
-
-// If we're called with the /webplugin command, we need to handle it and exit.
-// This is called from the browser and the command line arguments come from the
-// website so we need to be restrictive of what we let past. If everything from
-// the plugin is valid, we'll relaunch goopdate with the proper commands.
-HRESULT GoopdateImpl::HandleWebPlugin() {
- return webplugin_utils::DoOneClickInstall(args_);
-}
-
-HRESULT GoopdateImpl::DoInstall(bool* has_ui_been_displayed) {
- OPT_LOG(L1, (_T("[GoopdateImpl::DoInstall]")));
- ASSERT1(has_ui_been_displayed);
-
- // Some /install command lines, such as /silent /install will not necessarily
- // have an install source. To differentiate these from other sources, such as
- // other clients using the COM API, specify a generic source for /install.
- // TODO(omaha3): Updating two types of command line/args is undesirable, and
- // this does not use CommandLineBuilder. This could be addressed in several
- // ways. See the TODO above install.cc::LaunchHandoffProcess().
- ASSERT1(args_.mode == COMMANDLINE_MODE_INSTALL);
- CString install_command_line = cmd_line_;
- CommandLineArgs install_args = args_;
- if (args_.install_source.IsEmpty()) {
- ASSERT1(-1 == cmd_line_.Find(kCmdLineInstallSource));
- SafeCStringAppendFormat(&install_command_line, _T(" /%s %s"),
- kCmdLineInstallSource,
- kCmdLineInstallSource_InstallDefault);
- install_args.install_source = kCmdLineInstallSource_InstallDefault;
- }
-
- HRESULT hr = S_OK;
- if (args_.is_oem_set) {
- hr = OemInstall(!args_.is_silent_set, // is_interactive
- !args_.extra.runtime_only, // is_app_install
- args_.is_eula_required_set,
- args_.is_install_elevated,
- install_command_line,
- install_args,
- &is_machine_,
- has_ui_been_displayed);
- } else {
- hr = Install(!args_.is_silent_set, // is_interactive
- !args_.extra.runtime_only, // is_app_install
- args_.is_eula_required_set,
- false,
- args_.is_install_elevated,
- install_command_line,
- install_args,
- &is_machine_,
- has_ui_been_displayed);
- }
-
- if (FAILED(hr)) {
- CORE_LOG(LE, (_T("[Install failed][0x%08x]"), hr));
- return hr;
- }
-
- return S_OK;
-}
-
-HRESULT GoopdateImpl::DoSelfUpdate() {
- OPT_LOG(L1, (_T("[GoopdateImpl::DoSelfUpdate]")));
-
- HRESULT hr = install_self::UpdateSelf(is_machine_, args_.session_id);
- if (FAILED(hr)) {
- CORE_LOG(LE, (_T("[UpdateSelf failed][0x%08x]"), hr));
- return hr;
- }
-
- return S_OK;
-}
-
-// Attempts to launch the repair file elevated using the MSP. If elevation is
-// not needed or fails, attempts to install without elevating.
-// The code_red_metainstaller_path arg is the repair file.
-HRESULT GoopdateImpl::DoRecover() {
- OPT_LOG(L1, (_T("[GoopdateImpl::DoRecover()]")));
-
-// TODO(omaha3): Enable. Maybe build without the builder.
-#if 0
- CommandLineBuilder builder(COMMANDLINE_MODE_UPDATE);
-
- HRESULT hr = S_OK;
- if (LaunchRepairFileElevated(is_machine_,
- args_.code_red_metainstaller_path,
- builder.GetCommandLineArgs(),
- &hr)) {
- ASSERT1(SUCCEEDED(hr));
- return S_OK;
- }
-#else
- HRESULT hr = S_OK;
-#endif
-
- if (FAILED(hr)) {
- OPT_LOG(LW, (_T("[LaunchRepairFileElevated failed][0x%08x]"), hr));
- }
-
- hr = install_self::Repair(is_machine_);
- if (FAILED(hr)) {
- OPT_LOG(LE, (_T("[Non-elevated repair failed][0x%08x]"), hr));
- return hr;
- }
-
- return S_OK;
-}
-
-// Clears the EULA flag in the handoff instance in case an older installer that
-// does not know about the EULA flag is used to launch the install.
-// Failing to clear flag fails installation because this would prevent updates.
-HRESULT GoopdateImpl::DoHandoff(bool* has_ui_been_displayed) {
- OPT_LOG(L1, (_T("[GoopdateImpl::DoHandoff]")));
- ASSERT1(has_ui_been_displayed);
-
- if (!args_.is_eula_required_set) {
- HRESULT hr = install_self::SetEulaAccepted(is_machine_);
- if (FAILED(hr)) {
- CORE_LOG(LE, (_T("[install_self::SetEulaAccepted failed][0x%08x]"), hr));
- return hr;
- }
- }
-
- HRESULT hr = InitializeClientSecurity();
- if (FAILED(hr)) {
- return hr;
- }
-
- // If /sessionid wasn't specified on the command line, generate a random GUID
- // to use for the session ID. (This can happen if a metainstaller from the
- // prior version does a handoff to a newer version.)
- CString session_id = args_.session_id;
- if (session_id.IsEmpty()) {
- VERIFY1(SUCCEEDED(GetGuid(&session_id)));
- }
-
- hr = InstallApps(is_machine_,
- !args_.is_silent_set, // is_interactive.
- !args_.is_eula_required_set, // is_eula_accepted.
- args_.is_oem_set,
- args_.is_offline_set,
- args_.offline_dir,
- args_.extra,
- args_.install_source,
- session_id,
- has_ui_been_displayed);
- if (FAILED(hr)) {
- CORE_LOG(LE, (_T("[Install failed][0x%08x]"), hr));
- return hr;
- }
-
- return S_OK;
-}
-
-HRESULT GoopdateImpl::DoUpdateAllApps(bool* has_ui_been_displayed ) {
- OPT_LOG(L1, (_T("[GoopdateImpl::DoUpdateAllApps]")));
- ASSERT1(has_ui_been_displayed);
-
- bool is_interactive_update = !args_.is_silent_set;
-
- // TODO(omaha3): Interactive is used as an indication of an on-demand request.
- // It might also be useful to allow on-demand silent update requests.
- // This was a request when we added the ability to disable updates.
- // TODO(omaha3): These on-demand requests should also allow updates if the
- // app update policy is set to on-demand in addition to silent auto.
- const bool is_on_demand = is_interactive_update;
-
- CString install_source = args_.install_source;
-
- if (is_on_demand && install_source.IsEmpty()) {
- // Set an install source for interactive/on-demand update all apps.
- install_source = kCmdLineInstallSource_OnDemandUA;
- }
-
- // TODO(omaha): Consider moving InitializeClientSecurity calls inside
- // install_apps.cc or maybe to update3_utils::CreateGoogleUpdate3Class().
- HRESULT hr = InitializeClientSecurity();
- if (FAILED(hr)) {
- ASSERT1(false);
- return is_interactive_update ? hr : S_OK;
- }
-
- hr = UpdateApps(is_machine_,
- is_interactive_update,
- is_on_demand,
- install_source,
- args_.extra.language,
- has_ui_been_displayed);
- OPT_LOG(L2, (_T("[Update all apps process finished][0x%x]"), hr));
-
- // The UA worker always returns S_OK. UA can be launched by the scheduled task
- // or the core, neither of which wait for a return code. On Vista, returning
- // an error code from the scheduled task reportedly causes issues with the
- // task scheduler in rare cases, so returning S_OK helps with that as well.
- // However, in interactive cases, we should return the actual error so that it
- // can be reported to the user if necessary.
- return is_interactive_update ? hr : S_OK;
-}
-
-HRESULT GoopdateImpl::DoCrash() {
-#if DEBUG
- return static_cast<HRESULT>(Crash::CrashNow());
-#else
- return S_OK;
-#endif
-}
-
-HRESULT GoopdateImpl::HandleUninstall() {
- // TODO(omaha3): Why don't we always acquire this lock before uninstalling?
- // We don't in the /install case. I guess it's important that we uninstall
- // the first time in that case, but there's a chance that the case in the
- // referenced bug could occur while a user is installing.
-
- // Attempt a conditional uninstall and always return S_OK to avoid
- // executing error handling code in the case of an actual uninstall.
- // Do not attempt to uninstall if MSI is busy to avoid spurious uninstalls.
- // See http://b/1436223. The call to WaitForMSIExecute blocks with a
- // timeout. It is better to block here than block while holding the setup
- // lock.
- HRESULT hr = WaitForMSIExecute(kWaitForMSIExecuteMs);
- CORE_LOG(L2, (_T("[WaitForMSIExecute returned 0x%08x]"), hr));
- if (SUCCEEDED(hr)) {
- MaybeUninstallGoogleUpdate();
- }
- return S_OK;
-}
-
-HRESULT GoopdateImpl::HandlePing() {
- return Ping::HandlePing(is_machine_, args_.ping_string);
-}
-
-// TODO(omaha3): In Omaha 2, this was also called when /ig failed. There is a
-// separate call to UninstallSelf for /install in goopdate.cc. Should we call
-// this instead to ensure we ping? Should we try to only call from one location?
-// If we move it, make sure it is called regardless of LastChecked. See
-// http://b/2663423.
-
-// Uninstall is a tricky use case. Uninstall can primarily happen in three cases
-// and there are two mechanisms to uninstall. The cases in which Omaha
-// uninstalls are:
-// 1. The last registered application uninstalls. If Omaha is long-running,
-// Omaha monitors the Client keys and it will trigger an immediate uninstall in
-// this case.
-// 2. The core starts an update worker, if there are no registered
-// applications, the update worker will do the uninstall.
-// 3. An error, including user cancel, happens during Omaha or app installation
-// and there are no registered applications.
-// The uninstall is implemented in terms of the following mechanisms:
-// * An update worker launched with "/ua /uninstalled" by the core, in the
-// first two cases above.
-// * A direct uninstall, in the case of errors or user cancellations, in the
-// last case above.
-//
-// Omaha can uninstall only if there are no install workers running and no
-// registered applications. This check is done under the setup lock protection.
-// In addition, the uninstall worker takes the update worker lock. Acquiring
-// this lock is important since the silent installers can modify the
-// registration of apps and trigger uninstalls workers. Therefore, both
-// setup lock and the update worker locks are needed.
-//
-// In the direct uninstall case there is a small race condition, since there is
-// no other single lock that can be acquired to prevent changes to the
-// application registration. The code looks for install workers but the test is
-// racy if not protected by locks.
-void GoopdateImpl::MaybeUninstallGoogleUpdate() {
- CORE_LOG(L1, (_T("[MaybeUninstallGoogleUpdate]")));
- has_uninstalled_ =
- !!SUCCEEDED(install_self::UninstallSelf(is_machine_, true));
-}
-
-// In dbg builds, also checks the post conditions of a /install process to
-// ensure that the registry is correctly populated or has been cleaned up.
-HRESULT GoopdateImpl::UninstallIfNecessary() {
- ASSERT1(COMMANDLINE_MODE_INSTALL == args_.mode);
- ASSERT(!has_uninstalled_, (_T("Worker doesn't uninstall in /install mode")));
-
- if (is_machine_ && !vista_util::IsUserAdmin()) {
- // The non-elevated instance, so do not try to uninstall.
- return S_OK;
- } else {
- CORE_LOG(L2, (_T("[GoopdateImpl::Main /install][Uninstall if necessary]")));
- // COM must be initialized in order to uninstall the scheduled task(s).
- scoped_co_init init_com_apt(COINIT_MULTITHREADED);
- return install_self::UninstallSelf(is_machine_, false);
- }
-}
-
-void GoopdateImpl::OutOfMemoryHandler() {
- ::RaiseException(EXCEPTION_ACCESS_VIOLATION,
- EXCEPTION_NONCONTINUABLE,
- 0,
- NULL);
-}
-
-HRESULT GoopdateImpl::CaptureOSMetrics() {
- int major_version(0);
- int minor_version(0);
- int service_pack_major(0);
- int service_pack_minor(0);
- TCHAR name[MAX_PATH] = {0};
-
- HRESULT hr = SystemInfo::GetSystemVersion(&major_version,
- &minor_version,
- &service_pack_major,
- &service_pack_minor,
- name,
- arraysize(name));
- if (SUCCEEDED(hr)) {
- metric_windows_major_version = major_version;
- metric_windows_minor_version = minor_version;
- metric_windows_sp_major_version = service_pack_major;
- metric_windows_sp_minor_version = service_pack_minor;
- }
-
- return hr;
-}
-
-} // namespace detail
-
-namespace internal {
-
-// TODO(omaha3): Consider moving to app_registry_utils.
-// Returns early if Google Update's EULA is already accepted, as indicated by
-// the lack of eulaaccepted in the Update key.
-// The apps' values are not modified or deleted.
-HRESULT PromoteAppEulaAccepted(bool is_machine) {
- const TCHAR* update_key_name =
- ConfigManager::Instance()->registry_update(is_machine);
- if (!RegKey::HasValue(update_key_name, kRegValueOmahaEulaAccepted)) {
- return S_OK;
- }
-
- const TCHAR* state_key_name =
- ConfigManager::Instance()->registry_client_state(is_machine);
-
- RegKey state_key;
- HRESULT hr = state_key.Open(state_key_name, KEY_READ);
- if (FAILED(hr)) {
- if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) {
- return S_FALSE;
- }
- return hr;
- }
-
- // TODO(omaha): This should actually be iterating over registered products
- // rather than present ClientState keys. These are identical in most cases.
- int num_sub_keys = state_key.GetSubkeyCount();
- for (int i = 0; i < num_sub_keys; ++i) {
- CString sub_key_name;
- if (FAILED(state_key.GetSubkeyNameAt(i, &sub_key_name))) {
- continue;
- }
-
- if (app_registry_utils::IsAppEulaAccepted(is_machine, sub_key_name, true)) {
- ASSERT1(kGoogleUpdateAppId != sub_key_name);
- return install_self::SetEulaAccepted(is_machine);
- }
- }
-
- return S_OK;
-}
-
-// TODO(omaha): Use a registry override instead.
-#if !OFFICIAL_BUILD
-bool IsOmahaShellRunningFromStaging() {
- return !app_util::GetModuleName(NULL).CompareNoCase(kOmahaShellFileName) &&
- app_util::GetModuleDirectory(NULL).Right(_tcslen(_T("staging"))) ==
- _T("staging");
-}
-#endif
-
-// TODO(omaha): needs_admin is only used for one case. Can we avoid it?
-bool IsMachineProcess(CommandLineMode mode,
- bool is_running_from_official_machine_directory,
- bool is_local_system,
- bool is_machine_override,
- Tristate needs_admin) {
- switch (mode) {
- // These "install" operations may not be running from the installed
- // location.
- case COMMANDLINE_MODE_INSTALL:
- case COMMANDLINE_MODE_HANDOFF_INSTALL:
- case COMMANDLINE_MODE_REGISTER_PRODUCT:
- case COMMANDLINE_MODE_UNREGISTER_PRODUCT:
- ASSERT1(TRISTATE_NONE != needs_admin);
- return TRISTATE_TRUE == needs_admin;
-
- // The following is a Code Red repair executable, which runs from temp dir.
- case COMMANDLINE_MODE_RECOVER:
- return is_machine_override;
-
- // The following always runs as the user and may provide UI for on-demand
- // installs and browser launches.
- // The install location determines user vs. machine.
- case COMMANDLINE_MODE_COMSERVER:
- case COMMANDLINE_MODE_ONDEMAND:
-#if !OFFICIAL_BUILD
- // Return machine == true. This is to facilitate unit tests such as
- // GoogleUpdateCoreTest.LaunchCmdElevated_LocalServerRegistered.
- if (IsOmahaShellRunningFromStaging()) {
- return true;
- }
-#endif
-
- ASSERT1(goopdate_utils::IsRunningFromOfficialGoopdateDir(false) ||
- goopdate_utils::IsRunningFromOfficialGoopdateDir(true) ||
- _T("omaha_unittest.exe") == app_util::GetCurrentModuleName() ||
- _T("GoogleUpdate_unsigned.exe") ==
- app_util::GetModuleName(NULL)); // Running in debugger.
- return is_running_from_official_machine_directory;
-
- // The broker forwarder is elevatable and always runs as the user it was
- // created as.
- case COMMANDLINE_MODE_COMBROKER:
- return is_running_from_official_machine_directory;
-
- // The following always runs as the user and is user-initiated.
- case COMMANDLINE_MODE_WEBPLUGIN:
- // The install location determines user vs. machine.
- // This may not be the desired value when doing a cross-install or using
- // the opposite plugin (i.e. user plugin is often used before the machine
- // one).
- ASSERT1(goopdate_utils::IsRunningFromOfficialGoopdateDir(false) ||
- goopdate_utils::IsRunningFromOfficialGoopdateDir(true) ||
- _T("omaha_unittest.exe") == app_util::GetCurrentModuleName());
- return is_running_from_official_machine_directory;
-
- // The following all run silently as the user for user installs or Local
- // System for machine installs.
- case COMMANDLINE_MODE_UPDATE:
- case COMMANDLINE_MODE_CODE_RED_CHECK:
- return is_local_system;
-
- // The following all run silently as the user for user installs or Local
- // System for machine installs.
- case COMMANDLINE_MODE_UA:
- return is_local_system ? true : is_machine_override;
-
- // /ua runs silently as the user for user installs or Local System for
- // machine installs. Interactive machine /ua may be run as the user if
- // /machine is specified.
- case COMMANDLINE_MODE_CORE:
- case COMMANDLINE_MODE_CRASH_HANDLER:
- return is_local_system;
-
- // The following runs silently as Local System.
- case COMMANDLINE_MODE_SERVICE:
- case COMMANDLINE_MODE_MEDIUM_SERVICE:
- ASSERT1(is_local_system);
- return is_local_system;
-
- // The following run as machine for all installs.
- case COMMANDLINE_MODE_SERVICE_REGISTER:
- case COMMANDLINE_MODE_SERVICE_UNREGISTER:
- return true;
-
- // The crashing process determines whether it was a machine or user omaha
- // and correctly sets the /machine switch.
- case COMMANDLINE_MODE_REPORTCRASH:
- return is_machine_override;
-
- // The following all run silently as the user for all installs.
- case COMMANDLINE_MODE_REGSERVER:
- case COMMANDLINE_MODE_UNREGSERVER:
-#if !OFFICIAL_BUILD
- // Return machine == true. This is to facilitate unit tests such as
- // GoogleUpdateCoreTest.LaunchCmdElevated_LocalServerRegistered.
- if (IsOmahaShellRunningFromStaging()) {
- return true;
- }
-#endif
-
- ASSERT1(goopdate_utils::IsRunningFromOfficialGoopdateDir(false) ||
- goopdate_utils::IsRunningFromOfficialGoopdateDir(true) ||
- _T("omaha_unittest.exe") == app_util::GetCurrentModuleName());
- return is_running_from_official_machine_directory;
-
- // The following may run as user or Local System. Thus, use the directory.
- case COMMANDLINE_MODE_UNINSTALL:
- case COMMANDLINE_MODE_PING:
- ASSERT1(goopdate_utils::IsRunningFromOfficialGoopdateDir(false) ||
- goopdate_utils::IsRunningFromOfficialGoopdateDir(true) ||
- _T("omaha_unittest.exe") == app_util::GetCurrentModuleName());
- return is_running_from_official_machine_directory;
-
- // The following are miscellaneous modes that we do not expect to be running
- // in the wild.
- case COMMANDLINE_MODE_NOARGS:
- case COMMANDLINE_MODE_UNKNOWN:
- case COMMANDLINE_MODE_NETDIAGS:
- case COMMANDLINE_MODE_CRASH:
- default:
- return is_running_from_official_machine_directory;
- }
-}
-
-bool CanDisplayUi(CommandLineMode mode, bool is_silent) {
- switch (mode) {
- case COMMANDLINE_MODE_UNKNOWN:
- // This mode is not one of our known silent modes. Therefore, we can
- // display an error UI.
- return true;
-
- case COMMANDLINE_MODE_INSTALL:
- case COMMANDLINE_MODE_HANDOFF_INSTALL:
- case COMMANDLINE_MODE_UA:
- // These modes have UI unless they are silent.
- // UA is usually silent, but follows the same logic.
- return !is_silent;
-
- case COMMANDLINE_MODE_NOARGS:
- case COMMANDLINE_MODE_CORE:
- case COMMANDLINE_MODE_SERVICE:
- case COMMANDLINE_MODE_REGSERVER:
- case COMMANDLINE_MODE_UNREGSERVER:
- case COMMANDLINE_MODE_NETDIAGS:
- case COMMANDLINE_MODE_CRASH:
- case COMMANDLINE_MODE_REPORTCRASH:
- case COMMANDLINE_MODE_UPDATE:
- case COMMANDLINE_MODE_RECOVER:
- case COMMANDLINE_MODE_WEBPLUGIN:
- case COMMANDLINE_MODE_CODE_RED_CHECK:
- case COMMANDLINE_MODE_COMSERVER:
- case COMMANDLINE_MODE_REGISTER_PRODUCT:
- case COMMANDLINE_MODE_UNREGISTER_PRODUCT:
- case COMMANDLINE_MODE_SERVICE_REGISTER:
- case COMMANDLINE_MODE_SERVICE_UNREGISTER:
- case COMMANDLINE_MODE_CRASH_HANDLER:
- case COMMANDLINE_MODE_COMBROKER:
- case COMMANDLINE_MODE_ONDEMAND:
- case COMMANDLINE_MODE_MEDIUM_SERVICE:
- case COMMANDLINE_MODE_UNINSTALL:
- case COMMANDLINE_MODE_PING:
- default:
- // These modes are always silent.
- return false;
- }
-}
-
-} // namespace internal
-
-Goopdate* Goopdate::instance_ = NULL;
-
-Goopdate& Goopdate::Instance() {
- ASSERT1(instance_);
- return *instance_;
-}
-
-Goopdate::Goopdate(bool is_local_system) {
- CORE_LOG(L2, (_T("[Goopdate::Goopdate]")));
- impl_.reset(new detail::GoopdateImpl(this, is_local_system));
-
- ASSERT1(!instance_);
- instance_ = this;
-}
-
-Goopdate::~Goopdate() {
- CORE_LOG(L2, (_T("[Goopdate::~Goopdate]")));
-
- Stop();
-
- instance_ = NULL;
-}
-
-HRESULT Goopdate::Main(HINSTANCE instance,
- const TCHAR* cmd_line,
- int cmd_show) {
- return impl_->Main(instance, cmd_line, cmd_show);
-}
-
-HRESULT Goopdate::QueueUserWorkItem(UserWorkItem* work_item, uint32 flags) {
- return impl_->QueueUserWorkItem(work_item, flags);
-}
-
-void Goopdate::Stop() {
- return impl_->Stop();
-}
-
-bool Goopdate::is_local_system() const {
- return impl_->is_local_system();
-}
-
-} // namespace omaha
« no previous file with comments | « goopdate/goopdate.h ('k') | goopdate/goopdate.def » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698