Here's a script I've written, I've gathered all MS's VB scripts on scripting ACL's and written this.
This script has 2 improvements over AdsSecurity.dll
1. It doesn't need AdsSecurity.dll
2. It handles inheritance properly.

Although microsoft also claims thats with IADsSecurityUtility there is no need for ReOrdering anymore, I beg to differ. When using this script on a remote computer it sets the permissions correctly but after using the script, create a subfolder and open the properties tab on the permissions and you will get the notice that the order is not correct.

Update: inheritance works correctly if the parent's list of ACL's are in the correct order.

However I still feel that this is the best utility to use since it sets permissions easier and better the calcs,xcacls,SetACL and AdsSecurity.dll
besides it is incorporated in Windows XP and higher (unfortunately not on Windows 2000).

Anyway without further ado, here's the code:
Code:

;ACLControl()
;By Arend Pronk

Debug Off
Break On
Dim $iRC
$iRC=SetOption('Explicit','on')
$iRC=SetOption('NoVarsInStrings','on')
$iRC=SetOption('WrapAtEOL','on')

Function ACLControl($cmd, $object, Optional $Trustee, Optional $perms)
Dim $ADS_RIGHT_DELETE, $ADS_RIGHT_READ_CONTROL, $ADS_RIGHT_WRITE_DAC
Dim $ADS_RIGHT_WRITE_OWNER, $ADS_RIGHT_SYNCHRONIZE, $ADS_RIGHT_ACCESS_SYSTEM_SECURITY
Dim $ADS_RIGHT_GENERIC_READ, $ADS_RIGHT_GENERIC_WRITE, $ADS_RIGHT_GENERIC_EXECUTE
Dim $ADS_RIGHT_GENERIC_ALL, $ADS_RIGHT_DS_CREATE_CHILD, $ADS_RIGHT_DS_DELETE_CHILD
Dim $ADS_RIGHT_ACTRL_DS_LIST, $ADS_RIGHT_DS_SELF, $ADS_RIGHT_DS_READ_PROP
Dim $ADS_RIGHT_DS_WRITE_PROP, $ADS_RIGHT_DS_DELETE_TREE, $ADS_RIGHT_DS_LIST_OBJECT
Dim $ADS_RIGHT_DS_CONTROL_ACCESS, $ADS_ACETYPE_ACCESS_ALLOWED, $ADS_ACETYPE_ACCESS_DENIED
Dim $ADS_ACETYPE_SYSTEM_AUDIT, $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT, $ADS_ACETYPE_ACCESS_DENIED_OBJECT
Dim $ADS_ACETYPE_SYSTEM_AUDIT_OBJECT, $ADS_ACEFLAG_UNKNOWN, $ADS_ACEFLAG_INHERIT_ACE
Dim $ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE, $ADS_ACEFLAG_INHERIT_ONLY_ACE, $ADS_ACEFLAG_SUB_NEW
Dim $ADS_ACEFLAG_INHERITED_ACE, $ADS_ACEFLAG_VALID_INHERIT_FLAGS, $ADS_ACEFLAG_SUCCESSFUL_ACCESS
Dim $ADS_ACEFLAG_FAILED_ACCESS, $ADS_FLAG_OBJECT_TYPE_PRESENT, $ADS_FLAG_INHERITED_OBJECT_TYPE_PRESENT
Dim $ADS_PATH_FILE, $ADS_PATH_FILESHARE, $ADS_PATH_REGISTRY
Dim $ADS_SD_FORMAT_IID, $ADS_SD_FORMAT_RAW, $ADS_SD_FORMAT_HEXSTRING
;
; Define the ADS_RIGHTS_ENUM values.
;
$ADS_RIGHT_DELETE = &10000
$ADS_RIGHT_READ_CONTROL = &20000
$ADS_RIGHT_WRITE_DAC = &40000
$ADS_RIGHT_WRITE_OWNER = &80000
$ADS_RIGHT_SYNCHRONIZE = &100000
$ADS_RIGHT_ACCESS_SYSTEM_SECURITY = &1000000
$ADS_RIGHT_GENERIC_READ = &80000000
$ADS_RIGHT_GENERIC_WRITE = &40000000
$ADS_RIGHT_GENERIC_EXECUTE = &20000000
$ADS_RIGHT_GENERIC_ALL = &10000000
$ADS_RIGHT_DS_CREATE_CHILD = &1
$ADS_RIGHT_DS_DELETE_CHILD = &2
$ADS_RIGHT_ACTRL_DS_LIST = &4
$ADS_RIGHT_DS_SELF = &8
$ADS_RIGHT_DS_READ_PROP = &10
$ADS_RIGHT_DS_WRITE_PROP = &20
$ADS_RIGHT_DS_DELETE_TREE = &40
$ADS_RIGHT_DS_LIST_OBJECT = &80
$ADS_RIGHT_DS_CONTROL_ACCESS = &100
;
; Ace Type definitions
;
$ADS_ACETYPE_ACCESS_ALLOWED = &0
$ADS_ACETYPE_ACCESS_DENIED = &1
$ADS_ACETYPE_SYSTEM_AUDIT = &2
$ADS_ACETYPE_ACCESS_ALLOWED_OBJECT = &5
$ADS_ACETYPE_ACCESS_DENIED_OBJECT = &6
$ADS_ACETYPE_SYSTEM_AUDIT_OBJECT = &7
;
; Ace Flag Constants
;
$ADS_ACEFLAG_UNKNOWN = &1
$ADS_ACEFLAG_INHERIT_ACE = &2
$ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE = &4
$ADS_ACEFLAG_INHERIT_ONLY_ACE = &8
$ADS_ACEFLAG_SUB_NEW = &9
$ADS_ACEFLAG_INHERITED_ACE = &10
$ADS_ACEFLAG_VALID_INHERIT_FLAGS = &1F
$ADS_ACEFLAG_SUCCESSFUL_ACCESS = &40
$ADS_ACEFLAG_FAILED_ACCESS = &80
;
; Flags constants for AD objects
;
$ADS_FLAG_OBJECT_TYPE_PRESENT = &1
$ADS_FLAG_INHERITED_OBJECT_TYPE_PRESENT = &2
;
; IADsSecurityUtility Constants
;
$ADS_PATH_FILE = 1
$ADS_PATH_FILESHARE = 2
$ADS_PATH_REGISTRY = 3
;
; ADS_SD_FORMAT_ENUM
;
$ADS_SD_FORMAT_IID = 1
$ADS_SD_FORMAT_RAW = 2
$ADS_SD_FORMAT_HEXSTRING = 3

Dim $Ace, $oAce, $oSD, $oDacl, $oADsSecurityUtility

$oADsSecurityUtility = CreateObject("ADsSecurityUtility")
If @error <> 0
;couln't create the object, your OS must be lower then XP.
Exit @error
EndIf
$oSD = $oADsSecurityUtility.GetSecurityDescriptor($object, $ADS_PATH_FILE, $ADS_SD_FORMAT_IID)
$oDacl = $oSD.DiscretionaryAcl

Select
CASE $cmd = "SHOW"
For Each $Ace In $oDacl
? "Trustee: " + $Ace.Trustee
? "Flags: " + $Ace.AceFlags
? "AccessMask: " + $Ace.AccessMask
? "Type: " + $Ace.AceType + @CRLF
Next
CASE $cmd = "ADD"
If $trustee <> ""
$oAce = CreateObject("AccessControlEntry")
$oAce.Trustee = $Trustee
Select
CASE $perms = "FULL"
$oAce.AccessMask = $ADS_RIGHT_GENERIC_ALL
CASE $perms = "READ"
$oAce.AccessMask = $ADS_RIGHT_GENERIC_READ
CASE $perms = "READWRITE"
$oAce.AccessMask = $ADS_RIGHT_GENERIC_READ + $ADS_RIGHT_GENERIC_WRITE
CASE $perms = "RWEX"
$oAce.AccessMask = $ADS_RIGHT_GENERIC_READ + $ADS_RIGHT_GENERIC_WRITE + $ADS_RIGHT_GENERIC_EXECUTE
CASE 1
;Perms were not properly specified defaulting to READ
$oAce.AccessMask = $ADS_RIGHT_GENERIC_READ
ENDSELECT
$oAce.AceType = $ADS_ACETYPE_ACCESS_ALLOWED
$oAce.AceFlags = $ADS_ACEFLAG_INHERIT_ACE + 1
$oDacl.AddAce($oAce)
$oSD.DiscretionaryAcl = $oDacl
$oADsSecurityUtility.SetSecurityDescriptor($object, $ADS_PATH_FILE, $oSD, $ADS_SD_FORMAT_IID)
If @error <> 0
Exit @error
EndIf
Else
;no trustee specified...
Exit 1
EndIf
CASE $cmd = "DEL"
If $trustee <> ""
For Each $Ace in $oDacl
If $Ace.trustee = $trustee
$oDacl.RemoveAce($Ace)
EndIf
Next
$oSD.DiscretionaryAcl = $oDacl
$oADsSecurityUtility.SetSecurityDescriptor($object, $ADS_PATH_FILE, $oSD, $ADS_SD_FORMAT_IID)
If @error <> 0
Exit @error
EndIf
Else
Exit 1
EndIf
CASE 1
;no proper command specified...
Exit 1
EndSelect
$oAce = ""
$oDacl = ""
$oSD = ""
$oADsSecurityUtility = ""
EndFunction

ACLControl("ADD","\\Server\share$\folder","Domain\testuser","FULL")
ACLControl("SHOW","\\Server\share$\folder")
ACLControl("DEL","\\Server\share$\folder","Domain\testuser")



[update]
Changes many parts of the code.
It works properly now, inheritance and all, problem resided in the server shares I tested the ACL order wasn't correct in the first place. This UDF isn't a miracle worker, when ACL's are proper in the first place this UDF will work properly. If not then it will not. I've tested this setting permissions on other workstations in my domain like "\\PC-1\c$\temp" and that worked without problem.

Added improvements over the last version, this will be the final version for now it works with all commands and i'll post it to the UDF's as is.
Next version will have Share Permissions.
[/update]


Edited by apronk (2006-05-03 03:37 PM)