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

Unified Diff: goopdate/app_manager.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/app_manager.h ('k') | goopdate/app_manager_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: goopdate/app_manager.cc
diff --git a/goopdate/app_manager.cc b/goopdate/app_manager.cc
deleted file mode 100644
index a517354a804b9923cdf13ce26c3846bd5c9c3efc..0000000000000000000000000000000000000000
--- a/goopdate/app_manager.cc
+++ /dev/null
@@ -1,1336 +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.
-// ========================================================================
-
-#include "omaha/goopdate/app_manager.h"
-#include <algorithm>
-#include <cstdlib>
-#include <functional>
-#include <map>
-#include "base/scoped_ptr.h"
-#include "omaha/base/const_object_names.h"
-#include "omaha/base/error.h"
-#include "omaha/base/reg_key.h"
-#include "omaha/base/scoped_ptr_address.h"
-#include "omaha/base/time.h"
-#include "omaha/base/utils.h"
-#include "omaha/base/vistautil.h"
-#include "omaha/common/app_registry_utils.h"
-#include "omaha/common/config_manager.h"
-#include "omaha/common/const_goopdate.h"
-#include "omaha/common/oem_install_utils.h"
-#include "omaha/goopdate/application_usage_data.h"
-#include "omaha/goopdate/model.h"
-#include "omaha/goopdate/server_resource.h"
-#include "omaha/goopdate/string_formatter.h"
-
-namespace omaha {
-
-namespace {
-
-const uint32 kInitialInstallTimeDiff = static_cast<uint32>(-1 * kSecondsPerDay);
-
-// Returns the number of days haven been passed since the given time.
-// The parameter time is in the same format as C time() returns.
-int GetNumberOfDaysSince(int time) {
- ASSERT1(time >= 0);
- const int now = Time64ToInt32(GetCurrent100NSTime());
- ASSERT1(now >= time);
-
- if (now < time) {
- // In case the client computer clock is adjusted in between.
- return 0;
- }
- return (now - time) / kSecondsPerDay;
-}
-
-// Determines if an application is registered with Omaha.
-class IsAppRegisteredFunc
- : public std::unary_function<const CString&, HRESULT> {
- public:
- explicit IsAppRegisteredFunc(const CString& guid)
- : is_registered_(false),
- guid_(guid) {}
-
- bool is_registered() const { return is_registered_; }
-
- HRESULT operator() (const CString& guid) {
- if (guid.CompareNoCase(guid_) == 0) {
- is_registered_ = true;
- }
- return S_OK;
- }
- private:
- CString guid_;
- bool is_registered_;
-};
-
-// Enumerates all sub keys of the key and calls the functor for each of them,
-// ignoring errors to ensure all keys are processed.
-template <typename T>
-HRESULT EnumerateSubKeys(const TCHAR* key_name, T* functor) {
- RegKey client_key;
- HRESULT hr = client_key.Open(key_name, KEY_READ);
- if (FAILED(hr)) {
- return hr;
- }
-
- int num_sub_keys = client_key.GetSubkeyCount();
- for (int i = 0; i < num_sub_keys; ++i) {
- CString sub_key_name;
- hr = client_key.GetSubkeyNameAt(i, &sub_key_name);
- if (SUCCEEDED(hr)) {
- (*functor)(sub_key_name);
- }
- }
-
- return S_OK;
-}
-
-} // namespace
-
-typedef bool (*AppPredictFunc)(const AppManager& app_manager,
- const CString& app_id);
-
-bool IsUninstalledAppPredicate(const AppManager& app_manager,
- const CString& app_id) {
- return app_manager.IsAppUninstalled(app_id);
-}
-
-bool IsAppOemInstalledAndEulaAcceptedPredicate(const AppManager& app_manager,
- const CString& app_id) {
- return app_manager.IsAppOemInstalledAndEulaAccepted(app_id);
-}
-
-bool IsRegisteredAppPredicate(const AppManager& app_manager,
- const CString& app_id) {
- return app_manager.IsAppRegistered(app_id);
-}
-
-// Accumulates app IDs for apps that satisfies the predicate.
-class CollectProductsFunc
- : public std::unary_function<const CString&, HRESULT> {
- public:
- CollectProductsFunc(const AppPredictFunc predicate,
- const AppManager& app_manager,
- AppIdVector* app_ids)
- : predicate_(predicate),
- app_manager_(app_manager),
- app_ids_(app_ids) {
- ASSERT1(app_ids);
- }
-
- // Ignores errors and accumulates as many applications as possible.
- HRESULT operator() (const CString& app_id) const {
- if ((*predicate_)(app_manager_, app_id)) {
- app_ids_->push_back(app_id);
- }
-
- return S_OK;
- }
-
- private:
- const AppPredictFunc predicate_;
- const AppManager& app_manager_;
- AppIdVector* const app_ids_;
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(CollectProductsFunc);
-};
-
-// Runs application registration hooks registered under Omaha AppIds.
-// Reads the Hook Clsid entry under Clients\{AppID}. CoCreates the CLSID. Calls
-// IRegistrationUpdateHook::UpdateRegistry().
-class RunRegistrationUpdateHooksFunc
- : public std::unary_function<const CString&, HRESULT> {
- public:
- explicit RunRegistrationUpdateHooksFunc(const AppManager& app_manager)
- : app_manager_(app_manager) {
- }
-
- HRESULT operator() (const CString& app_id) {
- GUID app_guid = GUID_NULL;
- HRESULT hr = StringToGuidSafe(app_id, &app_guid);
- if (FAILED(hr)) {
- return hr;
- }
- RegKey client_key;
- hr = app_manager_.OpenClientKey(app_guid, &client_key);
- if (FAILED(hr)) {
- return hr;
- }
-
- CString hook_clsid_str;
- hr = client_key.GetValue(kRegValueUpdateHookClsid, &hook_clsid_str);
- if (FAILED(hr)) {
- return hr;
- }
- GUID hook_clsid = GUID_NULL;
- hr = StringToGuidSafe(hook_clsid_str, &hook_clsid);
- if (FAILED(hr)) {
- return hr;
- }
-
- CORE_LOG(L3, (_T("[Update Hook Clsid][%s][%s]"), app_id, hook_clsid_str));
-
- CComPtr<IRegistrationUpdateHook> registration_hook;
- hr = registration_hook.CoCreateInstance(hook_clsid);
- if (FAILED(hr)) {
- CORE_LOG(LE, (_T("[IRegistrationUpdateHook CoCreate failed][0x%x]"), hr));
- return hr;
- }
-
- hr = registration_hook->UpdateRegistry(CComBSTR(app_id),
- app_manager_.is_machine_);
- if (FAILED(hr)) {
- CORE_LOG(LE, (_T("[registration_hook UpdateRegistry failed][0x%x]"), hr));
- return hr;
- }
-
- return S_OK;
- }
-
- private:
- const AppManager& app_manager_;
-};
-
-AppManager* AppManager::instance_ = NULL;
-
-// We do not worry about contention on creation because only the Worker should
-// create AppManager during its initialization.
-HRESULT AppManager::CreateInstance(bool is_machine) {
- ASSERT1(!instance_);
- if (instance_) {
- return S_OK;
- }
-
- AppManager* instance(new AppManager(is_machine));
- if (!instance->InitializeRegistryLock()) {
- HRESULT hr(HRESULTFromLastError());
- delete instance;
- return hr;
- }
-
- instance_ = instance;
- return S_OK;
-}
-
-void AppManager::DeleteInstance() {
- delete instance_;
- instance_ = NULL;
-}
-
-AppManager* AppManager::Instance() {
- ASSERT1(instance_);
- return instance_;
-}
-
-HRESULT AppManager::ReadAppVersionNoLock(bool is_machine, const GUID& app_guid,
- CString* version) {
- ASSERT1(version);
- CORE_LOG(L2, (_T("[ReadAppVersionNoLock][%s]"), GuidToString(app_guid)));
-
- AppManager app_manager(is_machine);
- RegKey client_key;
- HRESULT hr = app_manager.OpenClientKey(app_guid, &client_key);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = client_key.GetValue(kRegValueProductVersion, version);
- if (FAILED(hr)) {
- return hr;
- }
-
- CORE_LOG(L3, (_T("[kRegValueProductVersion][%s]"), *version));
- return S_OK;
-}
-
-AppManager::AppManager(bool is_machine)
- : is_machine_(is_machine) {
- CORE_LOG(L3, (_T("[AppManager::AppManager][is_machine=%d]"), is_machine));
-}
-
-// App installers should use similar code to create a lock to acquire while
-// modifying Omaha registry.
-bool AppManager::InitializeRegistryLock() {
- NamedObjectAttributes lock_attr;
- GetNamedObjectAttributes(kRegistryAccessMutex, is_machine_, &lock_attr);
- return registry_access_lock_.InitializeWithSecAttr(lock_attr.name,
- &lock_attr.sa);
-}
-
-// Vulnerable to a race condition with installers. To prevent this, acquire
-// GetRegistryStableStateLock().
-bool AppManager::IsAppRegistered(const GUID& app_guid) const {
- return IsAppRegistered(GuidToString(app_guid));
-}
-
-// Vulnerable to a race condition with installers. To prevent this, acquire
-// GetRegistryStableStateLock().
-bool AppManager::IsAppRegistered(const CString& app_id) const {
- IsAppRegisteredFunc func(app_id);
- HRESULT hr = EnumerateSubKeys(
- ConfigManager::Instance()->registry_clients(is_machine_),
- &func);
- if (FAILED(hr)) {
- return false;
- }
-
- return func.is_registered();
-}
-
-bool AppManager::IsAppUninstalled(const CString& app_id) const {
- GUID app_guid = {0};
- if (FAILED(StringToGuidSafe(app_id, &app_guid))) {
- ASSERT1(false);
- return false;
- }
- return IsAppUninstalled(app_guid);
-}
-
-// An app is considered uninstalled if:
-// * The app's Clients key does not exist AND
-// * The app's ClientState key exists and contains the pv value.
-// We check for the pv key value in the ClientState to prevent Omaha from
-// detecting the key created in the following scenarios as an uninstalled app.
-// * Per-machine apps may write dr to per-user Omaha's key. Per-user Omaha
-// must not detect this as an uninstalled app.
-// * Omaha may create the app's ClientState key and write values from the
-// metainstaller tag before running the installer, which creates the
-// Clients key.
-bool AppManager::IsAppUninstalled(const GUID& app_guid) const {
- if (IsAppRegistered(app_guid)) {
- return false;
- }
-
- return RegKey::HasValue(GetClientStateKeyName(app_guid),
- kRegValueProductVersion);
-}
-
-bool AppManager::IsAppOemInstalledAndEulaAccepted(const CString& app_id) const {
- GUID app_guid = GUID_NULL;
- if (FAILED(StringToGuidSafe(app_id, &app_guid))) {
- ASSERT1(false);
- return false;
- }
-
- if (IsAppUninstalled(app_guid)) {
- return false;
- }
-
- if (!app_registry_utils::IsAppEulaAccepted(is_machine_, app_id, false)) {
- CORE_LOG(L3, (_T("[EULA not accepted for app %s, its OEM ping not sent.]"),
- app_id.GetString()));
- return false;
- }
-
- return RegKey::HasValue(GetClientStateKeyName(app_guid), kRegValueOemInstall);
-}
-
-// Vulnerable to a race condition with installers. To prevent this, hold
-// GetRegistryStableStateLock() while calling this function and related
-// functions, such as ReadAppPersistentData().
-HRESULT AppManager::GetRegisteredApps(AppIdVector* app_ids) const {
- ASSERT1(app_ids);
-
- CollectProductsFunc func(IsRegisteredAppPredicate, *this, app_ids);
-
- return EnumerateSubKeys(
- ConfigManager::Instance()->registry_clients(is_machine_),
- &func);
-}
-
-// Vulnerable to a race condition with installers. To prevent this, acquire
-// GetRegistryStableStateLock().
-HRESULT AppManager::GetUninstalledApps(AppIdVector* app_ids) const {
- ASSERT1(app_ids);
-
- CollectProductsFunc func(IsUninstalledAppPredicate, *this, app_ids);
-
- return EnumerateSubKeys(
- ConfigManager::Instance()->registry_client_state(is_machine_),
- &func);
-}
-
-HRESULT AppManager::GetOemInstalledAndEulaAcceptedApps(
- AppIdVector* app_ids) const {
- ASSERT1(app_ids);
-
- CollectProductsFunc func(IsAppOemInstalledAndEulaAcceptedPredicate,
- *this,
- app_ids);
-
- return EnumerateSubKeys(
- ConfigManager::Instance()->registry_client_state(is_machine_),
- &func);
-}
-
-HRESULT AppManager::RunRegistrationUpdateHook(const CString& app_id) const {
- return RunRegistrationUpdateHooksFunc(*this)(app_id);
-}
-
-// Vulnerable to a race condition with installers. We think this is acceptable.
-// If there is a future requirement for greater consistency, acquire
-// GetRegistryStableStateLock().
-HRESULT AppManager::RunAllRegistrationUpdateHooks() const {
- RunRegistrationUpdateHooksFunc func(*this);
- const TCHAR* key(ConfigManager::Instance()->registry_clients(is_machine_));
- return EnumerateSubKeys(key, &func);
-}
-
-CString AppManager::GetClientKeyName(const GUID& app_guid) const {
- return app_registry_utils::GetAppClientsKey(is_machine_,
- GuidToString(app_guid));
-}
-
-CString AppManager::GetClientStateKeyName(const GUID& app_guid) const {
- return app_registry_utils::GetAppClientStateKey(is_machine_,
- GuidToString(app_guid));
-}
-
-CString AppManager::GetClientStateMediumKeyName(const GUID& app_guid) const {
- ASSERT1(is_machine_);
- return app_registry_utils::GetAppClientStateMediumKey(is_machine_,
- GuidToString(app_guid));
-}
-
-// Assumes the registry access lock is held.
-HRESULT AppManager::OpenClientKey(const GUID& app_guid,
- RegKey* client_key) const {
- ASSERT1(client_key);
- return client_key->Open(GetClientKeyName(app_guid), KEY_READ);
-}
-
-// Assumes the registry access lock is held.
-HRESULT AppManager::OpenClientStateKey(const GUID& app_guid,
- REGSAM sam_desired,
- RegKey* client_state_key) const {
- ASSERT1(client_state_key);
- CString key_name = GetClientStateKeyName(app_guid);
- return client_state_key->Open(key_name, sam_desired);
-}
-
-// Also creates the ClientStateMedium key for machine apps, ensuring it exists
-// whenever ClientState exists. Does not create ClientStateMedium for Omaha.
-// This function is called for self-updates, so it must explicitly avoid this.
-// Assumes the registry access lock is held.
-HRESULT AppManager::CreateClientStateKey(const GUID& app_guid,
- RegKey* client_state_key) {
- ASSERT1(client_state_key);
- // TODO(omaha3): Add GetOwner() to GLock & add this to Open() functions too.
- // ASSERT1(::GetCurrentThreadId() == registry_access_lock_.GetOwner());
-
- const CString key_name = GetClientStateKeyName(app_guid);
- HRESULT hr = client_state_key->Create(key_name);
- if (FAILED(hr)) {
- CORE_LOG(L3, (_T("[RegKey::Create failed][0x%08x]"), hr));
- return hr;
- }
-
- if (!is_machine_) {
- return S_OK;
- }
-
- if (::IsEqualGUID(kGoopdateGuid, app_guid)) {
- return S_OK;
- }
-
- const CString medium_key_name = GetClientStateMediumKeyName(app_guid);
- hr = RegKey::CreateKey(medium_key_name);
- if (FAILED(hr)) {
- CORE_LOG(L3, (_T("[RegKey::Create ClientStateMedium failed][0x%08x]"), hr));
- return hr;
- }
-
- return S_OK;
-}
-
-// Reads the following values from the registry:
-// Clients key
-// pv
-// lang
-// name
-// ClientState key
-// lang (if not present in Clients)
-// ap
-// tttoken
-// iid
-// brand
-// client
-// experiment
-// (referral is intentionally not read)
-// InstallTime (converted to diff)
-// oeminstall
-// ClientState and ClientStateMedium key
-// eulaaccepted
-// ClientState key in HKCU/HKLM/Low integrity
-// did run
-//
-// app_guid_ is set to the app_guid argument.
-// Note: pv is not read from ClientState into app_data. It's
-// presence is checked for an uninstall
-// TODO(omaha3): We will need to get ClientState's pv when reporting uninstalls.
-// Note: If the application is uninstalled, the Clients key may not exist.
-HRESULT AppManager::ReadAppPersistentData(App* app) {
- ASSERT1(app);
-
- const GUID& app_guid = app->app_guid();
- const CString& app_guid_string = app->app_guid_string();
-
- CORE_LOG(L2, (_T("[AppManager::ReadAppPersistentData][%s]"),
- app_guid_string));
-
- ASSERT1(app->model()->IsLockedByCaller());
-
- __mutexScope(registry_access_lock_);
-
- const bool is_eula_accepted =
- app_registry_utils::IsAppEulaAccepted(is_machine_,
- app_guid_string,
- false);
- app->is_eula_accepted_ = is_eula_accepted ? TRISTATE_TRUE : TRISTATE_FALSE;
-
- bool client_key_exists = false;
- RegKey client_key;
- HRESULT hr = OpenClientKey(app_guid, &client_key);
- if (SUCCEEDED(hr)) {
- client_key_exists = true;
-
- CString version;
- hr = client_key.GetValue(kRegValueProductVersion, &version);
- CORE_LOG(L3, (_T("[AppManager::ReadAppPersistentData]")
- _T("[%s][version=%s]"), app_guid_string, version));
- if (FAILED(hr)) {
- return hr;
- }
-
- app->current_version()->set_version(version);
-
- // Language and name might not be written by installer, so ignore failures.
- client_key.GetValue(kRegValueLanguage, &app->language_);
- client_key.GetValue(kRegValueAppName, &app->display_name_);
- }
-
- // Ensure there is a valid display name.
- if (app->display_name_.IsEmpty()) {
- StringFormatter formatter(app->app_bundle()->display_language());
-
- CString company_name;
- VERIFY1(SUCCEEDED(formatter.LoadString(IDS_FRIENDLY_COMPANY_NAME,
- &company_name)));
-
- VERIFY1(SUCCEEDED(formatter.FormatMessage(&app->display_name_,
- IDS_DEFAULT_APP_DISPLAY_NAME,
- company_name)));
- }
-
- // If ClientState registry key doesn't exist, the function could return.
- // Before opening the key, set days_since_last* to -1, which is the
- // default value if reg key doesn't exist. If later we find that the values
- // are readable, new values will overwrite current ones.
- app->set_days_since_last_active_ping(-1);
- app->set_days_since_last_roll_call(-1);
-
- // The following do not rely on client_state_key, so check them before
- // possibly returning if OpenClientStateKey fails.
-
- // Reads the did run value.
- ApplicationUsageData app_usage(is_machine_, vista_util::IsVistaOrLater());
- app_usage.ReadDidRun(app_guid_string);
-
- // Sets did_run regardless of the return value of ReadDidRun above. If read
- // fails, active_state() should return ACTIVE_UNKNOWN which is intented.
- app->did_run_ = app_usage.active_state();
-
- // TODO(omaha3): Consider moving GetInstallTimeDiffSec() up here. Be careful
- // that the results when ClientState does not exist are desirable. See the
- // comments near that function and above set_days_since_last_active_ping call.
-
- RegKey client_state_key;
- hr = OpenClientStateKey(app_guid, KEY_READ, &client_state_key);
- if (FAILED(hr)) {
- // It is possible that the client state key has not yet been populated.
- // In this case just return the information that we have gathered thus far.
- // However if both keys do not exist, then we are doing something wrong.
- CORE_LOG(LW, (_T("[AppManager::ReadAppPersistentData - No ClientState]")));
- if (client_key_exists) {
- return S_OK;
- } else {
- return hr;
- }
- }
-
- // Read language from ClientState key if it was not found in the Clients key.
- if (app->language().IsEmpty()) {
- client_state_key.GetValue(kRegValueLanguage, &app->language_);
- }
-
- client_state_key.GetValue(kRegValueAdditionalParams, &app->ap_);
- client_state_key.GetValue(kRegValueTTToken, &app->tt_token_);
-
- CString iid;
- client_state_key.GetValue(kRegValueInstallationId, &iid);
- GUID iid_guid;
- if (SUCCEEDED(StringToGuidSafe(iid, &iid_guid))) {
- app->iid_ = iid_guid;
- }
-
- client_state_key.GetValue(kRegValueBrandCode, &app->brand_code_);
- ASSERT1(app->brand_code_.GetLength() <= kBrandIdLength);
- client_state_key.GetValue(kRegValueClientId, &app->client_id_);
-
- // We do not need the referral_id.
-
- DWORD last_active_ping_sec(0);
- if (SUCCEEDED(client_state_key.GetValue(kRegValueActivePingDayStartSec,
- &last_active_ping_sec))) {
- int days_since_last_active_ping =
- GetNumberOfDaysSince(static_cast<int32>(last_active_ping_sec));
- app->set_days_since_last_active_ping(days_since_last_active_ping);
- }
-
- DWORD last_roll_call_sec(0);
- if (SUCCEEDED(client_state_key.GetValue(kRegValueRollCallDayStartSec,
- &last_roll_call_sec))) {
- int days_since_last_roll_call =
- GetNumberOfDaysSince(static_cast<int32>(last_roll_call_sec));
- app->set_days_since_last_roll_call(days_since_last_roll_call);
- }
-
- app->install_time_diff_sec_ = GetInstallTimeDiffSec(app_guid);
- // Generally GetInstallTimeDiffSec() shouldn't return kInitialInstallTimeDiff
- // here. The only exception is in the unexpected case when ClientState exists
- // without a pv.
- ASSERT1((app->install_time_diff_sec_ != kInitialInstallTimeDiff) ||
- !RegKey::HasValue(GetClientStateKeyName(app_guid),
- kRegValueProductVersion));
-
- return S_OK;
-}
-
-void AppManager::ReadAppInstallTimeDiff(App* app) {
- ASSERT1(app);
- app->install_time_diff_sec_ = GetInstallTimeDiffSec(app->app_guid());
-}
-
-// Calls ReadAppPersistentData() to populate app and adds the following values
-// specific to uninstalled apps:
-// ClientState key
-// pv: set as current_version()->version
-//
-// Since this is an uninstalled app, values from the Clients key should not be
-// populated.
-HRESULT AppManager::ReadUninstalledAppPersistentData(App* app) {
- ASSERT1(app);
- ASSERT1(!IsAppRegistered(app->app_guid_string()));
-
- HRESULT hr = ReadAppPersistentData(app);
- if (FAILED(hr)) {
- return hr;
- }
-
- ASSERT1(app->current_version()->version().IsEmpty());
-
- RegKey client_state_key;
- hr = OpenClientStateKey(app->app_guid(), KEY_READ, &client_state_key);
- ASSERT(SUCCEEDED(hr), (_T("Uninstalled apps have a ClientState key.")));
-
- CString version;
- hr = client_state_key.GetValue(kRegValueProductVersion, &version);
- CORE_LOG(L3, (_T("[AppManager::ReadAppPersistentData]")
- _T("[%s][uninstalled version=%s]"),
- app->app_guid_string(), version));
- ASSERT(SUCCEEDED(hr), (_T("Uninstalled apps have a pv.")));
- app->current_version()->set_version(version);
-
- return S_OK;
-}
-
-// Sets the following values in the app's ClientState, to make them available to
-// the installer:
-// lang
-// ap
-// brand (in SetAppBranding)
-// client (in SetAppBranding)
-// experiment
-// referral (in SetAppBranding)
-// InstallTime (in SetAppBranding; converted from diff)
-// oeminstall (if appropriate)
-// eulaaccepted (set/deleted)
-// browser
-// usagestats
-// Sets eulaaccepted=0 if the app is not already registered and the app's EULA
-// has not been accepted. Deletes eulaaccepted if the EULA has been accepted.
-// Only call for initial or over-installs. Do not call for updates to avoid
-// mistakenly replacing data, such as the application's language, and causing
-// unexpected changes to the app during a silent update.
-HRESULT AppManager::WritePreInstallData(const App& app) {
- CORE_LOG(L2, (_T("[AppManager::WritePreInstallData][%s]"),
- app.app_guid_string()));
-
- ASSERT1(app.app_bundle()->is_machine() == is_machine_);
-
- ASSERT1(IsRegistryStableStateLockedByCaller());
- __mutexScope(registry_access_lock_);
-
- RegKey client_state_key;
- HRESULT hr = CreateClientStateKey(app.app_guid(), &client_state_key);
- if (FAILED(hr)) {
- return hr;
- }
-
- if (app.is_eula_accepted()) {
- hr = app_registry_utils::ClearAppEulaNotAccepted(is_machine_,
- app.app_guid_string());
- } else {
- if (!IsAppRegistered(app.app_guid())) {
- hr = app_registry_utils::SetAppEulaNotAccepted(is_machine_,
- app.app_guid_string());
- }
- }
- if (FAILED(hr)) {
- return hr;
- }
-
- if (!app.language().IsEmpty()) {
- VERIFY1(SUCCEEDED(client_state_key.SetValue(kRegValueLanguage,
- app.language())));
- }
-
- if (app.ap().IsEmpty()) {
- VERIFY1(SUCCEEDED(client_state_key.DeleteValue(kRegValueAdditionalParams)));
- } else {
- VERIFY1(SUCCEEDED(client_state_key.SetValue(kRegValueAdditionalParams,
- app.ap())));
- }
-
- CString state_key_path = GetClientStateKeyName(app.app_guid());
- VERIFY1(SUCCEEDED(app_registry_utils::SetAppBranding(state_key_path,
- app.brand_code(),
- app.client_id(),
- app.referral_id())));
-
- if (app.GetExperimentLabels().IsEmpty()) {
- VERIFY1(SUCCEEDED(client_state_key.DeleteValue(kRegValueExperimentLabels)));
- } else {
- VERIFY1(SUCCEEDED(client_state_key.SetValue(kRegValueExperimentLabels,
- app.GetExperimentLabels())));
- }
-
- if (oem_install_utils::IsOemInstalling(is_machine_)) {
- ASSERT1(is_machine_);
- VERIFY1(SUCCEEDED(client_state_key.SetValue(kRegValueOemInstall, _T("1"))));
- }
-
- if (BROWSER_UNKNOWN == app.browser_type()) {
- VERIFY1(SUCCEEDED(client_state_key.DeleteValue(kRegValueBrowser)));
- } else {
- DWORD browser_type = app.browser_type();
- VERIFY1(SUCCEEDED(client_state_key.SetValue(kRegValueBrowser,
- browser_type)));
- }
-
- if (TRISTATE_NONE != app.usage_stats_enable()) {
- VERIFY1(SUCCEEDED(app_registry_utils::SetUsageStatsEnable(
- is_machine_,
- app.app_guid_string(),
- app.usage_stats_enable())));
- }
-
- return S_OK;
-}
-
-// All values are optional.
-void AppManager::ReadInstallerResultApiValues(
- const GUID& app_guid,
- InstallerResult* installer_result,
- DWORD* installer_error,
- DWORD* installer_extra_code1,
- CString* installer_result_uistring,
- CString* installer_success_launch_cmd) {
- ASSERT1(installer_result);
- ASSERT1(installer_error);
- ASSERT1(installer_extra_code1);
- ASSERT1(installer_result_uistring);
- ASSERT1(installer_success_launch_cmd);
-
- __mutexScope(registry_access_lock_);
-
- RegKey client_state_key;
- HRESULT hr = OpenClientStateKey(app_guid, KEY_READ, &client_state_key);
- if (FAILED(hr)) {
- return;
- }
-
- if (SUCCEEDED(client_state_key.GetValue(
- kRegValueInstallerResult,
- reinterpret_cast<DWORD*>(installer_result)))) {
- CORE_LOG(L1, (_T("[InstallerResult in registry][%u]"), *installer_result));
- }
- if (*installer_result >= INSTALLER_RESULT_MAX) {
- CORE_LOG(LW, (_T("[Unsupported InstallerResult value]")));
- *installer_result = INSTALLER_RESULT_DEFAULT;
- }
-
- if (SUCCEEDED(client_state_key.GetValue(kRegValueInstallerError,
- installer_error))) {
- CORE_LOG(L1, (_T("[InstallerError in registry][%u]"), *installer_error));
- }
-
- if (SUCCEEDED(client_state_key.GetValue(kRegValueInstallerExtraCode1,
- installer_extra_code1))) {
- CORE_LOG(L1, (_T("[InstallerExtraCode1 in registry][%u]"),
- *installer_extra_code1));
- }
-
- if (SUCCEEDED(client_state_key.GetValue(kRegValueInstallerResultUIString,
- installer_result_uistring))) {
- CORE_LOG(L1, (_T("[InstallerResultUIString in registry][%s]"),
- *installer_result_uistring));
- }
-
- if (SUCCEEDED(client_state_key.GetValue(
- kRegValueInstallerSuccessLaunchCmdLine,
- installer_success_launch_cmd))) {
- CORE_LOG(L1, (_T("[InstallerSuccessLaunchCmdLine in registry][%s]"),
- *installer_success_launch_cmd));
- }
-
- ClearInstallerResultApiValues(app_guid);
-}
-
-void AppManager::ClearInstallerResultApiValues(const GUID& app_guid) {
- const CString client_state_key_name = GetClientStateKeyName(app_guid);
- const CString update_key_name =
- ConfigManager::Instance()->registry_update(is_machine_);
-
- ASSERT1(IsRegistryStableStateLockedByCaller());
- __mutexScope(registry_access_lock_);
-
- // Delete the old LastXXX values. These may not exist, so don't care if they
- // fail.
- RegKey::DeleteValue(client_state_key_name,
- kRegValueLastInstallerResult);
- RegKey::DeleteValue(client_state_key_name,
- kRegValueLastInstallerResultUIString);
- RegKey::DeleteValue(client_state_key_name,
- kRegValueLastInstallerError);
- RegKey::DeleteValue(client_state_key_name,
- kRegValueLastInstallerExtraCode1);
- RegKey::DeleteValue(client_state_key_name,
- kRegValueLastInstallerSuccessLaunchCmdLine);
-
- // Also delete any values from Google\Update.
- // TODO(Omaha): This is a temporary fix for bug 1539293. See TODO below.
- RegKey::DeleteValue(update_key_name,
- kRegValueLastInstallerResult);
- RegKey::DeleteValue(update_key_name,
- kRegValueLastInstallerResultUIString);
- RegKey::DeleteValue(update_key_name,
- kRegValueLastInstallerError);
- RegKey::DeleteValue(update_key_name,
- kRegValueLastInstallerExtraCode1);
- RegKey::DeleteValue(update_key_name,
- kRegValueLastInstallerSuccessLaunchCmdLine);
-
- // Rename current InstallerResultXXX values to LastXXX.
- RegKey::RenameValue(client_state_key_name,
- kRegValueInstallerResult,
- kRegValueLastInstallerResult);
- RegKey::RenameValue(client_state_key_name,
- kRegValueInstallerError,
- kRegValueLastInstallerError);
- RegKey::RenameValue(client_state_key_name,
- kRegValueInstallerExtraCode1,
- kRegValueLastInstallerExtraCode1);
- RegKey::RenameValue(client_state_key_name,
- kRegValueInstallerResultUIString,
- kRegValueLastInstallerResultUIString);
- RegKey::RenameValue(client_state_key_name,
- kRegValueInstallerSuccessLaunchCmdLine,
- kRegValueLastInstallerSuccessLaunchCmdLine);
-
- // Copy over to the Google\Update key.
- // TODO(Omaha3): This is a temporary fix for bug 1539293. Once Pack V2 is
- // deprecated (Pack stops taking offline installers for new versions of
- // Omaha apps), remove this. (It might be useful to leave the CopyValue calls
- // in DEBUG builds only.)
- RegKey::CopyValue(client_state_key_name,
- update_key_name,
- kRegValueLastInstallerResult);
- RegKey::CopyValue(client_state_key_name,
- update_key_name,
- kRegValueLastInstallerError);
- RegKey::CopyValue(client_state_key_name,
- update_key_name,
- kRegValueLastInstallerExtraCode1);
- RegKey::CopyValue(client_state_key_name,
- update_key_name,
- kRegValueLastInstallerResultUIString);
- RegKey::CopyValue(client_state_key_name,
- update_key_name,
- kRegValueLastInstallerSuccessLaunchCmdLine);
-}
-
-// Reads the following values from Clients:
-// pv
-// lang (if present)
-// name is not read. TODO(omaha3): May change if we persist name in registry.
-HRESULT AppManager::ReadInstallerRegistrationValues(App* app) {
- ASSERT1(app);
-
- const CString& app_guid_string = app->app_guid_string();
-
- CORE_LOG(L2, (_T("[AppManager::ReadInstallerRegistrationValues][%s]"),
- app_guid_string));
-
- ASSERT1(app->model()->IsLockedByCaller());
-
- __mutexScope(registry_access_lock_);
-
- RegKey client_key;
- if (FAILED(OpenClientKey(app->app_guid(), &client_key))) {
- OPT_LOG(LE, (_T("[Installer did not create key][%s]"), app_guid_string));
- return GOOPDATEINSTALL_E_INSTALLER_DID_NOT_WRITE_CLIENTS_KEY;
- }
-
- CString version;
- if (FAILED(client_key.GetValue(kRegValueProductVersion, &version))) {
- OPT_LOG(LE, (_T("[Installer did not register][%s]"), app_guid_string));
- return GOOPDATEINSTALL_E_INSTALLER_DID_NOT_WRITE_CLIENTS_KEY;
- }
-
- if (version.IsEmpty()) {
- OPT_LOG(LE, (_T("[Installer did not write version][%s]"), app_guid_string));
- return GOOPDATEINSTALL_E_INSTALLER_DID_NOT_WRITE_CLIENTS_KEY;
- }
-
- app->next_version()->set_version(version);
-
- CString language;
- if (SUCCEEDED(client_key.GetValue(kRegValueLanguage, &language))) {
- app->language_ = language;
- }
-
- return S_OK;
-}
-
-// Writes tttoken and updates relevant stats.
-void AppManager::PersistSuccessfulUpdateCheckResponse(
- const App& app,
- bool is_update_available) {
- CORE_LOG(L2, (_T("[AppManager::PersistSuccessfulUpdateCheckResponse]")
- _T("[%s][%d]"), app.app_guid_string(), is_update_available));
- __mutexScope(registry_access_lock_);
-
- VERIFY1(SUCCEEDED(SetTTToken(app)));
-
- const CString client_state_key = GetClientStateKeyName(app.app_guid());
-
- if (is_update_available) {
- if (app.error_code() == GOOPDATE_E_APP_UPDATE_DISABLED_BY_POLICY) {
- // The error indicates is_update and updates are disabled by policy.
- ASSERT1(app.is_update());
- app_registry_utils::ClearUpdateAvailableStats(client_state_key);
- } else if (app.is_update()) {
- // Only record an update available event for updates.
- // We have other mechanisms, including IID, to track install success.
- UpdateUpdateAvailableStats(app.app_guid());
- }
- } else {
- app_registry_utils::ClearUpdateAvailableStats(client_state_key);
- app_registry_utils::PersistSuccessfulUpdateCheck(client_state_key);
- }
-}
-
-// Writes the following values to the ClientState key:
-// pv (should be value written by installer in Clients key)
-// lang (should be value written by installer in Clients key)
-// iid (set/deleted)
-//
-// Does not write the following values because they were set by
-// WritePreInstallData() and would not have changed during installation unless
-// modified directly by the app installer.
-// ap
-// brand
-// client
-// experiment
-// referral
-// InstallTime (converted from diff)
-// oeminstall
-// eulaaccepted
-// browser
-// usagestats
-// TODO(omaha3): Maybe we should delete referral at this point. Ask Chrome.
-//
-// Other values, such as tttoken were set after the update check.
-//
-// The caller is responsible for modifying the values in app_data as
-// appropriate, including:
-// * Updating values in app_data to reflect installer's values (pv and lang)
-// * Clearing iid if appropriate.
-// * Clearing the did run value. TODO(omaha3): Depends on TODO below.
-void AppManager::PersistSuccessfulInstall(const App& app) {
- CORE_LOG(L2, (_T("[AppManager::PersistSuccessfulInstall][%s]"),
- app.app_guid_string()));
-
- ASSERT1(IsRegistryStableStateLockedByCaller());
- __mutexScope(registry_access_lock_);
-
- ASSERT1(!::IsEqualGUID(kGoopdateGuid, app.app_guid()));
-
- RegKey client_state_key;
- VERIFY1(SUCCEEDED(CreateClientStateKey(app.app_guid(), &client_state_key)));
-
- VERIFY1(SUCCEEDED(client_state_key.SetValue(kRegValueProductVersion,
- app.next_version()->version())));
-
- if (!app.language().IsEmpty()) {
- VERIFY1(SUCCEEDED(client_state_key.SetValue(kRegValueLanguage,
- app.language())));
- }
-
- if (::IsEqualGUID(app.iid(), GUID_NULL)) {
- VERIFY1(SUCCEEDED(client_state_key.DeleteValue(kRegValueInstallationId)));
- } else {
- VERIFY1(SUCCEEDED(client_state_key.SetValue(
- kRegValueInstallationId,
- GuidToString(app.iid()))));
- }
-
- const CString client_state_key_path = GetClientStateKeyName(app.app_guid());
- app_registry_utils::PersistSuccessfulInstall(client_state_key_path,
- app.is_update(),
- false); // TODO(omaha3): offline
-}
-
-HRESULT AppManager::SynchronizeClientState(const GUID& app_guid) {
- __mutexScope(registry_access_lock_);
-
- RegKey client_key;
- HRESULT hr = OpenClientKey(app_guid, &client_key);
- if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) {
- return S_OK;
- }
- if (FAILED(hr)) {
- return hr;
- }
-
- RegKey client_state_key;
- hr = CreateClientStateKey(app_guid, &client_state_key);
- if (FAILED(hr)) {
- return hr;
- }
-
- CString version;
- client_key.GetValue(kRegValueProductVersion, &version);
- if (FAILED(hr)) {
- return hr;
- }
- hr = client_state_key.SetValue(kRegValueProductVersion, version);
- if (FAILED(hr)) {
- return hr;
- }
-
- CString language;
- client_key.GetValue(kRegValueLanguage, &language);
- if (!language.IsEmpty()) {
- return client_state_key.SetValue(kRegValueLanguage, language);
- }
-
- return S_OK;
-}
-
-// TODO(omaha3): tttoken is not currently read from the server response.
-// TODO(omaha3): When implementing offline, we must make sure that the tttoken
-// is not deleted by the offline response processing.
-// TODO(omaha3): Having the parser write the server's token to the same member
-// that is used for the value from the tag exposes this value to the COM setter.
-// It would be nice to avoid that, possibly by only allowing that setter to work
-// in certain states.
-HRESULT AppManager::SetTTToken(const App& app) {
- CORE_LOG(L3, (_T("[AppManager::SetTTToken][token=%s]"), app.tt_token()));
-
- __mutexScope(registry_access_lock_);
-
- RegKey client_state_key;
- HRESULT hr = CreateClientStateKey(app.app_guid(), &client_state_key);
- if (FAILED(hr)) {
- return hr;
- }
-
- if (app.tt_token().IsEmpty()) {
- return client_state_key.DeleteValue(kRegValueTTToken);
- } else {
- return client_state_key.SetValue(kRegValueTTToken, app.tt_token());
- }
-}
-
-void AppManager::ClearOemInstalled(const AppIdVector& app_ids) {
- __mutexScope(registry_access_lock_);
-
- AppIdVector::const_iterator it;
- for (it = app_ids.begin(); it != app_ids.end(); ++it) {
- ASSERT1(IsAppOemInstalledAndEulaAccepted(*it));
- RegKey state_key;
-
- GUID app_guid = GUID_NULL;
- HRESULT hr = StringToGuidSafe(*it, &app_guid);
- if (FAILED(hr)) {
- continue;
- }
-
- hr = OpenClientStateKey(app_guid, KEY_ALL_ACCESS, &state_key);
- if (FAILED(hr)) {
- continue;
- }
-
- VERIFY1(SUCCEEDED(state_key.DeleteValue(kRegValueOemInstall)));
- }
-}
-
-void AppManager::UpdateUpdateAvailableStats(const GUID& app_guid) {
- __mutexScope(registry_access_lock_);
-
- RegKey state_key;
- HRESULT hr = CreateClientStateKey(app_guid, &state_key);
- if (FAILED(hr)) {
- ASSERT1(false);
- return;
- }
-
- DWORD update_available_count(0);
- hr = state_key.GetValue(kRegValueUpdateAvailableCount,
- &update_available_count);
- if (FAILED(hr)) {
- update_available_count = 0;
- }
- ++update_available_count;
- VERIFY1(SUCCEEDED(state_key.SetValue(kRegValueUpdateAvailableCount,
- update_available_count)));
-
- DWORD64 update_available_since_time(0);
- hr = state_key.GetValue(kRegValueUpdateAvailableSince,
- &update_available_since_time);
- if (FAILED(hr)) {
- // There is no existing value, so this must be the first update notice.
- VERIFY1(SUCCEEDED(state_key.SetValue(kRegValueUpdateAvailableSince,
- GetCurrent100NSTime())));
-
- // TODO(omaha): It would be nice to report the version that we were first
- // told to update to. This is available in UpdateResponse but we do not
- // currently send it down in update responses. If we start using it, add
- // kRegValueFirstUpdateResponseVersion.
- }
-}
-
-// Returns 0 for any values that are not found.
-void AppManager::ReadUpdateAvailableStats(
- const GUID& app_guid,
- DWORD* update_responses,
- DWORD64* time_since_first_response_ms) {
- ASSERT1(update_responses);
- ASSERT1(time_since_first_response_ms);
- *update_responses = 0;
- *time_since_first_response_ms = 0;
-
- __mutexScope(registry_access_lock_);
-
- RegKey state_key;
- HRESULT hr = OpenClientStateKey(app_guid, KEY_READ, &state_key);
- if (FAILED(hr)) {
- CORE_LOG(LW, (_T("[App ClientState key does not exist][%s]"),
- GuidToString(app_guid)));
- return;
- }
-
- DWORD update_responses_in_reg(0);
- hr = state_key.GetValue(kRegValueUpdateAvailableCount,
- &update_responses_in_reg);
- if (SUCCEEDED(hr)) {
- *update_responses = update_responses_in_reg;
- }
-
- DWORD64 update_available_since_time(0);
- hr = state_key.GetValue(kRegValueUpdateAvailableSince,
- &update_available_since_time);
- if (SUCCEEDED(hr)) {
- const DWORD64 current_time = GetCurrent100NSTime();
- ASSERT1(update_available_since_time <= current_time);
- const DWORD64 time_since_first_response_in_100ns =
- current_time - update_available_since_time;
- *time_since_first_response_ms =
- time_since_first_response_in_100ns / kMillisecsTo100ns;
- }
-}
-
-uint32 AppManager::GetInstallTimeDiffSec(const GUID& app_guid) const {
- if (!IsAppRegistered(app_guid) && !IsAppUninstalled(app_guid)) {
- return kInitialInstallTimeDiff;
- }
-
- RegKey client_state_key;
- HRESULT hr = OpenClientStateKey(app_guid, KEY_READ, &client_state_key);
- if (FAILED(hr)) {
- return 0;
- }
-
- DWORD install_time(0);
- DWORD install_time_diff_sec(0);
- if (SUCCEEDED(client_state_key.GetValue(kRegValueInstallTimeSec,
- &install_time))) {
- const uint32 now = Time64ToInt32(GetCurrent100NSTime());
- if (0 != install_time && now >= install_time) {
- install_time_diff_sec = now - install_time;
- // TODO(omaha3): Restore this assert. In Omaha 2, this function gets
- // called as part of installation verification and Job::UpdateJob(), so
- // the value can be 0. This will not be the case in Omaha 3.
- // ASSERT1(install_time_diff_sec != 0);
- }
- }
-
- return install_time_diff_sec;
-}
-
-// Clear the Installation ID if at least one of the conditions is true:
-// 1) DidRun==yes. First run is the last time we want to use the Installation
-// ID. So delete Installation ID if it is present.
-// 2) kMaxLifeOfInstallationIDSec has passed since the app was installed. This
-// is to ensure that Installation ID is cleared even if DidRun is never set.
-// 3) The app is Omaha. Always delete Installation ID if it is present
-// because DidRun does not apply.
-HRESULT AppManager::ClearInstallationId(const App& app) {
- ASSERT1(app.model()->IsLockedByCaller());
- __mutexScope(registry_access_lock_);
-
- if (::IsEqualGUID(app.iid(), GUID_NULL)) {
- return S_OK;
- }
-
- if ((ACTIVE_RUN == app.did_run()) ||
- (kMaxLifeOfInstallationIDSec <= app.install_time_diff_sec()) ||
- (::IsEqualGUID(kGoopdateGuid, app.app_guid()))) {
- CORE_LOG(L1, (_T("[Deleting iid for app][%s]"), app.app_guid_string()));
-
- RegKey client_state_key;
- HRESULT hr = CreateClientStateKey(app.app_guid(), &client_state_key);
- if (FAILED(hr)) {
- return hr;
- }
-
- return client_state_key.DeleteValue(kRegValueInstallationId);
- }
-
- return S_OK;
-}
-
-void AppManager::SetLastPingDayStartTime(const App& app,
- int elapsed_seconds_since_day_start) {
- ASSERT1(elapsed_seconds_since_day_start >= 0);
- ASSERT1(elapsed_seconds_since_day_start < kMaxTimeSinceMidnightSec);
- ASSERT1(app.model()->IsLockedByCaller());
-
- __mutexScope(registry_access_lock_);
-
- int now = Time64ToInt32(GetCurrent100NSTime());
-
- RegKey client_state_key;
- if (FAILED(CreateClientStateKey(app.app_guid(), &client_state_key))) {
- return;
- }
-
- bool did_send_active_ping = (app.did_run() == ACTIVE_RUN &&
- app.days_since_last_active_ping() != 0);
- if (did_send_active_ping) {
- VERIFY1(SUCCEEDED(client_state_key.SetValue(
- kRegValueActivePingDayStartSec,
- static_cast<DWORD>(now - elapsed_seconds_since_day_start))));
- }
-
- bool did_send_roll_call = (app.days_since_last_roll_call() != 0);
- if (did_send_roll_call) {
- VERIFY1(SUCCEEDED(client_state_key.SetValue(
- kRegValueRollCallDayStartSec,
- static_cast<DWORD>(now - elapsed_seconds_since_day_start))));
- }
-}
-
-// Writes the day start time when last active ping/roll call happened to
-// registry if the corresponding ping has been sent.
-// Removes installation id, if did run = true or if goopdate.
-// Clears did run.
-HRESULT AppManager::PersistUpdateCheckSuccessfullySent(
- const App& app,
- int elapsed_seconds_since_day_start) {
- ASSERT1(app.model()->IsLockedByCaller());
-
- ApplicationUsageData app_usage(app.app_bundle()->is_machine(),
- vista_util::IsVistaOrLater());
- VERIFY1(SUCCEEDED(app_usage.ResetDidRun(app.app_guid_string())));
-
- SetLastPingDayStartTime(app, elapsed_seconds_since_day_start);
-
- // Handle the installation id.
- VERIFY1(SUCCEEDED(ClearInstallationId(app)));
-
- return S_OK;
-}
-
-HRESULT AppManager::RemoveClientState(const GUID& app_guid) {
- CORE_LOG(L2, (_T("[AppManager::RemoveClientState][%s]"),
- GuidToString(app_guid)));
- ASSERT1(IsRegistryStableStateLockedByCaller());
- __mutexScope(registry_access_lock_);
-
- ASSERT1(!IsAppRegistered(app_guid));
-
- return app_registry_utils::RemoveClientState(is_machine_,
- GuidToString(app_guid));
-}
-
-// TODO(omaha3): May not need these
-#if 0
-// Writes 0.0.0.1 to pv. This value avoids any special cases, such as initial
-// install rules, for 0.0.0.0, while being unlikely to be higher than the
-// product's actual current version.
-HRESULT AppManager::RegisterProduct(const GUID& product_guid,
- const CString& product_name) {
- const TCHAR* const kRegisterProductVersion = _T("0.0.0.1");
-
- __mutexScope(GetRegistryStableStateLock());
- RegKey client_key;
- HRESULT hr = client_key.Create(GetClientKeyName(GUID_NULL, product_guid));
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = client_key.SetValue(kRegValueProductVersion, kRegisterProductVersion);
- if (FAILED(hr)) {
- return hr;
- }
-
- // AppName is not a required parameter since it's only used for being able to
- // easily tell what application is there when reading the registry.
- VERIFY1(SUCCEEDED(client_key.SetValue(kRegValueAppName, product_name)));
-
- return S_OK;
-}
-
-HRESULT AppManager::UnregisterProduct(const GUID& product_guid) {
- __mutexScope(GetRegistryStableStateLock());
- return RegKey::DeleteKey(GetClientKeyName(GUID_NULL, product_guid), true);
-}
-#endif
-
-} // namespace omaha
« no previous file with comments | « goopdate/app_manager.h ('k') | goopdate/app_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698