NTFS (File System) and Share security can be enumerated using the Win32_LogicalFileSecuritySetting and Win32_LogicalShareSecuritySetting WMI classes. This post demonstrates how to use each class to read the security descriptors.

In each case the WMI class contains a GetSecurityDescriptor method used to retrieve the Security Descriptor (as a Win32_SecurityDescriptor).

The references section at the bottom of this article include details of sources for all constants. A little PowerShell creeps in to show how the numeric values were retrieved and checked.


A DACL or Discretionary Access Control List is the most heavily used, it contains Access Control Entries that define who can, and who cannot, access a resource or object. These are seen when viewing the Security tab of an object.

An SACL or System Access Control List defines which actions will be audited when accessing an a resource or object. Seen by accessing the Audit tab through Security and Advanced.

NTFS security vs Share security

Both the NTFS and the Share security descriptor can be read in exactly the same way. However, there are important differences between them.

NTFS security descriptor

  • Supports inheritance on descriptor and on individual Access Control Entries
  • Can hold a Discretionary Access Control List and an System Access Control List

Share security descriptor

  • Has no owner or Primary Group
  • Control flags will be set (and usually limited) to SelfRelative and DiscretionaryACLPresent
  • Access Control Entry (ACE) Flags will not be set
  • Can hold a Discretionary Access Control List only
  • Supports a sub-set of Access Masks (rights) on each ACE

Getting the security descriptor



Error handling

The GetSecurityDescriptor method of each WMI class (Win32_LogicalFileSecuritySetting and Win32_LogicalShareSecuritySetting) has a return value to allow errors to be handled. The return codes are represented by the constants below.

Values in the security descriptor

The security descriptor contains three fields in addition to the DACL and SACL which are described later.

Control flags

Each security descriptor has a ControlFlags field which dictates how the descriptor behaves. This includes settings such as DACLProtected which indicates that the DACL cannot inherit values from a parent.

The script loads the values above into a Scripting.Dictionary object to simplify enumeration.

Note that they are intentionally entered in order from highest to lowest. A For Each loop will start with the highest value (because it was added first), then compare it to the ControlFlags value. In bitwise comparison, if the integer value can be there, then it must be there, that would all go wrong unless it starts with the highest possible value.

The values and names were taken from the .NET Framework, they can be displayed in PowerShell with the following command.

That logic is applied within the code as follows.

Primary group

The Primary Group is not very interesting unless Services for Unix is in use. In many cases it will be blank.

If set, it can be enumerated as a Win32_Trustee, an object containing a Domain, Username, SID array, SID length and SIDString.


As with the Primary Group, the owner is stored as a Win32_Trustee object. It can be read from the descriptor as follows.

Access control entries in the DACL and SACL

Both the DACL and SACL, if present, consist of one or more Access Control Entries (ACE). The ACE, like the security descriptor, breaks down into a number of different fields.

Access Mask

The access mask defines which rights should be used by the Access Control Entry. In the case of System ACL it defines which actions should be audited.

A number of the right names are omitted from the list below as they carry the same numeric value (mask the same bit), the meaning only changes in the context the right is applied.

Note that a number of the rights in the list are composites of simpler rights, including Read, FullControl, Write and Modify.

The list can be retrieved, using PowerShell again, with the following command:

Holding the flags in this fashion allows the Access Mask to be converted to a friendly form in the same way as the Control Flags were displayed.


The flags on an Access Control Entry defines whether the entry applies to Leaf or Container objects, how it behaves when inheritance is calculated, and whether or not the ACE is inherited or explicit.

Heading back to PowerShell again we can find the the names and values for these.

A few are intentionally left out as they are composites of values more interesting to display separately.

Enumeration of the Access Control Entry flags is performed as follows.


The value for the trustee (Win32_Trustee), the security principal (user, group, computer, etc) the right applies to is enumerated in the same way as the Owner above.


Finally, the ACEType consists of three values which define whether the ACE permits access, denies access or is an audit control.

Once again, we can discover all of the possible values for AceFlags using PowerShell.

However, this time the only values that are used in the script are 0 (Allow), 1 (Deny), and 2 (Audit).

Listing permissions for all Shares

Time to put all of that together. This sample lists the NTFS and Share permissions for each share configured on strComputer.



  1. Very nice, thank you, this saved me a bunch of time!


  2. This is really excellent. Now I am trying to get all outputs in a file and roll it



  3. Pingback: [VBS]Reading NTFS and Share security with VbScript | Lyfog

Leave a Reply

Your email address will not be published. Required fields are marked *