diff options
author | Jay Mundrawala <jdmundrawala@gmail.com> | 2015-08-28 17:59:12 -0700 |
---|---|---|
committer | Jay Mundrawala <jdmundrawala@gmail.com> | 2015-08-28 17:59:12 -0700 |
commit | 8926514f6f2f3975cade73b93cda8154115440df (patch) | |
tree | 9598c29e018dc6b3c29a471753ff7f9fffdc5ae6 | |
parent | 43592dae3b541825602c0a2213f83e9ac5382741 (diff) | |
parent | a84f30da26f47aeeab2d13a775cb4d33e8c34fd6 (diff) | |
download | chef-8926514f6f2f3975cade73b93cda8154115440df.tar.gz |
Merge pull request #3832 from chef/jdm/net-use
Update NetUse stuff to use FFI
-rw-r--r-- | lib/chef/util/windows/net_use.rb | 106 | ||||
-rw-r--r-- | lib/chef/win32/api/net.rb | 121 | ||||
-rw-r--r-- | lib/chef/win32/net.rb | 55 |
3 files changed, 172 insertions, 110 deletions
diff --git a/lib/chef/util/windows/net_use.rb b/lib/chef/util/windows/net_use.rb index 62d7e169dc..b94576e702 100644 --- a/lib/chef/util/windows/net_use.rb +++ b/lib/chef/util/windows/net_use.rb @@ -21,61 +21,18 @@ #see also cmd.exe: net use /? require 'chef/util/windows' +require 'chef/win32/net' class Chef::Util::Windows::NetUse < Chef::Util::Windows - - private - - USE_NOFORCE = 0 - USE_FORCE = 1 - USE_LOTS_OF_FORCE = 2 #every windows API should support this flag - - USE_INFO_2 = [ - [:local, nil], - [:remote, nil], - [:password, nil], - [:status, 0], - [:asg_type, 0], - [:refcount, 0], - [:usecount, 0], - [:username, nil], - [:domainname, nil] - ] - - USE_INFO_2_TEMPLATE = - USE_INFO_2.collect { |field| field[1].class == Fixnum ? 'i' : 'L' }.join - - SIZEOF_USE_INFO_2 = #sizeof(USE_INFO_2) - USE_INFO_2.inject(0) do |sum, item| - sum + (item[1].class == Fixnum ? 4 : PTR_SIZE) - end - - def use_info_2(args) - USE_INFO_2.collect { |field| - args.include?(field[0]) ? args[field[0]] : field[1] - } - end - - def use_info_2_pack(use) - use.collect { |v| - v.class == Fixnum ? v : str_to_ptr(multi_to_wide(v)) - }.pack(USE_INFO_2_TEMPLATE) + def initialize(localname) + @use_name = localname end - def use_info_2_unpack(buffer) - use = Hash.new - USE_INFO_2.each_with_index do |field,offset| - use[field[0]] = field[1].class == Fixnum ? - dword_to_i(buffer, offset) : lpwstr_to_s(buffer, offset) + def to_ui2_struct(use_info) + use_info.inject({}) do |memo, (k,v)| + memo["ui2_#{k}".to_sym] = v + memo end - use - end - - public - - def initialize(localname) - @localname = localname - @name = multi_to_wide(localname) end def add(args) @@ -84,38 +41,45 @@ class Chef::Util::Windows::NetUse < Chef::Util::Windows args = Hash.new args[:remote] = remote end - args[:local] ||= @localname - use = use_info_2(args) - buffer = use_info_2_pack(use) - rc = NetUseAdd.call(nil, 2, buffer, nil) - if rc != NERR_Success - raise ArgumentError, get_last_error(rc) + args[:local] ||= use_name + ui2_hash = to_ui2_struct(args) + + begin + Chef::ReservedNames::Win32::Net.net_use_add_l2(nil, ui2_hash) + rescue Chef::Exceptions::Win32APIError => e + raise ArgumentError, e end end - def get_info - ptr = 0.chr * PTR_SIZE - rc = NetUseGetInfo.call(nil, @name, 2, ptr) - - if rc != NERR_Success - raise ArgumentError, get_last_error(rc) + def from_use_info_struct(ui2_hash) + ui2_hash.inject({}) do |memo, (k,v)| + memo[k.to_s.sub('ui2_', '').to_sym] = v + memo end + end - ptr = ptr.unpack('L')[0] - buffer = 0.chr * SIZEOF_USE_INFO_2 - memcpy(buffer, ptr, buffer.size) - NetApiBufferFree(ptr) - use_info_2_unpack(buffer) + def get_info + begin + ui2 = Chef::ReservedNames::Win32::Net.net_use_get_info_l2(nil, use_name) + from_use_info_struct(ui2) + rescue Chef::Exceptions::Win32APIError => e + raise ArgumentError, e + end end def device get_info()[:remote] end - #XXX should we use some FORCE here? + def delete - rc = NetUseDel.call(nil, @name, USE_NOFORCE) - if rc != NERR_Success - raise ArgumentError, get_last_error(rc) + begin + Chef::ReservedNames::Win32::Net.net_use_del(nil, use_name, :use_noforce) + rescue Chef::Exceptions::Win32APIError => e + raise ArgumentError, e end end + + def use_name + @use_name + end end diff --git a/lib/chef/win32/api/net.rb b/lib/chef/win32/api/net.rb index 0519e93a96..6828d7ee2f 100644 --- a/lib/chef/win32/api/net.rb +++ b/lib/chef/win32/api/net.rb @@ -40,6 +40,10 @@ class Chef UF_NORMAL_ACCOUNT = 0x000200 UF_DONT_EXPIRE_PASSWD = 0x010000 + USE_NOFORCE = 0 + USE_FORCE = 1 + USE_LOTS_OF_FORCE = 2 #every windows API should support this flag + NERR_Success = 0 NERR_InvalidComputer = 2351 NERR_NotPrimary = 2226 @@ -55,37 +59,7 @@ class Chef ffi_lib "netapi32" - class USER_INFO_3 < FFI::Struct - layout :usri3_name, :LPWSTR, - :usri3_password, :LPWSTR, - :usri3_password_age, :DWORD, - :usri3_priv, :DWORD, - :usri3_home_dir, :LPWSTR, - :usri3_comment, :LPWSTR, - :usri3_flags, :DWORD, - :usri3_script_path, :LPWSTR, - :usri3_auth_flags, :DWORD, - :usri3_full_name, :LPWSTR, - :usri3_usr_comment, :LPWSTR, - :usri3_parms, :LPWSTR, - :usri3_workstations, :LPWSTR, - :usri3_last_logon, :DWORD, - :usri3_last_logoff, :DWORD, - :usri3_acct_expires, :DWORD, - :usri3_max_storage, :DWORD, - :usri3_units_per_week, :DWORD, - :usri3_logon_hours, :PBYTE, - :usri3_bad_pw_count, :DWORD, - :usri3_num_logons, :DWORD, - :usri3_logon_server, :LPWSTR, - :usri3_country_code, :DWORD, - :usri3_code_page, :DWORD, - :usri3_user_id, :DWORD, - :usri3_primary_group_id, :DWORD, - :usri3_profile, :LPWSTR, - :usri3_home_dir_drive, :LPWSTR, - :usri3_password_expired, :DWORD - + module StructHelpers def set(key, val) val = if val.is_a? String encoded = if val.encoding == Encoding::UTF_16LE @@ -117,6 +91,47 @@ class Chef end end + def as_ruby + members.inject({}) do |memo, key| + memo[key] = get(key) + memo + end + end + end + + + class USER_INFO_3 < FFI::Struct + include StructHelpers + layout :usri3_name, :LPWSTR, + :usri3_password, :LPWSTR, + :usri3_password_age, :DWORD, + :usri3_priv, :DWORD, + :usri3_home_dir, :LPWSTR, + :usri3_comment, :LPWSTR, + :usri3_flags, :DWORD, + :usri3_script_path, :LPWSTR, + :usri3_auth_flags, :DWORD, + :usri3_full_name, :LPWSTR, + :usri3_usr_comment, :LPWSTR, + :usri3_parms, :LPWSTR, + :usri3_workstations, :LPWSTR, + :usri3_last_logon, :DWORD, + :usri3_last_logoff, :DWORD, + :usri3_acct_expires, :DWORD, + :usri3_max_storage, :DWORD, + :usri3_units_per_week, :DWORD, + :usri3_logon_hours, :PBYTE, + :usri3_bad_pw_count, :DWORD, + :usri3_num_logons, :DWORD, + :usri3_logon_server, :LPWSTR, + :usri3_country_code, :DWORD, + :usri3_code_page, :DWORD, + :usri3_user_id, :DWORD, + :usri3_primary_group_id, :DWORD, + :usri3_profile, :LPWSTR, + :usri3_home_dir_drive, :LPWSTR, + :usri3_password_expired, :DWORD + def usri3_logon_hours val = self[:usri3_logon_hours] if !val.nil? && !val.null? @@ -125,13 +140,6 @@ class Chef nil end end - - def as_ruby - members.inject({}) do |memo, key| - memo[key] = get(key) - memo - end - end end class LOCALGROUP_MEMBERS_INFO_0 < FFI::Struct @@ -146,6 +154,21 @@ class Chef layout :lgrpi0_name, :LPWSTR end + class USE_INFO_2 < FFI::Struct + include StructHelpers + + layout :ui2_local, :LMSTR, + :ui2_remote, :LMSTR, + :ui2_password, :LMSTR, + :ui2_status, :DWORD, + :ui2_asg_type, :DWORD, + :ui2_refcount, :DWORD, + :ui2_usecount, :DWORD, + :ui2_username, :LPWSTR, + :ui2_domainname, :LMSTR + end + + #NET_API_STATUS NetLocalGroupAdd( #_In_ LPCWSTR servername, #_In_ DWORD level, @@ -272,6 +295,28 @@ class Chef #); safe_attach_function :NetUserDel, [:LPCWSTR, :LPCWSTR], :DWORD +#NET_API_STATUS NetUseDel( + #_In_ LMSTR UncServerName, + #_In_ LMSTR UseName, + #_In_ DWORD ForceCond +#); + safe_attach_function :NetUseDel, [:LMSTR, :LMSTR, :DWORD], :DWORD + +#NET_API_STATUS NetUseGetInfo( + #_In_ LMSTR UncServerName, + #_In_ LMSTR UseName, + #_In_ DWORD Level, + #_Out_ LPBYTE *BufPtr +#); + safe_attach_function :NetUseGetInfo, [:LMSTR, :LMSTR, :DWORD, :pointer], :DWORD + +#NET_API_STATUS NetUseAdd( + #_In_ LMSTR UncServerName, + #_In_ DWORD Level, + #_In_ LPBYTE Buf, + #_Out_ LPDWORD ParmError +#); + safe_attach_function :NetUseAdd, [:LMSTR, :DWORD, :LPBYTE, :LPDWORD], :DWORD end end end diff --git a/lib/chef/win32/net.rb b/lib/chef/win32/net.rb index 0de310daf1..c1ef3e83ce 100644 --- a/lib/chef/win32/net.rb +++ b/lib/chef/win32/net.rb @@ -22,7 +22,7 @@ require 'chef/mixin/wstring' class Chef module ReservedNames::Win32 - class NetUser + class Net include Chef::ReservedNames::Win32::API::Error extend Chef::ReservedNames::Win32::API::Error @@ -286,6 +286,59 @@ END net_api_error!(rc) end end + + def self.net_use_del(server_name, use_name, force=:use_noforce) + server_name = wstring(server_name) + use_name = wstring(use_name) + force_const = case force + when :use_noforce + USE_NOFORCE + when :use_force + USE_FORCE + when :use_lots_of_force + USE_LOTS_OF_FORCE + else + raise ArgumentError, "force must be one of [:use_noforce, :use_force, or :use_lots_of_force]" + end + + rc = NetUseDel(server_name, use_name, force_const) + if rc != NERR_Success + net_api_error!(rc) + end + end + + def self.net_use_get_info_l2(server_name, use_name) + server_name = wstring(server_name) + use_name = wstring(use_name) + ui2_p = FFI::MemoryPointer.new(:pointer) + + rc = NetUseGetInfo(server_name, use_name, 2, ui2_p) + if rc != NERR_Success + net_api_error!(rc) + end + + ui2 = USE_INFO_2.new(ui2_p.read_pointer).as_ruby + NetApiBufferFree(ui2_p.read_pointer) + + ui2 + end + + def self.net_use_add_l2(server_name, ui2_hash) + server_name = wstring(server_name) + group_name = wstring(group_name) + + buf = USE_INFO_2.new + + ui2_hash.each do |(k,v)| + buf.set(k,v) + end + + rc = NetUseAdd(server_name, 2, buf, nil) + if rc != NERR_Success + net_api_error!(rc) + end + end end + NetUser = Net # For backwards compatibility end end |