1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
#
# Author:: Seth Chisamore (<schisamo@chef.io>)
# Author:: Matt Wrock <matt@mattwrock.com>
# Copyright:: Copyright 2011-2016, Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require "win32/registry" if RUBY_PLATFORM =~ /mswin|mingw32|windows/
class Chef
class Provider
class Package
class Windows
class RegistryUninstallEntry
def self.find_entries(package_name)
logger.trace("Finding uninstall entries for #{package_name}")
entries = []
[
[::Win32::Registry::HKEY_LOCAL_MACHINE, (::Win32::Registry::Constants::KEY_READ | 0x0100)],
[::Win32::Registry::HKEY_LOCAL_MACHINE, (::Win32::Registry::Constants::KEY_READ | 0x0200)],
[::Win32::Registry::HKEY_CURRENT_USER],
].each do |hkey|
desired = hkey.length > 1 ? hkey[1] : ::Win32::Registry::Constants::KEY_READ
begin
::Win32::Registry.open(hkey[0], UNINSTALL_SUBKEY, desired) do |reg|
reg.each_key do |key, _wtime|
begin
entry = reg.open(key, desired)
display_name = read_registry_property(entry, "DisplayName")
if display_name.to_s.rstrip == package_name
quiet_uninstall_string = RegistryUninstallEntry.read_registry_property(entry, "QuietUninstallString")
entries.push(quiet_uninstall_string_key?(quiet_uninstall_string, hkey, key, entry))
end
rescue ::Win32::Registry::Error => ex
logger.trace("Registry error opening key '#{key}' on node #{desired}: #{ex}")
end
end
end
rescue ::Win32::Registry::Error => ex
logger.trace("Registry error opening hive '#{hkey[0]}' :: #{desired}: #{ex}")
end
end
entries
end
def self.quiet_uninstall_string_key?(quiet_uninstall_string, hkey, key, entry)
return RegistryUninstallEntry.new(hkey, key, entry) if quiet_uninstall_string.nil?
RegistryUninstallEntry.new(hkey, key, entry, "QuietUninstallString")
end
def self.read_registry_property(data, property)
data[property]
rescue ::Win32::Registry::Error
logger.trace("Failure to read property '#{property}'")
nil
end
def self.logger
Chef::Log
end
def initialize(hive, key, registry_data, uninstall_key = "UninstallString")
@logger = Chef::Log.with_child({ subsystem: "registry_uninstall_entry" })
logger.trace("Creating uninstall entry for #{hive}::#{key}")
@hive = hive
@key = key
@data = registry_data
@display_name = RegistryUninstallEntry.read_registry_property(registry_data, "DisplayName")
@display_version = RegistryUninstallEntry.read_registry_property(registry_data, "DisplayVersion")
@uninstall_string = RegistryUninstallEntry.read_registry_property(registry_data, uninstall_key)
end
attr_reader :hive
attr_reader :key
attr_reader :display_name
attr_reader :display_version
attr_reader :uninstall_string
attr_reader :data
attr_reader :logger
UNINSTALL_SUBKEY = 'Software\Microsoft\Windows\CurrentVersion\Uninstall'.freeze
end
end
end
end
end
|