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

Side by Side Diff: chrome/installer/setup/setup_main.cc

Issue 1271893003: Add options to write version number to registry. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: change DisplayVersion in Uninstall, too Created 5 years, 3 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/installer/setup/setup_main.h" 5 #include "chrome/installer/setup/setup_main.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 #include <msi.h> 8 #include <msi.h>
9 #include <shellapi.h> 9 #include <shellapi.h>
10 #include <shlobj.h> 10 #include <shlobj.h>
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 #endif 73 #endif
74 74
75 using installer::InstallerState; 75 using installer::InstallerState;
76 using installer::InstallationState; 76 using installer::InstallationState;
77 using installer::InstallationValidator; 77 using installer::InstallationValidator;
78 using installer::MasterPreferences; 78 using installer::MasterPreferences;
79 using installer::Product; 79 using installer::Product;
80 using installer::ProductState; 80 using installer::ProductState;
81 using installer::Products; 81 using installer::Products;
82 82
83 const wchar_t kGoogleUpdatePipeName[] = L"\\\\.\\pipe\\GoogleCrashServices\\"; 83 const wchar_t kGoogleUpdatePipeName[] = L"\\\\.\\pipe\\GoogleCrashServices\\";
grt (UTC plus 2) 2015/09/11 18:14:26 please move all of these constants that are only u
bcwhite 2015/09/11 19:24:44 Done.
84 const wchar_t kSystemPrincipalSid[] = L"S-1-5-18"; 84 const wchar_t kSystemPrincipalSid[] = L"S-1-5-18";
85 const wchar_t kDisplayVersion[] = L"DisplayVersion";
86 const wchar_t kMsiInstallRegistryPrefix[] =
87 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\"
88 L"S-1-5-18\\Products\\";
89 const wchar_t kMsiInstallRegistryPostfix[] = L"\\InstallProperties";
90 const wchar_t kMsiUninstallRegistryPrefix[] =
91 L"SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\";
92 const wchar_t kMsiUninstallRegistryPostfix[] = L"";
93 const wchar_t kMsiDisplayVersionOverwriteDelay[] = L"10"; // seconds as string
85 94
86 const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>( 95 const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>(
87 MiniDumpWithProcessThreadData | // Get PEB and TEB. 96 MiniDumpWithProcessThreadData | // Get PEB and TEB.
88 MiniDumpWithUnloadedModules | // Get unloaded modules when available. 97 MiniDumpWithUnloadedModules | // Get unloaded modules when available.
89 MiniDumpWithIndirectlyReferencedMemory); // Get memory referenced by stack. 98 MiniDumpWithIndirectlyReferencedMemory); // Get memory referenced by stack.
90 99
91 namespace { 100 namespace {
92 101
102 // Overwrite an existing DisplayVersion as written by the MSI installer
103 // with the real version number of Chrome.
104 LONG OverwriteDisplayVersion(const base::string16& path,
105 const base::string16& value) {
106 base::win::RegKey key;
107 LONG result = 0;
108 base::string16 existing;
109 if ((result = key.Open(HKEY_LOCAL_MACHINE, path.c_str(),
110 KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_WOW64_64KEY))
111 != ERROR_SUCCESS) {
112 LOG(ERROR) << "Failed to set DisplayVersion: " << path << " not found";
113 return result;
114 }
115 if ((result = key.ReadValue(kDisplayVersion, &existing)) != ERROR_SUCCESS) {
116 LOG(ERROR) << "Failed to set DisplayVersion: " << kDisplayVersion
117 << " not found under " << path;
118 return result;
119 }
120 if ((result = key.WriteValue(kDisplayVersion, value.c_str()))
121 != ERROR_SUCCESS) {
122 LOG(ERROR) << "Failed to set DisplayVersion: " << kDisplayVersion
123 << " could not be written under " << path;
124 return result;
125 }
126 VLOG(1) << "Set DisplayVersion at " << path << " to " << value
127 << " from " << existing;
128 return ERROR_SUCCESS;
129 }
130
131 LONG OverwriteDisplayVersions(const base::string16& product,
132 const base::string16& value) {
133 // The version is held in two places. Frist change it in the MSI Installer
134 // registry entry. It is held under a "squashed guid" key.
135 base::string16 reg_path(kMsiInstallRegistryPrefix);
136 reg_path += base::ASCIIToUTF16(
grt (UTC plus 2) 2015/09/11 18:14:26 can GuidToSquid operate on base::string16 so we do
bcwhite 2015/09/11 19:24:44 Done.
137 installer::GuidToSquid(base::UTF16ToASCII(product)));
138 reg_path += kMsiInstallRegistryPostfix;
139 LONG result1 = OverwriteDisplayVersion(reg_path, value);
140
141 // The display version also exists under the Unininstall registry key with
142 // the original guid.
143 reg_path = kMsiUninstallRegistryPrefix;
grt (UTC plus 2) 2015/09/11 18:14:26 i think it's more clear to use base::StringPrintf
bcwhite 2015/09/11 19:24:45 Done.
144 reg_path += L"{";
145 reg_path += product;
146 reg_path += L"}";
147 reg_path += kMsiUninstallRegistryPostfix;
148 LONG result2 = OverwriteDisplayVersion(reg_path, value);
149
150 return result1 != ERROR_SUCCESS ? result1 : result2;
151 }
152
153 void DelayedOverwriteDisplayVersions(const base::FilePath& setup_exe,
154 const base::string16& id,
155 const Version& version) {
156 // This process has to be able to exit so we launch ourselves with
157 // instructions on what to do and then return.
158 base::CommandLine command_line(setup_exe);
159 command_line.AppendSwitchNative(
160 installer::switches::kSetDisplayVersionProduct, id);
161 command_line.AppendSwitchNative(installer::switches::kSetDisplayVersionValue,
grt (UTC plus 2) 2015/09/11 18:14:26 nit: use AppendSwitchASCII and remove the ASCIIToU
bcwhite 2015/09/11 19:24:44 Done.
162 base::ASCIIToUTF16(version.GetString()));
163 command_line.AppendSwitchNative(installer::switches::kDelay,
164 kMsiDisplayVersionOverwriteDelay);
165
166 base::LaunchOptions launch_options;
167 launch_options.force_breakaway_from_job_ = true;
168 base::Process writer = base::LaunchProcess(command_line, launch_options);
169 if (!writer.IsValid()) {
170 LOG(ERROR) << "Failed to set DisplayVersion: "
grt (UTC plus 2) 2015/09/11 18:14:26 tip: PLOG(ERROR) and remove the GetLastError() tid
bcwhite 2015/09/11 19:24:45 Done.
171 << "could not launch subprocess to make desired changes."
172 << " (error=" << ::GetLastError() << ")\n"
grt (UTC plus 2) 2015/09/11 18:14:26 i think it's best not to put newlines in log messa
bcwhite 2015/09/11 19:24:44 Done.
173 << command_line.GetCommandLineString();
174 }
175 }
176
93 // Returns NULL if no compressed archive is available for processing, otherwise 177 // Returns NULL if no compressed archive is available for processing, otherwise
94 // returns a patch helper configured to uncompress and patch. 178 // returns a patch helper configured to uncompress and patch.
95 scoped_ptr<installer::ArchivePatchHelper> CreateChromeArchiveHelper( 179 scoped_ptr<installer::ArchivePatchHelper> CreateChromeArchiveHelper(
96 const base::FilePath& setup_exe, 180 const base::FilePath& setup_exe,
97 const base::CommandLine& command_line, 181 const base::CommandLine& command_line,
98 const installer::InstallerState& installer_state, 182 const installer::InstallerState& installer_state,
99 const base::FilePath& working_directory) { 183 const base::FilePath& working_directory) {
100 // A compressed archive is ordinarily given on the command line by the mini 184 // A compressed archive is ordinarily given on the command line by the mini
101 // installer. If one was not given, look for chrome.packed.7z next to the 185 // installer. If one was not given, look for chrome.packed.7z next to the
102 // running program. 186 // running program.
(...skipping 810 matching lines...) Expand 10 before | Expand all | Expand 10 after
913 997
914 // This method processes any command line options that make setup.exe do 998 // This method processes any command line options that make setup.exe do
915 // various tasks other than installation (renaming chrome.exe, showing eula 999 // various tasks other than installation (renaming chrome.exe, showing eula
916 // among others). This function returns true if any such command line option 1000 // among others). This function returns true if any such command line option
917 // has been found and processed (so setup.exe should exit at that point). 1001 // has been found and processed (so setup.exe should exit at that point).
918 bool HandleNonInstallCmdLineOptions(const InstallationState& original_state, 1002 bool HandleNonInstallCmdLineOptions(const InstallationState& original_state,
919 const base::FilePath& setup_exe, 1003 const base::FilePath& setup_exe,
920 const base::CommandLine& cmd_line, 1004 const base::CommandLine& cmd_line,
921 InstallerState* installer_state, 1005 InstallerState* installer_state,
922 int* exit_code) { 1006 int* exit_code) {
1007 // This option is independent of all others so doesn't belong in the if/else
1008 // block below.
1009 if (cmd_line.HasSwitch(installer::switches::kDelay)) {
1010 const std::string delay_seconds_string(
1011 cmd_line.GetSwitchValueASCII(installer::switches::kDelay));
1012 int delay_seconds;
1013 if (base::StringToInt(delay_seconds_string, &delay_seconds) &&
1014 delay_seconds > 0) {
1015 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(delay_seconds));
1016 }
1017 }
1018
923 // TODO(gab): Add a local |status| variable which each block below sets; 1019 // TODO(gab): Add a local |status| variable which each block below sets;
924 // only determine the |exit_code| from |status| at the end (this will allow 1020 // only determine the |exit_code| from |status| at the end (this will allow
925 // this method to validate that 1021 // this method to validate that
926 // (!handled || status != installer::UNKNOWN_STATUS)). 1022 // (!handled || status != installer::UNKNOWN_STATUS)).
927 bool handled = true; 1023 bool handled = true;
928 // TODO(tommi): Split these checks up into functions and use a data driven 1024 // TODO(tommi): Split these checks up into functions and use a data driven
929 // map of switch->function. 1025 // map of switch->function.
930 if (cmd_line.HasSwitch(installer::switches::kUpdateSetupExe)) { 1026 if (cmd_line.HasSwitch(installer::switches::kUpdateSetupExe)) {
931 installer::InstallStatus status = installer::SETUP_PATCH_FAILED; 1027 installer::InstallStatus status = installer::SETUP_PATCH_FAILED;
932 // If --update-setup-exe command line option is given, we apply the given 1028 // If --update-setup-exe command line option is given, we apply the given
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
1156 patch_file, 1252 patch_file,
1157 output_file); 1253 output_file);
1158 } else { 1254 } else {
1159 *exit_code = installer::PATCH_INVALID_ARGUMENTS; 1255 *exit_code = installer::PATCH_INVALID_ARGUMENTS;
1160 } 1256 }
1161 } else if (cmd_line.HasSwitch(installer::switches::kReenableAutoupdates)) { 1257 } else if (cmd_line.HasSwitch(installer::switches::kReenableAutoupdates)) {
1162 // setup.exe has been asked to attempt to reenable updates for Chrome. 1258 // setup.exe has been asked to attempt to reenable updates for Chrome.
1163 bool updates_enabled = GoogleUpdateSettings::ReenableAutoupdates(); 1259 bool updates_enabled = GoogleUpdateSettings::ReenableAutoupdates();
1164 *exit_code = updates_enabled ? installer::REENABLE_UPDATES_SUCCEEDED : 1260 *exit_code = updates_enabled ? installer::REENABLE_UPDATES_SUCCEEDED :
1165 installer::REENABLE_UPDATES_FAILED; 1261 installer::REENABLE_UPDATES_FAILED;
1262 } else if (cmd_line.HasSwitch(
1263 installer::switches::kSetDisplayVersionProduct)) {
1264 const base::string16 registry_product(
1265 cmd_line.GetSwitchValueNative(
1266 installer::switches::kSetDisplayVersionProduct));
1267 const base::string16 registry_value(
1268 cmd_line.GetSwitchValueNative(
1269 installer::switches::kSetDisplayVersionValue));
1270 *exit_code = OverwriteDisplayVersions(registry_product, registry_value);
1166 } else { 1271 } else {
1167 handled = false; 1272 handled = false;
1168 } 1273 }
1169 1274
1170 return handled; 1275 return handled;
1171 } 1276 }
1172 1277
1173 // Returns the Custom information for the client identified by the exe path 1278 // Returns the Custom information for the client identified by the exe path
1174 // passed in. This information is used for crash reporting. 1279 // passed in. This information is used for crash reporting.
1175 google_breakpad::CustomClientInfo* GetCustomInfo(const wchar_t* exe_path) { 1280 google_breakpad::CustomClientInfo* GetCustomInfo(const wchar_t* exe_path) {
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
1546 .Append(setup_path.BaseName()); 1651 .Append(setup_path.BaseName());
1547 } 1652 }
1548 const Products& products = installer_state.products(); 1653 const Products& products = installer_state.products();
1549 for (Products::const_iterator it = products.begin(); it < products.end(); 1654 for (Products::const_iterator it = products.begin(); it < products.end();
1550 ++it) { 1655 ++it) {
1551 const Product& product = **it; 1656 const Product& product = **it;
1552 product.LaunchUserExperiment(setup_path, install_status, system_install); 1657 product.LaunchUserExperiment(setup_path, install_status, system_install);
1553 } 1658 }
1554 } 1659 }
1555 1660
1556 // If installation completed successfully, return the path to the directory 1661 // If the installation completed successfully...
1557 // containing the newly installed setup.exe and uncompressed archive if the 1662 if (InstallUtil::GetInstallReturnCode(install_status) == 0) {
1558 // caller requested it. 1663 // Update the DisplayVersion created by an MSI-based install.
1559 if (installer_directory && 1664 std::string install_id;
1560 InstallUtil::GetInstallReturnCode(install_status) == 0) { 1665 if (prefs.GetString(installer::master_preferences::kMsiProductId,
1561 *installer_directory = 1666 &install_id)) {
1562 installer_state.GetInstallerDirectory(*installer_version); 1667 base::FilePath new_setup =
1668 installer_state.GetInstallerDirectory(*installer_version)
1669 .Append(kSetupExe);
1670 DelayedOverwriteDisplayVersions(
1671 new_setup, base::ASCIIToUTF16(install_id), *installer_version);
grt (UTC plus 2) 2015/09/11 18:14:26 nit: pass install_id directly and use AppendSwitch
bcwhite 2015/09/11 19:24:44 Done.
grt (UTC plus 2) 2015/09/11 20:07:01 Not done?
bcwhite 2015/09/12 03:49:23 Weird. I absolutely did change that; no idea how
1672 }
1673 // Return the path to the directory containing the newly installed
1674 // setup.exe and uncompressed archive if the caller requested it.
1675 if (installer_directory) {
1676 *installer_directory =
1677 installer_state.GetInstallerDirectory(*installer_version);
1678 }
1563 } 1679 }
1564 1680
1565 // temp_path's dtor will take care of deleting or scheduling itself for 1681 // temp_path's dtor will take care of deleting or scheduling itself for
1566 // deletion at reboot when this scope closes. 1682 // deletion at reboot when this scope closes.
1567 VLOG(1) << "Deleting temporary directory " << temp_path.path().value(); 1683 VLOG(1) << "Deleting temporary directory " << temp_path.path().value();
1568 1684
1569 return install_status; 1685 return install_status;
1570 } 1686 }
1571 1687
1572 } // namespace installer 1688 } // namespace installer
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
1717 // Note that we allow the status installer::UNINSTALL_REQUIRES_REBOOT 1833 // Note that we allow the status installer::UNINSTALL_REQUIRES_REBOOT
1718 // to pass through, since this is only returned on uninstall which is 1834 // to pass through, since this is only returned on uninstall which is
1719 // never invoked directly by Google Update. 1835 // never invoked directly by Google Update.
1720 return_code = InstallUtil::GetInstallReturnCode(install_status); 1836 return_code = InstallUtil::GetInstallReturnCode(install_status);
1721 } 1837 }
1722 1838
1723 VLOG(1) << "Installation complete, returning: " << return_code; 1839 VLOG(1) << "Installation complete, returning: " << return_code;
1724 1840
1725 return return_code; 1841 return return_code;
1726 } 1842 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698