dcsimg

Scripting NTFS permisions with ADSI (Part 2)

By ServerWatch Staff (Send Email)
Posted May 13, 2002


by Marcin Policht


In his latest article in a series discussing a scripting approach to modifying Security Descriptors, Marcin Policht takes a closer look at Access Masks and Access Control Entry Types.

This is the second article in the series discussing a scripting approach to modifying Security Descriptors. In the first one, I discussed the components that the descriptor is composed of and their role in determining resulting permissions. Even though the focus of the discussion was on permissions on file system objects (files and folders), keep in mind that security descriptors are also used to control access to registry and objects in Active Directory and can also be used to set auditing on object access (which I will cover in future articles).

In this article we took a closer look at Access Mask, which controls levels of permissions and Access Control Entry Type, which (when dealing with permissions) determines whether this level of permissions is allowed or denied. Each Access Control Entry, besides ACE Mask and ACE Type, also contains a SID of a trustee (user or group) to which they apply. Access Control Entry also contains control flags determining inheritance behavior - e.g. whether permissions set on a folder will propagate to all of its subfolders and files. As I mentioned, for now we will disregard SACL entries that deal with auditing object access.

The script below allows you to list Access Control Entries for an arbitrarily chosen file or folder. It is based on the information included in the Microsoft Knowledge Article Q279682 "How to Use ADsSecurity.dll to Add an Access Control Entry to an NTFS Folder". As explained previously, in order to be able to take advantage of its functionality, you will need to first copy ADsSecurity.DLL file to your local system and register using REGSVR32.EXE. ADsSecurity.DLL is part of the ADSI Software Development Kit, freely downloadable from the Microsoft Web Site.

Once you complete the registration process, copy the script below and save it into a file ACLs.vbs. In order to execute the script, you would use the following syntax:

cscript //nologo ACLs.vbs ACTION=SHOW TARGET=[File|Folder] [ACCOUNT=Domain\Account]

where TARGET parameter is the full path to a file or folder for which you want to list permissions. ACCOUNT parameter is optional and allows you to narrow down the list to a specific account only.

For example, in order to find out permissions on c:\boot.ini file, you would run the following:

cscript //nologo ACLs.vbs ACTION=SHOW TARGET=c:\boot.ini

If you want to limit the listing to display permissions on MPolicht account in the SWYNK domain, you would execute:

cscript //nologo ACLs.vbs ACTION=SHOW TARGET=c:\boot.ini ACCOUNT=SWYNK\MPolicht

The output of the script consists of one or more ACEs (depending on number of ACEs in the Security Descriptor and whether ACCOUNT parameter has been used). For each ACE, output contains the name of the Trustee, ACE Type, and ACE Permissions. If permissions fall into one of the four most common cumulative access levels (READ, CHANGE, FULL CONTROL, NO ACCESS) - as defined in the script - then the ACE Permissions entry will simply display the name of that level. Otherwise, ACE Permissions will list each individual ACE Mask set in the Access Control Entry. The listing will also display the total number of Access Control Entries in the Security Descriptor (this value does not depend on whether ACCOUNT parameter has been used).

Since the number of entries for a single file or folder can be fairly long, I decided to limit the display strictly to the target file or folder only. It would not be difficult, however, to repeat the same process for every file within the target folder or even run the script recursively for each subfolder (for example, by using methods and properties available via "Scripting.FileSystemObject" object model).

Notice, that although the script is fairly lengthy, it is partially due to the large number of constants and variables. The meaning of each is described in the comments accompanying each constant and variable declaration. The main portion of the script reads command line arguments, verifies their correctness, and executes the DisplayACLs subroutine. This sub uses the GetSecurityDescriptor method of the oADsSecurity object (exposed by ADsSecurity.dll). Once the object is instantiated, we can list its content. Discretionary Access Control List is retrieved via the line:

set oDACL = oTargetSD.DiscretionaryACL

This in turns allows us to enumerate (and display) each of the Access Control Entries that the Discretionary Access Control List consists of.

In my next article of this series, I will provide another script that will allow modifying a security descriptor by creating new (or replacing existing) Access Control Entries.



Option Explicit

'**************************************************
'*** Constant Declarations

'**************************************************
'*** Access Control Entry Inheritance Flags
'*** Possible values for the IADsAccessControlEntry::AceFlags property.  

const ADS_ACEFLAG_UNKNOWN                  	= &h1

'*** child objects will inherit ACE of current object
const ADS_ACEFLAG_INHERIT_ACE 			= &h2	
'*** prevents ACE inherited by the object from further propagation
const ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE 	= &h4
'*** indicates ACE used only for inheritance (it does not affect permissions on object itself)
const ADS_ACEFLAG_INHERIT_ONLY_ACE 		= &h8
'*** indicates that ACE was inherited	
const ADS_ACEFLAG_INHERITED_ACE 		= &h10
'*** indicates that inherit flags are valid (provides confirmation of valid settings)
const ADS_ACEFLAG_VALID_INHERIT_FLAGS 		= &h1f
'*** for auditing success in system audit ACE
const ADS_ACEFLAG_SUCCESSFUL_ACCESS 		= &h40
'*** for auditing failure in system audit ACE
const ADS_ACEFLAG_FAILED_ACCESS 		= &h80

'**************************************************
'*** Access Control Entry Type Values
'*** Possible values for the IADsAccessContronEntry::AceType property.  

const ADS_ACETYPE_ACCESS_ALLOWED           	= 0
const ADS_ACETYPE_ACCESS_DENIED            	= &h1
const ADS_ACETYPE_SYSTEM_AUDIT             	= &h2
const ADS_ACETYPE_ACCESS_ALLOWED_OBJECT    	= &h5
const ADS_ACETYPE_ACCESS_DENIED_OBJECT    	= &h6
const ADS_ACETYPE_SYSTEM_AUDIT_OBJECT     	= &h7

'**************************************************
'*** Access Control Entry Permission Type Values
'*** Possible values for the IADsAccessControlEntry::AccessMask property.  

'*** permission to read data from file or list contents of directory
'*** corresponds to List Folder / Read Data permissions in Windows UI
const FILE_READ_DATA 				= &h1		'bit number 0
const FILE_LIST_DIRECTORY 			= &h1		'bit number 0

'*** permission to write data to file or create file in directory
'*** corresponds to Create Files / Write Data permissions in Windows UI
const FILE_WRITE_DATA 				= &h2		'bit number 1
const FILE_ADD_FILE 				= &h2		'bit number 1

'*** permission to append data to file or to create subdirectory
'*** corresponds to Create Folders / Append Data permissions in Windows UI
const FILE_APPEND_DATA				= &h4		'bit number 2
const FILE_ADD_SUBDIRECTORY 			= &h4		'bit number 2

'*** permission to read extended attributes
'*** corresponds to Read Extended Attributes permissions in Windows UI
const FILE_READ_EA 				= &h8		'bit number 3

'*** permission to write extended attributes
'*** corresponds to Write Extended Attributes permissions in Windows UI
const FILE_WRITE_EA				= &h10		'bit number 4

'*** permission to execute file or traverse directory
'*** corresponds to Traverse Folder / Execute File permissions in Windows UI
const FILE_EXECUTE 				= &h20		'bit number 5
const FILE_TRAVERSE 				= &h20		'bit number 5

'*** permission to delete directory and all files it contains
'*** corresponds to Delete Subfolders and Files permissions in Windows UI
const FILE_DELETE_CHILD 			= &h40		'bit number 6

'*** permission to read file or folder attributes
'*** corresponds to Read Attributes permissions in Windows UI
const FILE_READ_ATTRIBUTES 			= &h80		'bit number 7

'*** permission to change file or folder attributes
'*** corresponds to Write Attributes permissions in Windows UI
const FILE_WRITE_ATTRIBUTES			= &h100		'bit number 8

'*** permission to delete file or folder
'*** corresponds to Delete permissions in Windows UI
const DELETE 					= &h10000	'bit number 16

'*** permission to read security descriptor
'*** corresponds to Read Permissions permissions in Windows UI
const READ_CONTROL				= &h20000	'bit number 17

'*** permission to change discretionary ACL
'*** corresponds to Change Permissions permissions in Windows UI
const WRITE_DAC 				= &h40000	'bit number 18

'*** permission to assign owner
'*** corresponds to Take Ownership permissions in Windows UI
const WRITE_OWNER				= &h80000	'bit number 19

'*** permission to synchronize
'*** bit indicating permission to perform synchronize operation, used sometimes during file access
'*** this permission is automaticaly granted with read and write access and revoked when read or write access is denied. 
'*** it is not displayed in the list of permissions in Windows UI
const SYNCHRONIZE 				= &h100000	'bit number 20

const ADS_RIGHT_GENERIC_ALL            		= &h10000000	'bit number 28
const ADS_RIGHT_GENERIC_EXECUTE        		= &h20000000	'bit number 29
const ADS_RIGHT_GENERIC_WRITE          		= &h40000000	'bit number 30
const ADS_RIGHT_GENERIC_READ           		= &h80000000	'bit number 31

'**************************************************
'*** Variable Declarations

Dim adsFILE_FULL	'value representing sum of access mask corresponding to full file access
Dim adsFOLDER_FULL	'value representing sum of access mask corresponding to full folder access
Dim adsFILE_CHANGE	'value representing sum of access mask corresponding to change file access
Dim adsFOLDER_CHANGE	'value representing sum of access mask corresponding to change folder access
Dim adsFILE_READ	'value representing sum of access mask corresponding to read file access
Dim adsFOLDER_READ	'value representing sum of access mask corresponding to read folder access
Dim adsFILE_NOACCESS	'value representing sum of access mask corresponding to denied full file access
Dim adsFOLDER_NOACCESS	'value representing sum of access mask corresponding to denied full folder access

adsFILE_FULL		= FILE_READ_DATA Or FILE_WRITE_DATA Or FILE_APPEND_DATA Or _
			FILE_READ_EA Or FILE_WRITE_EA Or FILE_EXECUTE Or FILE_DELETE_CHILD Or _
			FILE_READ_ATTRIBUTES Or FILE_WRITE_ATTRIBUTES Or DELETE Or _
			READ_CONTROL Or WRITE_DAC Or WRITE_OWNER Or SYNCHRONIZE
adsFOLDER_FULL 		= FILE_LIST_DIRECTORY Or FILE_ADD_FILE Or FILE_ADD_SUBDIRECTORY Or _
			FILE_READ_EA Or FILE_WRITE_EA Or FILE_TRAVERSE Or FILE_DELETE_CHILD Or _
			FILE_READ_ATTRIBUTES Or FILE_WRITE_ATTRIBUTES Or DELETE Or _
			READ_CONTROL Or WRITE_DAC Or WRITE_OWNER Or SYNCHRONIZE
adsFILE_CHANGE 		= FILE_READ_DATA Or FILE_WRITE_DATA Or FILE_APPEND_DATA Or _
			FILE_READ_EA Or FILE_WRITE_EA Or FILE_EXECUTE Or _
			FILE_READ_ATTRIBUTES Or FILE_WRITE_ATTRIBUTES Or DELETE Or _
			READ_CONTROL Or SYNCHRONIZE
adsFOLDER_CHANGE	= FILE_LIST_DIRECTORY Or FILE_ADD_FILE Or FILE_ADD_SUBDIRECTORY Or _
			FILE_READ_EA Or FILE_WRITE_EA Or FILE_TRAVERSE Or _
			FILE_READ_ATTRIBUTES Or FILE_WRITE_ATTRIBUTES Or DELETE Or _
			READ_CONTROL Or SYNCHRONIZE
adsFILE_READ 		= FILE_READ_DATA Or FILE_READ_EA Or FILE_EXECUTE Or _
			FILE_READ_ATTRIBUTES Or READ_CONTROL Or SYNCHRONIZE
adsFOLDER_READ		= FILE_LIST_DIRECTORY Or FILE_READ_EA Or FILE_TRAVERSE Or _
			FILE_READ_ATTRIBUTES Or READ_CONTROL Or SYNCHRONIZE
adsFILE_NOACCESS 	= FILE_READ_DATA Or FILE_WRITE_DATA Or FILE_APPEND_DATA Or _
			FILE_READ_EA Or FILE_WRITE_EA Or FILE_EXECUTE Or FILE_DELETE_CHILD Or _
			FILE_READ_ATTRIBUTES Or FILE_WRITE_ATTRIBUTES Or DELETE Or _
			READ_CONTROL Or WRITE_DAC Or WRITE_OWNER
adsFOLDER_NOACCESS 	= FILE_LIST_DIRECTORY Or FILE_ADD_FILE Or FILE_ADD_SUBDIRECTORY Or _
			FILE_READ_EA Or FILE_WRITE_EA Or FILE_TRAVERSE Or FILE_DELETE_CHILD Or _
			FILE_READ_ATTRIBUTES Or FILE_WRITE_ATTRIBUTES Or DELETE Or _
			READ_CONTROL Or WRITE_DAC Or WRITE_OWNER

Dim sAction		'type of action to perform (show or set)
Dim sPermission		'permission type (read, change, full, or no access)
Dim sAccount		'user or group account for which permissions are shown/set
Dim sTarget		'target file or folder path
Dim iTarget		'integer indicating type of target 0 - file, 1 - folder
Dim iOffset		'value used for display only (left justifying displayed values)

Dim oADSSecurity	'object representing ADsSecurity class
Dim oFSO		'object representing Scripting.FileSystemObject ProgID

'**************************************************
'*** Retrieve script arguments

Call GetArguments(Wscript.Arguments, sAction, sTarget, sAccount, sPermission)

'**************************************************
'*** Set variables

iOffset 		= 20
Set oFSO 		= CreateObject("Scripting.FileSystemObject")
Set oADSSecurity 	= CreateObject("ADsSecurity")

If oFSO.FileExists(sTarget) Then 
	iTarget = 0
ElseIf oFSO.FolderExists(sTarget) Then
	iTarget = 1
Else
	Call MsgBox("Target File or Folder does not exist", vbOKOnly, "Incorrect argument")
	WScript.Quit
End If

Select Case UCase(sAction)
	Case "SHOW"	
			Call DisplayACLs(sTarget, sAccount)
	Case Else
			Call DisplayUsage("ERROR: Incorrect ACTION type")			
End Select

Wscript.Quit

'**************************************************
'*** Subroutine reading command line arguments
'
Sub GetArguments(oArgs, sAction, sTarget, sAccount, sPermission)

Dim iCount

For iCount=0 To oArgs.Count - 1
	Select Case UCase(Split(WScript.Arguments(iCount), "=")(0))
		Case "ACTION" 	sAction 	= Split(WScript.Arguments(iCount), "=")(1)	
		Case "TARGET"	sTarget 	= Split(WScript.Arguments(iCount), "=")(1)
		Case "ACCOUNT" 	sAccount	= Split(WScript.Arguments(iCount), "=")(1)
		Case "PERM" 	sPermission 	= Split(WScript.Arguments(iCount), "=")(1)
	End Select
Next

If sAction = "" or sTarget = "" Then
	Call DisplayUsage("ERROR: Missing argument(s)")
	WScript.Quit
End If

end sub	


'**************************************************
'*** Subroutine displaying usage of the script from the command line
'
sub DisplayUsage(sHeader)

Dim sMsg

	sMsg = "To display permissions on file/folder (ACCOUNT parameter is optional) run:"
	sMsg = sMsg & VbCrLf & _
		"cscript //nologo ACLs.vbs ACTION=SHOW TARGET=[File|Folder] [ACCOUNT=Domain\Account]"
	sMsg = sMsg & VbCrLf & vbCrLf & "Where:"
	sMsg = sMsg & VbCrLf & String(7," ") & "ACTION is set to SHOW to display permissions"
	sMsg = sMsg & VbCrLf & String(7," ") & "TARGET is full path to the file or folder"
	sMsg = sMsg & VbCrLf & String(7," ") & "ACCOUNT is user or group account in the DOMAIN\AccountName format"

	Call MsgBox(sMsg, vbOKOnly, sHeader)

end sub

'**************************************************
'*** Subroutine displaying list of Trustees, AcL Types, and ACL Masks
'
Sub DisplayACLs(sTarget, sAccount)

Dim oACE		'object representing an Access Control Entry
Dim sMsg, sAccessMask	'strings containing message to be displayed
Dim hAccessMask		'number representing Access Mask value
Dim oTargetSD		'object representing security descriptor of target file or folder
Dim oDACL		'object representing Discretionary Access Control List

set oTargetSD = oADsSecurity.GetSecurityDescriptor("FILE://" & Cstr(sTarget))
set oDACL = oTargetSD.DiscretionaryACL

For Each oACE in oDACL
	If sAccount = "" or UCase(sAccount) = UCase(oACE.Trustee) Then 
		sMsg = vbCrLf & "Trustee:" & String(iOffset - Len("Trustee:"), Chr(32)) & oACE.Trustee & vbCrLf
		sMsg = sMsg & "ACE Type:" & String(iOffset - Len("ACE Type:"), Chr(32)) 
		Select Case oACE.AceType    
			Case ADS_ACETYPE_ACCESS_ALLOWED       
				'Implicit Allow ACE
				sMsg = sMsg & "ACCESS_ALLOWED"
			Case ADS_ACETYPE_ACCESS_DENIED       
				'Implicit Deny ACE
				sMsg = sMsg & "ACCESS_DENIED"
			Case ADS_ACETYPE_ACCESS_ALLOWED_OBJECT       
				'Object Allowed ACE
				sMsg = sMsg & "ACCESS_ALLOWED_OBJECT"    
			Case ADS_ACETYPE_ACCESS_DENIED_OBJECT        
				'Object Deny ACE
				sMsg = sMsg & "ACCESS_DENIED_OBJECT"
		End Select 
		Wscript.Echo sMsg

		sAccessMask = ""
		hAccessMask = 0
		If iTarget = 0 Then
			If (oACE.AccessMask AND FILE_READ_DATA) Then
				sAccessMask = String(iOffset, Chr(32)) & "FILE_READ_DATA" & vbCrLf
				hAccessMask = hAccessMask + FILE_READ_DATA
			End If
			If (oACE.AccessMask AND FILE_WRITE_DATA) Then
				sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_WRITE_DATA" & vbCrLf
				hAccessMask = hAccessMask + FILE_WRITE_DATA
			End If
			If (oACE.AccessMask AND FILE_APPEND_DATA) Then
				sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_APPEND_DATA" & vbCrLf
				hAccessMask = hAccessMask + FILE_APPEND_DATA
			End If
			If (oACE.AccessMask AND FILE_READ_EA) Then
				sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_READ_EA" & vbCrLf
				hAccessMask = hAccessMask + FILE_READ_EA
			End If
			If (oACE.AccessMask AND FILE_WRITE_EA) Then
				sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_WRITE_EA" & vbCrLf
				hAccessMask = hAccessMask + FILE_WRITE_EA
			End If
			If (oACE.AccessMask AND FILE_EXECUTE) Then
				sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_EXECUTE" & vbCrLf
				hAccessMask = hAccessMask + FILE_EXECUTE
			End If
			If (oACE.AccessMask AND FILE_DELETE_CHILD) Then
				sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_DELETE_CHILD" & vbCrLf
				hAccessMask = hAccessMask + FILE_DELETE_CHILD
			End If
			If (oACE.AccessMask AND FILE_READ_ATTRIBUTES) Then
				sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_READ_ATTRIBUTES" & vbCrLf
				hAccessMask = hAccessMask + FILE_READ_ATTRIBUTES
			End If
			If (oACE.AccessMask AND FILE_WRITE_ATTRIBUTES) Then
				sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_WRITE_ATTRIBUTES" & vbCrLf
				hAccessMask = hAccessMask + FILE_WRITE_ATTRIBUTES
			End If
			If (oACE.AccessMask AND DELETE) Then
				sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "DELETE" & vbCrLf
				hAccessMask = hAccessMask + DELETE
			End If
			If (oACE.AccessMask AND READ_CONTROL) Then
				sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "READ_CONTROL" & vbCrLf
				hAccessMask = hAccessMask + READ_CONTROL
			End If
			If (oACE.AccessMask AND WRITE_DAC) Then
				sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "WRITE_DAC" & vbCrLf
				hAccessMask = hAccessMask + WRITE_DAC
			End If
			If (oACE.AccessMask AND WRITE_OWNER) Then
				sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "WRITE_OWNER" & vbCrLf
				hAccessMask = hAccessMask + WRITE_OWNER
			End If
			If (oACE.AccessMask AND SYNCHRONIZE) Then
				sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "SYNCHRONIZE" & vbCrLf
				hAccessMask = hAccessMask + SYNCHRONIZE
			End If
		End If

		If iTarget = 1 Then
			If (oACE.AccessMask AND FILE_LIST_DIRECTORY) Then
				sAccessMask = String(iOffset, Chr(32)) & "FILE_LIST_DIRECTORY" & vbCrLf
				hAccessMask = hAccessMask + FILE_LIST_DIRECTORY
			End If
			If (oACE.AccessMask AND FILE_ADD_FILE) Then
				sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_ADD_FILE" & vbCrLf
				hAccessMask = hAccessMask + FILE_ADD_FILE
			End If
			If (oACE.AccessMask AND FILE_ADD_SUBDIRECTORY) Then
				sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_ADD_SUBDIRECTORY" & vbCrLf
				hAccessMask = hAccessMask + FILE_ADD_SUBDIRECTORY
			End If
			If (oACE.AccessMask AND FILE_READ_EA) Then
				sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_READ_EA" & vbCrLf
				hAccessMask = hAccessMask + FILE_READ_EA
			End If
			If (oACE.AccessMask AND FILE_WRITE_EA) Then
				sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_WRITE_EA" & vbCrLf
				hAccessMask = hAccessMask + FILE_WRITE_EA
			End If
			If (oACE.AccessMask AND FILE_TRAVERSE) Then
				sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_TRAVERSE" & vbCrLf
				hAccessMask = hAccessMask + FILE_TRAVERSE
			End If
			If (oACE.AccessMask AND FILE_DELETE_CHILD) Then
				sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_DELETE_CHILD" & vbCrLf
				hAccessMask = hAccessMask + FILE_DELETE_CHILD
			End If
			If (oACE.AccessMask AND FILE_READ_ATTRIBUTES) Then
				sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_READ_ATTRIBUTES" & vbCrLf
				hAccessMask = hAccessMask + FILE_READ_ATTRIBUTES
			End If
			If (oACE.AccessMask AND FILE_WRITE_ATTRIBUTES) Then
				sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_WRITE_ATTRIBUTES" & vbCrLf
				hAccessMask = hAccessMask + FILE_WRITE_ATTRIBUTES
			End If
			If (oACE.AccessMask AND DELETE) Then
				sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "DELETE" & vbCrLf
				hAccessMask = hAccessMask + DELETE
			End If
			If (oACE.AccessMask AND READ_CONTROL) Then
				sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "READ_CONTROL" & vbCrLf
				hAccessMask = hAccessMask + READ_CONTROL
			End If
			If (oACE.AccessMask AND WRITE_DAC) Then
				sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "WRITE_DAC" & vbCrLf
				hAccessMask = hAccessMask + WRITE_DAC
			End If
			If (oACE.AccessMask AND WRITE_OWNER) Then
				sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "WRITE_OWNER" & vbCrLf
				hAccessMask = hAccessMask + WRITE_OWNER
			End If
			If (oACE.AccessMask AND SYNCHRONIZE) Then
				sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "SYNCHRONIZE" & vbCrLf
				hAccessMask = hAccessMask + SYNCHRONIZE
			End If
		End If
		sMsg = "ACE Permissions:" & String(iOffset - Len("ACE Permissions:"), Chr(32)) 
		Select Case hAccessMask
			Case adsFILE_FULL 	Wscript.Echo sMsg & "FULL CONTROL"
			Case adsFOLDER_FULL 	Wscript.Echo sMsg & "FULL CONTROL"
			Case adsFILE_CHANGE 	Wscript.Echo sMsg & "CHANGE"
			Case adsFOLDER_CHANGE 	Wscript.Echo sMsg & "CHANGE"
			Case adsFILE_READ 	Wscript.Echo sMsg & "READ"
			Case adsFOLDER_READ 	Wscript.Echo sMsg & "READ"
			Case adsFILE_NOACCESS 	Wscript.Echo sMsg & "NO ACCESS"
			Case adsFOLDER_NOACCESS Wscript.Echo sMsg & "NO ACCESS"
			Case Else		WScript.Echo sMsg & "" & oACE.AccessMask
						WScript.Echo sAccessMask
		End Select

		sMsg = "ACE Flags:" & String(iOffset - Len("ACE Flags:"), Chr(32)) 
		If (oACE.AceFlags AND ADS_ACEFLAG_INHERIT_ACE) Then
			WScript.Echo sMsg & "ADS_ACEFLAG_INHERIT_ACE"
		End If
		If (oACE.AceFlags AND ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE) Then 
			WScript.Echo sMsg & "ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE"
		End If
		If (oACE.AceFlags AND ADS_ACEFLAG_INHERIT_ONLY_ACE) Then
			WScript.Echo sMsg & "ADS_ACEFLAG_INHERIT_ONLY_ACE"
		End If
		If (oACE.AceFlags AND ADS_ACEFLAG_INHERITED_ACE) Then
			WScript.Echo sMsg & "ADS_ACEFLAG_INHERITED_ACE"
		End If
		If (oACE.AceFlags AND ADS_ACEFLAG_VALID_INHERIT_FLAGS) Then
			WScript.Echo sMsg & "ADS_ACEFLAG_VALID_INHERIT_FLAGS"
		End If
		If (oACE.AceFlags AND ADS_ACEFLAG_SUCCESSFUL_ACCESS) Then
			WScript.Echo sMsg & "ADS_ACEFLAG_SUCCESSFUL_ACCESS"
		End If
		If (oACE.AceFlags AND ADS_ACEFLAG_FAILED_ACCESS) Then
			WScript.Echo sMsg & "ADS_ACEFLAG_FAILED_ACCESS"
		End If
		If (oACE.AceFlags AND ADS_ACEFLAG_UNKNOWN) Then
			WScript.Echo sMsg & "ADS_ACEFLAG_UNKNOWN"
		End If
	End If
Next

WScript.Echo "Total ACE entries:" &_
		String(iOffset - Len("Total ACE entries:"), Chr(32)) & oDACL.AceCount
WScript.Echo "ACL revision:" &_ 
		String(iOffset - Len("ACL revision:"), Chr(32)) & oDACL.ACLRevision

End Sub


Page 1 of 1


Comment and Contribute

Your name/nickname

Your email

(Maximum characters: 1200). You have characters left.