Solved

Remove Inherited NTFS Permissions

Posted on 2004-08-27
3
1,007 Views
Last Modified: 2012-06-21

Greetings All!

VB6:  I need to be able to copy a folder and all it's contents (including sub-folders) to a users machine, but then remove all inherited NTFS permissions, and then add back what I want.  The idea here is that a user will run the app, copy the folder over to their machine, but then be able to only add/edit/remove files within the folder structure that has been copied, but not mess with the folder structure.

I have all the copy folder code down, no problem.  I can even set new permissions to the copied folder with no problem.  However, these new permissions are moot unless I can remove the inherited permissions that were implied when the folder was copied.  If could just toggle the "Inherit Permissions..." flag, that would work just as well.

Thanks!
LightOut
0
Comment
Question by:LightOut
  • 2
3 Comments
 
LVL 8

Accepted Solution

by:
mladenovicz earned 500 total points
ID: 11914238
Success status of high level access control APIs
Public Const ERROR_SUCCESS = 0&
' Type of Securable Object we are operating in this sample code
Public Const SE_FILE_OBJECT = 1&
' The Security Information constants required
Public Const DACL_SECURITY_INFORMATION = 4&
Public Const SET_ACCESS = 2&
' Standard access rights extracted from WinNT.h
Public Const SYNCHRONIZE = &H100000
Public Const READ_CONTROL = &H20000
Public Const WRITE_DAC = &H40000
Public Const WRITE_OWNER = &H80000
Public Const STANDARD_RIGHTS_READ = (READ_CONTROL)
Public Const STANDARD_RIGHTS_WRITE = (READ_CONTROL)
Public Const DELETE = &H10000
' Generic access rights extracted from WinNT.h
Public Const GENERIC_ALL = &H10000000
Public Const GENERIC_EXECUTE = &H20000000
Public Const GENERIC_READ = &H80000000
Public Const GENERIC_WRITE = &H40000000
' Inheritance Flags
Public Const OBJECT_INHERIT_ACE = &H1        ' (0x1)
Public Const CONTAINER_INHERIT_ACE = &H2     ' (0x2)
Public Const NO_PROPAGATE_INHERIT_ACE = &H4  ' (0x4)
Public Const INHERIT_ONLY_ACE = &H8          ' (0x8)
Public Const INHERITED_ACE = &H10            ' (0x10)
Public Const VALID_INHERIT_FLAGS = &H1F      ' (0x1F)

' Token Specific Access Rights
Public Const TOKEN_ASSIGN_PRIMARY = &H1
Public Const TOKEN_DUPLICATE = &H2
Public Const TOKEN_IMPERSONATE = &H4
Public Const TOKEN_QUERY = &H8
Public Const TOKEN_QUERY_SOURCE = &H10
Public Const TOKEN_ADJUST_PRIVILEGES = &H20
Public Const TOKEN_ADJUST_GROUPS = &H40
Public Const TOKEN_ADJUST_DEFAULT = &H80

' NT well-known SIDs
Public Const SECURITY_DIALUP_RID = &H1
Public Const SECURITY_NETWORK_RID = &H2
Public Const SECURITY_BATCH_RID = &H3
Public Const SECURITY_INTERACTIVE_RID = &H4
Public Const SECURITY_SERVICE_RID = &H6
Public Const SECURITY_ANONYMOUS_LOGON_RID = &H7
Public Const SECURITY_LOGON_IDS_RID = &H5
Public Const SECURITY_LOCAL_SYSTEM_RID = &H12
Public Const SECURITY_NT_NON_UNIQUE = &H15
Public Const SECURITY_BUILTIN_DOMAIN_RID = &H20

' Well-known domain relative sub-authority values (RIDs)
Public Const DOMAIN_ALIAS_RID_ADMINS = &H220
Public Const DOMAIN_ALIAS_RID_USERS = &H221
Public Const DOMAIN_ALIAS_RID_GUESTS = &H222
Public Const DOMAIN_ALIAS_RID_POWER_USERS = &H223
Public Const DOMAIN_ALIAS_RID_ACCOUNT_OPS = &H224
Public Const DOMAIN_ALIAS_RID_SYSTEM_OPS = &H225
Public Const DOMAIN_ALIAS_RID_PRINT_OPS = &H226
Public Const DOMAIN_ALIAS_RID_BACKUP_OPS = &H227
Public Const DOMAIN_ALIAS_RID_REPLICATOR = &H228

Const ANYSIZE_ARRAY = 1
Const SECURITY_NT_AUTHORITY = &H5
Const ERROR_ACCESS_DENIED = 5&
Const SE_TAKE_OWNERSHIP_NAME = "SeTakeOwnershipPrivilege"
Const OWNER_SECURITY_INFORMATION = &H1
Const SE_PRIVILEGE_ENABLED = &H2

Const SECURITY_DESCRIPTOR_REVISION = 1
Const ACL_REVISION = 2
Const MAXDWORD = &HFFFFFFFF

' 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
Public Type EXPLICIT_ACCESS
    grfAccessPermissions As Long
    grfAccessMode As Long
    grfInheritance As Long
    pTRUSTEE As TRUSTEE
End Type

Public Type SID_IDENTIFIER_AUTHORITY
        Value(6) As Byte
End Type

Public Type LUID
    LowPart As Long
    HighPart As Long
End Type

Public Type LUID_AND_ATTRIBUTES
    pLuid As LUID
    Attributes As Long
End Type

Public Type TOKEN_PRIVILEGES
    PrivilegeCount As Long
    Privileges(ANYSIZE_ARRAY) As LUID_AND_ATTRIBUTES
End Type

Type ACL
   AclRevision As Byte
   Sbz1 As Byte
   AclSize As Integer
   AceCount As Integer
   Sbz2 As Integer
End Type

Type SECURITY_DESCRIPTOR
   Revision As Byte
   Sbz1 As Byte
   Control As Long
   Owner As Long
   Group As Long
   sACL As ACL
   Dacl As ACL
End Type

Type ACL_SIZE_INFORMATION
   AceCount As Long
   AclBytesInUse As Long
   AclBytesFree As Long
End Type

Type ACE_HEADER
   AceType As Byte
   AceFlags As Byte
   AceSize As Integer
End Type

Type ACCESS_ALLOWED_ACE
   Header As ACE_HEADER
   Mask As Long
   SidStart As Long
End Type

' High Level access control API declarations
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)
   
Public Declare Function SetEntriesInAcl Lib "advapi32.dll" Alias _
    "SetEntriesInAclA" _
    (ByVal CountofExplicitEntries As Long, _
    ea As Any, _
    ByVal OldAcl As Long, _
    NewAcl As Long) As Long
   
Public 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
   
Public 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
   
' other APIs needed for set ownership
Declare Function AllocateAndInitializeSid Lib "advapi32" ( _
    pIdentifierAuthority As SID_IDENTIFIER_AUTHORITY, _
    ByVal nSubAuthorityCount As Byte, ByVal nSubAuthority0 As Long, _
    ByVal nSubAuthority1 As Long, ByVal nSubAuthority2 As Long, _
    ByVal nSubAuthority3 As Long, ByVal nSubAuthority4 As Long, _
    ByVal nSubAuthority5 As Long, ByVal nSubAuthority6 As Long, _
    ByVal nSubAuthority7 As Long, lpPSid As Long) As Long
   
Declare Function LocalFree Lib "kernel32" (ByVal hMem As Long) As Long

Declare Function GetCurrentProcess Lib "kernel32" () As Long
Declare Function OpenProcessToken Lib "advapi32" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, TokenHandle As Long) As Long
Declare Function LookupPrivilegeValue Lib "advapi32" Alias "LookupPrivilegeValueA" (ByVal lpSystemName As String, ByVal lpName As String, lpLuid As LUID) As Long
Declare Function AdjustTokenPrivileges Lib "advapi32" (ByVal TokenHandle As Long, ByVal DisableAllPrivileges As Long, NewState As TOKEN_PRIVILEGES, ByVal BufferLength As Long, PreviousState As TOKEN_PRIVILEGES, ReturnLength As Long) As Long
Declare Sub FreeSid Lib "advapi32" (pSid As Any)

Declare Function GetFileSecurity Lib "advapi32.dll" Alias "GetFileSecurityA" (ByVal lpFileName As String, ByVal RequestedInformation As Long, pSecurityDescriptor As Byte, ByVal nLength As Long, lpnLengthNeeded As Long) As Long
Declare Function GetSecurityDescriptorDacl Lib "advapi32.dll" (pSecurityDescriptor As Byte, lpbDaclPresent As Long, pDacl As Long, lpbDaclDefaulted As Long) As Long
Declare Function InitializeSecurityDescriptor Lib "advapi32.dll" (pSecurityDescriptor As SECURITY_DESCRIPTOR, ByVal dwRevision As Long) As Long
Declare Function GetAclInformation Lib "advapi32.dll" (ByVal pAcl As Long, pAclInformation As Any, ByVal nAclInformationLength As Long, ByVal dwAclInformationClass As Long) As Long
Declare Function InitializeAcl Lib "advapi32.dll" (pAcl As Byte, ByVal nAclLength As Long, ByVal dwAclRevision As Long) As Long
Declare Function GetAce Lib "advapi32.dll" (ByVal pAcl As Long, ByVal dwAceIndex As Long, pace As Any) As Long
Declare Function AddAce Lib "advapi32.dll" (ByVal pAcl As Long, ByVal dwAceRevision As Long, ByVal dwStartingAceIndex As Long, ByVal pAceList As Long, ByVal nAceListLength As Long) As Long
Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (hpvDest As Any, ByVal hpvSource As Long, ByVal cbCopy As Long)
Declare Function SetSecurityDescriptorDacl Lib "advapi32.dll" (pSecurityDescriptor As SECURITY_DESCRIPTOR, ByVal bDaclPresent As Long, pDacl As Byte, ByVal bDaclDefaulted As Long) As Long
Declare Function SetFileSecurity Lib "advapi32.dll" Alias "SetFileSecurityA" (ByVal lpFileName As String, ByVal SecurityInformation As Long, pSecurityDescriptor As SECURITY_DESCRIPTOR) As Long


Public Function DeleteInheritedACEs(sFileName As String) As Boolean
Dim lResult             As Long                 ' Result of various API calls.
Dim i                   As Integer              ' Used in looping.
Dim lSizeNeeded         As Long                 ' Size needed for SD for file.
Dim sNewSD              As SECURITY_DESCRIPTOR  ' New security descriptor.
Dim sACLInfo            As ACL_SIZE_INFORMATION ' Used in grabbing the ACL from the File SD.
Dim sCurrentACE         As ACCESS_ALLOWED_ACE   ' Current ACE.
Dim lDaclPresent        As Long                 ' Used in grabbing the DACL from the File SD.
Dim lDaclDefaulted      As Long                 ' Used in grabbing the DACL from the File SD.
Dim lACLSize            As Long                 ' Size of the ACL structure used to get the ACL from the File SD.
Dim pAcl                As Long                 ' Current ACL for this file.
Dim lNewACLSize         As Long                 ' Size of new ACL to create.
Dim bNewACL()           As Byte                 ' Buffer to hold new ACL.
Dim pCurrentAce         As Long                 ' Our current ACE.
Dim bSDBuf()            As Byte                 ' Buffer that holds the security descriptor for this file.
Dim sErrMsg             As String

    On Error GoTo Proc_Err
   
    ' The GetFileSecurity API will retrieve the Security Descriptor
    ' for the file. However, you must call this API twice: once to get
    ' the proper size for the Security Descriptor and once to get the
    ' actual Security Descriptor information.

    lResult = GetFileSecurity(sFileName, DACL_SECURITY_INFORMATION, _
      0, 0, lSizeNeeded)

    ' Redimension the Security Descriptor buffer to the proper size.
    ReDim bSDBuf(lSizeNeeded)

    ' Now get the actual Security Descriptor for the file.
    lResult = GetFileSecurity(sFileName, DACL_SECURITY_INFORMATION, _
      bSDBuf(0), lSizeNeeded, lSizeNeeded)

    ' A return code of zero means the call failed; test for this
    ' before continuing.
    If (lResult = 0) Then
        sErrMsg = "Error: Unable to Get the File Security Descriptor"
        GoTo Proc_Err
    End If

    ' Call InitializeSecurityDescriptor to build a new SD for the
    ' file.
    lResult = InitializeSecurityDescriptor(sNewSD, _
      SECURITY_DESCRIPTOR_REVISION)

    ' A return code of zero means the call failed; test for this
    ' before continuing.
    If (lResult = 0) Then
        sErrMsg = "Error: Unable to Initialize New Security Descriptor"
        GoTo Proc_Err
    End If

    ' You now have the file's SD and a new Security Descriptor
    ' that will replace the current one. Next, pull the DACL from
    ' the SD. To do so, call the GetSecurityDescriptorDacl API
    ' function.

    lResult = GetSecurityDescriptorDacl(bSDBuf(0), lDaclPresent, _
      pAcl, lDaclDefaulted)

    ' A return code of zero means the call failed; test for this
    ' before continuing.
    If (lResult = 0) Then
        sErrMsg = "Error: Unable to Get DACL from File Security " _
         & "Descriptor"
        GoTo Proc_Err
    End If

    ' You have the file's SD, and want to now pull the ACL from the
    ' SD. To do so, call the GetACLInformation API function.
    ' See if ACL exists for this file before getting the ACL
    ' information.
    If (lDaclPresent = False) Then
        sErrMsg = "Error: No ACL Information Available for this File"
        GoTo Proc_Err
    End If

    ' Attempt to get the ACL from the file's Security Descriptor.
    lResult = GetAclInformation(pAcl, sACLInfo, Len(sACLInfo), 2&)

    ' A return code of zero means the call failed; test for this
    ' before continuing.
    If (lResult = 0) Then
        sErrMsg = "Error: Unable to Get ACL from File Security Descriptor"
        GoTo Proc_Err
    End If
   
    'compute the new ACL size requirements.
    ' we need at least the same size as old ACL
    lNewACLSize = sACLInfo.AclBytesInUse

    ' Resize our new ACL buffer to its proper size.
    ReDim bNewACL(lNewACLSize)

    ' Use the InitializeAcl API function call to initialize the new ACL.
    lResult = InitializeAcl(bNewACL(0), lNewACLSize, ACL_REVISION)

    ' A return code of zero means the call failed; test for this
    ' before continuing.
    If (lResult = 0) Then
        sErrMsg = "Error: Unable to Initialize New ACL"
        GoTo Proc_Err
    End If
   
    ' If a DACL is present, copy it to a new DACL.
    If (lDaclPresent) Then

        ' Copy the ACEs from the file to the new ACL.
        If (sACLInfo.AceCount > 0) Then

            ' Grab each ACE and stuff them into the new ACL.
            For i = 0 To (sACLInfo.AceCount - 1)

                ' Attempt to grab the next ACE.
                lResult = GetAce(pAcl, i, pCurrentAce)

                ' Make sure you have the current ACE under question.
                If (lResult = 0) Then
                    sErrMsg = "Error: Unable to Obtain ACE (" & i & ")"
                    GoTo Proc_Err
                End If

                ' You have a pointer to the ACE. Place it
                ' into a structure, so you can get at its size.
                CopyMemory sCurrentACE, pCurrentAce, LenB(sCurrentACE)
               
                If sCurrentACE.Header.AceFlags And INHERITED_ACE Then
                    ' we have an inherited ACE
                    ' we don't want inherited ACEs in new DACL
                    ' do nothing
                Else
                    ' Now that you have the ACE, add it to the new ACL.
                    lResult = AddAce(VarPtr(bNewACL(0)), ACL_REVISION, _
                                    MAXDWORD, pCurrentAce, _
                                    sCurrentACE.Header.AceSize)

                    ' Make sure you have the current ACE under question.
                    If (lResult = 0) Then
                        sErrMsg = "Error: Unable to Add ACE to New ACL"
                        GoTo Proc_Err
                    End If
                 
                End If
            Next
           
            ' Set the file's Security Descriptor to the new DACL.
            lResult = SetSecurityDescriptorDacl(sNewSD, 1, _
            bNewACL(0), 0)

            ' Make sure you set the SD to the new DACL.
            If (lResult = 0) Then
                sErrMsg = "Error: " & _
                "Unable to Set New DACL to Security Descriptor"
                GoTo Proc_Err
            End If

            ' The final step is to add the Security Descriptor back to
            ' the file!
            lResult = SetFileSecurity(sFileName, _
                DACL_SECURITY_INFORMATION, sNewSD)

            ' Make sure you added the Security Descriptor to the file!
            If (lResult = 0) Then
                sErrMsg = "Error: Unable to Set New Security Descriptor " _
               & " to File : " & sFileName
                GoTo Proc_Err
            Else
                DeleteInheritedACEs = True
            End If

        End If

    End If
   
    Exit Function
   
Proc_Err:
    DeleteInheritedACEs = False
End Function
0
 

Author Comment

by:LightOut
ID: 11914419

AHHHHHH!!! THANK YOU mladenovicz !!!  I would give you 500 points for each 3 posts if I could! :)

LightOut.

0
 
LVL 8

Expert Comment

by:mladenovicz
ID: 11914508
I had problems with my internet connection so I accidentaly posted code a few times ;)
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

I’ve seen a number of people looking for examples of how to access web services from VB6.  I’ve been using a test harness I built in VB6 (using many resources I found online) that I use for small projects to work out how to communicate with web serv…
Introduction In a recent article (http://www.experts-exchange.com/A_7811-A-Better-Concatenate-Function.html) for the Excel community, I showed an improved version of the Excel Concatenate() function.  While writing that article I realized that no o…
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now