| OLD | NEW |
| (Empty) | |
| 1 # Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. |
| 4 |
| 5 import _winreg |
| 6 |
| 7 import visitor |
| 8 |
| 9 class RegistryVisitor(visitor.Visitor): |
| 10 """ Visitor for registry entry in property. |
| 11 """ |
| 12 def _VisitEntry(self, entry_name, entry_value): |
| 13 """ Visit one registry entry's key and values. Values are not checked if |
| 14 the key is not present in the registry. |
| 15 |
| 16 Args: |
| 17 entry_name: A string represents regsitry name in the property. |
| 18 entry_value: A dictionary represents the following keys and values: |
| 19 'exists' - a string indicating whether the registry key's existence |
| 20 is 'required', 'optional', or 'forbidden'. |
| 21 'values' - (optional) a dictionary where each key is a registry |
| 22 value and its associated value is a dictionary with the |
| 23 following key and values: |
| 24 |
| 25 'type' - (optional) a string indicating the type of the |
| 26 registry value. If not present, the corresponding |
| 27 value is expected to be absent in the registry. |
| 28 'data' - the associated data of the registry value if |
| 29 'type' is specified. If it is a string, it is |
| 30 expanded using Expand. |
| 31 """ |
| 32 key = self._variable_expander.Expand(entry_name) |
| 33 root_key, sub_key = key.split('\\', 1) |
| 34 root_key_value = self._RootKeyConstant(root_key) |
| 35 should_key_exist = entry_value['exists'] |
| 36 try: |
| 37 # Query the Windows registry for the registry key. It will throw a |
| 38 # WindowsError if the key doesn't exist. |
| 39 key_handle = _winreg.OpenKey(root_key_value, sub_key, 0, |
| 40 _winreg.KEY_QUERY_VALUE) |
| 41 except WindowsError: |
| 42 # Key doesn't exist. See that it matches the expectation. |
| 43 # Values are not checked if the missing key's existence is optional. |
| 44 return self._HandleRegistryKey(root_key_value, sub_key, False, |
| 45 should_key_exist, key) |
| 46 # The key exists, see that it matches the expectation. |
| 47 self._HandleRegistryKey(root_key_value, sub_key, True, should_key_exist, |
| 48 key) |
| 49 |
| 50 # Verify the expected values. |
| 51 if 'values' not in entry_value: |
| 52 return |
| 53 for value, value_expectation in entry_value['values'].iteritems(): |
| 54 # Query the value. It will throw a WindowsError if the value doesn't |
| 55 # exist. |
| 56 value_data = None |
| 57 value_type = None |
| 58 expected_data = value_expectation.get('data', None) |
| 59 if isinstance(expected_data, basestring): |
| 60 expected_data = self._variable_expander.Expand(expected_data) |
| 61 expected_type = self._ValueTypeConstant( |
| 62 value_expectation.get('type', None)) |
| 63 try: |
| 64 value_data, value_type = _winreg.QueryValueEx(key_handle, value) |
| 65 except WindowsError: |
| 66 pass |
| 67 |
| 68 self._HandleRegistryValue(value_data, value_type, expected_data, |
| 69 expected_type, key, value) |
| 70 |
| 71 |
| 72 |
| 73 def _HandleRegistryKey(self, root, key_path, is_key_exists, should_key_exist, |
| 74 key): |
| 75 """ Abstract function to check a regsitry key. |
| 76 |
| 77 Args: |
| 78 root: An integer represnets HKEY_* constant. |
| 79 key_path: A string represents the path of key. |
| 80 is_key_exists: A boolean represnets whether the key exists or not. |
| 81 should_key_exist: a string represents whether the registry key's |
| 82 existence is 'required', 'optional', or 'forbidden'. |
| 83 key: A string represents the whole name of the key. |
| 84 """ |
| 85 raise NotImplementedError() |
| 86 |
| 87 def _HandleRegistryValue(self, value_data, value_type, expected_data, |
| 88 expected_type, key, value): |
| 89 """ Abstract function to check one value of the registry key. |
| 90 |
| 91 Args: |
| 92 value_data: A instance represents the data of the registry value. |
| 93 value_type: A _winreg const represents the type of the registry value. |
| 94 expected_data: A instance represents the data of expected registry |
| 95 value. |
| 96 expected_type: A _winreg const represents the type of expected |
| 97 registry value. |
| 98 key: A string represents the whole name of the key. |
| 99 value: A string represents the name of the value. |
| 100 """ |
| 101 raise NotImplementedError() |
| 102 |
| 103 def _RootKeyConstant(self, root_key): |
| 104 """Converts a root registry key string into a _winreg.HKEY_* constant.""" |
| 105 root_key_mapping = { |
| 106 'HKEY_CLASSES_ROOT': _winreg.HKEY_CLASSES_ROOT, |
| 107 'HKEY_CURRENT_USER': _winreg.HKEY_CURRENT_USER, |
| 108 'HKEY_LOCAL_MACHINE': _winreg.HKEY_LOCAL_MACHINE, |
| 109 'HKEY_USERS': _winreg.HKEY_USERS, |
| 110 } |
| 111 if root_key not in root_key_mapping: |
| 112 raise KeyError("Unknown root registry key '%s'" % root_key) |
| 113 return root_key_mapping[root_key] |
| 114 |
| 115 def _ValueTypeConstant(self, value_type): |
| 116 """Converts a registry value type string into a _winreg.REG_* constant.""" |
| 117 if value_type is None: |
| 118 return None |
| 119 value_type_mapping = { |
| 120 'BINARY': _winreg.REG_BINARY, |
| 121 'DWORD': _winreg.REG_DWORD, |
| 122 'DWORD_LITTLE_ENDIAN': _winreg.REG_DWORD_LITTLE_ENDIAN, |
| 123 'DWORD_BIG_ENDIAN': _winreg.REG_DWORD_BIG_ENDIAN, |
| 124 'EXPAND_SZ': _winreg.REG_EXPAND_SZ, |
| 125 'LINK': _winreg.REG_LINK, |
| 126 'MULTI_SZ': _winreg.REG_MULTI_SZ, |
| 127 'NONE': _winreg.REG_NONE, |
| 128 'SZ': _winreg.REG_SZ, |
| 129 } |
| 130 if value_type not in value_type_mapping: |
| 131 raise KeyError("Unknown registry value type '%s'" % value_type) |
| 132 return value_type_mapping[value_type] |
| 133 |
| 134 class RegistryVerifier(RegistryVisitor): |
| 135 """Verifies that the current registry matches the specified criteria.""" |
| 136 |
| 137 def _HandleRegistryKey(self, root, key_path, is_key_exists, should_key_exist, |
| 138 key): |
| 139 """ Overridden RegistryVisitor._HandleRegistryKey to verify a registry key |
| 140 according to the expected key. |
| 141 """ |
| 142 if should_key_exist == 'forbidden': |
| 143 assert not is_key_exists, 'Registry key %s exists' % key |
| 144 elif should_key_exist == 'required': |
| 145 assert is_key_exists, 'Registry key %s is missing' % key |
| 146 |
| 147 def _HandleRegistryValue(self, value_data, value_type, expected_data, |
| 148 expected_type, key, value): |
| 149 """ Overridden RegistryVisitor._HandleRegistryValue to verify a registry |
| 150 value according to the expected value. |
| 151 """ |
| 152 error_message = "" |
| 153 if expected_type == None: |
| 154 error_message = ('Value %s of registry key %s exists ' |
| 155 'with value %s') % (value, key, value_data) |
| 156 elif value_type == None: |
| 157 error_message = 'Value %s of registry key %s is missing' % (value, key) |
| 158 else: |
| 159 error_message = 'Value %s of registry key %s has unexpected type %s' % ( |
| 160 value, key, expected_type) |
| 161 assert expected_type == value_type, error_message |
| 162 assert expected_data == value_data, ( |
| 163 'Value %s of registry key %s has unexpected data.\n' |
| 164 ' Expected: %s\n' |
| 165 ' Actual: %s') % (value, key, expected_data, value_data) |
| 166 |
| 167 class RegistryCleaner(RegistryVisitor): |
| 168 """ Reset the currect registry to match the expectation. |
| 169 """ |
| 170 def _HandleRegistryKey(self, root, key_path, is_key_exists, should_key_exist, |
| 171 key): |
| 172 """ Overridden RegistryVisitor._HandleRegistryKey to delete a registry key |
| 173 if necessary. |
| 174 """ |
| 175 if is_key_exists and should_key_exist == 'forbidden': |
| 176 try: |
| 177 self._DeleteRegKey(root, key_path) |
| 178 except WindowsError: |
| 179 # Suppress any delete error |
| 180 pass |
| 181 |
| 182 def _HandleRegistryValue(self, value_data, value_type, expected_data, |
| 183 expected_type, key, value): |
| 184 """ Overridden RegistryVisitor._HandleRegistryValue.""" |
| 185 pass |
| 186 |
| 187 def _DeleteRegKey(self, root, key_path): |
| 188 """ Delete a registry key recursively. |
| 189 |
| 190 Args: |
| 191 root: An integer represents HKEY_ constant. |
| 192 key_path: A string represents the path of key that needs to be |
| 193 deleted. |
| 194 """ |
| 195 with _winreg.OpenKey(root, key_path, 0, _winreg.KEY_SET_VALUE | |
| 196 _winreg.KEY_READ | |
| 197 _winreg.KEY_WOW64_32KEY) as key: |
| 198 num_of_sub_keys, _, _ = _winreg.QueryInfoKey(key) |
| 199 for i in range(0, num_of_sub_keys): |
| 200 self._DeleteRegKey(root, key_path + "\\" + _winreg.EnumKey(key, i)) |
| 201 _winreg.DeleteKey(root, key_path) |
| OLD | NEW |