How to use high-level access control APIs from Visual Basic (295004)
The information in this article applies to:
- Microsoft Win32 Application Programming Interface (API), when used with:
- the operating system: Microsoft Windows 2000
- the operating system: Microsoft Windows XP
This article was previously published under Q295004 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
Modification Type: | Major | Last Reviewed: | 7/19/2005 |
---|
Keywords: | kbACL kbAPI kbhowto kbKernBase kbSecurity KB295004 |
---|
|