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

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: start subprocess to set DisplayVersion Created 5 years, 4 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 using installer::InstallerState; 73 using installer::InstallerState;
74 using installer::InstallationState; 74 using installer::InstallationState;
75 using installer::InstallationValidator; 75 using installer::InstallationValidator;
76 using installer::MasterPreferences; 76 using installer::MasterPreferences;
77 using installer::Product; 77 using installer::Product;
78 using installer::ProductState; 78 using installer::ProductState;
79 using installer::Products; 79 using installer::Products;
80 80
81 const wchar_t kGoogleUpdatePipeName[] = L"\\\\.\\pipe\\GoogleCrashServices\\"; 81 const wchar_t kGoogleUpdatePipeName[] = L"\\\\.\\pipe\\GoogleCrashServices\\";
82 const wchar_t kSystemPrincipalSid[] = L"S-1-5-18"; 82 const wchar_t kSystemPrincipalSid[] = L"S-1-5-18";
83 const wchar_t kDisplayVersion[] = L"DisplayVersion";
84 const wchar_t kMsiInstallRegistryPrefix[] =
85 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\"
86 L"S-1-5-18\\Products\\";
87 const wchar_t kMsiInstallRegistryPostfix[] = L"\\InstallProperties";
88 const wchar_t kMsiDisplayVersionOverwriteDelay[] = L"30"; // seconds as string
83 89
84 const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>( 90 const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>(
85 MiniDumpWithProcessThreadData | // Get PEB and TEB. 91 MiniDumpWithProcessThreadData | // Get PEB and TEB.
86 MiniDumpWithUnloadedModules | // Get unloaded modules when available. 92 MiniDumpWithUnloadedModules | // Get unloaded modules when available.
87 MiniDumpWithIndirectlyReferencedMemory); // Get memory referenced by stack. 93 MiniDumpWithIndirectlyReferencedMemory); // Get memory referenced by stack.
88 94
89 namespace { 95 namespace {
90 96
97 // Overwrite an existing DisplayVersion as written by the MSI installer
98 // with the real version number of Chrome.
99 LONG OverwriteDisplayVersion(const base::string16& path,
100 const base::string16& value) {
101 base::win::RegKey key;
102 LONG result = 0;
103 base::string16 existing;
104 if ((result = key.Open(HKEY_LOCAL_MACHINE, path.c_str(),
105 KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_WOW64_64KEY))
106 != ERROR_SUCCESS) {
107 LOG(ERROR) << "Failed to set DisplayVersion: " << path << " not found";
108 return result;
109 }
110 if ((result = key.ReadValue(kDisplayVersion, &existing)) != ERROR_SUCCESS) {
111 LOG(ERROR) << "Failed to set DisplayVersion: " << kDisplayVersion
112 << " not found under " << path;
113 return result;
114 }
115 if ((result = key.WriteValue(kDisplayVersion, value.c_str()))
116 != ERROR_SUCCESS) {
117 LOG(ERROR) << "Failed to set DisplayVersion: " << kDisplayVersion
118 << " could not be written under " << path;
119 return result;
120 }
121 VLOG(1) << "Set DisplayVersion at " << path << " to " << value
122 << " from " << existing;
123 return ERROR_SUCCESS;
124 }
125
126 void DelayedOverwriteDisplayVersion(const base::FilePath& setup_exe,
127 const std::string& id,
128 const Version& version) {
129 base::string16 reg_path(kMsiInstallRegistryPrefix);
130 reg_path += base::UTF8ToUTF16(id);
131 reg_path += kMsiInstallRegistryPostfix;
132
133 // This process has to be able to exit so we launch ourselves with
134 // instructions on what to do and then return.
135 base::string16 command_line;
robertshield 2015/08/18 17:27:26 base::CommandLine provides convenience methods to
bcwhite 2015/09/02 15:21:45 Done.
136 command_line += L"\"";
137 command_line += setup_exe.AsUTF16Unsafe();
138 command_line += L"\" --";
139 command_line += base::UTF8ToUTF16(
140 installer::switches::kSetDisplayVersionPath);
141 command_line += L"=";
142 command_line += reg_path;
143 command_line += L" --";
144 command_line += base::UTF8ToUTF16(
145 installer::switches::kSetDisplayVersionValue);
146 command_line += L"=";
147 command_line += base::UTF8ToUTF16(version.GetString());
148 command_line += L" --";
149 command_line += base::UTF8ToUTF16(installer::switches::kDelay);
150 command_line += L"=";
151 command_line += kMsiDisplayVersionOverwriteDelay;
152
153 STARTUPINFOW si = {sizeof(si)};
154 PROCESS_INFORMATION pi = {0};
155 if (!::CreateProcess(setup_exe.AsUTF16Unsafe().c_str(),
robertshield 2015/08/18 17:27:26 use base::LaunchProcess here (https://code.google.
grt (UTC plus 2) 2015/08/19 17:43:30 i wonder if this should also use force_breakaway_f
robertshield 2015/08/19 17:57:07 I don't think it would hurt. MSI could also concei
bcwhite 2015/09/02 15:21:45 Why here but not elsewhere in this file?
grt (UTC plus 2) 2015/09/02 20:43:55 base::LaunchProcess should always be used unless s
bcwhite 2015/09/09 18:20:22 Done.
156 (LPWSTR)command_line.c_str(), // discards const
robertshield 2015/08/18 17:27:26 can you const_cast instead?
bcwhite 2015/09/02 15:21:45 Already gone with switch to base::CommandLine.
157 NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL,
158 &si, &pi)) {
159 LOG(ERROR) << "Failed to set DisplayVersion: "
160 << "could not launch subprocess to make desired changes."
161 << " (error=" << ::GetLastError() << ")\n"
162 << command_line;
163 return;
164 }
165 ::CloseHandle(pi.hThread);
166 }
167
91 // Returns NULL if no compressed archive is available for processing, otherwise 168 // Returns NULL if no compressed archive is available for processing, otherwise
92 // returns a patch helper configured to uncompress and patch. 169 // returns a patch helper configured to uncompress and patch.
93 scoped_ptr<installer::ArchivePatchHelper> CreateChromeArchiveHelper( 170 scoped_ptr<installer::ArchivePatchHelper> CreateChromeArchiveHelper(
94 const base::FilePath& setup_exe, 171 const base::FilePath& setup_exe,
95 const base::CommandLine& command_line, 172 const base::CommandLine& command_line,
96 const installer::InstallerState& installer_state, 173 const installer::InstallerState& installer_state,
97 const base::FilePath& working_directory) { 174 const base::FilePath& working_directory) {
98 // A compressed archive is ordinarily given on the command line by the mini 175 // A compressed archive is ordinarily given on the command line by the mini
99 // installer. If one was not given, look for chrome.packed.7z next to the 176 // installer. If one was not given, look for chrome.packed.7z next to the
100 // running program. 177 // running program.
(...skipping 810 matching lines...) Expand 10 before | Expand all | Expand 10 after
911 988
912 // This method processes any command line options that make setup.exe do 989 // This method processes any command line options that make setup.exe do
913 // various tasks other than installation (renaming chrome.exe, showing eula 990 // various tasks other than installation (renaming chrome.exe, showing eula
914 // among others). This function returns true if any such command line option 991 // among others). This function returns true if any such command line option
915 // has been found and processed (so setup.exe should exit at that point). 992 // has been found and processed (so setup.exe should exit at that point).
916 bool HandleNonInstallCmdLineOptions(const InstallationState& original_state, 993 bool HandleNonInstallCmdLineOptions(const InstallationState& original_state,
917 const base::FilePath& setup_exe, 994 const base::FilePath& setup_exe,
918 const base::CommandLine& cmd_line, 995 const base::CommandLine& cmd_line,
919 InstallerState* installer_state, 996 InstallerState* installer_state,
920 int* exit_code) { 997 int* exit_code) {
998 // This option is independent of all others so doesn't belong in the if/else
999 // block below.
1000 if (cmd_line.HasSwitch(installer::switches::kDelay)) {
1001 const std::string delay_seconds_string(
1002 cmd_line.GetSwitchValueASCII(installer::switches::kDelay));
1003 int delay_seconds;
1004 if (base::StringToInt(delay_seconds_string, &delay_seconds) &&
1005 delay_seconds > 0) {
1006 ::Sleep(delay_seconds * 1000);
1007 }
1008 }
1009
921 // TODO(gab): Add a local |status| variable which each block below sets; 1010 // TODO(gab): Add a local |status| variable which each block below sets;
922 // only determine the |exit_code| from |status| at the end (this will allow 1011 // only determine the |exit_code| from |status| at the end (this will allow
923 // this method to validate that 1012 // this method to validate that
924 // (!handled || status != installer::UNKNOWN_STATUS)). 1013 // (!handled || status != installer::UNKNOWN_STATUS)).
925 bool handled = true; 1014 bool handled = true;
926 // TODO(tommi): Split these checks up into functions and use a data driven 1015 // TODO(tommi): Split these checks up into functions and use a data driven
927 // map of switch->function. 1016 // map of switch->function.
928 if (cmd_line.HasSwitch(installer::switches::kUpdateSetupExe)) { 1017 if (cmd_line.HasSwitch(installer::switches::kUpdateSetupExe)) {
929 installer::InstallStatus status = installer::SETUP_PATCH_FAILED; 1018 installer::InstallStatus status = installer::SETUP_PATCH_FAILED;
930 // If --update-setup-exe command line option is given, we apply the given 1019 // If --update-setup-exe command line option is given, we apply the given
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
1145 patch_file, 1234 patch_file,
1146 output_file); 1235 output_file);
1147 } else { 1236 } else {
1148 *exit_code = installer::PATCH_INVALID_ARGUMENTS; 1237 *exit_code = installer::PATCH_INVALID_ARGUMENTS;
1149 } 1238 }
1150 } else if (cmd_line.HasSwitch(installer::switches::kReenableAutoupdates)) { 1239 } else if (cmd_line.HasSwitch(installer::switches::kReenableAutoupdates)) {
1151 // setup.exe has been asked to attempt to reenable updates for Chrome. 1240 // setup.exe has been asked to attempt to reenable updates for Chrome.
1152 bool updates_enabled = GoogleUpdateSettings::ReenableAutoupdates(); 1241 bool updates_enabled = GoogleUpdateSettings::ReenableAutoupdates();
1153 *exit_code = updates_enabled ? installer::REENABLE_UPDATES_SUCCEEDED : 1242 *exit_code = updates_enabled ? installer::REENABLE_UPDATES_SUCCEEDED :
1154 installer::REENABLE_UPDATES_FAILED; 1243 installer::REENABLE_UPDATES_FAILED;
1244 } else if (cmd_line.HasSwitch(installer::switches::kSetDisplayVersionPath)) {
1245 const base::string16 registry_path(
1246 cmd_line.GetSwitchValueNative(
1247 installer::switches::kSetDisplayVersionPath));
1248 const base::string16 registry_value(
grt (UTC plus 2) 2015/08/19 17:43:30 i think it's better to extract the version from th
bcwhite 2015/09/02 15:21:45 If the original process has already gone through t
1249 cmd_line.GetSwitchValueNative(
1250 installer::switches::kSetDisplayVersionValue));
1251 *exit_code = OverwriteDisplayVersion(registry_path, registry_value);
1155 } else { 1252 } else {
1156 handled = false; 1253 handled = false;
1157 } 1254 }
1158 1255
1159 return handled; 1256 return handled;
1160 } 1257 }
1161 1258
1162 // Returns the Custom information for the client identified by the exe path 1259 // Returns the Custom information for the client identified by the exe path
1163 // passed in. This information is used for crash reporting. 1260 // passed in. This information is used for crash reporting.
1164 google_breakpad::CustomClientInfo* GetCustomInfo(const wchar_t* exe_path) { 1261 google_breakpad::CustomClientInfo* GetCustomInfo(const wchar_t* exe_path) {
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after
1529 .Append(setup_path.BaseName()); 1626 .Append(setup_path.BaseName());
1530 } 1627 }
1531 const Products& products = installer_state.products(); 1628 const Products& products = installer_state.products();
1532 for (Products::const_iterator it = products.begin(); it < products.end(); 1629 for (Products::const_iterator it = products.begin(); it < products.end();
1533 ++it) { 1630 ++it) {
1534 const Product& product = **it; 1631 const Product& product = **it;
1535 product.LaunchUserExperiment(setup_path, install_status, system_install); 1632 product.LaunchUserExperiment(setup_path, install_status, system_install);
1536 } 1633 }
1537 } 1634 }
1538 1635
1539 // If installation completed successfully, return the path to the directory 1636 // If the installation completed successfully...
1540 // containing the newly installed setup.exe and uncompressed archive if the 1637 if (InstallUtil::GetInstallReturnCode(install_status) == 0) {
1541 // caller requested it. 1638 // Update the DisplayVersion created by an MSI-based install.
1542 if (installer_directory && 1639 std::string install_id;
1543 InstallUtil::GetInstallReturnCode(install_status) == 0) { 1640 if (prefs.GetString(installer::master_preferences::kMsiInstallId,
1544 *installer_directory = 1641 &install_id)) {
1545 installer_state.GetInstallerDirectory(*installer_version); 1642 DelayedOverwriteDisplayVersion(setup_exe, install_id, *installer_version);
grt (UTC plus 2) 2015/08/19 17:43:30 if i'm reading the code correctly, |setup_exe| is
bcwhite 2015/09/02 15:21:45 Done.
1643 }
1644 // Return the path to the directory containing the newly installed
1645 // setup.exe and uncompressed archive if the caller requested it.
1646 if (installer_directory)
1647 *installer_directory =
1648 installer_state.GetInstallerDirectory(*installer_version);
1546 } 1649 }
1547 1650
1548 // temp_path's dtor will take care of deleting or scheduling itself for 1651 // temp_path's dtor will take care of deleting or scheduling itself for
1549 // deletion at reboot when this scope closes. 1652 // deletion at reboot when this scope closes.
1550 VLOG(1) << "Deleting temporary directory " << temp_path.path().value(); 1653 VLOG(1) << "Deleting temporary directory " << temp_path.path().value();
1551 1654
1552 return install_status; 1655 return install_status;
1553 } 1656 }
1554 1657
1555 } // namespace installer 1658 } // namespace installer
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
1700 // Note that we allow the status installer::UNINSTALL_REQUIRES_REBOOT 1803 // Note that we allow the status installer::UNINSTALL_REQUIRES_REBOOT
1701 // to pass through, since this is only returned on uninstall which is 1804 // to pass through, since this is only returned on uninstall which is
1702 // never invoked directly by Google Update. 1805 // never invoked directly by Google Update.
1703 return_code = InstallUtil::GetInstallReturnCode(install_status); 1806 return_code = InstallUtil::GetInstallReturnCode(install_status);
1704 } 1807 }
1705 1808
1706 VLOG(1) << "Installation complete, returning: " << return_code; 1809 VLOG(1) << "Installation complete, returning: " << return_code;
1707 1810
1708 return return_code; 1811 return return_code;
1709 } 1812 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698