lib/win32/security/acl.rb in win32-security-0.1.4 vs lib/win32/security/acl.rb in win32-security-0.2.0

- old
+ new

@@ -1,73 +1,73 @@ -require 'windows/security' -require 'windows/error' -require 'windows/limits' -require 'windows/msvcrt/buffer' +require File.join(File.dirname(__FILE__), 'windows', 'constants') +require File.join(File.dirname(__FILE__), 'windows', 'structs') +require File.join(File.dirname(__FILE__), 'windows', 'functions') # The Win32 module serves as a namespace only. module Win32 - + # The Security class serves as a toplevel class namespace. class Security - + # The ACL class encapsulates an Access Control List. class ACL - include Windows::Error - include Windows::Security - include Windows::Limits - include Windows::MSVCRT::Buffer - + include Windows::Security::Constants + include Windows::Security::Functions + include Windows::Security::Structs + extend Windows::Security::Functions + # The version of the Win32::Security::ACL class. - VERSION = '0.1.0' + VERSION = '0.2.0' - # The binary representation of the ACL structure + # The underlying ACL structure. attr_reader :acl # The revision level. attr_reader :revision # Creates and returns a new Win32::Security::ACL object. This object # encapsulates an ACL structure, including a binary representation of # the ACL itself, and the revision information. # def initialize(revision = ACL_REVISION) - acl = 0.chr * 8 # This can be increased later as needed + acl = ACL_STRUCT.new unless InitializeAcl(acl, acl.size, revision) - raise Error, get_last_error + raise SystemCallError.new("InitializeAcl", FFI.errno) end @acl = acl @revision = revision end # Returns the number of ACE's in the ACL object. # def ace_count - buf = 0.chr * 12 # sizeof(ACL_SIZE_INFORMATION) + info = ACL_SIZE_INFORMATION.new - unless GetAclInformation(@acl, buf, buf.size, AclSizeInformation) - raise Error, get_last_error + unless GetAclInformation(@acl, info, info.size, AclSizeInformation) + raise SystemCallError.new("GetAclInformation", FFI.errno) end - buf[0, 4].unpack('L')[0] + info[:AceCount] end # Adds an access allowed ACE to the given +sid+. The +mask+ is a # bitwise OR'd value of access rights. # + # TODO: Move this into the SID class? def add_access_allowed_ace(sid, mask=0) unless AddAccessAllowedAce(@acl, @revision, mask, sid) - raise Error, get_last_error + raise SystemCallError.new("AddAccessAllowedAce", FFI.errno) end end # Adds an access denied ACE to the given +sid+. # def add_access_denied_ace(sid, mask=0) unless AddAccessDeniedAce(@acl, @revision, mask, sid) - raise Error, get_last_error + raise SystemCallError.new("AddAccessDeniedAce", FFI.errno) end end # Adds an ACE to the ACL object with the given +revision+ at +index+ # or the end of the chain if no index is specified. @@ -77,11 +77,11 @@ # This is untested and will require an actual implementation of # Win32::Security::Ace before it can work properly. # def add_ace(ace, index=MAXDWORD) unless AddAce(@acl, @revision, index, ace, ace.length) - raise Error, get_last_error + raise SystemCallError.new("AddAce", FFI.errno) end index end @@ -93,45 +93,46 @@ # This is untested and will require an actual implementation of # Win32::Security::Ace before it can work properly. # def delete_ace(index=MAXDWORD) unless DeleteAce(@ace, index) - raise Error, get_last_error + raise SystemCallError.new("DeleteAce", FFI.errno) end index end # Finds and returns a pointer (address) to an ACE in the ACL at the # given +index+. If no index is provided, then an address to the # first free byte of the ACL is returned. # def find_ace(index = nil) - ptr = [0].pack('L') + pptr = FFI::MemoryPointer.new(:pointer) if index.nil? - unless FindFirstFreeAce(@acl, ptr) - raise Error, get_last_error + unless FindFirstFreeAce(@acl, pptr) + raise SystemCallError.new("DeleteAce", FFI.errno) end else - unless GetAce(@acl, index, ptr) - raise Error, get_last_error + unless GetAce(@acl, index, pptr) + raise SystemCallError.new("GetAce", FFI.errno) end end - [ptr].pack('p*').unpack('L')[0] + pptr.read_pointer.address end # Sets the revision information level, where the +revision_level+ # can be ACL_REVISION1, ACL_REVISION2, ACL_REVISION3 or ACL_REVISION4. # # Returns the revision level if successful. # def revision=(revision_level) - buf = [revision_level].pack('L') + buf = FFI::MemoryPointer.new(:ulong) + buf.write_ulong(revision_level) unless SetAclInformation(@acl, buf, buf.size, AclRevisionInformation) - raise Error, get_last_error + raise SystemCallError.new("SetAclInformation", FFI.errno) end @revision = revision_level revision_level