diff options
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/app/client_util.cc | 15 | ||||
-rw-r--r-- | chrome/app/client_util.h | 3 | ||||
-rw-r--r-- | chrome/app/google_update_client.cc | 3 | ||||
-rw-r--r-- | chrome/browser/google_update.cc | 101 | ||||
-rw-r--r-- | chrome/installer/util/install_util.cc | 22 | ||||
-rwxr-xr-x | chrome/installer/util/install_util.h | 7 |
6 files changed, 113 insertions, 38 deletions
diff --git a/chrome/app/client_util.cc b/chrome/app/client_util.cc index 333a525..a8841cd 100644 --- a/chrome/app/client_util.cc +++ b/chrome/app/client_util.cc @@ -3,8 +3,7 @@ // found in the LICENSE file. #include "chrome/app/client_util.h" - -#include <shlobj.h> +#include "chrome/installer/util/install_util.h" namespace client_util { const wchar_t kProductVersionKey[] = L"pv"; @@ -17,7 +16,7 @@ bool FileExists(const wchar_t* const file_path) { bool GetChromiumVersion(const wchar_t* const exe_path, const wchar_t* const reg_key_path, wchar_t** version) { - HKEY reg_root = IsUserModeInstall(exe_path) ? HKEY_CURRENT_USER : + HKEY reg_root = InstallUtil::IsPerUserInstall(exe_path) ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; HKEY reg_key; if (::RegOpenKeyEx(reg_root, reg_key_path, 0, @@ -69,15 +68,5 @@ void GetExecutablePath(wchar_t* exe_path) { } } -bool IsUserModeInstall(const wchar_t* const exe_path) { - wchar_t buffer[MAX_PATH] = {0}; - if (!FAILED(SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL, - SHGFP_TYPE_CURRENT, buffer))) { - if (exe_path == wcsstr(exe_path, buffer)) { - return false; - } - } - return true; -} } // namespace client_util diff --git a/chrome/app/client_util.h b/chrome/app/client_util.h index e4b479e..f0b75bb 100644 --- a/chrome/app/client_util.h +++ b/chrome/app/client_util.h @@ -40,9 +40,6 @@ std::wstring GetDLLPath(const std::wstring dll_name, // function. The buffer should already be allocated (ideally of MAX_PATH size). void GetExecutablePath(wchar_t* exe_path); -// Returns false if this is system level install (exe_path is same as -// Program Files path) else returns true. -bool IsUserModeInstall(const wchar_t* const exe_path); } // namespace client_util #endif // CHROME_APP_CLIENT_UTIL_H_ diff --git a/chrome/app/google_update_client.cc b/chrome/app/google_update_client.cc index b691ec5..8ae8aee 100644 --- a/chrome/app/google_update_client.cc +++ b/chrome/app/google_update_client.cc @@ -9,6 +9,7 @@ #include "chrome/app/client_util.h" #include "chrome/installer/util/google_update_constants.h" +#include "chrome/installer/util/install_util.h" namespace { const wchar_t kEnvProductVersionKey[] = L"CHROME_VERSION"; @@ -108,7 +109,7 @@ bool GoogleUpdateClient::Launch(HINSTANCE instance, bool GoogleUpdateClient::Init(const wchar_t* client_guid, const wchar_t* client_dll) { client_util::GetExecutablePath(dll_path_); - user_mode_ = client_util::IsUserModeInstall(dll_path_); + user_mode_ = InstallUtil::IsPerUserInstall(dll_path_); guid_.assign(client_guid); dll_.assign(client_dll); diff --git a/chrome/browser/google_update.cc b/chrome/browser/google_update.cc index 0269e4c..a609fb4 100644 --- a/chrome/browser/google_update.cc +++ b/chrome/browser/google_update.cc @@ -9,40 +9,73 @@ #include "base/message_loop.h" #include "base/path_service.h" +#include "base/string_util.h" #include "base/task.h" #include "base/thread.h" +#include "base/win_util.h" + +#include "chrome/app/client_util.h" #include "chrome/browser/browser_process.h" #include "chrome/installer/util/google_update_constants.h" #include "chrome/installer/util/helper.h" +#include "chrome/installer/util/install_util.h" #include "google_update_idl_i.c" namespace { // Check if the currently running Chrome can be updated by Google Update by // checking if it is running from the standard location. Return true if running // from the standard location, otherwise return false. -bool CanUpdateCurrentChrome() { - std::wstring current_exe_path; - if (PathService::Get(base::DIR_EXE, ¤t_exe_path)) { - std::wstring user_exe_path = installer::GetChromeInstallPath(false); - std::wstring machine_exe_path = installer::GetChromeInstallPath(true); - std::transform(current_exe_path.begin(), current_exe_path.end(), - current_exe_path.begin(), tolower); - std::transform(user_exe_path.begin(), user_exe_path.end(), - user_exe_path.begin(), tolower); - std::transform(machine_exe_path.begin(), machine_exe_path.end(), - machine_exe_path.begin(), tolower); - if (current_exe_path != user_exe_path && - current_exe_path != machine_exe_path ) { - LOG(ERROR) << L"Google Update cannot update Chrome installed in a " - << L"non-standard location: " << current_exe_path.c_str() - << L". The standard location is: " << user_exe_path.c_str() - << L" or " << machine_exe_path.c_str() << L"."; - return false; - } +bool CanUpdateCurrentChrome(const std::wstring& chrome_exe_path) { + std::wstring user_exe_path = installer::GetChromeInstallPath(false); + std::wstring machine_exe_path = installer::GetChromeInstallPath(true); + std::transform(user_exe_path.begin(), user_exe_path.end(), + user_exe_path.begin(), tolower); + std::transform(machine_exe_path.begin(), machine_exe_path.end(), + machine_exe_path.begin(), tolower); + if (chrome_exe_path != user_exe_path && + chrome_exe_path != machine_exe_path ) { + LOG(ERROR) << L"Google Update cannot update Chrome installed in a " + << L"non-standard location: " << chrome_exe_path.c_str() + << L". The standard location is: " << user_exe_path.c_str() + << L" or " << machine_exe_path.c_str() << L"."; + return false; } return true; } + +// Creates an instance of a COM Local Server class using either plain vanilla +// CoCreateInstance, or using the Elevation moniker if running on Vista. +HRESULT CoCreateInstanceAsAdmin(REFCLSID class_id, REFIID interface_id, + void** interface_ptr) { + if (!interface_ptr) + return E_POINTER; + + // For Vista we need to instantiate the COM server via the elevation + // moniker. This ensures that the UAC dialog shows up. + if (win_util::GetWinVersion() == win_util::WINVERSION_VISTA) { + wchar_t class_id_as_string[MAX_PATH] = {0}; + StringFromGUID2(class_id, class_id_as_string, + arraysize(class_id_as_string)); + + std::wstring elevation_moniker_name = + StringPrintf(L"Elevation:Administrator!new:%s", class_id_as_string); + + BIND_OPTS3 bind_opts; + memset(&bind_opts, 0, sizeof(bind_opts)); + + bind_opts.cbStruct = sizeof(bind_opts); + bind_opts.dwClassContext = CLSCTX_LOCAL_SERVER; + return CoGetObject(elevation_moniker_name.c_str(), &bind_opts, + interface_id, reinterpret_cast<void**>(interface_ptr)); + } + + return CoCreateInstance(class_id, NULL, CLSCTX_LOCAL_SERVER, + interface_id, + reinterpret_cast<void**>(interface_ptr)); +} + + } // namespace //////////////////////////////////////////////////////////////////////////////// @@ -188,12 +221,23 @@ void GoogleUpdate::RemoveStatusChangeListener() { bool GoogleUpdate::InitiateGoogleUpdateCheck(bool install_if_newer, MessageLoop* main_loop) { - if (!CanUpdateCurrentChrome()) { + + std::wstring chrome_exe_path; + if (!PathService::Get(base::DIR_EXE, &chrome_exe_path)) { + NOTREACHED(); + return false; + } + + std::transform(chrome_exe_path.begin(), chrome_exe_path.end(), + chrome_exe_path.begin(), tolower); + + if (!CanUpdateCurrentChrome(chrome_exe_path)) { main_loop->PostTask(FROM_HERE, NewRunnableMethod(this, &GoogleUpdate::ReportResults, UPGRADE_ERROR, CANNOT_UPGRADE_CHROME_IN_THIS_DIRECTORY)); return false; } + CComObject<GoogleUpdateJobObserver>* job_observer; HRESULT hr = CComObject<GoogleUpdateJobObserver>::CreateInstance(&job_observer); @@ -205,7 +249,22 @@ bool GoogleUpdate::InitiateGoogleUpdateCheck(bool install_if_newer, CComPtr<IJobObserver> job_holder(job_observer); CComPtr<IGoogleUpdate> on_demand; - hr = on_demand.CoCreateInstance(CLSID_OnDemandUserAppsClass); + + if (InstallUtil::IsPerUserInstall(chrome_exe_path.c_str())) { + hr = on_demand.CoCreateInstance(CLSID_OnDemandUserAppsClass); + } else { + // The Update operation needs Admin privileges for writing + // to %ProgramFiles%. On Vista we need to elevate before instantiating + // the updater instance. + if (!install_if_newer) { + hr = on_demand.CoCreateInstance(CLSID_OnDemandMachineAppsClass); + } else { + hr = CoCreateInstanceAsAdmin(CLSID_OnDemandMachineAppsClass, + IID_IGoogleUpdate, + reinterpret_cast<void**>(&on_demand)); + } + } + if (hr != S_OK) return ReportFailure(hr, GOOGLE_UPDATE_ONDEMAND_CLASS_NOT_FOUND, main_loop); diff --git a/chrome/installer/util/install_util.cc b/chrome/installer/util/install_util.cc index a372070..bec4af8 100644 --- a/chrome/installer/util/install_util.cc +++ b/chrome/installer/util/install_util.cc @@ -7,12 +7,15 @@ #include "install_util.h" +#include <algorithm> #include <shellapi.h> +#include <shlobj.h> #include "base/logging.h" #include "base/registry.h" #include "base/string_util.h" #include "base/win_util.h" + #include "chrome/installer/util/browser_distribution.h" #include "chrome/installer/util/google_update_constants.h" #include "chrome/installer/util/l10n_string_util.h" @@ -109,3 +112,22 @@ void InstallUtil::WriteInstallerResult(bool system_install, if (!install_list->Do()) LOG(ERROR) << "Failed to record installer error information in registry."; } + +bool InstallUtil::IsPerUserInstall(const wchar_t* const exe_path) { + std::wstring exe_path_copy = exe_path; + + wchar_t program_files_path[MAX_PATH] = {0}; + if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL, + SHGFP_TYPE_CURRENT, program_files_path))) { + std::wstring program_files_path_copy = program_files_path; + + if (std::equal(program_files_path_copy.begin(), + program_files_path_copy.end(), exe_path_copy.begin(), + CaseInsensitiveCompare<wchar_t>())) { + return false; + } + } else { + NOTREACHED(); + } + return true; +}
\ No newline at end of file diff --git a/chrome/installer/util/install_util.h b/chrome/installer/util/install_util.h index 95c4bf9..ee6e2ff 100755 --- a/chrome/installer/util/install_util.h +++ b/chrome/installer/util/install_util.h @@ -10,6 +10,7 @@ #define CHROME_INSTALLER_UTIL_INSTALL_UTIL_H__ #include <string> +#include <tchar.h> #include <windows.h> #include "base/basictypes.h" @@ -46,6 +47,12 @@ class InstallUtil { installer_util::InstallStatus status, int string_resource_id, const std::wstring* const launch_cmd); + + // Returns true if this installation path is per user, otherwise returns + // false (per machine install, meaning: the exe_path contains path to + // Program Files). + static bool IsPerUserInstall(const wchar_t* const exe_path); + private: DISALLOW_EVIL_CONSTRUCTORS(InstallUtil); }; |