[Win32utils-devel] Help with File.set_permissions port

Park Heesob phasis at nownuri.net
Sun Mar 26 08:35:51 EST 2006


Hi,
> I've got a (broken) version of File.set_permissions in CVS, and I need
> some help finishing it off please.
> 
> Heesob, can you take a look?
> 
> Thanks,
> 
> Dan

Here is set_permissions:
  
    def self.set_permissions(file, perms)
      raise TypeError unless perms.kind_of?(Hash)
      
      account_rights = 0
      pSD = 0.chr * SECURITY_DESCRIPTOR_MIN_LENGTH
      
      if @@InitializeSecurityDescriptor.call(pSD, 1) == 0
         raise ArgumentError, get_last_error
      end
      
      cb_acl = 1024
      cb_sid = 1024
      
      acl_new = 0.chr * cb_acl
      
      if @@InitializeAcl.call(acl_new, cb_acl, ACL_REVISION2) == 0
         raise ArgumentError, get_last_error
      end
      
      pSID     = 0.chr * cb_sid
      psnuType = 0.chr * cb_sid
      
      allAce = 0.chr * ALLOW_ACE_LENGTH      
      pAllAce = @@memset.call(allAce,0,0) # address of allAce
                  
      # pAllAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE
      allAce[0] = 0
      
      perms.each{ |account, mask|
         next if mask.nil?
         cchDomain = [80].pack('L')
         cbSID = [1024].pack('L')
         domain_buf = 0.chr * 80
         
         server, account = account.split("\\")
         
         if ['BUILTIN', 'NT AUTHORITY'].include?(server.upcase)
            server = nil
         end
         
         val = @@LookupAccountName.call(
            server,
            account,
            pSID,
            cbSID,
            domain_buf,
            cchDomain,
            psnuType
         )
         
         if val == 0
            raise ArgumentError, get_last_error
         end
         
         size = [0,0,0,0,0].pack('CCSLL').length # sizeof(ACCESS_ALLOWED_ACE)
         
         val = @@CopySid.call(
            ALLOW_ACE_LENGTH - size,
            pAllAce + 8,  # address of pAllAce->SidStart          
            pSID
         )
         
         if val == 0
            raise ArgumentError, get_last_error
         end
                  
         if (GENERIC_ALL & mask).nonzero?
            account_rights = GENERIC_ALL & mask
         elsif (GENERIC_RIGHTS_CHK & mask).nonzero?
            account_rights = GENERIC_RIGHTS_MASK & mask
         end

         # pAllAce->Header.AceFlags = INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE ;
         allAce[1] = INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE
         
         2.times{
       
            if account_rights != 0
       
               allAce[2,2] = [12 - 4 + @@GetLengthSid.call(pSID)].pack('S')
                              
    			     allAce[4,4] = [account_rights].pack('L')
    			   val = @@AddAce.call(
    			      acl_new,
    			      ACL_REVISION2,
    			      MAXDWORD,    			      
    			      pAllAce,
    			      allAce[2,2].unpack('S').first
    			   )
    			   
    			   if val == 0
    			      raise ArgumentError, get_last_error
    			   end
    			   # pAllAce->Header.AceFlags = CONTAINER_INHERIT_ACE
    			   allAce[1] = CONTAINER_INHERIT_ACE
            else
               # pAllAce->Header.AceFlags = 0
               allAce[1] = 0
            end
            
            account_rights = REST_RIGHTS_MASK & mask
         }
      }
      
      if @@SetSecurityDescriptorDacl.call(pSD, 1, acl_new, 0) == 0
         raise ArgumentError, get_last_error
      end
      
      if @@SetFileSecurity.call(file, DACL_SECURITY_INFORMATION, pSD) == 0
         raise ArgumentError, get_last_error
      end
      
      self
   end

And update or define functions like this:

   @@CopySid         = Win32API.new('advapi32', 'CopySid', 'LLP', 'I')
   @@AddAce          = Win32API.new('advapi32', 'AddAce', 'PLLLL', 'I')
   @@memset          = Win32API.new('msvcrt', 'memset', 'PLL', 'L') 

Today's point:   
  memset is introduced for acquiring address of ruby string.
  str = "1234"
  pstr = memset.call(a,0,0) # address of str


Regards,

Park Heesob






More information about the win32utils-devel mailing list