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

Side by Side Diff: chrome/installer/mini_installer/mini_installer.cc

Issue 2663003003: Fix -full fallback for diff updates (M56). (Closed)
Patch Set: Created 3 years, 10 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 // mini_installer.exe is the first exe that is run when chrome is being 5 // mini_installer.exe is the first exe that is run when chrome is being
6 // installed or upgraded. It is designed to be extremely small (~5KB with no 6 // installed or upgraded. It is designed to be extremely small (~5KB with no
7 // extra resources linked) and it has two main jobs: 7 // extra resources linked) and it has two main jobs:
8 // 1) unpack the resources (possibly decompressing some) 8 // 1) unpack the resources (possibly decompressing some)
9 // 2) run the real installer (setup.exe) with appropriate flags. 9 // 2) run the real installer (setup.exe) with appropriate flags.
10 // 10 //
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 // of resource callbacks. 67 // of resource callbacks.
68 struct Context { 68 struct Context {
69 // Input to the call back method. Specifies the dir to save resources. 69 // Input to the call back method. Specifies the dir to save resources.
70 const wchar_t* base_path; 70 const wchar_t* base_path;
71 // First output from call back method. Full path of Chrome archive. 71 // First output from call back method. Full path of Chrome archive.
72 PathString* chrome_resource_path; 72 PathString* chrome_resource_path;
73 // Second output from call back method. Full path of Setup archive/exe. 73 // Second output from call back method. Full path of Setup archive/exe.
74 PathString* setup_resource_path; 74 PathString* setup_resource_path;
75 }; 75 };
76 76
77 77 #if defined(GOOGLE_CHROME_BUILD)
78 // Opens the Google Update ClientState key for the current install 78 // Opens the Google Update ClientState key. If |binaries| is false, opens the
79 // configuration. This includes locating the correct key in the face of 79 // key for Google Chrome or Chrome SxS (canary). If |binaries| is true and an
80 // multi-install. The flag will by default be written to HKCU, but if 80 // existing multi-install Chrome is being updated, opens the key for the
81 // --system-level is included in the command line, it will be written to 81 // binaries; otherwise, returns false.
huangs 2017/01/31 17:40:04 NIT: "opens the key for the binaries" at end: Mayb
grt (UTC plus 2) 2017/02/02 08:17:16 Done.
82 // HKLM instead. 82 bool OpenInstallStateKey(const Configuration& configuration,
83 bool OpenInstallStateKey(const Configuration& configuration, RegKey* key) { 83 bool binaries,
84 RegKey* key) {
85 if (binaries && !configuration.is_updating_multi_chrome())
86 return false;
84 const HKEY root_key = 87 const HKEY root_key =
85 configuration.is_system_level() ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 88 configuration.is_system_level() ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
86 const wchar_t* app_guid = configuration.chrome_app_guid(); 89 const wchar_t* app_guid = binaries ? google_update::kMultiInstallAppGuid
90 : configuration.chrome_app_guid();
87 const REGSAM key_access = KEY_QUERY_VALUE | KEY_SET_VALUE; 91 const REGSAM key_access = KEY_QUERY_VALUE | KEY_SET_VALUE;
88 92
89 return OpenClientStateKey(root_key, app_guid, key_access, key); 93 return OpenClientStateKey(root_key, app_guid, key_access, key) ==
94 ERROR_SUCCESS;
90 } 95 }
91 96
92 // Writes install results into registry where it is read by Google Update. 97 // Writes install results into the registry where it is read by Google Update.
93 // Don't write anything if there is already a result present, likely 98 // Don't write anything if there is already a result present, likely
94 // written by setup.exe. 99 // written by setup.exe.
95 void WriteInstallResults(const Configuration& configuration, 100 void WriteInstallResults(const Configuration& configuration,
huangs 2017/01/31 17:40:04 NIT: Rename to WriteInstallResultsToGoogleUpdate()
grt (UTC plus 2) 2017/02/02 08:17:16 I've added a TODO above the #if above for where I
96 ProcessExitResult result) { 101 ProcessExitResult result) {
97 #if defined(GOOGLE_CHROME_BUILD)
98 // Calls to setup.exe will write a "success" result if everything was good 102 // Calls to setup.exe will write a "success" result if everything was good
99 // so we don't need to write anything from here. 103 // so we don't need to write anything from here.
100 if (result.IsSuccess()) 104 if (result.IsSuccess())
101 return; 105 return;
102 106
103 RegKey key; 107 // Write the value in Chrome ClientState key and in the binaries' if an
104 DWORD value; 108 // existing multi-install Chrome is being updated.
105 if (OpenInstallStateKey(configuration, &key)) { 109 for (int i = 0; i < 2; ++i) {
huangs 2017/01/31 17:40:04 NIT: Maybe be move explicit? for (bool binaries
grt (UTC plus 2) 2017/02/02 08:17:16 Awesome. I wasn't sure this was permitted by the s
106 if (key.ReadDWValue(kInstallerResultRegistryValue, &value) 110 RegKey key;
107 != ERROR_SUCCESS || value == 0) { 111 DWORD value;
108 key.WriteDWValue(kInstallerResultRegistryValue, 112 if (OpenInstallStateKey(configuration, i != 0, &key)) {
109 result.exit_code ? 1 /* FAILED_CUSTOM_ERROR */ 113 if (key.ReadDWValue(kInstallerResultRegistryValue, &value) !=
110 : 0 /* SUCCESS */); 114 ERROR_SUCCESS ||
111 key.WriteDWValue(kInstallerErrorRegistryValue, result.exit_code); 115 value == 0) {
112 key.WriteDWValue(kInstallerExtraCode1RegistryValue, result.windows_error); 116 key.WriteDWValue(kInstallerResultRegistryValue,
117 result.exit_code ? 1 /* FAILED_CUSTOM_ERROR */
118 : 0 /* SUCCESS */);
119 key.WriteDWValue(kInstallerErrorRegistryValue, result.exit_code);
120 key.WriteDWValue(kInstallerExtraCode1RegistryValue,
121 result.windows_error);
122 }
113 } 123 }
114 key.Close();
115 } 124 }
116 #endif
117 } 125 }
118 126
119 // This function sets the flag in registry to indicate that Google Update 127 // This function sets the flag in registry to indicate that Google Update
120 // should try full installer next time. If the current installer works, this 128 // should try full installer next time. If the current installer works, this
121 // flag is cleared by setup.exe at the end of install. 129 // flag is cleared by setup.exe at the end of install.
122 void SetInstallerFlags(const Configuration& configuration) { 130 void SetInstallerFlags(const Configuration& configuration) {
123 RegKey key;
124 StackString<128> value; 131 StackString<128> value;
125 LONG ret = ERROR_SUCCESS;
126 132
127 if (!OpenInstallStateKey(configuration, &key)) 133 for (int i = 0; i < 2; ++i) {
huangs 2017/01/31 17:40:04 NIT: Same as above.
128 return; 134 RegKey key;
135 if (!OpenInstallStateKey(configuration, i != 0, &key))
136 continue;
129 137
130 ret = key.ReadSZValue(kApRegistryValue, value.get(), value.capacity()); 138 LONG ret = key.ReadSZValue(kApRegistryValue, value.get(), value.capacity());
131 139
132 // The conditions below are handling two cases: 140 // The conditions below are handling two cases:
133 // 1. When ap value is present, we want to add the required tag only if it is 141 // 1. When ap value is present, we want to add the required tag only if it
134 // not present. 142 // is not present.
135 // 2. When ap value is missing, we are going to create it with the required 143 // 2. When ap value is missing, we are going to create it with the required
136 // tag. 144 // tag.
137 if ((ret == ERROR_SUCCESS) || (ret == ERROR_FILE_NOT_FOUND)) { 145 if ((ret == ERROR_SUCCESS) || (ret == ERROR_FILE_NOT_FOUND)) {
138 if (ret == ERROR_FILE_NOT_FOUND) 146 if (ret == ERROR_FILE_NOT_FOUND)
139 value.clear(); 147 value.clear();
140 148
141 if (!StrEndsWith(value.get(), kFullInstallerSuffix) && 149 if (!StrEndsWith(value.get(), kFullInstallerSuffix) &&
142 value.append(kFullInstallerSuffix)) { 150 value.append(kFullInstallerSuffix)) {
143 key.WriteSZValue(kApRegistryValue, value.get()); 151 key.WriteSZValue(kApRegistryValue, value.get());
152 }
144 } 153 }
145 } 154 }
146 } 155 }
156 #endif // GOOGLE_CHROME_BUILD
147 157
148 // Gets the setup.exe path from Registry by looking at the value of Uninstall 158 // Gets the setup.exe path from Registry by looking at the value of Uninstall
149 // string. |size| is measured in wchar_t units. 159 // string. |size| is measured in wchar_t units.
150 ProcessExitResult GetSetupExePathForAppGuid(bool system_level, 160 ProcessExitResult GetSetupExePathForAppGuid(bool system_level,
151 const wchar_t* app_guid, 161 const wchar_t* app_guid,
152 const wchar_t* previous_version, 162 const wchar_t* previous_version,
153 wchar_t* path, 163 wchar_t* path,
154 size_t size) { 164 size_t size) {
155 const HKEY root_key = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 165 const HKEY root_key = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
156 RegKey key; 166 RegKey key;
157 if (!OpenClientStateKey(root_key, app_guid, KEY_QUERY_VALUE, &key)) 167 LONG result = OpenClientStateKey(root_key, app_guid, KEY_QUERY_VALUE, &key);
158 return ProcessExitResult(UNABLE_TO_FIND_REGISTRY_KEY); 168 if (result == ERROR_SUCCESS)
159 DWORD result = key.ReadSZValue(kUninstallRegistryValue, path, size); 169 result = key.ReadSZValue(kUninstallRegistryValue, path, size);
160 if (result != ERROR_SUCCESS) 170 if (result != ERROR_SUCCESS)
161 return ProcessExitResult(UNABLE_TO_FIND_REGISTRY_KEY, result); 171 return ProcessExitResult(UNABLE_TO_FIND_REGISTRY_KEY, result);
162 172
163 // Check that the path to the existing installer includes the expected 173 // Check that the path to the existing installer includes the expected
164 // version number. It's not necessary for accuracy to verify before/after 174 // version number. It's not necessary for accuracy to verify before/after
165 // delimiters. 175 // delimiters.
166 if (!SearchStringI(path, previous_version)) 176 if (!SearchStringI(path, previous_version))
167 return ProcessExitResult(PATCH_NOT_FOR_INSTALLED_VERSION); 177 return ProcessExitResult(PATCH_NOT_FOR_INSTALLED_VERSION);
168 178
169 return ProcessExitResult(SUCCESS_EXIT_CODE); 179 return ProcessExitResult(SUCCESS_EXIT_CODE);
170 } 180 }
171 181
172 // Gets the path to setup.exe of the previous version. The overall path is found 182 // Gets the path to setup.exe of the previous version. The overall path is found
173 // in the Uninstall string in the registry. A previous version number specified 183 // in the Uninstall string in the registry. A previous version number specified
174 // in |configuration| is used if available. |size| is measured in wchar_t units. 184 // in |configuration| is used if available. |size| is measured in wchar_t units.
175 ProcessExitResult GetPreviousSetupExePath(const Configuration& configuration, 185 ProcessExitResult GetPreviousSetupExePath(const Configuration& configuration,
176 wchar_t* path, 186 wchar_t* path,
177 size_t size) { 187 size_t size) {
178 bool system_level = configuration.is_system_level(); 188 bool system_level = configuration.is_system_level();
179 const wchar_t* previous_version = configuration.previous_version(); 189 const wchar_t* previous_version = configuration.previous_version();
180 ProcessExitResult exit_code = ProcessExitResult(GENERIC_ERROR); 190 ProcessExitResult exit_code = ProcessExitResult(GENERIC_ERROR);
181 191
182 // If this is a multi install, first try looking in the binaries for the path. 192 // Check Chrome's ClientState key for the path to setup.exe. This will have
183 if (configuration.is_multi_install()) { 193 // the correct path for all well-functioning installs.
184 exit_code = GetSetupExePathForAppGuid( 194 exit_code =
185 system_level, google_update::kMultiInstallAppGuid, previous_version, 195 GetSetupExePathForAppGuid(system_level, configuration.chrome_app_guid(),
186 path, size); 196 previous_version, path, size);
187 }
188 197
189 // Failing that, look in Chrome Frame's client state key if --chrome-frame was 198 // Failing that, check the binaries if updating multi-install Chrome.
190 // specified. 199 if (!exit_code.IsSuccess() && configuration.is_updating_multi_chrome()) {
191 if (!exit_code.IsSuccess() && configuration.has_chrome_frame()) { 200 exit_code = GetSetupExePathForAppGuid(system_level,
192 exit_code = GetSetupExePathForAppGuid( 201 google_update::kMultiInstallAppGuid,
193 system_level, google_update::kChromeFrameAppGuid, previous_version, 202 previous_version, path, size);
194 path, size);
195 }
196
197 // Make a last-ditch effort to look in the Chrome client state key.
198 if (!exit_code.IsSuccess()) {
199 exit_code = GetSetupExePathForAppGuid(
200 system_level, configuration.chrome_app_guid(), previous_version,
201 path, size);
202 } 203 }
203 204
204 return exit_code; 205 return exit_code;
205 } 206 }
206 207
207 // Calls CreateProcess with good default parameters and waits for the process to 208 // Calls CreateProcess with good default parameters and waits for the process to
208 // terminate returning the process exit code. |exit_code|, if non-NULL, is 209 // terminate returning the process exit code. |exit_code|, if non-NULL, is
209 // populated with the process exit code. 210 // populated with the process exit code.
210 ProcessExitResult RunProcessAndWait(const wchar_t* exe_path, wchar_t* cmdline) { 211 ProcessExitResult RunProcessAndWait(const wchar_t* exe_path, wchar_t* cmdline) {
211 STARTUPINFOW si = {sizeof(si)}; 212 STARTUPINFOW si = {sizeof(si)};
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 return ProcessExitResult(UNABLE_TO_EXTRACT_SETUP, ::GetLastError()); 455 return ProcessExitResult(UNABLE_TO_EXTRACT_SETUP, ::GetLastError());
455 } 456 }
456 } 457 }
457 #endif 458 #endif
458 459
459 return exit_code; 460 return exit_code;
460 } 461 }
461 462
462 // Executes setup.exe, waits for it to finish and returns the exit code. 463 // Executes setup.exe, waits for it to finish and returns the exit code.
463 ProcessExitResult RunSetup(const Configuration& configuration, 464 ProcessExitResult RunSetup(const Configuration& configuration,
464 const wchar_t* archive_path, 465 const wchar_t* archive_path,
465 const wchar_t* setup_path) { 466 const wchar_t* setup_path) {
466 // There could be three full paths in the command line for setup.exe (path 467 // There could be three full paths in the command line for setup.exe (path
467 // to exe itself, path to archive and path to log file), so we declare 468 // to exe itself, path to archive and path to log file), so we declare
468 // total size as three + one additional to hold command line options. 469 // total size as three + one additional to hold command line options.
469 CommandString cmd_line; 470 CommandString cmd_line;
470 471
471 // Get the path to setup.exe first. 472 // Get the path to setup.exe first.
472 if (::lstrlen(setup_path) > 0) { 473 if (::lstrlen(setup_path) > 0) {
473 if (!cmd_line.assign(L"\"") || 474 if (!cmd_line.assign(L"\"") ||
474 !cmd_line.append(setup_path) || 475 !cmd_line.append(setup_path) ||
475 !cmd_line.append(L"\"")) 476 !cmd_line.append(L"\""))
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
846 return exit_code; 847 return exit_code;
847 848
848 // First get a path where we can extract payload 849 // First get a path where we can extract payload
849 PathString base_path; 850 PathString base_path;
850 if (!GetWorkDir(module, &base_path, &exit_code)) 851 if (!GetWorkDir(module, &base_path, &exit_code))
851 return exit_code; 852 return exit_code;
852 853
853 #if defined(GOOGLE_CHROME_BUILD) 854 #if defined(GOOGLE_CHROME_BUILD)
854 // Set the magic suffix in registry to try full installer next time. We ignore 855 // Set the magic suffix in registry to try full installer next time. We ignore
855 // any errors here and we try to set the suffix for user level unless 856 // any errors here and we try to set the suffix for user level unless
856 // --system-level is on the command line in which case we set it for system 857 // GoogleUpdateIsMachine=1 is present in the environment or --system-level is
857 // level instead. This only applies to the Google Chrome distribution. 858 // on the command line in which case we set it for system level instead. This
859 // only applies to the Google Chrome distribution.
858 SetInstallerFlags(configuration); 860 SetInstallerFlags(configuration);
859 #endif 861 #endif
860 862
861 PathString archive_path; 863 PathString archive_path;
862 PathString setup_path; 864 PathString setup_path;
863 exit_code = UnpackBinaryResources(configuration, module, base_path.get(), 865 exit_code = UnpackBinaryResources(configuration, module, base_path.get(),
864 &archive_path, &setup_path); 866 &archive_path, &setup_path);
865 867
866 // While unpacking the binaries, we paged in a whole bunch of memory that 868 // While unpacking the binaries, we paged in a whole bunch of memory that
867 // we don't need anymore. Let's give it back to the pool before running 869 // we don't need anymore. Let's give it back to the pool before running
868 // setup. 870 // setup.
869 ::SetProcessWorkingSetSize(::GetCurrentProcess(), (SIZE_T)-1, (SIZE_T)-1); 871 ::SetProcessWorkingSetSize(::GetCurrentProcess(), (SIZE_T)-1, (SIZE_T)-1);
870 872
871 if (exit_code.IsSuccess()) 873 if (exit_code.IsSuccess())
872 exit_code = RunSetup(configuration, archive_path.get(), setup_path.get()); 874 exit_code = RunSetup(configuration, archive_path.get(), setup_path.get());
873 875
874 if (ShouldDeleteExtractedFiles()) 876 if (ShouldDeleteExtractedFiles())
875 DeleteExtractedFiles(base_path.get(), archive_path.get(), setup_path.get()); 877 DeleteExtractedFiles(base_path.get(), archive_path.get(), setup_path.get());
876 878
879 #if defined(GOOGLE_CHROME_BUILD)
877 WriteInstallResults(configuration, exit_code); 880 WriteInstallResults(configuration, exit_code);
881 #endif
882
878 return exit_code; 883 return exit_code;
879 } 884 }
880 885
881 } // namespace mini_installer 886 } // namespace mini_installer
882 887
883 int MainEntryPoint() { 888 int MainEntryPoint() {
884 mini_installer::ProcessExitResult result = 889 mini_installer::ProcessExitResult result =
885 mini_installer::WMain(::GetModuleHandle(NULL)); 890 mini_installer::WMain(::GetModuleHandle(NULL));
886 891
887 ::ExitProcess(result.exit_code); 892 ::ExitProcess(result.exit_code);
(...skipping 12 matching lines...) Expand all
900 #pragma function(memset) 905 #pragma function(memset)
901 void* memset(void* dest, int c, size_t count) { 906 void* memset(void* dest, int c, size_t count) {
902 void* start = dest; 907 void* start = dest;
903 while (count--) { 908 while (count--) {
904 *reinterpret_cast<char*>(dest) = static_cast<char>(c); 909 *reinterpret_cast<char*>(dest) = static_cast<char>(c);
905 dest = reinterpret_cast<char*>(dest) + 1; 910 dest = reinterpret_cast<char*>(dest) + 1;
906 } 911 }
907 return start; 912 return start;
908 } 913 }
909 } // extern "C" 914 } // extern "C"
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698