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

Side by Side Diff: chrome/installer/setup/setup_util.cc

Issue 1327793004: Delete Chrome state in registry on uninstall when the user profile is being deleted. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 3 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
« no previous file with comments | « chrome/installer/setup/setup_util.h ('k') | chrome/installer/setup/setup_util_unittest.cc » ('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) 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 // This file declares util functions for setup project. 5 // This file declares util functions for setup project.
6 6
7 #include "chrome/installer/setup/setup_util.h" 7 #include "chrome/installer/setup/setup_util.h"
8 8
9 #include <windows.h> 9 #include <windows.h>
10 10
11 #include <algorithm>
12 #include <iterator>
13 #include <set>
14
11 #include "base/command_line.h" 15 #include "base/command_line.h"
12 #include "base/cpu.h" 16 #include "base/cpu.h"
13 #include "base/files/file_enumerator.h" 17 #include "base/files/file_enumerator.h"
14 #include "base/files/file_path.h" 18 #include "base/files/file_path.h"
15 #include "base/files/file_util.h" 19 #include "base/files/file_util.h"
16 #include "base/logging.h" 20 #include "base/logging.h"
21 #include "base/numerics/safe_conversions.h"
17 #include "base/process/kill.h" 22 #include "base/process/kill.h"
18 #include "base/process/launch.h" 23 #include "base/process/launch.h"
19 #include "base/process/process_handle.h" 24 #include "base/process/process_handle.h"
20 #include "base/strings/string_util.h" 25 #include "base/strings/string_util.h"
21 #include "base/strings/utf_string_conversions.h" 26 #include "base/strings/utf_string_conversions.h"
22 #include "base/version.h" 27 #include "base/version.h"
23 #include "base/win/registry.h" 28 #include "base/win/registry.h"
24 #include "base/win/windows_version.h" 29 #include "base/win/windows_version.h"
25 #include "chrome/installer/setup/setup_constants.h" 30 #include "chrome/installer/setup/setup_constants.h"
26 #include "chrome/installer/util/app_registration_data.h" 31 #include "chrome/installer/util/app_registration_data.h"
(...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 const AppRegistrationData& reg_data, 476 const AppRegistrationData& reg_data,
472 const wchar_t* name) { 477 const wchar_t* name) {
473 base::string16 cmd_key(reg_data.GetVersionKey()); 478 base::string16 cmd_key(reg_data.GetVersionKey());
474 cmd_key.append(1, base::FilePath::kSeparators[0]) 479 cmd_key.append(1, base::FilePath::kSeparators[0])
475 .append(google_update::kRegCommandsKey) 480 .append(google_update::kRegCommandsKey)
476 .append(1, base::FilePath::kSeparators[0]) 481 .append(1, base::FilePath::kSeparators[0])
477 .append(name); 482 .append(name);
478 return cmd_key; 483 return cmd_key;
479 } 484 }
480 485
486 void DeleteRegistryKeyPartial(
487 HKEY root,
488 const base::string16& path,
489 const std::vector<base::string16>& keys_to_preserve) {
490 // Downcase the list of keys to preserve (all must be ASCII strings).
491 std::set<base::string16> lowered_keys_to_preserve;
492 std::transform(
493 keys_to_preserve.begin(), keys_to_preserve.end(),
494 std::inserter(lowered_keys_to_preserve, lowered_keys_to_preserve.begin()),
495 [](const base::string16& str) {
496 DCHECK(!str.empty());
497 DCHECK(base::IsStringASCII(str));
498 return base::ToLowerASCII(str);
499 });
500 base::win::RegKey key;
501 LONG result = key.Open(root, path.c_str(), (KEY_ENUMERATE_SUB_KEYS |
502 KEY_QUERY_VALUE | KEY_SET_VALUE));
503 if (result != ERROR_SUCCESS) {
504 LOG_IF(ERROR, result != ERROR_FILE_NOT_FOUND) << "Failed to open " << path
505 << "; result = " << result;
506 return;
507 }
508
509 // Repeatedly iterate over all subkeys deleting those that should not be
510 // preserved until only those remain. Multiple passes are needed since
511 // deleting one key may change the enumeration order of all remaining keys.
512
513 // Subkeys or values to be skipped on subsequent passes.
514 std::set<base::string16> to_skip;
515 DWORD index = 0;
516 const size_t kMaxKeyNameLength = 256; // MSDN says 255; +1 for terminator.
517 base::string16 name(kMaxKeyNameLength, base::char16());
518 bool did_delete = false; // True if at least one item was deleted.
519 while (true) {
520 DWORD name_length = base::saturated_cast<DWORD>(name.capacity());
521 name.resize(name_length);
522 result = ::RegEnumKeyEx(key.Handle(), index, &name[0], &name_length,
523 nullptr, nullptr, nullptr, nullptr);
robertshield 2015/09/03 20:23:33 This may work, but the thing that gives me pause i
grt (UTC plus 2) 2015/09/04 02:22:47 That sentence is saying "hey, the enumeration orde
524 if (result == ERROR_MORE_DATA) {
525 // Unexpected, but perhaps the max key name length was raised. MSDN
526 // doesn't clearly say that name_length will contain the necessary
527 // length in this case, so double the buffer and try again.
528 name.reserve(name.capacity() * 2);
529 continue;
530 }
531 if (result == ERROR_NO_MORE_ITEMS) {
532 if (!did_delete)
533 break; // All subkeys were deleted. The job is done.
534 // Otherwise, loop again.
535 did_delete = false;
536 index = 0;
537 continue;
538 }
539 if (result != ERROR_SUCCESS)
540 break;
541 // Shrink the string to the actual length of the name.
542 name.resize(name_length);
543
544 // Skip over this key if it couldn't be deleted on a previous iteration.
545 if (to_skip.count(name)) {
546 ++index;
547 continue;
548 }
549
550 // Skip over this key if it is one of the keys to preserve.
551 if (base::IsStringASCII(name) &&
552 lowered_keys_to_preserve.count(base::ToLowerASCII(name))) {
553 // Add the true name of the key to the list of keys to skip for subsequent
554 // iterations.
555 to_skip.insert(name);
556 ++index;
557 continue;
558 }
559
560 // Delete this key.
561 result = key.DeleteKey(name.c_str());
562 if (result != ERROR_SUCCESS) {
563 LOG(ERROR) << "Failed to delete subkey " << name << " under path "
564 << path;
565 // Skip over this key on subsequent iterations.
566 to_skip.insert(name);
robertshield 2015/09/03 20:23:33 Hrmm, needing to preserve a list of items to skip
567 ++index;
568 continue;
569 }
570 did_delete = true;
571 }
572
573 // Delete the key if it no longer has any subkeys.
574 if (to_skip.empty()) {
robertshield 2015/09/03 20:23:34 doesn't DeleteEmptyKey already check whether the k
grt (UTC plus 2) 2015/09/04 02:22:48 Yes, though there's no need to call it if you know
575 result = key.DeleteEmptyKey(L"");
576 LOG_IF(ERROR, result != ERROR_SUCCESS) << "Failed to delete empty key "
577 << path << "; result: " << result;
578 return;
579 }
580
581 // Delete all values since subkeys are being preserved.
582 to_skip.clear();
583 did_delete = false;
584 index = 0;
585 while (true) {
586 DWORD name_length = base::saturated_cast<int16_t>(name.capacity());
587 name.resize(name_length);
588 result = ::RegEnumValue(key.Handle(), index, &name[0], &name_length,
589 nullptr, nullptr, nullptr, nullptr);
590 if (result == ERROR_MORE_DATA) {
591 if (name_length <
592 static_cast<DWORD>(std::numeric_limits<int16_t>::max())) {
593 // Double the space to hold the value name and try again.
594 name.reserve(name.capacity() * 2);
595 continue;
596 }
597 // Otherwise, the max has been exceeded. Nothing more to be done.
598 break;
599 }
600 if (result == ERROR_NO_MORE_ITEMS) {
601 if (!did_delete)
602 break; // All values were deleted. The job is done.
603 // Otherwise, loop again.
604 did_delete = false;
605 index = 0;
606 continue;
607 }
608 if (result != ERROR_SUCCESS)
609 break;
610 // Shrink the string to the actual length of the name.
611 name.resize(name_length);
612
613 // Skip over this value if it couldn't be deleted on a previous iteration.
614 if (to_skip.count(name)) {
615 ++index;
616 continue;
617 }
618
619 // Delete this value.
620 result = key.DeleteValue(name.c_str());
621 if (result != ERROR_SUCCESS) {
622 LOG(ERROR) << "Failed to delete value " << name << " in key " << path;
623 // Skip over this value on subsequent iterations.
624 to_skip.insert(name);
625 ++index;
626 continue;
627 }
628 did_delete = true;
629 }
630 }
631
481 ScopedTokenPrivilege::ScopedTokenPrivilege(const wchar_t* privilege_name) 632 ScopedTokenPrivilege::ScopedTokenPrivilege(const wchar_t* privilege_name)
482 : is_enabled_(false) { 633 : is_enabled_(false) {
483 HANDLE temp_handle; 634 HANDLE temp_handle;
484 if (!::OpenProcessToken(::GetCurrentProcess(), 635 if (!::OpenProcessToken(::GetCurrentProcess(),
485 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, 636 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
486 &temp_handle)) { 637 &temp_handle)) {
487 return; 638 return;
488 } 639 }
489 token_.Set(temp_handle); 640 token_.Set(temp_handle);
490 641
(...skipping 22 matching lines...) Expand all
513 } 664 }
514 665
515 ScopedTokenPrivilege::~ScopedTokenPrivilege() { 666 ScopedTokenPrivilege::~ScopedTokenPrivilege() {
516 if (is_enabled_ && previous_privileges_.PrivilegeCount != 0) { 667 if (is_enabled_ && previous_privileges_.PrivilegeCount != 0) {
517 ::AdjustTokenPrivileges(token_.Get(), FALSE, &previous_privileges_, 668 ::AdjustTokenPrivileges(token_.Get(), FALSE, &previous_privileges_,
518 sizeof(TOKEN_PRIVILEGES), NULL, NULL); 669 sizeof(TOKEN_PRIVILEGES), NULL, NULL);
519 } 670 }
520 } 671 }
521 672
522 } // namespace installer 673 } // namespace installer
OLDNEW
« no previous file with comments | « chrome/installer/setup/setup_util.h ('k') | chrome/installer/setup/setup_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698