Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/install_static/install_util.h" | 5 #include "chrome/install_static/install_util.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 #include <assert.h> | 8 #include <assert.h> |
| 9 #include <stdlib.h> | 9 #include <stdlib.h> |
| 10 #include <string.h> | 10 #include <string.h> |
| (...skipping 563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 574 bool trim_spaces) { | 574 bool trim_spaces) { |
| 575 return TokenizeStringT<std::string>(str, delimiter, trim_spaces); | 575 return TokenizeStringT<std::string>(str, delimiter, trim_spaces); |
| 576 } | 576 } |
| 577 | 577 |
| 578 std::vector<std::wstring> TokenizeString16(const std::wstring& str, | 578 std::vector<std::wstring> TokenizeString16(const std::wstring& str, |
| 579 wchar_t delimiter, | 579 wchar_t delimiter, |
| 580 bool trim_spaces) { | 580 bool trim_spaces) { |
| 581 return TokenizeStringT<std::wstring>(str, delimiter, trim_spaces); | 581 return TokenizeStringT<std::wstring>(str, delimiter, trim_spaces); |
| 582 } | 582 } |
| 583 | 583 |
| 584 std::vector<std::wstring> TokenizeCommandLineToArray( | |
| 585 const std::wstring& command_line) { | |
| 586 // This is baroquely complex to do properly, see e.g. | |
| 587 // https://blogs.msdn.microsoft.com/oldnewthing/20100917-00/?p=12833 | |
| 588 // http://www.windowsinspired.com/how-a-windows-programs-splits-its-command-li ne-into-individual-arguments/ | |
| 589 // and many others. We cannot use CommandLineToArgvW() in chrome_elf, because | |
| 590 // it's in shell32.dll. Previously, __wgetmainargs() in the CRT was available, | |
| 591 // and it's still documented for VS 2015 at | |
| 592 // https://msdn.microsoft.com/en-us/library/ff770599.aspx but unfortunately, | |
| 593 // isn't actually available. | |
| 594 // | |
| 595 // This parsing matches CommandLineToArgvW()s for arguments, rather than the | |
| 596 // CRTs. These are different only in the most obscure of cases and will not | |
| 597 // matter in any practical situation. See the windowsinspired.com post above | |
| 598 // for details. | |
| 599 // | |
| 600 // TODO(scottmg): argv[0] normally has special handling. We should likely do | |
| 601 // that. | |
| 602 | |
| 603 enum class SpecialChars { | |
| 604 kInterpret, | |
| 605 kIgnore, | |
| 606 } state; | |
| 607 | |
| 608 std::vector<std::wstring> result; | |
| 609 std::wstring token; | |
| 610 | |
| 611 const wchar_t* p = command_line.c_str(); | |
| 612 // This loops the entire string, with a subloop for each argument. | |
| 613 for (;;) { | |
| 614 // Advance past leading whitespace (only space and tab are handled). | |
| 615 while (p[0] == L' ' || p[0] == L'\t') | |
|
Nico
2016/12/01 05:01:09
wcsspn()?
scottmg
2016/12/01 05:34:26
Done.
| |
| 616 ++p; | |
| 617 | |
| 618 // End of arguments. | |
| 619 if (p[0] == 0) { | |
| 620 if (!token.empty()) | |
| 621 result.push_back(token); | |
| 622 break; | |
| 623 } | |
| 624 | |
| 625 state = SpecialChars::kInterpret; | |
| 626 | |
| 627 // Scan an argument. | |
| 628 for (;;) { | |
| 629 // Count and advance past leading backslashes. | |
| 630 int num_backslashes = 0; | |
| 631 while (p[0] == L'\\') { | |
| 632 ++p; | |
| 633 ++num_backslashes; | |
| 634 } | |
| 635 | |
| 636 if (p[0] == L'"') { | |
| 637 for (int i = 1; i < num_backslashes; i += 2) | |
| 638 token += L'\\'; | |
| 639 | |
| 640 if (num_backslashes % 2 == 1) { | |
| 641 token += L'"'; | |
| 642 } else if (p[1] == L'"' && state == SpecialChars::kIgnore) { | |
| 643 ++p; | |
| 644 token += L'"'; | |
| 645 state = SpecialChars::kInterpret; | |
| 646 } else { | |
| 647 state = state == SpecialChars::kInterpret ? SpecialChars::kIgnore | |
| 648 : SpecialChars::kInterpret; | |
| 649 } | |
| 650 } else { | |
| 651 for (int i = 0; i < num_backslashes; ++i) | |
| 652 token += L'\\'; | |
| 653 if (p[0] == 0 || ((p[0] == L' ' || p[0] == '\t') && | |
|
Nico
2016/12/01 05:01:09
wstrstr(L" \t", p[0])
scottmg
2016/12/01 05:34:26
You mean wcschr right? Not sure if that's clearer
| |
| 654 state == SpecialChars::kInterpret)) { | |
| 655 result.push_back(token); | |
| 656 token.clear(); | |
| 657 break; | |
| 658 } else { | |
| 659 token += *p; | |
| 660 } | |
| 661 } | |
| 662 | |
| 663 ++p; | |
| 664 } | |
| 665 } | |
| 666 | |
| 667 return result; | |
| 668 } | |
| 669 | |
| 584 std::wstring GetSwitchValueFromCommandLine(const std::wstring& command_line, | 670 std::wstring GetSwitchValueFromCommandLine(const std::wstring& command_line, |
| 585 const std::wstring& switch_name) { | 671 const std::wstring& switch_name) { |
| 586 assert(!command_line.empty()); | 672 assert(!command_line.empty()); |
| 587 assert(!switch_name.empty()); | 673 assert(!switch_name.empty()); |
| 588 | 674 |
| 589 std::wstring command_line_copy = command_line; | 675 std::vector<std::wstring> as_array = TokenizeCommandLineToArray(command_line); |
| 590 // Remove leading and trailing spaces. | 676 std::wstring switch_with_equal = L"--" + switch_name + L"="; |
| 591 TrimT<std::wstring>(&command_line_copy); | 677 for (size_t i = 1; i < as_array.size(); ++i) { |
| 678 const std::wstring& arg = as_array[i]; | |
| 679 if (arg.compare(0, switch_with_equal.size(), switch_with_equal) == 0) { | |
| 680 return arg.substr(switch_with_equal.size()); | |
| 681 } | |
| 682 } | |
| 592 | 683 |
| 593 // Find the switch in the command line. If we don't find the switch, return | 684 return std::wstring(); |
| 594 // an empty string. | |
| 595 std::wstring switch_token = L"--"; | |
| 596 switch_token += switch_name; | |
| 597 switch_token += L"="; | |
| 598 size_t switch_offset = command_line_copy.find(switch_token); | |
| 599 if (switch_offset == std::string::npos) | |
| 600 return std::wstring(); | |
| 601 | |
| 602 // The format is "--<switch name>=blah". Look for a space after the | |
| 603 // "--<switch name>=" string. If we don't find a space assume that the switch | |
| 604 // value ends at the end of the command line. | |
| 605 size_t switch_value_start_offset = switch_offset + switch_token.length(); | |
| 606 if (std::wstring(kWhiteSpaces16).find( | |
| 607 command_line_copy[switch_value_start_offset]) != std::wstring::npos) { | |
| 608 switch_value_start_offset = command_line_copy.find_first_not_of( | |
| 609 GetWhiteSpacesForType<std::wstring>(), switch_value_start_offset); | |
| 610 if (switch_value_start_offset == std::wstring::npos) | |
| 611 return std::wstring(); | |
| 612 } | |
| 613 size_t switch_value_end_offset = | |
| 614 command_line_copy.find_first_of(GetWhiteSpacesForType<std::wstring>(), | |
| 615 switch_value_start_offset); | |
| 616 if (switch_value_end_offset == std::wstring::npos) | |
| 617 switch_value_end_offset = command_line_copy.length(); | |
| 618 | |
| 619 std::wstring switch_value = command_line_copy.substr( | |
| 620 switch_value_start_offset, | |
| 621 switch_value_end_offset - (switch_offset + switch_token.length())); | |
| 622 TrimT<std::wstring>(&switch_value); | |
| 623 return switch_value; | |
| 624 } | 685 } |
| 625 | 686 |
| 626 bool RecursiveDirectoryCreate(const std::wstring& full_path) { | 687 bool RecursiveDirectoryCreate(const std::wstring& full_path) { |
| 627 // If the path exists, we've succeeded if it's a directory, failed otherwise. | 688 // If the path exists, we've succeeded if it's a directory, failed otherwise. |
| 628 const wchar_t* full_path_str = full_path.c_str(); | 689 const wchar_t* full_path_str = full_path.c_str(); |
| 629 DWORD file_attributes = ::GetFileAttributes(full_path_str); | 690 DWORD file_attributes = ::GetFileAttributes(full_path_str); |
| 630 if (file_attributes != INVALID_FILE_ATTRIBUTES) { | 691 if (file_attributes != INVALID_FILE_ATTRIBUTES) { |
| 631 if ((file_attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { | 692 if ((file_attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { |
| 632 Trace(L"%hs( %ls directory exists )\n", __func__, full_path_str); | 693 Trace(L"%hs( %ls directory exists )\n", __func__, full_path_str); |
| 633 return true; | 694 return true; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 683 case ChannelStrategy::ADDITIONAL_PARAMETERS: | 744 case ChannelStrategy::ADDITIONAL_PARAMETERS: |
| 684 return ChannelFromAdditionalParameters(mode, system_level, multi_install); | 745 return ChannelFromAdditionalParameters(mode, system_level, multi_install); |
| 685 case ChannelStrategy::FIXED: | 746 case ChannelStrategy::FIXED: |
| 686 return mode.default_channel_name; | 747 return mode.default_channel_name; |
| 687 } | 748 } |
| 688 | 749 |
| 689 return std::wstring(); | 750 return std::wstring(); |
| 690 } | 751 } |
| 691 | 752 |
| 692 } // namespace install_static | 753 } // namespace install_static |
| OLD | NEW |