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

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

Issue 2992: Let mini_installer pass any arbitrary command line flags to setup.exe. This w... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 years, 2 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
« no previous file with comments | « no previous file | chrome/installer/mini_installer/mini_installer.ico » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 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 appropiate flags. 9 // 2) run the real installer (setup.exe) with appropiate flags.
10 // 10 //
(...skipping 11 matching lines...) Expand all
22 // object files that exist in $(VCInstallDir)\crt\src which are memset.obj and 22 // object files that exist in $(VCInstallDir)\crt\src which are memset.obj and
23 // P4_memset.obj. These two object files rely on the existence of a static 23 // P4_memset.obj. These two object files rely on the existence of a static
24 // variable named __sse2_available which indicates the presence of intel sse2 24 // variable named __sse2_available which indicates the presence of intel sse2
25 // extensions. We define it to false which causes a slower but safe code for 25 // extensions. We define it to false which causes a slower but safe code for
26 // memcpy and memset intrinsics. 26 // memcpy and memset intrinsics.
27 27
28 // having the linker merge the sections is saving us ~500 bytes. 28 // having the linker merge the sections is saving us ~500 bytes.
29 #pragma comment(linker, "/MERGE:.rdata=.text") 29 #pragma comment(linker, "/MERGE:.rdata=.text")
30 30
31 #include <windows.h> 31 #include <windows.h>
32 #include <Shellapi.h>
32 #include <shlwapi.h> 33 #include <shlwapi.h>
33 #include <stdlib.h> 34 #include <stdlib.h>
34 35
35 #include "chrome/installer/mini_installer/mini_installer.h" 36 #include "chrome/installer/mini_installer/mini_installer.h"
36 #include "chrome/installer/mini_installer/pe_resource.h" 37 #include "chrome/installer/mini_installer/pe_resource.h"
37 38
38 // Required linker symbol. See remarks above. 39 // Required linker symbol. See remarks above.
39 extern "C" unsigned int __sse2_available = 0; 40 extern "C" unsigned int __sse2_available = 0;
40 41
41 namespace mini_installer { 42 namespace mini_installer {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 bool SafeStrCopy(wchar_t* dest, const wchar_t* src, size_t dest_size) { 84 bool SafeStrCopy(wchar_t* dest, const wchar_t* src, size_t dest_size) {
84 for (size_t length = 0; length < dest_size; ++dest, ++src, ++length) { 85 for (size_t length = 0; length < dest_size; ++dest, ++src, ++length) {
85 *dest = *src; 86 *dest = *src;
86 if (L'\0' == *src) { 87 if (L'\0' == *src) {
87 return true; 88 return true;
88 } 89 }
89 } 90 }
90 return false; 91 return false;
91 } 92 }
92 93
94 // Function to check if a string (specified by str) ends with another string
95 // (specified by end_str).
96 bool StrEndsWith(wchar_t *str, wchar_t *end_str) {
97 if (str == NULL || end_str == NULL || lstrlen(str) < lstrlen(end_str))
98 return false;
99
100 for (int i = lstrlen(str) - 1, j = lstrlen(end_str) - 1; j >= 0; --i, --j) {
101 if (str[i] != end_str[j])
102 return false;
103 }
104
105 return true;
106 }
93 107
94 // Helper function to read a value from registry. Returns true if value 108 // Helper function to read a value from registry. Returns true if value
95 // is read successfully and stored in parameter value. Returns false otherwise. 109 // is read successfully and stored in parameter value. Returns false otherwise.
96 bool ReadValueFromRegistry(HKEY root_key, const wchar_t *sub_key, 110 bool ReadValueFromRegistry(HKEY root_key, const wchar_t *sub_key,
97 const wchar_t *value_name, wchar_t *value, 111 const wchar_t *value_name, wchar_t *value,
98 size_t size) { 112 size_t size) {
99 HKEY key; 113 HKEY key;
100 114
101 if ((::RegOpenKeyEx(root_key, sub_key, NULL, 115 if ((::RegOpenKeyEx(root_key, sub_key, NULL,
102 KEY_READ, &key) == ERROR_SUCCESS) && 116 KEY_READ, &key) == ERROR_SUCCESS) &&
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 if (::GetLastError() != ERROR_RESOURCE_TYPE_NOT_FOUND) { 261 if (::GetLastError() != ERROR_RESOURCE_TYPE_NOT_FOUND) {
248 return false; 262 return false;
249 } 263 }
250 } else if (0 == ::lstrcmpiW(name, kSetupName)) { 264 } else if (0 == ::lstrcmpiW(name, kSetupName)) {
251 *unpacked_setup = true; 265 *unpacked_setup = true;
252 } 266 }
253 267
254 return true; 268 return true;
255 } 269 }
256 270
271 // Append any command line params passed to mini_installer to the given buffer
272 // so that they can be passed on to setup.exe. We do not return any error from
273 // this method and simply skip making any changes in case of error.
274 void AppendCommandLineFlags(wchar_t* buffer, int size) {
275 int args_num;
276 wchar_t** args = ::CommandLineToArgvW(::GetCommandLine(), &args_num);
277 if (args_num <= 0)
278 return;
279
280 wchar_t full_exe_path[MAX_PATH];
281 int len = ::GetModuleFileNameW(NULL, full_exe_path, MAX_PATH);
282 if (len <= 0 && len >= MAX_PATH)
283 return;
284
285 wchar_t* exe_name = GetNameFromPathExt(full_exe_path, len);
286 if (exe_name == NULL)
287 return;
288
289 int start = 1;
290 if (args_num > 0 && !StrEndsWith(args[0], exe_name))
291 start = 0;
292
293 for (int i = start; i < args_num; ++i) {
294 if (size < lstrlen(args[i]) + 1)
295 break;
296
297 ::lstrcat(buffer, L" ");
298 ::lstrcat(buffer, args[i]);
299 size = size - (lstrlen(args[i]) + 1);
300 }
301 LocalFree(args);
302 }
257 303
258 // Executes setup.exe, waits for it to finish and returns the exit code. 304 // Executes setup.exe, waits for it to finish and returns the exit code.
259 bool RunSetup(bool have_upacked_setup, const wchar_t* base_path, 305 bool RunSetup(bool have_upacked_setup, const wchar_t* base_path,
260 const wchar_t* archive_name, int* exit_code) { 306 const wchar_t* archive_name, int* exit_code) {
261 wchar_t cmd_line[MAX_PATH * 2]; 307 // There could be three full paths in the command line for setup.exe (path
262 wchar_t cmd_args[MAX_PATH * 2]; 308 // to exe itself, path to archive and path to log file), so we declare
309 // total size as three + one additional to hold command line options.
310 wchar_t cmd_line[MAX_PATH * 4];
263 311
264 if (!SafeStrCopy(cmd_args, L" --install-archive=\"", _countof(cmd_args)) || 312 // Get the path to setup.exe first.
265 !::lstrcat(cmd_args, base_path) ||
266 !::lstrcat(cmd_args, archive_name) ||
267 !::lstrcat(cmd_args, L"\"")) {
268 return false;
269 }
270
271 if (have_upacked_setup) { 313 if (have_upacked_setup) {
272 if (!SafeStrCopy(cmd_line, L"\"", _countof(cmd_line)) || 314 if (!SafeStrCopy(cmd_line, L"\"", _countof(cmd_line)) ||
273 !::lstrcat(cmd_line, base_path) || 315 !::lstrcat(cmd_line, base_path) ||
274 !::lstrcat(cmd_line, kSetupName) || 316 !::lstrcat(cmd_line, kSetupName) ||
275 !::lstrcat(cmd_line, L"\"")) { 317 !::lstrcat(cmd_line, L"\"")) {
276 return false; 318 return false;
277 } 319 }
278 } else { 320 } else {
279 if (!GetSetupExePathFromRegistry(cmd_line, sizeof(cmd_line))) { 321 if (!GetSetupExePathFromRegistry(cmd_line, sizeof(cmd_line))) {
280 return false; 322 return false;
281 } 323 }
282 } 324 }
283 325
284 return (::lstrcat(cmd_line, cmd_args) && 326 // Append the command line param for chrome archive file
285 RunProcessAndWait(NULL, cmd_line, exit_code)); 327 if (!::lstrcat(cmd_line, L" --install-archive=\"") ||
328 !::lstrcat(cmd_line, base_path) ||
329 !::lstrcat(cmd_line, archive_name) ||
330 !::lstrcat(cmd_line, L"\"")) {
331 return false;
332 }
333
334 // Get any command line option specified for mini_installer and pass them
335 // on to setup.exe
336 AppendCommandLineFlags(cmd_line, _countof(cmd_line) - lstrlen(cmd_line));
337
338 return (RunProcessAndWait(NULL, cmd_line, exit_code));
286 } 339 }
287 340
288 341
289 void DeleteExtractedFiles(const wchar_t* base_path, 342 void DeleteExtractedFiles(const wchar_t* base_path,
290 const wchar_t* archive_name) { 343 const wchar_t* archive_name) {
291 wchar_t file_path[MAX_PATH]; 344 wchar_t file_path[MAX_PATH];
292 // Delete setup.exe. 345 // Delete setup.exe.
293 SafeStrCopy(file_path, base_path, MAX_PATH); 346 SafeStrCopy(file_path, base_path, MAX_PATH);
294 ::lstrcat(file_path, kSetupName); 347 ::lstrcat(file_path, kSetupName);
295 ::DeleteFile(file_path); 348 ::DeleteFile(file_path);
(...skipping 12 matching lines...) Expand all
308 DWORD len = ::GetTempPath(MAX_PATH, base_path); 361 DWORD len = ::GetTempPath(MAX_PATH, base_path);
309 if (len >= MAX_PATH || len <= 0) { 362 if (len >= MAX_PATH || len <= 0) {
310 // Problem in getting TEMP path so just use current directory as base path 363 // Problem in getting TEMP path so just use current directory as base path
311 len = ::GetModuleFileNameW(module, base_path, MAX_PATH); 364 len = ::GetModuleFileNameW(module, base_path, MAX_PATH);
312 if (len >= MAX_PATH || len <= 0) 365 if (len >= MAX_PATH || len <= 0)
313 return false; // Can't even get current directory? Return with error. 366 return false; // Can't even get current directory? Return with error.
314 wchar_t* name = GetNameFromPathExt(base_path, len); 367 wchar_t* name = GetNameFromPathExt(base_path, len);
315 *name = L'\0'; 368 *name = L'\0';
316 } 369 }
317 370
318 wchar_t temp_name[MAX_PATH + 1]; 371 wchar_t temp_name[MAX_PATH];
319 if (!GetTempFileName(base_path, L"CR_", 0, temp_name)) 372 if (!GetTempFileName(base_path, L"CR_", 0, temp_name))
320 return false; // Didn't get any temp name to use. Return error. 373 return false; // Didn't get any temp name to use. Return error.
321 len = GetLongPathName(temp_name, work_dir, MAX_PATH); 374 len = GetLongPathName(temp_name, work_dir, MAX_PATH);
322 if (len > MAX_PATH + 1 || len == 0) 375 if (len >= MAX_PATH || len <= 0)
323 return false; // Couldn't get full path to temp dir. Return error. 376 return false; // Couldn't get full path to temp dir. Return error.
324 377
325 // GetTempFileName creates the file as well so delete it before creating 378 // GetTempFileName creates the file as well so delete it before creating
326 // the directory in its place. 379 // the directory in its place.
327 if (!::DeleteFile(work_dir) || !::CreateDirectory(work_dir, NULL)) 380 if (!::DeleteFile(work_dir) || !::CreateDirectory(work_dir, NULL))
328 return false; // What's the use of temp dir if we can not create it? 381 return false; // What's the use of temp dir if we can not create it?
329 ::lstrcat(work_dir, L"\\"); 382 ::lstrcat(work_dir, L"\\");
330 return true; 383 return true;
331 } 384 }
332 385
333 int WMain(HMODULE module) { 386 int WMain(HMODULE module) {
334 // First get a path where we can extract payload 387 // First get a path where we can extract payload
335 wchar_t base_path[MAX_PATH]; 388 wchar_t base_path[MAX_PATH];
336 if (!GetWorkDir(module, base_path)) 389 if (!GetWorkDir(module, base_path))
337 return 1; 390 return 101;
338 391
339 wchar_t archive_name[MAX_PATH]; 392 wchar_t archive_name[MAX_PATH]; // len(archive_name) < MAX_PATH-len(base_path)
340 bool have_upacked_setup; 393 bool have_upacked_setup;
341 if (!UnpackBinaryResources(module, base_path, 394 if (!UnpackBinaryResources(module, base_path,
342 &have_upacked_setup, archive_name)) { 395 &have_upacked_setup, archive_name)) {
343 return 1; 396 return 102;
344 } 397 }
345 398
346 int setup_exit_code = 2; 399 int setup_exit_code = 103;
347 if (!RunSetup(have_upacked_setup, base_path, 400 if (!RunSetup(have_upacked_setup, base_path,
348 archive_name, &setup_exit_code)) { 401 archive_name, &setup_exit_code)) {
349 return setup_exit_code; 402 return setup_exit_code;
350 } 403 }
351 404
352 wchar_t value[4]; 405 wchar_t value[4];
353 if ((!ReadValueFromRegistry(HKEY_CURRENT_USER, kCleanupRegistryKey, 406 if ((!ReadValueFromRegistry(HKEY_CURRENT_USER, kCleanupRegistryKey,
354 kCleanupRegistryValueName, value, 4)) || 407 kCleanupRegistryValueName, value, 4)) ||
355 (value[0] != L'0')) { 408 (value[0] != L'0')) {
356 DeleteExtractedFiles(base_path, archive_name); 409 DeleteExtractedFiles(base_path, archive_name);
357 } 410 }
358 411
359 return setup_exit_code; 412 return setup_exit_code;
360 } 413 }
361 } // namespace mini_installer 414 } // namespace mini_installer
362 415
363 416
364 int MainEntryPoint() { 417 int MainEntryPoint() {
365 int result = mini_installer::WMain(::GetModuleHandle(NULL)); 418 int result = mini_installer::WMain(::GetModuleHandle(NULL));
366 ::ExitProcess(result); 419 ::ExitProcess(result);
367 } 420 }
368 421
OLDNEW
« no previous file with comments | « no previous file | chrome/installer/mini_installer/mini_installer.ico » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698