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

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

Issue 365143002: mini_installer code cleanups (no functional changes). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 5 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 | Annotate | Revision Log
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 //
11 // In order to be really small the app doesn't link against the CRT and 11 // In order to be really small the app doesn't link against the CRT and
12 // defines the following compiler/linker flags: 12 // defines the following compiler/linker flags:
13 // EnableIntrinsicFunctions="true" compiler: /Oi 13 // EnableIntrinsicFunctions="true" compiler: /Oi
14 // BasicRuntimeChecks="0" 14 // BasicRuntimeChecks="0"
15 // BufferSecurityCheck="false" compiler: /GS- 15 // BufferSecurityCheck="false" compiler: /GS-
16 // EntryPointSymbol="MainEntryPoint" linker: /ENTRY 16 // EntryPointSymbol="MainEntryPoint" linker: /ENTRY
17 // IgnoreAllDefaultLibraries="true" linker: /NODEFAULTLIB 17 // IgnoreAllDefaultLibraries="true" linker: /NODEFAULTLIB
18 // OptimizeForWindows98="1" liker: /OPT:NOWIN98 18 // OptimizeForWindows98="1" liker: /OPT:NOWIN98
19 // linker: /SAFESEH:NO 19 // linker: /SAFESEH:NO
20 20
21 // have the linker merge the sections, saving us ~500 bytes. 21 // have the linker merge the sections, saving us ~500 bytes.
22 #pragma comment(linker, "/MERGE:.rdata=.text") 22 #pragma comment(linker, "/MERGE:.rdata=.text")
23 23
24 #include <windows.h> 24 #include <windows.h>
25 #include <shellapi.h> 25 #include <shellapi.h>
26 26
27 #include "chrome/installer/mini_installer/appid.h" 27 #include "chrome/installer/mini_installer/appid.h"
28 #include "chrome/installer/mini_installer/configuration.h" 28 #include "chrome/installer/mini_installer/configuration.h"
29 #include "chrome/installer/mini_installer/decompress.h" 29 #include "chrome/installer/mini_installer/decompress.h"
30 #include "chrome/installer/mini_installer/mini_installer.h" 30 #include "chrome/installer/mini_installer/exit_code.h"
31 #include "chrome/installer/mini_installer/mini_installer_constants.h"
31 #include "chrome/installer/mini_installer/mini_string.h" 32 #include "chrome/installer/mini_installer/mini_string.h"
32 #include "chrome/installer/mini_installer/pe_resource.h" 33 #include "chrome/installer/mini_installer/pe_resource.h"
33 34
34 namespace mini_installer { 35 namespace mini_installer {
35 36
37 // The type of a process exit code.
gab 2014/07/07 13:45:01 Remove this comment, the variable name is explicit
grt (UTC plus 2) 2014/07/07 14:24:06 Done.
38 typedef DWORD ProcessExitCode;
36 typedef StackString<MAX_PATH> PathString; 39 typedef StackString<MAX_PATH> PathString;
37 typedef StackString<MAX_PATH * 4> CommandString; 40 typedef StackString<MAX_PATH * 4> CommandString;
38 41
39 // This structure passes data back and forth for the processing 42 // This structure passes data back and forth for the processing
40 // of resource callbacks. 43 // of resource callbacks.
41 struct Context { 44 struct Context {
42 // Input to the call back method. Specifies the dir to save resources. 45 // Input to the call back method. Specifies the dir to save resources.
43 const wchar_t* base_path; 46 const wchar_t* base_path;
44 // First output from call back method. Full path of Chrome archive. 47 // First output from call back method. Full path of Chrome archive.
45 PathString* chrome_resource_path; 48 PathString* chrome_resource_path;
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 key.ReadValue(value_name, value, size) == ERROR_SUCCESS) { 139 key.ReadValue(value_name, value, size) == ERROR_SUCCESS) {
137 return true; 140 return true;
138 } 141 }
139 return false; 142 return false;
140 } 143 }
141 144
142 // Opens the Google Update ClientState key for a product. 145 // Opens the Google Update ClientState key for a product.
143 bool OpenClientStateKey(HKEY root_key, const wchar_t* app_guid, REGSAM access, 146 bool OpenClientStateKey(HKEY root_key, const wchar_t* app_guid, REGSAM access,
144 RegKey* key) { 147 RegKey* key) {
145 PathString client_state_key; 148 PathString client_state_key;
146 return client_state_key.assign(kApRegistryKeyBase) && 149 return client_state_key.assign(kClientStateKeyBase) &&
147 client_state_key.append(app_guid) && 150 client_state_key.append(app_guid) &&
148 (key->Open(root_key, 151 (key->Open(root_key,
149 client_state_key.get(), 152 client_state_key.get(),
150 access | KEY_WOW64_32KEY) == ERROR_SUCCESS); 153 access | KEY_WOW64_32KEY) == ERROR_SUCCESS);
151 } 154 }
152 155
153 // This function sets the flag in registry to indicate that Google Update 156 // This function sets the flag in registry to indicate that Google Update
154 // should try full installer next time. If the current installer works, this 157 // should try full installer next time. If the current installer works, this
155 // flag is cleared by setup.exe at the end of install. The flag will by default 158 // flag is cleared by setup.exe at the end of install. The flag will by default
156 // be written to HKCU, but if --system-level is included in the command line, 159 // be written to HKCU, but if --system-level is included in the command line,
(...skipping 20 matching lines...) Expand all
177 // ClientState key in the registry. Only it need be modified. 180 // ClientState key in the registry. Only it need be modified.
178 // 3. Migrating a single-install into a multi-install. The product will have 181 // 3. Migrating a single-install into a multi-install. The product will have
179 // a ClientState key in the registry. Only it need be modified. 182 // a ClientState key in the registry. Only it need be modified.
180 // To handle all cases, we inspect the product's ClientState to see if it 183 // To handle all cases, we inspect the product's ClientState to see if it
181 // exists and its "ap" value does not contain "-multi". This is case 3, so we 184 // exists and its "ap" value does not contain "-multi". This is case 3, so we
182 // modify the product's ClientState. Otherwise, we check the 185 // modify the product's ClientState. Otherwise, we check the
183 // multi-installer's ClientState and modify it if it exists. 186 // multi-installer's ClientState and modify it if it exists.
184 if (configuration.is_multi_install()) { 187 if (configuration.is_multi_install()) {
185 if (OpenClientStateKey(root_key, app_guid, key_access, &key)) { 188 if (OpenClientStateKey(root_key, app_guid, key_access, &key)) {
186 // The product has a client state key. See if it's a single-install. 189 // The product has a client state key. See if it's a single-install.
187 ret = key.ReadValue(kApRegistryValueName, value.get(), value.capacity()); 190 ret = key.ReadValue(kApRegistryValue, value.get(), value.capacity());
188 if (ret != ERROR_FILE_NOT_FOUND && 191 if (ret != ERROR_FILE_NOT_FOUND &&
189 (ret != ERROR_SUCCESS || 192 (ret != ERROR_SUCCESS ||
190 FindTagInStr(value.get(), kMultiInstallTag, NULL))) { 193 FindTagInStr(value.get(), kMultiInstallTag, NULL))) {
191 // Error or case 2: modify the multi-installer's value. 194 // Error or case 2: modify the multi-installer's value.
192 key.Close(); 195 key.Close();
193 app_guid = google_update::kMultiInstallAppGuid; 196 app_guid = google_update::kMultiInstallAppGuid;
194 } // else case 3: modify this value. 197 } // else case 3: modify this value.
195 } else { 198 } else {
196 // case 1 or 2: modify the multi-installer's value. 199 // case 1 or 2: modify the multi-installer's value.
197 key.Close(); 200 key.Close();
198 app_guid = google_update::kMultiInstallAppGuid; 201 app_guid = google_update::kMultiInstallAppGuid;
199 } 202 }
200 } 203 }
201 204
202 if (!key.is_valid()) { 205 if (!key.is_valid()) {
203 if (!OpenClientStateKey(root_key, app_guid, key_access, &key)) 206 if (!OpenClientStateKey(root_key, app_guid, key_access, &key))
204 return; 207 return;
205 208
206 value.clear(); 209 value.clear();
207 ret = key.ReadValue(kApRegistryValueName, value.get(), value.capacity()); 210 ret = key.ReadValue(kApRegistryValue, value.get(), value.capacity());
208 } 211 }
209 212
210 // The conditions below are handling two cases: 213 // The conditions below are handling two cases:
211 // 1. When ap value is present, we want to add the required tag only if it is 214 // 1. When ap value is present, we want to add the required tag only if it is
212 // not present. 215 // not present.
213 // 2. When ap value is missing, we are going to create it with the required 216 // 2. When ap value is missing, we are going to create it with the required
214 // tag. 217 // tag.
215 if ((ret == ERROR_SUCCESS) || (ret == ERROR_FILE_NOT_FOUND)) { 218 if ((ret == ERROR_SUCCESS) || (ret == ERROR_FILE_NOT_FOUND)) {
216 if (ret == ERROR_FILE_NOT_FOUND) 219 if (ret == ERROR_FILE_NOT_FOUND)
217 value.clear(); 220 value.clear();
218 221
219 if (!StrEndsWith(value.get(), kFullInstallerSuffix) && 222 if (!StrEndsWith(value.get(), kFullInstallerSuffix) &&
220 value.append(kFullInstallerSuffix)) { 223 value.append(kFullInstallerSuffix)) {
221 key.WriteValue(kApRegistryValueName, value.get()); 224 key.WriteValue(kApRegistryValue, value.get());
222 } 225 }
223 } 226 }
224 } 227 }
225 228
226 // Gets the setup.exe path from Registry by looking the value of Uninstall 229 // Gets the setup.exe path from Registry by looking the value of Uninstall
227 // string. |size| is measured in wchar_t units. 230 // string. |size| is measured in wchar_t units.
228 bool GetSetupExePathForGuidFromRegistry(bool system_level, 231 bool GetSetupExePathForGuidFromRegistry(bool system_level,
229 const wchar_t* app_guid, 232 const wchar_t* app_guid,
230 wchar_t* path, 233 wchar_t* path,
231 size_t size) { 234 size_t size) {
232 const HKEY root_key = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 235 const HKEY root_key = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
233 RegKey key; 236 RegKey key;
234 return OpenClientStateKey(root_key, app_guid, KEY_QUERY_VALUE, &key) && 237 return OpenClientStateKey(root_key, app_guid, KEY_QUERY_VALUE, &key) &&
235 (key.ReadValue(kUninstallRegistryValueName, path, size) == ERROR_SUCCESS); 238 (key.ReadValue(kUninstallRegistryValue, path, size) == ERROR_SUCCESS);
236 } 239 }
237 240
238 // Gets the setup.exe path from Registry by looking the value of Uninstall 241 // Gets the setup.exe path from Registry by looking the value of Uninstall
239 // string. |size| is measured in wchar_t units. 242 // string. |size| is measured in wchar_t units.
240 bool GetSetupExePathFromRegistry(const Configuration& configuration, 243 bool GetSetupExePathFromRegistry(const Configuration& configuration,
241 wchar_t* path, 244 wchar_t* path,
242 size_t size) { 245 size_t size) {
243 bool system_level = configuration.is_system_level(); 246 bool system_level = configuration.is_system_level();
244 247
245 // If this is a multi install, first try looking in the binaries for the path. 248 // If this is a multi install, first try looking in the binaries for the path.
(...skipping 16 matching lines...) Expand all
262 return true; 265 return true;
263 } 266 }
264 if (configuration.has_app_host() && GetSetupExePathForGuidFromRegistry( 267 if (configuration.has_app_host() && GetSetupExePathForGuidFromRegistry(
265 system_level, google_update::kChromeAppHostAppGuid, path, size)) { 268 system_level, google_update::kChromeAppHostAppGuid, path, size)) {
266 return true; 269 return true;
267 } 270 }
268 271
269 return false; 272 return false;
270 } 273 }
271 274
272 // Calls CreateProcess with good default parameters and waits for the process 275 // Calls CreateProcess with good default parameters and waits for the process to
273 // to terminate returning the process exit code. 276 // terminate returning the process exit code. |exit_code|, if non-NULL, is
277 // populated with the process exit code.
274 bool RunProcessAndWait(const wchar_t* exe_path, wchar_t* cmdline, 278 bool RunProcessAndWait(const wchar_t* exe_path, wchar_t* cmdline,
275 int* exit_code) { 279 ProcessExitCode* exit_code) {
276 STARTUPINFOW si = {sizeof(si)}; 280 STARTUPINFOW si = {sizeof(si)};
277 PROCESS_INFORMATION pi = {0}; 281 PROCESS_INFORMATION pi = {0};
278 if (!::CreateProcess(exe_path, cmdline, NULL, NULL, FALSE, CREATE_NO_WINDOW, 282 if (!::CreateProcess(exe_path, cmdline, NULL, NULL, FALSE, CREATE_NO_WINDOW,
279 NULL, NULL, &si, &pi)) { 283 NULL, NULL, &si, &pi)) {
280 return false; 284 return false;
281 } 285 }
282 286
283 ::CloseHandle(pi.hThread); 287 ::CloseHandle(pi.hThread);
284 288
285 bool ret = true; 289 bool ret = true;
286 DWORD wr = ::WaitForSingleObject(pi.hProcess, INFINITE); 290 DWORD wr = ::WaitForSingleObject(pi.hProcess, INFINITE);
287 if (WAIT_OBJECT_0 != wr) { 291 if (WAIT_OBJECT_0 != wr) {
288 ret = false; 292 ret = false;
289 } else if (exit_code) { 293 } else if (exit_code) {
290 if (!::GetExitCodeProcess(pi.hProcess, 294 if (!::GetExitCodeProcess(pi.hProcess, exit_code))
291 reinterpret_cast<DWORD*>(exit_code))) {
292 ret = false; 295 ret = false;
293 }
294 } 296 }
295 297
296 ::CloseHandle(pi.hProcess); 298 ::CloseHandle(pi.hProcess);
297 299
298 return ret; 300 return ret;
299 } 301 }
300 302
301 // Append any command line params passed to mini_installer to the given buffer 303 // Append any command line params passed to mini_installer to the given buffer
302 // so that they can be passed on to setup.exe. We do not return any error from 304 // so that they can be passed on to setup.exe. We do not return any error from
303 // this method and simply skip making any changes in case of error. 305 // this method and simply skip making any changes in case of error.
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
345 (resource.Size() > kMaxResourceSize)) { 347 (resource.Size() > kMaxResourceSize)) {
346 return FALSE; 348 return FALSE;
347 } 349 }
348 350
349 PathString full_path; 351 PathString full_path;
350 if (!full_path.assign(ctx->base_path) || 352 if (!full_path.assign(ctx->base_path) ||
351 !full_path.append(name) || 353 !full_path.append(name) ||
352 !resource.WriteToDisk(full_path.get())) 354 !resource.WriteToDisk(full_path.get()))
353 return FALSE; 355 return FALSE;
354 356
355 if (StrStartsWith(name, kChromePrefix)) { 357 if (StrStartsWith(name, kChromeArchivePrefix)) {
356 if (!ctx->chrome_resource_path->assign(full_path.get())) 358 if (!ctx->chrome_resource_path->assign(full_path.get()))
357 return FALSE; 359 return FALSE;
358 } else if (StrStartsWith(name, kSetupPrefix)) { 360 } else if (StrStartsWith(name, kSetupPrefix)) {
359 if (!ctx->setup_resource_path->assign(full_path.get())) 361 if (!ctx->setup_resource_path->assign(full_path.get()))
360 return FALSE; 362 return FALSE;
361 } else { 363 } else {
362 // Resources should either start with 'chrome' or 'setup'. We don't handle 364 // Resources should either start with 'chrome' or 'setup'. We don't handle
363 // anything else. 365 // anything else.
364 return FALSE; 366 return FALSE;
365 } 367 }
366 368
367 return TRUE; 369 return TRUE;
368 } 370 }
369 371
370 // Finds and writes to disk resources of various types. Returns false 372 // Finds and writes to disk resources of various types. Returns false
371 // if there is a problem in writing any resource to disk. setup.exe resource 373 // if there is a problem in writing any resource to disk. setup.exe resource
372 // can come in one of three possible forms: 374 // can come in one of three possible forms:
373 // - Resource type 'B7', compressed using LZMA (*.7z) 375 // - Resource type 'B7', compressed using LZMA (*.7z)
374 // - Resource type 'BL', compressed using LZ (*.ex_) 376 // - Resource type 'BL', compressed using LZ (*.ex_)
375 // - Resource type 'BN', uncompressed (*.exe) 377 // - Resource type 'BN', uncompressed (*.exe)
376 // If setup.exe is present in more than one form, the precedence order is 378 // If setup.exe is present in more than one form, the precedence order is
377 // BN < BL < B7 379 // BN < BL < B7
378 // For more details see chrome/tools/build/win/create_installer_archive.py. 380 // For more details see chrome/tools/build/win/create_installer_archive.py.
379 bool UnpackBinaryResources(const Configuration& configuration, HMODULE module, 381 bool UnpackBinaryResources(const Configuration& configuration, HMODULE module,
380 const wchar_t* base_path, PathString* archive_path, 382 const wchar_t* base_path, PathString* archive_path,
381 PathString* setup_path) { 383 PathString* setup_path) {
382 // Generate the setup.exe path where we patch/uncompress setup resource. 384 // Generate the setup.exe path where we patch/uncompress setup resource.
383 PathString setup_dest_path; 385 PathString setup_dest_path;
384 if (!setup_dest_path.assign(base_path) || 386 if (!setup_dest_path.assign(base_path) ||
385 !setup_dest_path.append(kSetupName)) 387 !setup_dest_path.append(kSetupExe))
386 return false; 388 return false;
387 389
388 // Prepare the input to OnResourceFound method that needs a location where 390 // Prepare the input to OnResourceFound method that needs a location where
389 // it will write all the resources. 391 // it will write all the resources.
390 Context context = { 392 Context context = {
391 base_path, 393 base_path,
392 archive_path, 394 archive_path,
393 setup_path, 395 setup_path,
394 }; 396 };
395 397
396 // Get the resources of type 'B7' (7zip archive). 398 // Get the resources of type 'B7' (7zip archive).
397 // We need a chrome archive to do the installation. So if there 399 // We need a chrome archive to do the installation. So if there
398 // is a problem in fetching B7 resource, just return an error. 400 // is a problem in fetching B7 resource, just return an error.
399 if (!::EnumResourceNames(module, kLZMAResourceType, OnResourceFound, 401 if (!::EnumResourceNames(module, kLZMAResourceType, OnResourceFound,
400 reinterpret_cast<LONG_PTR>(&context)) || 402 reinterpret_cast<LONG_PTR>(&context)) ||
401 archive_path->length() == 0) 403 archive_path->length() == 0)
402 return false; 404 return false;
403 405
404 // If we found setup 'B7' resource, handle it. 406 // If we found setup 'B7' resource, handle it.
405 if (setup_path->length() > 0) { 407 if (setup_path->length() > 0) {
406 CommandString cmd_line; 408 CommandString cmd_line;
407 // Get the path to setup.exe first. 409 // Get the path to setup.exe first.
408 bool success = true; 410 bool success = true;
409 if (!GetSetupExePathFromRegistry(configuration, cmd_line.get(), 411 if (!GetSetupExePathFromRegistry(configuration, cmd_line.get(),
410 cmd_line.capacity()) || 412 cmd_line.capacity()) ||
413 !cmd_line.append(L" --") ||
411 !cmd_line.append(kCmdUpdateSetupExe) || 414 !cmd_line.append(kCmdUpdateSetupExe) ||
412 !cmd_line.append(L"=\"") || 415 !cmd_line.append(L"=\"") ||
413 !cmd_line.append(setup_path->get()) || 416 !cmd_line.append(setup_path->get()) ||
414 !cmd_line.append(L"\"") || 417 !cmd_line.append(L"\" --") ||
415 !cmd_line.append(kCmdNewSetupExe) || 418 !cmd_line.append(kCmdNewSetupExe) ||
416 !cmd_line.append(L"=\"") || 419 !cmd_line.append(L"=\"") ||
417 !cmd_line.append(setup_dest_path.get()) || 420 !cmd_line.append(setup_dest_path.get()) ||
418 !cmd_line.append(L"\"")) { 421 !cmd_line.append(L"\"")) {
gab 2014/07/07 13:45:01 Use the CommandLine API to build the command line
grt (UTC plus 2) 2014/07/07 14:24:06 base/ is not available here.
419 success = false; 422 success = false;
420 } 423 }
421 424
422 // Get any command line option specified for mini_installer and pass them 425 // Get any command line option specified for mini_installer and pass them
423 // on to setup.exe. This is important since switches such as 426 // on to setup.exe. This is important since switches such as
424 // --multi-install and --chrome-frame affect where setup.exe will write 427 // --multi-install and --chrome-frame affect where setup.exe will write
425 // installer results for consumption by Google Update. 428 // installer results for consumption by Google Update.
426 AppendCommandLineFlags(configuration, &cmd_line); 429 AppendCommandLineFlags(configuration, &cmd_line);
427 430
428 int exit_code = 0; 431 ProcessExitCode exit_code = SUCCESS_EXIT_CODE;
429 if (success && 432 if (success &&
430 (!RunProcessAndWait(NULL, cmd_line.get(), &exit_code) || 433 (!RunProcessAndWait(NULL, cmd_line.get(), &exit_code) ||
431 exit_code != ERROR_SUCCESS)) { 434 exit_code != SUCCESS_EXIT_CODE)) {
432 success = false; 435 success = false;
433 } 436 }
434 437
435 if (!success) 438 if (!success)
436 DeleteFile(setup_path->get()); 439 DeleteFile(setup_path->get());
437 440
438 return success && setup_path->assign(setup_dest_path.get()); 441 return success && setup_path->assign(setup_dest_path.get());
439 } 442 }
440 443
441 // setup.exe wasn't sent as 'B7', lets see if it was sent as 'BL' 444 // setup.exe wasn't sent as 'B7', lets see if it was sent as 'BL'
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 ::DeleteFile(setup_dest_path.get()); 483 ::DeleteFile(setup_dest_path.get());
481 } 484 }
482 } 485 }
483 } 486 }
484 487
485 return setup_path->length() > 0; 488 return setup_path->length() > 0;
486 } 489 }
487 490
488 // Executes setup.exe, waits for it to finish and returns the exit code. 491 // Executes setup.exe, waits for it to finish and returns the exit code.
489 bool RunSetup(const Configuration& configuration, const wchar_t* archive_path, 492 bool RunSetup(const Configuration& configuration, const wchar_t* archive_path,
490 const wchar_t* setup_path, int* exit_code) { 493 const wchar_t* setup_path, ProcessExitCode* exit_code) {
491 // There could be three full paths in the command line for setup.exe (path 494 // There could be three full paths in the command line for setup.exe (path
492 // to exe itself, path to archive and path to log file), so we declare 495 // to exe itself, path to archive and path to log file), so we declare
493 // total size as three + one additional to hold command line options. 496 // total size as three + one additional to hold command line options.
494 CommandString cmd_line; 497 CommandString cmd_line;
495 498
496 // Get the path to setup.exe first. 499 // Get the path to setup.exe first.
497 if (::lstrlen(setup_path) > 0) { 500 if (::lstrlen(setup_path) > 0) {
498 if (!cmd_line.assign(L"\"") || 501 if (!cmd_line.assign(L"\"") ||
499 !cmd_line.append(setup_path) || 502 !cmd_line.append(setup_path) ||
500 !cmd_line.append(L"\"")) 503 !cmd_line.append(L"\""))
501 return false; 504 return false;
502 } else if (!GetSetupExePathFromRegistry(configuration, cmd_line.get(), 505 } else if (!GetSetupExePathFromRegistry(configuration, cmd_line.get(),
503 cmd_line.capacity())) { 506 cmd_line.capacity())) {
504 return false; 507 return false;
505 } 508 }
506 509
507 // Append the command line param for chrome archive file 510 // Append the command line param for chrome archive file
508 if (!cmd_line.append(kCmdInstallArchive) || 511 if (!cmd_line.append(L" --") ||
512 !cmd_line.append(kCmdInstallArchive) ||
509 !cmd_line.append(L"=\"") || 513 !cmd_line.append(L"=\"") ||
510 !cmd_line.append(archive_path) || 514 !cmd_line.append(archive_path) ||
511 !cmd_line.append(L"\"")) 515 !cmd_line.append(L"\""))
gab 2014/07/07 13:45:01 Use CommandLine API here too.
grt (UTC plus 2) 2014/07/07 14:24:06 same comment
512 return false; 516 return false;
513 517
514 // Get any command line option specified for mini_installer and pass them 518 // Get any command line option specified for mini_installer and pass them
515 // on to setup.exe 519 // on to setup.exe
516 AppendCommandLineFlags(configuration, &cmd_line); 520 AppendCommandLineFlags(configuration, &cmd_line);
517 521
518 return RunProcessAndWait(NULL, cmd_line.get(), exit_code); 522 return RunProcessAndWait(NULL, cmd_line.get(), exit_code);
519 } 523 }
520 524
521 // Deletes given files and working dir. 525 // Deletes given files and working dir.
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
707 for (int i = 0; i < arraysize(kDirectoryPrefixes); ++i) { 711 for (int i = 0; i < arraysize(kDirectoryPrefixes); ++i) {
708 DeleteDirectoriesWithPrefix(temp.get(), kDirectoryPrefixes[i]); 712 DeleteDirectoriesWithPrefix(temp.get(), kDirectoryPrefixes[i]);
709 } 713 }
710 } 714 }
711 715
712 // Checks the command line for specific mini installer flags. 716 // Checks the command line for specific mini installer flags.
713 // If the function returns true, the command line has been processed and all 717 // If the function returns true, the command line has been processed and all
714 // required actions taken. The installer must exit and return the returned 718 // required actions taken. The installer must exit and return the returned
715 // |exit_code|. 719 // |exit_code|.
716 bool ProcessNonInstallOperations(const Configuration& configuration, 720 bool ProcessNonInstallOperations(const Configuration& configuration,
717 int* exit_code) { 721 ProcessExitCode* exit_code) {
718 bool ret = false; 722 bool ret = false;
719 723
720 switch (configuration.operation()) { 724 switch (configuration.operation()) {
721 case Configuration::CLEANUP: 725 case Configuration::CLEANUP:
722 // Cleanup has already taken place in DeleteOldChromeTempDirectories at 726 // Cleanup has already taken place in DeleteOldChromeTempDirectories at
723 // this point, so just tell our caller to exit early. 727 // this point, so just tell our caller to exit early.
724 *exit_code = 0; 728 *exit_code = SUCCESS_EXIT_CODE;
725 ret = true; 729 ret = true;
726 break; 730 break;
727 731
728 default: break; 732 default: break;
729 } 733 }
730 734
731 return ret; 735 return ret;
732 } 736 }
733 737
734 // Returns true if we should delete the temp files we create (default). 738 // Returns true if we should delete the temp files we create (default).
735 // Returns false iff the user has manually created a ChromeInstallerCleanup 739 // Returns false iff the user has manually created a ChromeInstallerCleanup
736 // string value in the registry under HKCU\\Software\\[Google|Chromium] 740 // string value in the registry under HKCU\\Software\\[Google|Chromium]
737 // and set its value to "0". That explicitly forbids the mini installer from 741 // and set its value to "0". That explicitly forbids the mini installer from
738 // deleting these files. 742 // deleting these files.
739 // Support for this has been publicly mentioned in troubleshooting tips so 743 // Support for this has been publicly mentioned in troubleshooting tips so
740 // we continue to support it. 744 // we continue to support it.
741 bool ShouldDeleteExtractedFiles() { 745 bool ShouldDeleteExtractedFiles() {
742 wchar_t value[2] = {0}; 746 wchar_t value[2] = {0};
743 if (ReadValueFromRegistry(HKEY_CURRENT_USER, kCleanupRegistryKey, 747 if (ReadValueFromRegistry(HKEY_CURRENT_USER, kCleanupRegistryKey,
744 kCleanupRegistryValueName, value, 748 kCleanupRegistryValue, value, arraysize(value)) &&
745 arraysize(value)) &&
746 value[0] == L'0') { 749 value[0] == L'0') {
747 return false; 750 return false;
748 } 751 }
749 752
750 return true; 753 return true;
751 } 754 }
752 755
753 // Main function. First gets a working dir, unpacks the resources and finally 756 // Main function. First gets a working dir, unpacks the resources and finally
754 // executes setup.exe to do the install/upgrade. 757 // executes setup.exe to do the install/upgrade.
755 int WMain(HMODULE module) { 758 ProcessExitCode WMain(HMODULE module) {
756 #if defined(COMPONENT_BUILD) 759 #if defined(COMPONENT_BUILD)
757 if (::GetEnvironmentVariable(L"MINI_INSTALLER_TEST", NULL, 0) == 0) { 760 if (::GetEnvironmentVariable(L"MINI_INSTALLER_TEST", NULL, 0) == 0) {
758 static const wchar_t kComponentBuildIncompatibleMessage[] = 761 static const wchar_t kComponentBuildIncompatibleMessage[] =
759 L"mini_installer.exe is incompatible with the component build, please" 762 L"mini_installer.exe is incompatible with the component build, please"
760 L" run setup.exe with the same command line instead. See" 763 L" run setup.exe with the same command line instead. See"
761 L" http://crbug.com/127233#c17 for details."; 764 L" http://crbug.com/127233#c17 for details.";
762 ::MessageBox(NULL, kComponentBuildIncompatibleMessage, NULL, MB_ICONERROR); 765 ::MessageBox(NULL, kComponentBuildIncompatibleMessage, NULL, MB_ICONERROR);
763 return 1; 766 return GENERIC_ERROR;
764 } 767 }
765 #endif 768 #endif
766 769
767 // Always start with deleting potential leftovers from previous installations. 770 // Always start with deleting potential leftovers from previous installations.
768 // This can make the difference between success and failure. We've seen 771 // This can make the difference between success and failure. We've seen
769 // many installations out in the field fail due to out of disk space problems 772 // many installations out in the field fail due to out of disk space problems
770 // so this could buy us some space. 773 // so this could buy us some space.
771 DeleteOldChromeTempDirectories(); 774 DeleteOldChromeTempDirectories();
772 775
773 // TODO(grt): Make the exit codes more granular so we know where the popular 776 // TODO(grt): Make the exit codes more granular so we know where the popular
774 // errors truly are. 777 // errors truly are.
775 int exit_code = 101; 778 ProcessExitCode exit_code = GENERIC_INITIALIZATION_FAILURE;
776 779
777 // Parse the command line. 780 // Parse the command line.
778 Configuration configuration; 781 Configuration configuration;
779 if (!configuration.Initialize()) 782 if (!configuration.Initialize())
780 return exit_code; 783 return exit_code;
781 784
782 if (configuration.query_component_build()) { 785 if (configuration.query_component_build()) {
783 // Exit immediately with an exit code of 1 to indicate component build and 0 786 // Exit immediately with an exit code of 1 to indicate component build and 0
784 // to indicate static build. This is used by the tests in 787 // to indicate static build. This is used by the tests in
785 // /src/chrome/test/mini_installer/. 788 // /src/chrome/test/mini_installer/.
786 #if defined(COMPONENT_BUILD) 789 #if defined(COMPONENT_BUILD)
787 return 1; 790 return GENERIC_ERROR;
gab 2014/07/07 13:45:01 This doesn't match what the comment above says (i.
grt (UTC plus 2) 2014/07/07 14:24:06 0/1 are the generic success/error codes for any ex
788 #else 791 #else
789 return 0; 792 return SUCCESS_EXIT_CODE;
790 #endif 793 #endif
791 } 794 }
792 795
793 // If the --cleanup switch was specified on the command line, then that means 796 // If the --cleanup switch was specified on the command line, then that means
794 // we should only do the cleanup and then exit. 797 // we should only do the cleanup and then exit.
795 if (ProcessNonInstallOperations(configuration, &exit_code)) 798 if (ProcessNonInstallOperations(configuration, &exit_code))
796 return exit_code; 799 return exit_code;
797 800
798 // First get a path where we can extract payload 801 // First get a path where we can extract payload
799 PathString base_path; 802 PathString base_path;
800 if (!GetWorkDir(module, &base_path)) 803 if (!GetWorkDir(module, &base_path))
801 return 101; 804 return GENERIC_INITIALIZATION_FAILURE;
802 805
803 #if defined(GOOGLE_CHROME_BUILD) 806 #if defined(GOOGLE_CHROME_BUILD)
804 // Set the magic suffix in registry to try full installer next time. We ignore 807 // Set the magic suffix in registry to try full installer next time. We ignore
805 // any errors here and we try to set the suffix for user level unless 808 // any errors here and we try to set the suffix for user level unless
806 // --system-level is on the command line in which case we set it for system 809 // --system-level is on the command line in which case we set it for system
807 // level instead. This only applies to the Google Chrome distribution. 810 // level instead. This only applies to the Google Chrome distribution.
808 SetInstallerFlags(configuration); 811 SetInstallerFlags(configuration);
809 #endif 812 #endif
810 813
811 PathString archive_path; 814 PathString archive_path;
812 PathString setup_path; 815 PathString setup_path;
813 if (!UnpackBinaryResources(configuration, module, base_path.get(), 816 if (!UnpackBinaryResources(configuration, module, base_path.get(),
814 &archive_path, &setup_path)) { 817 &archive_path, &setup_path)) {
815 exit_code = 102; 818 exit_code = GENERIC_UNPACKING_FAILURE;
816 } else { 819 } else {
817 // While unpacking the binaries, we paged in a whole bunch of memory that 820 // While unpacking the binaries, we paged in a whole bunch of memory that
818 // we don't need anymore. Let's give it back to the pool before running 821 // we don't need anymore. Let's give it back to the pool before running
819 // setup. 822 // setup.
820 ::SetProcessWorkingSetSize(::GetCurrentProcess(), -1, -1); 823 ::SetProcessWorkingSetSize(::GetCurrentProcess(), -1, -1);
821 if (!RunSetup(configuration, archive_path.get(), setup_path.get(), 824 if (!RunSetup(configuration, archive_path.get(), setup_path.get(),
822 &exit_code)) { 825 &exit_code)) {
823 exit_code = 103; 826 exit_code = GENERIC_SETUP_FAILURE;
824 } 827 }
825 } 828 }
826 829
827 if (ShouldDeleteExtractedFiles()) 830 if (ShouldDeleteExtractedFiles())
828 DeleteExtractedFiles(base_path.get(), archive_path.get(), setup_path.get()); 831 DeleteExtractedFiles(base_path.get(), archive_path.get(), setup_path.get());
829 832
830 return exit_code; 833 return exit_code;
831 } 834 }
832 835
833 } // namespace mini_installer 836 } // namespace mini_installer
834 837
835 int MainEntryPoint() { 838 int MainEntryPoint() {
836 int result = mini_installer::WMain(::GetModuleHandle(NULL)); 839 mini_installer::ProcessExitCode result =
840 mini_installer::WMain(::GetModuleHandle(NULL));
837 ::ExitProcess(result); 841 ::ExitProcess(result);
838 } 842 }
839 843
840 // VC Express editions don't come with the memset CRT obj file and linking to 844 // VC Express editions don't come with the memset CRT obj file and linking to
841 // the obj files between versions becomes a bit problematic. Therefore, 845 // the obj files between versions becomes a bit problematic. Therefore,
842 // simply implement memset. 846 // simply implement memset.
843 // 847 //
844 // This also avoids having to explicitly set the __sse2_available hack when 848 // This also avoids having to explicitly set the __sse2_available hack when
845 // linking with both the x64 and x86 obj files which is required when not 849 // linking with both the x64 and x86 obj files which is required when not
846 // linking with the std C lib in certain instances (including Chromium) with 850 // linking with the std C lib in certain instances (including Chromium) with
847 // MSVC. __sse2_available determines whether to use SSE2 intructions with 851 // MSVC. __sse2_available determines whether to use SSE2 intructions with
848 // std C lib routines, and is set by MSVC's std C lib implementation normally. 852 // std C lib routines, and is set by MSVC's std C lib implementation normally.
849 extern "C" { 853 extern "C" {
850 #pragma function(memset) 854 #pragma function(memset)
851 void* memset(void* dest, int c, size_t count) { 855 void* memset(void* dest, int c, size_t count) {
852 void* start = dest; 856 void* start = dest;
853 while (count--) { 857 while (count--) {
854 *reinterpret_cast<char*>(dest) = static_cast<char>(c); 858 *reinterpret_cast<char*>(dest) = static_cast<char>(c);
855 dest = reinterpret_cast<char*>(dest) + 1; 859 dest = reinterpret_cast<char*>(dest) + 1;
856 } 860 }
857 return start; 861 return start;
858 } 862 }
859 } // extern "C" 863 } // extern "C"
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698