diff options
author | jtimberman <joshua@opscode.com> | 2011-12-23 14:38:28 -0700 |
---|---|---|
committer | jtimberman <joshua@opscode.com> | 2011-12-23 14:38:28 -0700 |
commit | 25744c4fe66f916118797f22384402f1f85fa8e5 (patch) | |
tree | dac3dc82d08b16bea159b72c9ec05061f56bdabd /libraries | |
parent | e8873add2751a3de8a92eec5e0d3f99db8dfc727 (diff) | |
download | mixlib-shellout-25744c4fe66f916118797f22384402f1f85fa8e5.tar.gz |
COOK-939, COOK-940 - type parameter and fix return logic
* Add a type parameter to windows_registry to support binary keys
* Rearrange return logic so multiple values can be written
Diffstat (limited to 'libraries')
-rw-r--r-- | libraries/registry_helper.rb | 682 |
1 files changed, 343 insertions, 339 deletions
diff --git a/libraries/registry_helper.rb b/libraries/registry_helper.rb index 27304fa..5a903cc 100644 --- a/libraries/registry_helper.rb +++ b/libraries/registry_helper.rb @@ -1,339 +1,343 @@ -#
-# Author:: Doug MacEachern (<dougm@vmware.com>)
-# Author:: Seth Chisamore (<schisamo@opscode.com>)
-# Author:: Paul Morotn (<pmorton@biaprotect.com>)
-# Cookbook Name:: windows
-# Provider:: registry
-#
-# Copyright:: 2010, VMware, Inc.
-# Copyright:: 2011, Opscode, Inc.
-# Copyright:: 2011, Business Intelligence Associates, Inc
-#
-# 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.
-#
-
-if RUBY_PLATFORM =~ /mswin|mingw32|windows/
- require 'win32/registry'
- require 'ruby-wmi'
-end
-
-module Windows
- module RegistryHelper
-
- @@native_registry_constant = ENV['PROCESSOR_ARCHITEW6432'] == 'AMD64' ? 0x0100 : 0x0200
-
- def get_hive_name(path)
- Chef::Log.debug("Resolving registry shortcuts to full names")
-
- reg_path = path.split("\\")
- hive_name = reg_path.shift
-
- hkey = {
- "HKLM" => "HKEY_LOCAL_MACHINE",
- "HKCU" => "HKEY_CURRENT_USER",
- "HKU" => "HKEY_USERS"
- }[hive_name] || hive_name
-
- Chef::Log.debug("Hive resolved to #{hkey}")
- return hkey
- end
-
- def get_hive(path)
-
- Chef::Log.debug("Getting hive for #{path}")
- reg_path = path.split("\\")
- hive_name = reg_path.shift
-
- hkey = get_hive_name(path)
-
- hive = {
- "HKEY_LOCAL_MACHINE" => Win32::Registry::HKEY_LOCAL_MACHINE,
- "HKEY_USERS" => Win32::Registry::HKEY_USERS,
- "HKEY_CURRENT_USER" => Win32::Registry::HKEY_CURRENT_USER
- }[hkey]
-
- unless hive
- Chef::Application.fatal!("Unsupported registry hive '#{hive_name}'")
- end
-
-
- Chef::Log.debug("Registry hive resolved to #{hkey}")
- return hive
- end
-
- def unload_hive(path)
- hive = get_hive(path)
- if hive == Win32::Registry::HKEY_USERS
- reg_path = path.split("\\")
- priv = Chef::WindowsPrivileged.new
- begin
- priv.reg_unload_key(reg_path[1])
- rescue
- end
- end
- end
-
- def set_value(mode,path,values,type=nil)
- hive, reg_path, hive_name, root_key, hive_loaded = get_reg_path_info(path)
- key_name = reg_path.join("\\")
-
- Chef::Log.debug("Creating #{path})")
-
- if !key_exists?(path,true)
- create_key(path)
- end
-
- hive.send(mode, key_name, Win32::Registry::KEY_ALL_ACCESS | @@native_registry_constant) do |reg|
- values.each do |k,val|
- key = "#{k}" #wtf. avoid "can't modify frozen string" in win32/registry.rb
- cur_val = nil
- begin
- cur_val = reg[key]
- rescue
- #subkey does not exist (ok)
- end
- if cur_val != val
- Chef::Log.debug("setting #{key}=#{val}")
- if type.nil?
- reg[key] = val
- else
- reg[key, REG_BINARY] = val
- end
-
- ensure_hive_unloaded(hive_loaded)
-
- return true
- end
- end
- end
- return false
- end
-
- def get_value(path,value)
- hive, reg_path, hive_name, root_key, hive_loaded = get_reg_path_info(path)
- key = reg_path.join("\\")
-
- hive.open(key, Win32::Registry::KEY_ALL_ACCESS | @@native_registry_constant) do | reg |
- begin
- return reg[value]
- rescue
- return nil
- ensure
- ensure_hive_unloaded(hive_loaded)
- end
- end
- end
-
- def get_values(path)
- hive, reg_path, hive_name, root_key, hive_loaded = get_reg_path_info(path)
- key = reg_path.join("\\")
- hive.open(key, Win32::Registry::KEY_ALL_ACCESS | @@native_registry_constant) do | reg |
- values = []
- begin
- reg.each_value do |name, type, data|
- values << [name, type, data]
- end
- rescue
- ensure
- ensure_hive_unloaded(hive_loaded)
- end
- values
- end
- end
-
- def delete_value(path,values)
- hive, reg_path, hive_name, root_key, hive_loaded = get_reg_path_info(path)
- key = reg_path.join("\\")
- Chef::Log.debug("Deleting values in #{path}")
- hive.open(key, Win32::Registry::KEY_ALL_ACCESS | @@native_registry_constant) do | reg |
- values.each_key { |key|
- name = "#{key}"
- Chef::Log.debug("Deleting value #{name} in #{path}")
- reg.delete_value(name)
- }
- end
-
- end
-
- def create_key(path)
- hive, reg_path, hive_name, root_key, hive_loaded = get_reg_path_info(path)
- key = reg_path.join("\\")
- Chef::Log.debug("Creating registry key #{path}")
- hive.create(key)
- end
-
- def value_exists?(path,value)
- if key_exists?(path,true)
-
- hive, reg_path, hive_name, root_key , hive_loaded = get_reg_path_info(path)
- key = reg_path.join("\\")
-
- Chef::Log.debug("Attempting to open #{key}");
- Chef::Log.debug("Native Constant #{@@native_registry_constant}")
- Chef::Log.debug("Hive #{hive}")
-
- hive.open(key, Win32::Registry::KEY_READ | @@native_registry_constant) do | reg |
- begin
- rtn_value = reg[value]
- return true
- rescue
- return false
- ensure
- ensure_hive_unloaded(hive_loaded)
- end
- end
-
- end
- return false
- end
-
- # TODO: Does not load user registry...
- def key_exists?(path, load_hive = false)
- if load_hive
- hive, reg_path, hive_name, root_key , hive_loaded = get_reg_path_info(path)
- key = reg_path.join("\\")
- else
- hive = get_hive(path)
- reg_path = path.split("\\")
- hive_name = reg_path.shift
- root_key = reg_path[0]
- key = reg_path.join("\\")
- hive_loaded = false
- end
-
- begin
- hive.open(key, Win32::Registry::Constants::KEY_READ | @@native_registry_constant )
- return true
- rescue
- return false
- ensure
- ensure_hive_unloaded(hive_loaded)
- end
- end
-
- def get_user_hive_location(sid)
- reg_key = "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\#{sid}"
- Chef::Log.debug("Looking for profile at #{reg_key}")
- if key_exists?(reg_key)
- return get_value(reg_key,'ProfileImagePath')
- else
- return nil
- end
-
- end
-
- def resolve_user_to_sid(username)
- begin
- sid = WMI::Win32_UserAccount.find(:first, :conditions => {:name => username}).sid
- Chef::Log.debug("Resolved user SID to #{sid}")
- return sid
- rescue
- return nil
- end
- end
-
- def hive_loaded?(path)
- hive = get_hive(path)
- reg_path = path.split("\\")
- hive_name = reg_path.shift
- user_hive = path[0]
-
- if is_user_hive?(hive)
- return key_exists?("#{hive_name}\\#{user_hive}")
- else
- return true
- end
- end
-
- def is_user_hive?(hive)
- if hive == Win32::Registry::HKEY_USERS
- return true
- else
- return true
- end
- end
-
- def get_reg_path_info(path)
- hive = get_hive(path)
- reg_path = path.split("\\")
- hive_name = reg_path.shift
- root_key = reg_path[0]
- hive_loaded = false
-
- if is_user_hive?(hive) && !key_exists?("#{hive_name}\\#{root_key}")
- reg_path, hive_loaded = load_user_hive(hive,reg_path,root_key)
- root_key = reg_path[0]
- Chef::Log.debug("Resolved user (#{path}) to (#{reg_path.join('/')})")
- end
-
- return hive, reg_path, hive_name, root_key, hive_loaded
- end
-
- def load_user_hive(hive,reg_path,user_hive)
- Chef::Log.debug("Reg Path #{reg_path}")
- # See if the hive is loaded. Logged in users will have a key that is named their SID
- # if the user has specified the a path by SID and the user is logged in, this function
- # should not be executed.
- if is_user_hive?(hive) && !key_exists?("HKU\\#{user_hive}")
- Chef::Log.debug("The user is not logged in and has not been specified by SID")
- sid = resolve_user_to_sid(user_hive)
- Chef::Log.debug("User SID resolved to (#{sid})")
- # Now that the user has been resolved to a SID, check and see if the hive exists.
- # If this exists by SID, the user is logged in and we should use that key.
- # TODO: Replace the username with the sid and send it back because the username
- # does not exist as the key location.
- load_reg = false
- if key_exists?("HKU\\#{sid}")
- reg_path[0] = sid #use the active profile (user is logged on)
- Chef::Log.debug("HKEY_USERS Mapped: #{user_hive} -> #{sid}")
- else
- Chef::Log.debug("User is not logged in")
- load_reg = true
- end
-
- # The user is not logged in, so we should load the registry from disk
- if load_reg
- profile_path = get_user_hive_location(sid)
- if profile_path != nil
- ntuser_dat = "#{profile_path}\\NTUSER.DAT"
- if ::File.exists?(ntuser_dat)
- priv = Chef::WindowsPrivileged.new
- if priv.reg_load_key(sid,ntuser_dat)
- Chef::Log.debug("RegLoadKey(#{sid}, #{user_hive}, #{ntuser_dat})")
- reg_path[0] = sid
- else
- Chef::Log.debug("Failed RegLoadKey(#{sid}, #{user_hive}, #{ntuser_dat})")
- end
- end
- end
- end
- end
-
- return reg_path, load_reg
-
- end
-
- private
- def ensure_hive_unloaded(hive_loaded=false)
- if(hive_loaded)
- Chef::Log.debug("Hive was loaded, we really should unload it")
- unload_hive(path)
- end
- end
- end
-end
-
-module Registry
- module_function
- extend Windows::RegistryHelper
-end
+# +# Author:: Doug MacEachern (<dougm@vmware.com>) +# Author:: Seth Chisamore (<schisamo@opscode.com>) +# Author:: Paul Morton (<pmorton@biaprotect.com>) +# Cookbook Name:: windows +# Provider:: registry +# +# Copyright:: 2010, VMware, Inc. +# Copyright:: 2011, Opscode, Inc. +# Copyright:: 2011, Business Intelligence Associates, Inc +# +# 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. +# + +if RUBY_PLATFORM =~ /mswin|mingw32|windows/ + require 'win32/registry' + require 'ruby-wmi' +end + +module Windows + module RegistryHelper + + @@native_registry_constant = ENV['PROCESSOR_ARCHITEW6432'] == 'AMD64' ? 0x0100 : 0x0200 + + def get_hive_name(path) + Chef::Log.debug("Resolving registry shortcuts to full names") + + reg_path = path.split("\\") + hive_name = reg_path.shift + + hkey = { + "HKLM" => "HKEY_LOCAL_MACHINE", + "HKCU" => "HKEY_CURRENT_USER", + "HKU" => "HKEY_USERS" + }[hive_name] || hive_name + + Chef::Log.debug("Hive resolved to #{hkey}") + return hkey + end + + def get_hive(path) + + Chef::Log.debug("Getting hive for #{path}") + reg_path = path.split("\\") + hive_name = reg_path.shift + + hkey = get_hive_name(path) + + hive = { + "HKEY_LOCAL_MACHINE" => Win32::Registry::HKEY_LOCAL_MACHINE, + "HKEY_USERS" => Win32::Registry::HKEY_USERS, + "HKEY_CURRENT_USER" => Win32::Registry::HKEY_CURRENT_USER + }[hkey] + + unless hive + Chef::Application.fatal!("Unsupported registry hive '#{hive_name}'") + end + + + Chef::Log.debug("Registry hive resolved to #{hkey}") + return hive + end + + def unload_hive(path) + hive = get_hive(path) + if hive == Win32::Registry::HKEY_USERS + reg_path = path.split("\\") + priv = Chef::WindowsPrivileged.new + begin + priv.reg_unload_key(reg_path[1]) + rescue + end + end + end + + def set_value(mode,path,values,type=nil) + hive, reg_path, hive_name, root_key, hive_loaded = get_reg_path_info(path) + key_name = reg_path.join("\\") + + Chef::Log.debug("Creating #{path})") + + if !key_exists?(path,true) + create_key(path) + end + + hive.send(mode, key_name, Win32::Registry::KEY_ALL_ACCESS | @@native_registry_constant) do |reg| + Chef::Log.debug("Values!: #{values}") + changed_something = false + values.each do |k,val| + key = "#{k}" #wtf. avoid "can't modify frozen string" in win32/registry.rb + cur_val = nil + begin + Chef::Log.debug("Registry key is: #{reg[key]}, value is: #{val}") + cur_val = reg[key] + rescue + #subkey does not exist (ok) + end + if cur_val != val + Chef::Log.debug("setting #{key}=#{val}") + if type.nil? + reg[key] = val + else + reg[key, Win32::Registry::REG_BINARY] = val + end + + ensure_hive_unloaded(hive_loaded) + + changed_something = true + end + end + return changed_something + end + return false + end + + def get_value(path,value) + hive, reg_path, hive_name, root_key, hive_loaded = get_reg_path_info(path) + key = reg_path.join("\\") + + hive.open(key, Win32::Registry::KEY_ALL_ACCESS | @@native_registry_constant) do | reg | + begin + return reg[value] + rescue + return nil + ensure + ensure_hive_unloaded(hive_loaded) + end + end + end + + def get_values(path) + hive, reg_path, hive_name, root_key, hive_loaded = get_reg_path_info(path) + key = reg_path.join("\\") + hive.open(key, Win32::Registry::KEY_ALL_ACCESS | @@native_registry_constant) do | reg | + values = [] + begin + reg.each_value do |name, type, data| + values << [name, type, data] + end + rescue + ensure + ensure_hive_unloaded(hive_loaded) + end + values + end + end + + def delete_value(path,values) + hive, reg_path, hive_name, root_key, hive_loaded = get_reg_path_info(path) + key = reg_path.join("\\") + Chef::Log.debug("Deleting values in #{path}") + hive.open(key, Win32::Registry::KEY_ALL_ACCESS | @@native_registry_constant) do | reg | + values.each_key { |key| + name = "#{key}" + Chef::Log.debug("Deleting value #{name} in #{path}") + reg.delete_value(name) + } + end + + end + + def create_key(path) + hive, reg_path, hive_name, root_key, hive_loaded = get_reg_path_info(path) + key = reg_path.join("\\") + Chef::Log.debug("Creating registry key #{path}") + hive.create(key) + end + + def value_exists?(path,value) + if key_exists?(path,true) + + hive, reg_path, hive_name, root_key , hive_loaded = get_reg_path_info(path) + key = reg_path.join("\\") + + Chef::Log.debug("Attempting to open #{key}"); + Chef::Log.debug("Native Constant #{@@native_registry_constant}") + Chef::Log.debug("Hive #{hive}") + + hive.open(key, Win32::Registry::KEY_READ | @@native_registry_constant) do | reg | + begin + rtn_value = reg[value] + return true + rescue + return false + ensure + ensure_hive_unloaded(hive_loaded) + end + end + + end + return false + end + + # TODO: Does not load user registry... + def key_exists?(path, load_hive = false) + if load_hive + hive, reg_path, hive_name, root_key , hive_loaded = get_reg_path_info(path) + key = reg_path.join("\\") + else + hive = get_hive(path) + reg_path = path.split("\\") + hive_name = reg_path.shift + root_key = reg_path[0] + key = reg_path.join("\\") + hive_loaded = false + end + + begin + hive.open(key, Win32::Registry::Constants::KEY_READ | @@native_registry_constant ) + return true + rescue + return false + ensure + ensure_hive_unloaded(hive_loaded) + end + end + + def get_user_hive_location(sid) + reg_key = "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\#{sid}" + Chef::Log.debug("Looking for profile at #{reg_key}") + if key_exists?(reg_key) + return get_value(reg_key,'ProfileImagePath') + else + return nil + end + + end + + def resolve_user_to_sid(username) + begin + sid = WMI::Win32_UserAccount.find(:first, :conditions => {:name => username}).sid + Chef::Log.debug("Resolved user SID to #{sid}") + return sid + rescue + return nil + end + end + + def hive_loaded?(path) + hive = get_hive(path) + reg_path = path.split("\\") + hive_name = reg_path.shift + user_hive = path[0] + + if is_user_hive?(hive) + return key_exists?("#{hive_name}\\#{user_hive}") + else + return true + end + end + + def is_user_hive?(hive) + if hive == Win32::Registry::HKEY_USERS + return true + else + return true + end + end + + def get_reg_path_info(path) + hive = get_hive(path) + reg_path = path.split("\\") + hive_name = reg_path.shift + root_key = reg_path[0] + hive_loaded = false + + if is_user_hive?(hive) && !key_exists?("#{hive_name}\\#{root_key}") + reg_path, hive_loaded = load_user_hive(hive,reg_path,root_key) + root_key = reg_path[0] + Chef::Log.debug("Resolved user (#{path}) to (#{reg_path.join('/')})") + end + + return hive, reg_path, hive_name, root_key, hive_loaded + end + + def load_user_hive(hive,reg_path,user_hive) + Chef::Log.debug("Reg Path #{reg_path}") + # See if the hive is loaded. Logged in users will have a key that is named their SID + # if the user has specified the a path by SID and the user is logged in, this function + # should not be executed. + if is_user_hive?(hive) && !key_exists?("HKU\\#{user_hive}") + Chef::Log.debug("The user is not logged in and has not been specified by SID") + sid = resolve_user_to_sid(user_hive) + Chef::Log.debug("User SID resolved to (#{sid})") + # Now that the user has been resolved to a SID, check and see if the hive exists. + # If this exists by SID, the user is logged in and we should use that key. + # TODO: Replace the username with the sid and send it back because the username + # does not exist as the key location. + load_reg = false + if key_exists?("HKU\\#{sid}") + reg_path[0] = sid #use the active profile (user is logged on) + Chef::Log.debug("HKEY_USERS Mapped: #{user_hive} -> #{sid}") + else + Chef::Log.debug("User is not logged in") + load_reg = true + end + + # The user is not logged in, so we should load the registry from disk + if load_reg + profile_path = get_user_hive_location(sid) + if profile_path != nil + ntuser_dat = "#{profile_path}\\NTUSER.DAT" + if ::File.exists?(ntuser_dat) + priv = Chef::WindowsPrivileged.new + if priv.reg_load_key(sid,ntuser_dat) + Chef::Log.debug("RegLoadKey(#{sid}, #{user_hive}, #{ntuser_dat})") + reg_path[0] = sid + else + Chef::Log.debug("Failed RegLoadKey(#{sid}, #{user_hive}, #{ntuser_dat})") + end + end + end + end + end + + return reg_path, load_reg + + end + + private + def ensure_hive_unloaded(hive_loaded=false) + if(hive_loaded) + Chef::Log.debug("Hive was loaded, we really should unload it") + unload_hive(path) + end + end + end +end + +module Registry + module_function + extend Windows::RegistryHelper +end |