How to use high-level access control APIs from Visual Basic

Summary

The Win32 API provides two sets of APIs for working with security descriptors (SDs) and access control lists (ACLs). Low-level as well as high-level access control API sets provide an interface for working with SDs and ACLs. For Microsoft Windows 2000 and MIcrosoft Windows XP, the high-level access control APIs have been enhanced to support object-specific access control entries (ACEs), directory service (DS) objects, and automatic inheritance. This article provides sample code that uses high-level access control APIs to modify an existing discretionary access control list (DACL) on a folder securable object.

More Information

The following Visual Basic sample code uses the GetNamedSecurityInfo() API to retrieve the existing DACL of the C:\Test1 folder. Then, it builds the EXPLICIT_ACCESS structure for everyone trustee with GENERIC_READ access by using the BuildExplicitAccessWithName() API. In this example, the ACE is constructed with inheritance CONTAINER_INHERIT_ACE or OBJECT_INHERIT_ACE, which applies as an effective ACE for the C:\Test1 folder and an inheritable ACE for subfolders as well as files.

The SetEntriesInAcl() API creates a new access-control list (ACL) by merging new access-control information specified in EXPLICIT_ACCESS structures into an existing ACL and returns a newly updated DACL in memory. This updated DACL is then used to set security on the C:\Test1 folder by using the SetNamedSecurityInfo() API.

Option Explicit

' Success status of high level access control APIs
Private Const ERROR_SUCCESS = 0&

' Type of Securable Object we are operating in this sample code
Private Const SE_FILE_OBJECT = 1&

' The Security Information constants required
Private Const DACL_SECURITY_INFORMATION = 4&
Private Const SET_ACCESS = 2&

' Standard access rights extracted from WinNT.h
Private Const SYNCHRONIZE = &H100000
Private Const READ_CONTROL = &H20000
Private Const WRITE_DAC = &H40000
Private Const WRITE_OWNER = &H80000
Private Const STANDARD_RIGHTS_READ = (READ_CONTROL)
Private Const STANDARD_RIGHTS_WRITE = (READ_CONTROL)
Private Const DELETE = &H10000

' Generic access rights extracted from WinNT.h
Private Const GENERIC_ALL = &H10000000
Private Const GENERIC_EXECUTE = &H20000000
Private Const GENERIC_READ = &H80000000
Private Const GENERIC_WRITE = &H40000000

' Inheritance Flags
Private Const CONTAINER_INHERIT_ACE = &H2
Private Const OBJECT_INHERIT_ACE = &H1

' The TRUSTEE structure identifies the user account, group account, or logon session
' to which an ACE applies. The structure can use a name or a security identifier (SID)
' to identify the trustee.

' Access control APIs, such as SetEntriesInAcl and GetExplicitEntriesFromAcl, use this
' structure to identify the account associated with the access-control or audit-control
' information in an EXPLICIT_ACCESS structure.
Private Type TRUSTEE
pMultipleTrustee As Long
MultipleTrusteeOperation As Long
TrusteeForm As Long
TrusteeType As Long
ptstrName As String
End Type

' EXPLICIT_ACCESS structure that specifies access-control information for a specified
' trustee such as access mask as well as inheritance flags
Private Type EXPLICIT_ACCESS
grfAccessPermissions As Long
grfAccessMode As Long
grfInheritance As Long
pTRUSTEE As TRUSTEE
End Type

' High Level access control API declarations
Private Declare Sub BuildExplicitAccessWithName Lib "Advapi32.dll" Alias _
"BuildExplicitAccessWithNameA" _
(ea As Any, _
ByVal TrusteeName As String, _
ByVal AccessPermissions As Long, _
ByVal AccessMode As Integer, _
ByVal Inheritance As Long)

Private Declare Function SetEntriesInAcl Lib "Advapi32.dll" Alias _
"SetEntriesInAclA" _
(ByVal CountofExplicitEntries As Long, _
ea As Any, _
ByVal OldAcl As Long, _
NewAcl As Long) As Long

Private Declare Function GetNamedSecurityInfo Lib "Advapi32.dll" Alias _
"GetNamedSecurityInfoA" _
(ByVal ObjName As String, _
ByVal SE_OBJECT_TYPE As Long, _
ByVal SecInfo As Long, _
ByVal pSid As Long, _
ByVal pSidGroup As Long, _
pDacl As Long, _
ByVal pSacl As Long, _
pSecurityDescriptor As Long) As Long

Private Declare Function SetNamedSecurityInfo Lib "Advapi32.dll" Alias _
"SetNamedSecurityInfoA" _
(ByVal ObjName As String, _
ByVal SE_OBJECT As Long, _
ByVal SecInfo As Long, _
ByVal pSid As Long, _
ByVal pSidGroup As Long, _
ByVal pDacl As Long, _
ByVal pSacl As Long) As Long

Private Declare Function LocalFree Lib "kernel32" (ByVal hMem As Long) As Long

Private Sub Command1_Click()

Dim result As Long
Dim pSecDesc As Long
Dim ea As EXPLICIT_ACCESS
Dim pNewDACL As Long
Dim pOldDACL As Long

' Get the DACL information of c:\test1 folder using GetNamedSecurityInfo() API.
' SE_FILE_OBJECT constant says that the named securable object is a file or folder
result = GetNamedSecurityInfo("c:\test1", SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, 0&, 0&, pOldDACL, 0&, pSecDesc)
If result = ERROR_SUCCESS Then

' Construct an EXPLICIT_ACCESS structure for Everyone with GENERIC_READ access that will apply for c:\test1
' as well as subfolder and files using BuildExplicitAccessWithName() API
BuildExplicitAccessWithName ea, "Users", GENERIC_READ, SET_ACCESS, CONTAINER_INHERIT_ACE Or OBJECT_INHERIT_ACE

' Merge constructed EXPLICIT_ACCESS structure to the existing DACL and get an updated DACL in memory from
' SetEntriesInAcl() API
result = SetEntriesInAcl(1, ea, pOldDACL, pNewDACL)
If result = ERROR_SUCCESS Then
MsgBox "SetEntriesInAcl succeeded"

' Call SetNamedSecurityInfo() API with the updated DACL in memory to change the DACL of c:\test1 folder
result = SetNamedSecurityInfo("c:\test1", SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, 0&, 0&, pNewDACL, 0&)
If result = ERROR_SUCCESS Then
MsgBox "SetNamedSecurityInfo succeeded"
Else
MsgBox "SetNamedSecurityInfo failed with error code : " & result
End If

' Free the memory allocated for the new DACL by the SetEntriesInAcl() API, using LocalFree() API
LocalFree pNewDACL
Else
MsgBox "SetEntriesInAcl failed with error code : " & result
End If

' Free the memory allocated for the security descriptor by the GetNamedSecurityInfo() API, using LocalFree() API
LocalFree pSecDesc
Else
MsgBox "GetNamedSecurityInfo failed with error code : " & result
End If
End Sub

References

For more information, click the following article numbers to view the articles in the Microsoft Knowledge Base:

102102 How to add an access-allowed ACE to a file

316440 How to use low-level access control APIs from Visual Basic

Propriedades

ID do Artigo: 295004 - Última Revisão: 21 de nov de 2006 - Revisão: 1

Comentários