summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJay Mundrawala <jdmundrawala@gmail.com>2015-08-28 17:59:12 -0700
committerJay Mundrawala <jdmundrawala@gmail.com>2015-08-28 17:59:12 -0700
commit8926514f6f2f3975cade73b93cda8154115440df (patch)
tree9598c29e018dc6b3c29a471753ff7f9fffdc5ae6
parent43592dae3b541825602c0a2213f83e9ac5382741 (diff)
parenta84f30da26f47aeeab2d13a775cb4d33e8c34fd6 (diff)
downloadchef-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.rb106
-rw-r--r--lib/chef/win32/api/net.rb121
-rw-r--r--lib/chef/win32/net.rb55
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