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

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

Issue 2655473002: Handle spaces in the name of the mini_installer. (Closed)
Patch Set: better comments 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 23 matching lines...) Expand all
34 34
35 #include <sddl.h> 35 #include <sddl.h>
36 #include <shellapi.h> 36 #include <shellapi.h>
37 #include <stdlib.h> 37 #include <stdlib.h>
38 #include <stddef.h> 38 #include <stddef.h>
39 39
40 #include "chrome/installer/mini_installer/appid.h" 40 #include "chrome/installer/mini_installer/appid.h"
41 #include "chrome/installer/mini_installer/configuration.h" 41 #include "chrome/installer/mini_installer/configuration.h"
42 #include "chrome/installer/mini_installer/decompress.h" 42 #include "chrome/installer/mini_installer/decompress.h"
43 #include "chrome/installer/mini_installer/mini_installer_constants.h" 43 #include "chrome/installer/mini_installer/mini_installer_constants.h"
44 #include "chrome/installer/mini_installer/mini_string.h"
45 #include "chrome/installer/mini_installer/pe_resource.h" 44 #include "chrome/installer/mini_installer/pe_resource.h"
46 #include "chrome/installer/mini_installer/regkey.h" 45 #include "chrome/installer/mini_installer/regkey.h"
47 46
48 namespace mini_installer { 47 namespace mini_installer {
49 48
50 typedef StackString<MAX_PATH> PathString; 49 typedef StackString<MAX_PATH> PathString;
51 typedef StackString<MAX_PATH * 4> CommandString;
52 50
53 // This structure passes data back and forth for the processing 51 // This structure passes data back and forth for the processing
54 // of resource callbacks. 52 // of resource callbacks.
55 struct Context { 53 struct Context {
56 // Input to the call back method. Specifies the dir to save resources. 54 // Input to the call back method. Specifies the dir to save resources.
57 const wchar_t* base_path; 55 const wchar_t* base_path;
58 // First output from call back method. Full path of Chrome archive. 56 // First output from call back method. Full path of Chrome archive.
59 PathString* chrome_resource_path; 57 PathString* chrome_resource_path;
60 // Second output from call back method. Full path of Setup archive/exe. 58 // Second output from call back method. Full path of Setup archive/exe.
61 PathString* setup_resource_path; 59 PathString* setup_resource_path;
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 // could return a different object but since we never spawn more than one 210 // could return a different object but since we never spawn more than one
213 // sub-process at a time that case should never happen. 211 // sub-process at a time that case should never happen.
214 return ProcessExitResult(WAIT_FOR_PROCESS_FAILED, ::GetLastError()); 212 return ProcessExitResult(WAIT_FOR_PROCESS_FAILED, ::GetLastError());
215 } 213 }
216 214
217 ::CloseHandle(pi.hProcess); 215 ::CloseHandle(pi.hProcess);
218 216
219 return ProcessExitResult(exit_code); 217 return ProcessExitResult(exit_code);
220 } 218 }
221 219
222 // Appends any command line params passed to mini_installer to the given buffer 220 void AppendCommandLineFlags(const wchar_t* command_line,
223 // so that they can be passed on to setup.exe.
224 // |buffer| is unchanged in case of error.
225 void AppendCommandLineFlags(const Configuration& configuration,
226 CommandString* buffer) { 221 CommandString* buffer) {
227 PathString full_exe_path; 222 // The program name (the first argument parsed by CommandLineToArgvW) is
228 size_t len = ::GetModuleFileName( 223 // delimited by whitespace or a double quote based on the first character of
229 NULL, full_exe_path.get(), static_cast<DWORD>(full_exe_path.capacity())); 224 // the full command line string. Use the same logic here to scan past the
230 if (!len || len >= full_exe_path.capacity()) 225 // program name in the program's command line (obtained during startup from
226 // GetCommandLine). See
227 // http://www.windowsinspired.com/how-a-windows-programs-splits-its-command-li ne-into-individual-arguments/
228 // for gory details regarding how CommandLineToArgvW works.
229 wchar_t a_char = 0;
230 if (*command_line == L'"') {
231 // Scan forward past the closing double quote.
232 ++command_line;
233 while (true) {
234 a_char = *command_line;
235 if (!a_char)
236 break;
237 ++command_line;
238 if (a_char == L'"') {
239 a_char = *command_line;
240 break;
241 }
242 } // postcondition: |a_char| contains the character at *command_line.
243 } else {
244 // Scan forward for the first space or tab character.
245 while (true) {
246 a_char = *command_line;
247 if (!a_char || a_char == L' ' || a_char == L'\t')
248 break;
249 ++command_line;
250 } // postcondition: |a_char| contains the character at *command_line.
251 }
252
253 if (!a_char)
231 return; 254 return;
232 255
233 const wchar_t* exe_name = 256 // Append a space if |command_line| doesn't begin with one.
234 GetNameFromPathExt(full_exe_path.get(), static_cast<DWORD>(len)); 257 if (a_char != ' ' && a_char != '\t' && !buffer->append(L" "))
235
236 // - configuration.program() returns the first command line argument
237 // passed into the program (that the user probably typed in this case).
238 // "mini_installer.exe"
239 // "mini_installer"
240 // "out\Release\mini_installer"
241 // - |exe_name| is the executable file of the current process.
242 // "mini_installer.exe"
243 //
244 // Note that there are three possibilities to handle here.
245 // Receive a cmdline containing:
246 // 1) executable name WITH extension
247 // 2) executable name with NO extension
248 // 3) NO executable name as part of cmdline
249 const wchar_t* cmd_to_append = L"";
250 const wchar_t* arg0 = configuration.program();
251 if (!arg0)
252 return; 258 return;
253 const wchar_t* arg0_base_name = GetNameFromPathExt(arg0, ::lstrlen(arg0)); 259 buffer->append(command_line);
254 if (!StrStartsWith(exe_name, arg0_base_name)) {
255 // State 3: NO executable name as part of cmdline.
256 buffer->append(L" ");
257 cmd_to_append = configuration.command_line();
258 } else if (configuration.argument_count() > 1) {
259 // State 1 or 2: Executable name is in cmdline.
260 // - Append everything AFTER the executable name.
261 // (Using arg0_base_name here to make sure to match with or without
262 // extension. Then move to the space following the token.)
263 const wchar_t* tmp = SearchStringI(configuration.command_line(),
264 arg0_base_name);
265 tmp = SearchStringI(tmp, L" ");
266 cmd_to_append = tmp;
267 }
268
269 buffer->append(cmd_to_append);
270 } 260 }
271 261
272
273 // Windows defined callback used in the EnumResourceNames call. For each 262 // Windows defined callback used in the EnumResourceNames call. For each
274 // matching resource found, the callback is invoked and at this point we write 263 // matching resource found, the callback is invoked and at this point we write
275 // it to disk. We expect resource names to start with 'chrome' or 'setup'. Any 264 // it to disk. We expect resource names to start with 'chrome' or 'setup'. Any
276 // other name is treated as an error. 265 // other name is treated as an error.
277 BOOL CALLBACK OnResourceFound(HMODULE module, const wchar_t* type, 266 BOOL CALLBACK OnResourceFound(HMODULE module, const wchar_t* type,
278 wchar_t* name, LONG_PTR context) { 267 wchar_t* name, LONG_PTR context) {
279 if (NULL == context) 268 if (NULL == context)
280 return FALSE; 269 return FALSE;
281 270
282 Context* ctx = reinterpret_cast<Context*>(context); 271 Context* ctx = reinterpret_cast<Context*>(context);
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 !cmd_line.append(kCmdNewSetupExe) || 376 !cmd_line.append(kCmdNewSetupExe) ||
388 !cmd_line.append(L"=\"") || 377 !cmd_line.append(L"=\"") ||
389 !cmd_line.append(setup_dest_path.get()) || 378 !cmd_line.append(setup_dest_path.get()) ||
390 !cmd_line.append(L"\"")) { 379 !cmd_line.append(L"\"")) {
391 exit_code = ProcessExitResult(COMMAND_STRING_OVERFLOW); 380 exit_code = ProcessExitResult(COMMAND_STRING_OVERFLOW);
392 } 381 }
393 } 382 }
394 383
395 // Get any command line option specified for mini_installer and pass them 384 // Get any command line option specified for mini_installer and pass them
396 // on to setup.exe. 385 // on to setup.exe.
397 AppendCommandLineFlags(configuration, &cmd_line); 386 AppendCommandLineFlags(configuration.command_line(), &cmd_line);
398 387
399 if (exit_code.IsSuccess()) 388 if (exit_code.IsSuccess())
400 exit_code = RunProcessAndWait(exe_path.get(), cmd_line.get()); 389 exit_code = RunProcessAndWait(exe_path.get(), cmd_line.get());
401 390
402 if (!exit_code.IsSuccess()) 391 if (!exit_code.IsSuccess())
403 DeleteFile(setup_path->get()); 392 DeleteFile(setup_path->get());
404 else if (!setup_path->assign(setup_dest_path.get())) 393 else if (!setup_path->assign(setup_dest_path.get()))
405 exit_code = ProcessExitResult(PATH_STRING_OVERFLOW); 394 exit_code = ProcessExitResult(PATH_STRING_OVERFLOW);
406 395
407 return exit_code; 396 return exit_code;
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
486 (!cmd_line.append(L" --") || 475 (!cmd_line.append(L" --") ||
487 !cmd_line.append(kCmdPreviousVersion) || 476 !cmd_line.append(kCmdPreviousVersion) ||
488 !cmd_line.append(L"=\"") || 477 !cmd_line.append(L"=\"") ||
489 !cmd_line.append(configuration.previous_version()) || 478 !cmd_line.append(configuration.previous_version()) ||
490 !cmd_line.append(L"\""))) { 479 !cmd_line.append(L"\""))) {
491 return ProcessExitResult(COMMAND_STRING_OVERFLOW); 480 return ProcessExitResult(COMMAND_STRING_OVERFLOW);
492 } 481 }
493 482
494 // Get any command line option specified for mini_installer and pass them 483 // Get any command line option specified for mini_installer and pass them
495 // on to setup.exe 484 // on to setup.exe
496 AppendCommandLineFlags(configuration, &cmd_line); 485 AppendCommandLineFlags(configuration.command_line(), &cmd_line);
497 486
498 return RunProcessAndWait(NULL, cmd_line.get()); 487 return RunProcessAndWait(NULL, cmd_line.get());
499 } 488 }
500 489
501 // Deletes given files and working dir. 490 // Deletes given files and working dir.
502 void DeleteExtractedFiles(const wchar_t* base_path, 491 void DeleteExtractedFiles(const wchar_t* base_path,
503 const wchar_t* archive_path, 492 const wchar_t* archive_path,
504 const wchar_t* setup_path) { 493 const wchar_t* setup_path) {
505 ::DeleteFile(archive_path); 494 ::DeleteFile(archive_path);
506 ::DeleteFile(setup_path); 495 ::DeleteFile(setup_path);
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after
865 DeleteExtractedFiles(base_path.get(), archive_path.get(), setup_path.get()); 854 DeleteExtractedFiles(base_path.get(), archive_path.get(), setup_path.get());
866 855
867 #if defined(GOOGLE_CHROME_BUILD) 856 #if defined(GOOGLE_CHROME_BUILD)
868 WriteInstallResults(configuration, exit_code); 857 WriteInstallResults(configuration, exit_code);
869 #endif 858 #endif
870 859
871 return exit_code; 860 return exit_code;
872 } 861 }
873 862
874 } // namespace mini_installer 863 } // namespace mini_installer
OLDNEW
« no previous file with comments | « chrome/installer/mini_installer/mini_installer.h ('k') | chrome/installer/mini_installer/mini_installer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698