Geoff Chappell - Software Analyst
This function prepares a security descriptor.
PSECURITY_DESCRIPTOR GetShellSecurityDescriptor ( PSHELL_USER_PERMISSION apUserPerm, int cUserPerm);
The apUserPerm argument provides the address of an array of SHELL_USER_PERMISSION structures, each of which describes permissions to apply to some user or group.
The cUserPerm argument provides a count of SHELL_USER_PERMISSION structures in the array.
Since the SHELL_USER_PERMISSION structure appears to be used only as input to this function, its format is as well given here with the parameters.
typedef struct _SHELL_USER_PERMISSION { SHELL_USER_SID susID; DWORD dwAccessType; BOOL fInherit; ACCESS_MASK dwAccessMask; DWORD dwInheritMask; ACCESS_MASK dwInheritAccessMask; } SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION;
The user or group is described by the susID member. It has the format of a SHELL_USER_SID structure and provides sufficient information from which to build a SID. The successive members provide the identifier authority and two subauthorities, or only one if the second is zero. If the authority is SECURITY_NULL_SID_AUTHORITY and the two subauthorities are each zero (SECURITY_NULL_RID), then the susID member is understood to describe the current user.
typedef struct _SHELL_USER_SID { SID_IDENTIFIER_AUTHORITY sidAuthority; DWORD dwUserGroupID; DWORD dwUserID; } SHELL_USER_SID, *PSHELL_USER_SID;
The dwAccessType member is zero (ACCESS_ALLOWED_ACE_TYPE) to allow access, else non-zero to deny access. The dwAccessMask member provides the access rights that are to be allowed or denied.
The fInherit member is non-zero if access is to be inheritable. In this case, the dwInheritMask member provides flags that govern the inheritance (as in the AceFlags member of an ACE) and the dwInheritAccessMask member provides the access rights that are to be transferred when inheriting.
The function returns the address of a security descriptor, if successful, else NULL.
The function fails immediately if pUserPerm is NULL or if cUserPerm is not positive.
For each SHELL_USER_PERMISSION structure, the function prepares either one ACE or two for the security descriptor, depending on whether the permissions are inheritable. The first ACE
A second ACE for this same SHELL_USER_PERMISSION is prepared if and only if fInherit is non-zero. This second ACE
The SID for each ACE is built from the authority and subauthorities provided by susID, except that if susID describes the current user, the function obtains a SID from the access token for the current process.
The security descriptor is constructed in one memory block such that the SECURITY_DESCRIPTOR structure (in absolute format) is followed immediately by an ACL, including the ACEs. This ACL is set as the security descriptor’s DACL. The order of the ACEs is the same as the SHELL_USER_PERMISSION structures that they were built from. The memory block is obtained from LocalAlloc and may be returned through LocalFree when the caller is done with it.
The GetShellSecurityDescriptor function is exported from SHLWAPI as ordinal 475 in version 5.50 and higher.
Though this function dates from as long ago as 2000, it was still not documented by Microsoft in the MSDN Library at least as late as the CD edition dated January 2004.
This function has, however, got documented since then (in 2006, or perhaps some time during 2005), albeit as requiring “version 6.0 or later”. This article now uses Microsoft’s nomenclature.