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

Article translations Article translations
Article ID: 295004 - View products that this article applies to.
This article was previously published under Q295004
Expand all | Collapse all

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

Properties

Article ID: 295004 - Last Review: November 21, 2006 - Revision: 4.1
APPLIES TO
  • Microsoft Win32 Application Programming Interface, when used with:
    • Microsoft Windows 2000 Standard Edition
    • the operating system: Microsoft Windows XP
Keywords: 
kbhowto kbapi kbkernbase kbsecurity kbacl KB295004

Give Feedback

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com