# File lib/win32/file.rb, line 103
      def set_permissions(file, perms)
         raise TypeError unless perms.kind_of?(Hash)

         account_rights = 0
         sec_desc = 0.chr * SECURITY_DESCRIPTOR_MIN_LENGTH

         unless InitializeSecurityDescriptor(sec_desc, 1)
            raise ArgumentError, get_last_error
         end

         cb_acl = 1024
         cb_sid = 1024

         acl_new = 0.chr * cb_acl

         unless InitializeAcl(acl_new, cb_acl, ACL_REVISION2)
            raise ArgumentError, get_last_error
         end

         sid      = 0.chr * cb_sid
         snu_type = 0.chr * cb_sid

         all_ace = 0.chr * ALLOW_ACE_LENGTH
         all_ace_ptr = memset(all_ace, 0, 0) # address of all_ace

         # all_ace_ptr->Header.AceType = ACCESS_ALLOWED_ACE_TYPE
         all_ace[0] = 0

         perms.each{ |account, mask|
            next if mask.nil?
           
            cch_domain = [80].pack('L')
            cb_sid     = [1024].pack('L')
            domain_buf = 0.chr * 80

            server, account = account.split("\\")

            if ['BUILTIN', 'NT AUTHORITY'].include?(server.upcase)
               server = nil
            end

            val = LookupAccountName(
               server,
               account,
               sid,
               cb_sid,
               domain_buf,
               cch_domain,
               snu_type
            )

            if val == 0
               raise ArgumentError, get_last_error
            end

            size = [0,0,0,0,0].pack('CCSLL').length # sizeof(ACCESS_ALLOWED_ACE)
            
            val = CopySid(
               ALLOW_ACE_LENGTH - size,
               all_ace_ptr + 8,  # address of all_ace_ptr->SidStart
               sid
            )

            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

            # all_ace_ptr->Header.AceFlags = INHERIT_ONLY_ACE|OBJECT_INHERIT_ACE
            all_ace[1] = INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE

            2.times{
               if account_rights != 0
                  all_ace[2,2] = [12 - 4 + GetLengthSid(sid)].pack('S')
                  all_ace[4,4] = [account_rights].pack('L')

                  val = AddAce(
                     acl_new,
                     ACL_REVISION2,
                     MAXDWORD,
                     all_ace_ptr,
                     all_ace[2,2].unpack('S').first
                  )

                  if val == 0
                     raise ArgumentError, get_last_error
                  end

                  # all_ace_ptr->Header.AceFlags = CONTAINER_INHERIT_ACE
                  all_ace[1] = CONTAINER_INHERIT_ACE
               else
                  # all_ace_ptr->Header.AceFlags = 0
                  all_ace[1] = 0
               end

               account_rights = REST_RIGHTS_MASK & mask
            }
         }

         unless SetSecurityDescriptorDacl(sec_desc, 1, acl_new, 0)
            raise ArgumentError, get_last_error
         end

         unless SetFileSecurity(file, DACL_SECURITY_INFORMATION, sec_desc)
            raise ArgumentError, get_last_error
         end

         self
      end