OLD | NEW |
---|---|
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 Loading... | |
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\\"; | |
84 const wchar_t kSystemPrincipalSid[] = L"S-1-5-18"; | |
85 | |
86 const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>( | 83 const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>( |
87 MiniDumpWithProcessThreadData | // Get PEB and TEB. | 84 MiniDumpWithProcessThreadData | // Get PEB and TEB. |
88 MiniDumpWithUnloadedModules | // Get unloaded modules when available. | 85 MiniDumpWithUnloadedModules | // Get unloaded modules when available. |
89 MiniDumpWithIndirectlyReferencedMemory); // Get memory referenced by stack. | 86 MiniDumpWithIndirectlyReferencedMemory); // Get memory referenced by stack. |
90 | 87 |
91 namespace { | 88 namespace { |
92 | 89 |
90 const wchar_t kGoogleUpdatePipeName[] = L"\\\\.\\pipe\\GoogleCrashServices\\"; | |
91 const wchar_t kSystemPrincipalSid[] = L"S-1-5-18"; | |
92 const wchar_t kDisplayVersion[] = L"DisplayVersion"; | |
93 const wchar_t kMsiInstallRegistryPrefix[] = | |
94 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" | |
95 L"S-1-5-18\\Products\\"; | |
96 const wchar_t kMsiInstallRegistryPostfix[] = L"\\InstallProperties"; | |
97 const wchar_t kMsiUninstallRegistryPrefix[] = | |
98 L"SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"; | |
grt (UTC plus 2)
2015/09/11 20:07:01
apologies for missing this earlier: the KEY_WOW64_
bcwhite
2015/09/12 03:49:23
Done.
| |
99 const wchar_t kMsiUninstallRegistryPostfix[] = L""; | |
100 const wchar_t kMsiDisplayVersionOverwriteDelay[] = L"10"; // seconds as string | |
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 = base::StringPrintf( | |
136 L"%s%s%s", kMsiInstallRegistryPrefix, installer::GuidToSquid(product), | |
grt (UTC plus 2)
2015/09/11 20:07:01
what i had in mind was a format string of:
L"S
bcwhite
2015/09/12 03:49:23
Done.
| |
137 kMsiInstallRegistryPostfix); | |
138 LONG result1 = OverwriteDisplayVersion(reg_path, value); | |
139 | |
140 // The display version also exists under the Unininstall registry key with | |
141 // the original guid. | |
142 reg_path = base::StringPrintf( | |
143 L"%s{%s}%s", kMsiUninstallRegistryPrefix, product, | |
grt (UTC plus 2)
2015/09/11 20:07:01
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Un
bcwhite
2015/09/12 03:49:23
Done.
| |
144 kMsiUninstallRegistryPostfix); | |
145 LONG result2 = OverwriteDisplayVersion(reg_path, value); | |
146 | |
147 return result1 != ERROR_SUCCESS ? result1 : result2; | |
148 } | |
149 | |
150 void DelayedOverwriteDisplayVersions(const base::FilePath& setup_exe, | |
151 const base::string16& id, | |
152 const Version& version) { | |
153 // This process has to be able to exit so we launch ourselves with | |
154 // instructions on what to do and then return. | |
155 base::CommandLine command_line(setup_exe); | |
156 command_line.AppendSwitchNative( | |
157 installer::switches::kSetDisplayVersionProduct, id); | |
158 command_line.AppendSwitchASCII(installer::switches::kSetDisplayVersionValue, | |
159 version.GetString()); | |
160 command_line.AppendSwitchNative(installer::switches::kDelay, | |
161 kMsiDisplayVersionOverwriteDelay); | |
162 | |
163 base::LaunchOptions launch_options; | |
164 launch_options.force_breakaway_from_job_ = true; | |
165 base::Process writer = base::LaunchProcess(command_line, launch_options); | |
166 if (!writer.IsValid()) { | |
167 PLOG(ERROR) << "Failed to set DisplayVersion: " | |
168 << "could not launch subprocess to make desired changes."; | |
169 LOG(ERROR) << command_line.GetCommandLineString(); | |
grt (UTC plus 2)
2015/09/11 20:07:01
nit: merge this into the previous log message.
bcwhite
2015/09/12 03:49:23
Done.
| |
170 } | |
171 } | |
172 | |
93 // Returns NULL if no compressed archive is available for processing, otherwise | 173 // Returns NULL if no compressed archive is available for processing, otherwise |
94 // returns a patch helper configured to uncompress and patch. | 174 // returns a patch helper configured to uncompress and patch. |
95 scoped_ptr<installer::ArchivePatchHelper> CreateChromeArchiveHelper( | 175 scoped_ptr<installer::ArchivePatchHelper> CreateChromeArchiveHelper( |
96 const base::FilePath& setup_exe, | 176 const base::FilePath& setup_exe, |
97 const base::CommandLine& command_line, | 177 const base::CommandLine& command_line, |
98 const installer::InstallerState& installer_state, | 178 const installer::InstallerState& installer_state, |
99 const base::FilePath& working_directory) { | 179 const base::FilePath& working_directory) { |
100 // A compressed archive is ordinarily given on the command line by the mini | 180 // 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 | 181 // installer. If one was not given, look for chrome.packed.7z next to the |
102 // running program. | 182 // running program. |
(...skipping 810 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
913 | 993 |
914 // This method processes any command line options that make setup.exe do | 994 // This method processes any command line options that make setup.exe do |
915 // various tasks other than installation (renaming chrome.exe, showing eula | 995 // various tasks other than installation (renaming chrome.exe, showing eula |
916 // among others). This function returns true if any such command line option | 996 // 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). | 997 // has been found and processed (so setup.exe should exit at that point). |
918 bool HandleNonInstallCmdLineOptions(const InstallationState& original_state, | 998 bool HandleNonInstallCmdLineOptions(const InstallationState& original_state, |
919 const base::FilePath& setup_exe, | 999 const base::FilePath& setup_exe, |
920 const base::CommandLine& cmd_line, | 1000 const base::CommandLine& cmd_line, |
921 InstallerState* installer_state, | 1001 InstallerState* installer_state, |
922 int* exit_code) { | 1002 int* exit_code) { |
1003 // This option is independent of all others so doesn't belong in the if/else | |
1004 // block below. | |
1005 if (cmd_line.HasSwitch(installer::switches::kDelay)) { | |
1006 const std::string delay_seconds_string( | |
1007 cmd_line.GetSwitchValueASCII(installer::switches::kDelay)); | |
1008 int delay_seconds; | |
1009 if (base::StringToInt(delay_seconds_string, &delay_seconds) && | |
1010 delay_seconds > 0) { | |
1011 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(delay_seconds)); | |
1012 } | |
1013 } | |
1014 | |
923 // TODO(gab): Add a local |status| variable which each block below sets; | 1015 // 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 | 1016 // only determine the |exit_code| from |status| at the end (this will allow |
925 // this method to validate that | 1017 // this method to validate that |
926 // (!handled || status != installer::UNKNOWN_STATUS)). | 1018 // (!handled || status != installer::UNKNOWN_STATUS)). |
927 bool handled = true; | 1019 bool handled = true; |
928 // TODO(tommi): Split these checks up into functions and use a data driven | 1020 // TODO(tommi): Split these checks up into functions and use a data driven |
929 // map of switch->function. | 1021 // map of switch->function. |
930 if (cmd_line.HasSwitch(installer::switches::kUpdateSetupExe)) { | 1022 if (cmd_line.HasSwitch(installer::switches::kUpdateSetupExe)) { |
931 installer::InstallStatus status = installer::SETUP_PATCH_FAILED; | 1023 installer::InstallStatus status = installer::SETUP_PATCH_FAILED; |
932 // If --update-setup-exe command line option is given, we apply the given | 1024 // 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 Loading... | |
1156 patch_file, | 1248 patch_file, |
1157 output_file); | 1249 output_file); |
1158 } else { | 1250 } else { |
1159 *exit_code = installer::PATCH_INVALID_ARGUMENTS; | 1251 *exit_code = installer::PATCH_INVALID_ARGUMENTS; |
1160 } | 1252 } |
1161 } else if (cmd_line.HasSwitch(installer::switches::kReenableAutoupdates)) { | 1253 } else if (cmd_line.HasSwitch(installer::switches::kReenableAutoupdates)) { |
1162 // setup.exe has been asked to attempt to reenable updates for Chrome. | 1254 // setup.exe has been asked to attempt to reenable updates for Chrome. |
1163 bool updates_enabled = GoogleUpdateSettings::ReenableAutoupdates(); | 1255 bool updates_enabled = GoogleUpdateSettings::ReenableAutoupdates(); |
1164 *exit_code = updates_enabled ? installer::REENABLE_UPDATES_SUCCEEDED : | 1256 *exit_code = updates_enabled ? installer::REENABLE_UPDATES_SUCCEEDED : |
1165 installer::REENABLE_UPDATES_FAILED; | 1257 installer::REENABLE_UPDATES_FAILED; |
1258 } else if (cmd_line.HasSwitch( | |
1259 installer::switches::kSetDisplayVersionProduct)) { | |
1260 const base::string16 registry_product( | |
1261 cmd_line.GetSwitchValueNative( | |
1262 installer::switches::kSetDisplayVersionProduct)); | |
1263 const base::string16 registry_value( | |
1264 cmd_line.GetSwitchValueNative( | |
1265 installer::switches::kSetDisplayVersionValue)); | |
1266 *exit_code = OverwriteDisplayVersions(registry_product, registry_value); | |
1166 } else { | 1267 } else { |
1167 handled = false; | 1268 handled = false; |
1168 } | 1269 } |
1169 | 1270 |
1170 return handled; | 1271 return handled; |
1171 } | 1272 } |
1172 | 1273 |
1173 // Returns the Custom information for the client identified by the exe path | 1274 // Returns the Custom information for the client identified by the exe path |
1174 // passed in. This information is used for crash reporting. | 1275 // passed in. This information is used for crash reporting. |
1175 google_breakpad::CustomClientInfo* GetCustomInfo(const wchar_t* exe_path) { | 1276 google_breakpad::CustomClientInfo* GetCustomInfo(const wchar_t* exe_path) { |
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1546 .Append(setup_path.BaseName()); | 1647 .Append(setup_path.BaseName()); |
1547 } | 1648 } |
1548 const Products& products = installer_state.products(); | 1649 const Products& products = installer_state.products(); |
1549 for (Products::const_iterator it = products.begin(); it < products.end(); | 1650 for (Products::const_iterator it = products.begin(); it < products.end(); |
1550 ++it) { | 1651 ++it) { |
1551 const Product& product = **it; | 1652 const Product& product = **it; |
1552 product.LaunchUserExperiment(setup_path, install_status, system_install); | 1653 product.LaunchUserExperiment(setup_path, install_status, system_install); |
1553 } | 1654 } |
1554 } | 1655 } |
1555 | 1656 |
1556 // If installation completed successfully, return the path to the directory | 1657 // If the installation completed successfully... |
1557 // containing the newly installed setup.exe and uncompressed archive if the | 1658 if (InstallUtil::GetInstallReturnCode(install_status) == 0) { |
1558 // caller requested it. | 1659 // Update the DisplayVersion created by an MSI-based install. |
1559 if (installer_directory && | 1660 std::string install_id; |
1560 InstallUtil::GetInstallReturnCode(install_status) == 0) { | 1661 if (prefs.GetString(installer::master_preferences::kMsiProductId, |
1561 *installer_directory = | 1662 &install_id)) { |
1562 installer_state.GetInstallerDirectory(*installer_version); | 1663 base::FilePath new_setup = |
1664 installer_state.GetInstallerDirectory(*installer_version) | |
1665 .Append(kSetupExe); | |
1666 DelayedOverwriteDisplayVersions( | |
1667 new_setup, base::ASCIIToUTF16(install_id), *installer_version); | |
1668 } | |
1669 // Return the path to the directory containing the newly installed | |
1670 // setup.exe and uncompressed archive if the caller requested it. | |
1671 if (installer_directory) { | |
1672 *installer_directory = | |
1673 installer_state.GetInstallerDirectory(*installer_version); | |
1674 } | |
1563 } | 1675 } |
1564 | 1676 |
1565 // temp_path's dtor will take care of deleting or scheduling itself for | 1677 // temp_path's dtor will take care of deleting or scheduling itself for |
1566 // deletion at reboot when this scope closes. | 1678 // deletion at reboot when this scope closes. |
1567 VLOG(1) << "Deleting temporary directory " << temp_path.path().value(); | 1679 VLOG(1) << "Deleting temporary directory " << temp_path.path().value(); |
1568 | 1680 |
1569 return install_status; | 1681 return install_status; |
1570 } | 1682 } |
1571 | 1683 |
1572 } // namespace installer | 1684 } // namespace installer |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1717 // Note that we allow the status installer::UNINSTALL_REQUIRES_REBOOT | 1829 // Note that we allow the status installer::UNINSTALL_REQUIRES_REBOOT |
1718 // to pass through, since this is only returned on uninstall which is | 1830 // to pass through, since this is only returned on uninstall which is |
1719 // never invoked directly by Google Update. | 1831 // never invoked directly by Google Update. |
1720 return_code = InstallUtil::GetInstallReturnCode(install_status); | 1832 return_code = InstallUtil::GetInstallReturnCode(install_status); |
1721 } | 1833 } |
1722 | 1834 |
1723 VLOG(1) << "Installation complete, returning: " << return_code; | 1835 VLOG(1) << "Installation complete, returning: " << return_code; |
1724 | 1836 |
1725 return return_code; | 1837 return return_code; |
1726 } | 1838 } |
OLD | NEW |