diff options
author | Jay Mundrawala <jdmundrawala@gmail.com> | 2015-05-08 07:03:34 -0700 |
---|---|---|
committer | Jay Mundrawala <jdmundrawala@gmail.com> | 2015-05-15 08:51:16 -0700 |
commit | ca93171b6d2ed8a5a36c1f10f09a26b47fea47bf (patch) | |
tree | b16051150c8f541367fec8825bc86e8329c2aafb | |
parent | e0fb4b98b6af2c4eb03eab7b84d2ea55cba87d35 (diff) | |
download | chef-ca93171b6d2ed8a5a36c1f10f09a26b47fea47bf.tar.gz |
NetUserGetInfo uses ffi
-rw-r--r-- | lib/chef/util/windows/net_user.rb | 26 | ||||
-rw-r--r-- | lib/chef/win32/api/net.rb | 48 | ||||
-rw-r--r-- | lib/chef/win32/user.rb | 51 |
3 files changed, 106 insertions, 19 deletions
diff --git a/lib/chef/util/windows/net_user.rb b/lib/chef/util/windows/net_user.rb index e79d9212c5..1144645eef 100644 --- a/lib/chef/util/windows/net_user.rb +++ b/lib/chef/util/windows/net_user.rb @@ -123,6 +123,14 @@ class Chef::Util::Windows::NetUser < Chef::Util::Windows end end + def usri3_to_hash(usri3) + t = USER_INFO_3_TRANSFORM.invert + usri3.inject({}) do |memo, (k,v)| + memo[USER_INFO_3_TRANSFORM[k]] = v + memo + end + end + def user_info_3(args) USER_INFO_3.collect { |field| args.include?(field[0]) ? args[field[0]] : field[1] @@ -175,20 +183,12 @@ class Chef::Util::Windows::NetUser < Chef::Util::Windows end def get_info - ptr = 0.chr * PTR_SIZE - rc = NetUserGetInfo.call(nil, @name, 3, ptr) - - if rc == NERR_UserNotFound - raise Chef::Exceptions::UserIDNotFound, get_last_error(rc) - elsif rc != NERR_Success - raise ArgumentError, get_last_error(rc) + begin + ui3 = Chef::ReservedNames::Win32::NetUser::net_user_get_info_l3(nil, @username) + rescue Chef::Exceptions::Win32APIError => e + raise ArgumentError, e end - - ptr = ptr.unpack('L')[0] - buffer = 0.chr * SIZEOF_USER_INFO_3 - memcpy(buffer, ptr, buffer.size) - NetApiBufferFree(ptr) - user_info_3_unpack(buffer) + usri3_to_hash(ui3) end def add(args) diff --git a/lib/chef/win32/api/net.rb b/lib/chef/win32/api/net.rb index f2cfa93828..5eb77ae2b0 100644 --- a/lib/chef/win32/api/net.rb +++ b/lib/chef/win32/api/net.rb @@ -45,6 +45,7 @@ class Chef NERR_NotPrimary = 2226 NERR_SpeGroupOp = 2234 NERR_LastAdmin = 2452 + NERR_BadUsername = 2202 NERR_BadPassword = 2203 NERR_PasswordTooShort = 2245 NERR_UserNotFound = 2221 @@ -85,11 +86,44 @@ class Chef def set(key, val) - if val.class == String + if val.is_a? String val = FFI::MemoryPointer.from_string(val.to_wstring) end self[key] = val end + + def get(key) + if respond_to? key + send(key) + else + val = self[key] + if val.is_a? FFI::Pointer + if val.null? + nil + else + val.read_wstring + end + else + val + end + end + end + + def usri3_logon_hours + val = self[:usri3_logon_hours] + if !val.nil? && !val.null? + val.read_bytes(21) + else + nil + end + end + + def as_ruby + members.inject({}) do |memo, key| + memo[key] = get(key) + memo + end + end end class LOCALGROUP_MEMBERS_INFO_3 < FFI::Struct @@ -130,6 +164,18 @@ class Chef #); safe_attach_function :NetLocalGroupAddMembers, [:LPCWSTR, :LPCWSTR, :DWORD, :LPBYTE, :DWORD ], :DWORD +#NET_API_STATUS NetUserGetInfo( +# _In_ LPCWSTR servername, +# _In_ LPCWSTR username, +# _In_ DWORD level, +# _Out_ LPBYTE *bufptr +#); + safe_attach_function :NetUserGetInfo, [:LPCWSTR, :LPCWSTR, :DWORD, :LPBYTE], :DWORD + +#NET_API_STATUS NetApiBufferFree( +# _In_ LPVOID Buffer +#); + safe_attach_function :NetApiBufferFree, [:LPVOID], :DWORD end end end diff --git a/lib/chef/win32/user.rb b/lib/chef/win32/user.rb index 095989236e..345eb3b6c7 100644 --- a/lib/chef/win32/user.rb +++ b/lib/chef/win32/user.rb @@ -65,10 +65,6 @@ class Chef end def self.net_api_error!(code) - formatted_message = "" - formatted_message << "---- Begin Win32 API output ----\n" - formatted_message << "Net Api Error Code: #{code}\n" - msg = case code when NERR_InvalidComputer "The user does not have access to the requested information." @@ -83,7 +79,7 @@ class Chef when NERR_BadPassword "The password parameter is invalid." when NERR_UserNotFound - "The user name could not be found." + raise Chef::Exceptions::UserIDNotFound, code when NERR_PasswordTooShort <<END The password is shorter than required. (The password could also be too @@ -96,8 +92,12 @@ END "Received unknown error code (#{code})" end + formatted_message = "" + formatted_message << "---- Begin Win32 API output ----\n" + formatted_message << "Net Api Error Code: #{code}\n" formatted_message << "Net Api Error Message: #{msg}\n" formatted_message << "---- End Win32 API output ----\n" + raise Chef::Exceptions::Win32APIError, msg + "\n" + formatted_message end @@ -121,6 +121,37 @@ END end end + def self.net_user_get_info_l3(server_name, user_name) + server_name = wstring(server_name) + user_name = wstring(user_name) + + ui3_p = FFI::MemoryPointer.new(:pointer) + + rc = NetUserGetInfo(server_name, user_name, 3, ui3_p) + + if rc != NERR_Success + if Chef::ReservedNames::Win32::Error.get_last_error != 0 + Chef::ReservedNames::Win32::Error.raise! + else + net_api_error!(rc) + end + end + + ui3 = USER_INFO_3.new(ui3_p.read_pointer).as_ruby + + rc = NetApiBufferFree(ui3_p.read_pointer) + + if rc != NERR_Success + if Chef::ReservedNames::Win32::Error.get_last_error != 0 + Chef::ReservedNames::Win32::Error.raise! + else + net_api_error!(rc) + end + end + + ui3 + end + def self.net_local_group_add_member(server_name, group_name, domain_user) server_name = server_name.to_wstring if server_name group_name = group_name.to_wstring @@ -140,6 +171,16 @@ END end end + private + + def self.wstring(str) + if str.nil? || str.encoding == Encoding::UTF_16LE + str + else + str.to_wstring + end + end + end end end |