15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2010 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <shlwapi.h> 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "base/files/file_path.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/registry.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/create_reg_key_work_item.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/install_util.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/logging_installer.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::win::RegKey; 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO: refactor this because it is only used once. 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UpOneDirectoryOrEmpty(std::wstring* dir) { 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath path = base::FilePath::FromWStringHack(*dir); 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath directory = path.DirName(); 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there is no separator, we will get back kCurrentDirectory. 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In this case, clear dir. 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (directory == path || directory.value() == 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath::kCurrentDirectory) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dir->clear(); 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *dir = directory.value(); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CreateRegKeyWorkItem::~CreateRegKeyWorkItem() { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CreateRegKeyWorkItem::CreateRegKeyWorkItem(HKEY predefined_root, 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring& path) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : predefined_root_(predefined_root), 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path_(path), 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_created_(false) { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CreateRegKeyWorkItem::Do() { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!InitKeyList()) { 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Nothing needs to be done here. 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "no key to create"; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RegKey key; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring key_path; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // To create keys, we iterate from back to front. 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = key_list_.size(); i > 0; i--) { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD disposition; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_path.assign(key_list_[i - 1]); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (key.CreateWithDisposition(predefined_root_, key_path.c_str(), 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &disposition, KEY_READ) == ERROR_SUCCESS) { 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (disposition == REG_OPENED_EXISTING_KEY) { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (key_created_) { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This should not happen. Someone created a subkey under the key 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we just created? 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << key_path << " exists, this is not expected."; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove the key path from list if it is already present. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_list_.pop_back(); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (disposition == REG_CREATED_NEW_KEY) { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "created " << key_path; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_created_ = true; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "unkown disposition"; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to create " << key_path; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CreateRegKeyWorkItem::Rollback() { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!key_created_) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring key_path; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // To delete keys, we iterate from front to back. 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::wstring>::iterator itr; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (itr = key_list_.begin(); itr != key_list_.end(); ++itr) { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_path.assign(*itr); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SHDeleteEmptyKey(predefined_root_, key_path.c_str()) == 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ERROR_SUCCESS) { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "rollback: delete " << key_path; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "rollback: can not delete " << key_path; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The key might have been deleted, but we don't reliably know what 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // error code(s) are returned in this case. So we just keep tring delete 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the rest. 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_created_ = false; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_list_.clear(); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CreateRegKeyWorkItem::InitKeyList() { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (path_.empty()) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring key_path(path_); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_list_.push_back(key_path); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is pure string operation so it does not matter whether the 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // path is file path or registry path. 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpOneDirectoryOrEmpty(&key_path); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (!key_path.empty()); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 125