module Puppet::Util::Windows::Registry
Constants
- ERROR_NO_MORE_ITEMS
- KEY32
- KEY64
msdn.microsoft.com/en-us/library/windows/desktop/aa384129(v=vs.85).aspx
- KEY_ALL_ACCESS
- KEY_READ
- KEY_WRITE
- MAX_KEY_CHAR_LENGTH
max number of wide characters including NULL terminator
- MAX_VALUE_CHAR_LENGTH
max number of wide characters including NULL terminator
Public Instance Methods
# File lib/puppet/util/windows/registry.rb 59 def delete_key(key, subkey_name, mode = KEY64) 60 reg_delete_key_ex(key, subkey_name, mode) 61 end
# File lib/puppet/util/windows/registry.rb 107 def delete_value(key, subkey_name) 108 reg_delete_value(key, subkey_name) 109 end
subkey is String
which contains name of subkey. wtime is last write time as FILETIME (64-bit integer). (see Registry.wtime2time)
# File lib/puppet/util/windows/registry.rb 43 def each_key(key, &block) 44 index = 0 45 subkey = nil 46 47 subkey_max_len, _ = reg_query_info_key_max_lengths(key) 48 49 loop do 50 subkey, filetime = reg_enum_key(key, index, subkey_max_len) 51 yield subkey, filetime if !subkey.nil? 52 index += 1 53 break if subkey.nil? 54 end 55 56 index 57 end
# File lib/puppet/util/windows/registry.rb 91 def each_value(key, &block) 92 index = 0 93 subkey = nil 94 95 _, value_max_len = reg_query_info_key_max_lengths(key) 96 97 loop do 98 subkey, type, data = reg_enum_value(key, index, value_max_len) 99 yield subkey, type, data if !subkey.nil? 100 index += 1 101 break if subkey.nil? 102 end 103 104 index 105 end
# File lib/puppet/util/windows/registry.rb 35 def keys(key) 36 keys = {} 37 each_key(key) { |subkey, filetime| keys[subkey] = filetime } 38 keys 39 end
# File lib/puppet/util/windows/registry.rb 24 def open(name, path, mode = KEY_READ | KEY64, &block) 25 hkey = root(name) 26 begin 27 hkey.open(path, mode) do |subkey| 28 return yield subkey 29 end 30 rescue Win32::Registry::Error => error 31 raise Puppet::Util::Windows::Error.new(_("Failed to open registry key '%{key}\\%{path}'") % { key: hkey.keyname, path: path }, error.code, error) 32 end 33 end
# File lib/puppet/util/windows/registry.rb 18 def root(name) 19 Win32::Registry.const_get(name) 20 rescue NameError 21 raise Puppet::Error, _("Invalid registry key '%{name}'") % { name: name }, $!.backtrace 22 end
# File lib/puppet/util/windows/registry.rb 63 def values(key) 64 vals = {} 65 each_value(key) { |subkey, type, data| vals[subkey] = data } 66 vals 67 end
Retrieve a set of values from a registry key given their names Value names listed but not found in the registry will not be added to the resultant Hashtable
@param key [RegistryKey] An open handle to a Registry
Key @param names [String An array of names of registry values to return if they exist @return [Hashtable<String, Object>] A hashtable of all of the found values in the registry key
# File lib/puppet/util/windows/registry.rb 76 def values_by_name(key, names) 77 vals = {} 78 names.each do |name| 79 FFI::Pointer.from_string_to_wide_string(name) do |subkeyname_ptr| 80 begin 81 _, vals[name] = read(key, subkeyname_ptr) 82 rescue Puppet::Util::Windows::Error => e 83 # ignore missing names, but raise other errors 84 raise e unless e.code == Puppet::Util::Windows::Error::ERROR_FILE_NOT_FOUND 85 end 86 end 87 end 88 vals 89 end
Private Instance Methods
# File lib/puppet/util/windows/registry.rb 267 def query_value_ex(key, name_ptr, &block) 268 FFI::MemoryPointer.new(:dword) do |type_ptr| 269 FFI::MemoryPointer.new(:dword) do |length_ptr| 270 result = RegQueryValueExW(key.hkey, name_ptr, 271 FFI::Pointer::NULL, type_ptr, 272 FFI::Pointer::NULL, length_ptr) 273 274 FFI::MemoryPointer.new(:byte, length_ptr.read_dword) do |buffer_ptr| 275 result = RegQueryValueExW(key.hkey, name_ptr, 276 FFI::Pointer::NULL, type_ptr, 277 buffer_ptr, length_ptr) 278 279 if result != FFI::ERROR_SUCCESS 280 # buffer is raw bytes, *not* chars - less a NULL terminator 281 name_length = (name_ptr.size / FFI.type_size(:wchar)) - 1 if name_ptr.size > 0 282 msg = _("Failed to read registry value %{value} at %{key}") % { value: name_ptr.read_wide_string(name_length), key: key.keyname } 283 raise Puppet::Util::Windows::Error.new(msg, result) 284 end 285 286 # allows caller to use FFI MemoryPointer helpers to read / shape 287 yield [type_ptr.read_dword, buffer_ptr, length_ptr.read_dword] 288 end 289 end 290 end 291 end
Read a registry value named name and return array of [ type, data ]. When name is nil, the `default' value is read. type is value type. (see Win32::Registry::Constants module) data is value data, its class is: :REG_SZ, REG_EXPAND_SZ
String
:REG_MULTI_SZ
Array of String
:REG_DWORD, REG_DWORD_BIG_ENDIAN, REG_QWORD
Integer
:REG_BINARY
String (contains binary data)
When rtype is specified, the value type must be included by rtype array, or TypeError is raised.
# File lib/puppet/util/windows/registry.rb 228 def read(key, name_ptr, *rtype) 229 result = nil 230 231 query_value_ex(key, name_ptr) do |type, data_ptr, byte_length| 232 unless rtype.empty? or rtype.include?(type) 233 raise TypeError, _("Type mismatch (expect %{rtype} but %{type} present)") % { rtype: rtype.inspect, type: type } 234 end 235 236 string_length = 0 237 # buffer is raw bytes, *not* chars - less a NULL terminator 238 string_length = (byte_length / FFI.type_size(:wchar)) - 1 if byte_length > 0 239 240 begin 241 case type 242 when Win32::Registry::REG_SZ, Win32::Registry::REG_EXPAND_SZ 243 result = [ type, data_ptr.read_wide_string(string_length, Encoding::UTF_8, true) ] 244 when Win32::Registry::REG_MULTI_SZ 245 result = [ type, data_ptr.read_wide_string(string_length).split(/\0/) ] 246 when Win32::Registry::REG_BINARY 247 result = [ type, data_ptr.read_bytes(byte_length) ] 248 when Win32::Registry::REG_DWORD 249 result = [ type, data_ptr.read_dword ] 250 when Win32::Registry::REG_DWORD_BIG_ENDIAN 251 result = [ type, data_ptr.order(:big).read_dword ] 252 when Win32::Registry::REG_QWORD 253 result = [ type, data_ptr.read_qword ] 254 else 255 raise TypeError, _("Type %{type} is not supported.") % { type: type } 256 end 257 rescue IndexError => ex 258 raise if (ex.message !~ /^Memory access .* is out of bounds$/i) 259 parent_key_name = key.parent ? "#{key.parent.keyname}\\" : "" 260 Puppet.warning _("A value in the registry key %{parent_key_name}%{key} is corrupt or invalid") % { parent_key_name: parent_key_name, key: key.keyname } 261 end 262 end 263 264 result 265 end
# File lib/puppet/util/windows/registry.rb 308 def reg_delete_key_ex(key, name, regsam = KEY64) 309 result = 0 310 311 FFI::Pointer.from_string_to_wide_string(name) do |name_ptr| 312 result = RegDeleteKeyExW(key.hkey, name_ptr, regsam, 0) 313 314 if result != FFI::ERROR_SUCCESS 315 msg = _("Failed to delete registry key %{name} at %{key}") % { name: name, key: key.keyname } 316 raise Puppet::Util::Windows::Error.new(msg, result) 317 end 318 end 319 320 result 321 end
# File lib/puppet/util/windows/registry.rb 293 def reg_delete_value(key, name) 294 result = 0 295 296 FFI::Pointer.from_string_to_wide_string(name) do |name_ptr| 297 result = RegDeleteValueW(key.hkey, name_ptr) 298 299 if result != FFI::ERROR_SUCCESS 300 msg = _("Failed to delete registry value %{name} at %{key}") % { name: name, key: key.keyname } 301 raise Puppet::Util::Windows::Error.new(msg, result) 302 end 303 end 304 305 result 306 end
# File lib/puppet/util/windows/registry.rb 116 def reg_enum_key(key, index, max_key_char_length = MAX_KEY_CHAR_LENGTH) 117 subkey, filetime = nil, nil 118 119 FFI::MemoryPointer.new(:dword) do |subkey_length_ptr| 120 FFI::MemoryPointer.new(FFI::WIN32::FILETIME.size) do |filetime_ptr| 121 FFI::MemoryPointer.new(:wchar, max_key_char_length) do |subkey_ptr| 122 subkey_length_ptr.write_dword(max_key_char_length) 123 124 # RegEnumKeyEx cannot be called twice to properly size the buffer 125 result = RegEnumKeyExW(key.hkey, index, 126 subkey_ptr, subkey_length_ptr, 127 FFI::Pointer::NULL, FFI::Pointer::NULL, 128 FFI::Pointer::NULL, filetime_ptr) 129 130 break if result == ERROR_NO_MORE_ITEMS 131 132 if result != FFI::ERROR_SUCCESS 133 msg = _("Failed to enumerate %{key} registry keys at index %{index}") % { key: key.keyname, index: index } 134 raise Puppet::Util::Windows::Error.new(msg, result) 135 end 136 137 filetime = FFI::WIN32::FILETIME.new(filetime_ptr) 138 subkey_length = subkey_length_ptr.read_dword 139 subkey = subkey_ptr.read_wide_string(subkey_length) 140 end 141 end 142 end 143 144 [subkey, filetime] 145 end
# File lib/puppet/util/windows/registry.rb 150 def reg_enum_value(key, index, max_value_length = MAX_VALUE_CHAR_LENGTH) 151 subkey, type, data = nil, nil, nil 152 153 FFI::MemoryPointer.new(:dword) do |subkey_length_ptr| 154 FFI::MemoryPointer.new(:wchar, max_value_length) do |subkey_ptr| 155 # RegEnumValueW cannot be called twice to properly size the buffer 156 subkey_length_ptr.write_dword(max_value_length) 157 158 result = RegEnumValueW(key.hkey, index, 159 subkey_ptr, subkey_length_ptr, 160 FFI::Pointer::NULL, FFI::Pointer::NULL, 161 FFI::Pointer::NULL, FFI::Pointer::NULL 162 ) 163 164 break if result == ERROR_NO_MORE_ITEMS 165 166 if result != FFI::ERROR_SUCCESS 167 msg = _("Failed to enumerate %{key} registry values at index %{index}") % { key: key.keyname, index: index } 168 raise Puppet::Util::Windows::Error.new(msg, result) 169 end 170 171 subkey_length = subkey_length_ptr.read_dword 172 subkey = subkey_ptr.read_wide_string(subkey_length) 173 174 type, data = read(key, subkey_ptr) 175 end 176 end 177 178 [subkey, type, data] 179 end
# File lib/puppet/util/windows/registry.rb 181 def reg_query_info_key_max_lengths(key) 182 result = nil 183 184 FFI::MemoryPointer.new(:dword) do |max_subkey_name_length_ptr| 185 FFI::MemoryPointer.new(:dword) do |max_value_name_length_ptr| 186 187 status = RegQueryInfoKeyW(key.hkey, 188 FFI::MemoryPointer::NULL, FFI::MemoryPointer::NULL, 189 FFI::MemoryPointer::NULL, FFI::MemoryPointer::NULL, 190 max_subkey_name_length_ptr, FFI::MemoryPointer::NULL, 191 FFI::MemoryPointer::NULL, max_value_name_length_ptr, 192 FFI::MemoryPointer::NULL, FFI::MemoryPointer::NULL, 193 FFI::MemoryPointer::NULL 194 ) 195 196 if status != FFI::ERROR_SUCCESS 197 msg = _("Failed to query registry %{key} for sizes") % { key: key.keyname } 198 raise Puppet::Util::Windows::Error.new(msg, status) 199 end 200 201 result = [ 202 # Unicode characters *not* including trailing NULL 203 max_subkey_name_length_ptr.read_dword + 1, 204 max_value_name_length_ptr.read_dword + 1, 205 ] 206 end 207 end 208 209 result 210 end