Inheritable ACE doesn't inherit (code included)

Archived from groups: microsoft.public.win2000.security (More info?)

I've got a function that I'm using to create an inheritable ACE. I
want to grant permission on a directory, and have it be inherited by
its children.

The function was largely stolen from MSDN, and it almost works. If I
go into Explorer and pull up the directory, everyhing looks fine -- all
of the correct switches are set, etc... If I look at the children --
no permissions are inherited.

Doing it manually using Explorer's Security tab works fine.

And, in fact, if I take the "broken" ACL on the directory and modify it
in any way using the Security tab and apply the changes... voila, it
gets inherited by its children.

The function follows.

PS: in the if(){} block below, I'm sure that AddAccessAllowedAceEx is
being called. I've dumped the ACE using another tool and the flag bits
look the same in the header whether this function adjusts the
permissions, or the Security tab does it. I'm completely lost.

BOOL AddAccessRights(TCHAR *lpszFileName, TCHAR *lpszAccountName, DWORD
dwAccessMask)
{
// SID variables.
LPVOID pUserSID = NULL;

// File SD variables.
PSECURITY_DESCRIPTOR pFileSD = NULL;
DWORD cbFileSD = 0;

// New SD variables.
SECURITY_DESCRIPTOR newSD;

// ACL variables.
PACL pACL = NULL;
BOOL fDaclPresent;
BOOL fDaclDefaulted;
ACL_SIZE_INFORMATION AclInfo;

// New ACL variables.
PACL pNewACL = NULL;
DWORD cbNewACL = 0;

// Temporary ACE.
LPVOID pTempAce = NULL;
UINT CurrentAceIndex = 0;

UINT newAceIndex = 0;

// Assume function will fail.
BOOL fResult = FALSE;

SetSecurityDescriptorControlFnPtr _SetSecurityDescriptorControl;
AddAccessAllowedAceExFnPtr _AddAccessAllowedAceEx;

SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION;

//
// STEP 1: Get SID of the account name specified.
//
if (! (pUserSID = GetUserSid(lpszAccountName)))
{
fResult = 1;
goto EXITFUNC;
}

//
// STEP 2: Get security descriptor (SD) of the file specified.
//
if (! GetFileSecurity(lpszFileName, secInfo, pFileSD, 0, &cbFileSD))
{
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
err_msg();
fResult = 2;
goto EXITFUNC;
}
}

if (! (pFileSD = malloc(cbFileSD)))
{
fResult = -1;
goto EXITFUNC;
}

if (! GetFileSecurity(lpszFileName, secInfo, pFileSD, cbFileSD,
&cbFileSD))
{
err_msg();
fResult = 2;
goto EXITFUNC;
}

//
// STEP 3: Initialize new SD.
//
if (!InitializeSecurityDescriptor(&newSD,
SECURITY_DESCRIPTOR_REVISION))
{
err_msg();
fResult = 3;
goto EXITFUNC;
}

//
// STEP 4: Get DACL from the old SD.
//
if (!GetSecurityDescriptorDacl(pFileSD, &fDaclPresent, &pACL,
&fDaclDefaulted))
{
err_msg();
fResult = 4;
goto EXITFUNC;
}

//
// STEP 5: Get size information for DACL.
//
AclInfo.AceCount = 0; // Assume NULL DACL.
AclInfo.AclBytesFree = 0;
AclInfo.AclBytesInUse = sizeof(ACL);

if (pACL == NULL)
fDaclPresent = FALSE;

// If not NULL DACL, gather size information from DACL.
if (fDaclPresent)
{
if (!GetAclInformation(pACL, &AclInfo, sizeof(ACL_SIZE_INFORMATION),
AclSizeInformation))
{
err_msg();
fResult = 5;
goto EXITFUNC;
}
}

//
// STEP 6: Compute size needed for the new ACL.
//
cbNewACL = AclInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE) +
GetLengthSid(pUserSID) - sizeof(DWORD);

//
// STEP 7: Allocate memory for new ACL.
//
if (! (pNewACL = (PACL) malloc(cbNewACL)))
{
fResult = -1;
goto EXITFUNC;
}

//
// STEP 8: Initialize the new ACL.
//
if (!InitializeAcl(pNewACL, cbNewACL, ACL_REVISION2))
{
err_msg();
fResult = 6;
goto EXITFUNC;
}

//
// STEP 9 If DACL is present, copy all the ACEs from the old DACL
// to the new DACL.
//
// The following code assumes that the old DACL is
// already in Windows 2000 preferred order. To conform
// to the new Windows 2000 preferred order, first we will
// copy all non-inherited ACEs from the old DACL to the
// new DACL, irrespective of the ACE type.
//
newAceIndex = 0;

if (fDaclPresent && AclInfo.AceCount)
{
for (CurrentAceIndex = 0; CurrentAceIndex < AclInfo.AceCount;
CurrentAceIndex++)
{
//
// STEP 10: Get an ACE.
//
if (!GetAce(pACL, CurrentAceIndex, &pTempAce))
{
err_msg();
fResult = 7;
goto EXITFUNC;
}

//
// STEP 11: Check if it is a non-inherited ACE.
// If it is an inherited ACE, break from the loop so
// that the new access allowed non-inherited ACE can
// be added in the correct position, immediately after
// all non-inherited ACEs.
//
if (((ACCESS_ALLOWED_ACE *)pTempAce)->Header.AceFlags &
INHERITED_ACE)
break;

//
// STEP 12: Skip adding the ACE, if the SID matches
// with the account specified, as we are going to
// add an access allowed ACE with a different access
// mask.
//
if (EqualSid(pUserSID, &(((ACCESS_ALLOWED_ACE
*)pTempAce)->SidStart)))
continue;

//
// STEP 13: Add the ACE to the new ACL.
//
if (!AddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce,
((PACE_HEADER) pTempAce)->AceSize))
{
err_msg();
fResult = 7;
goto EXITFUNC;
}

newAceIndex++;
}
}

//
// STEP 14: Add the access-allowed ACE to the new DACL.
// The new ACE added here will be in the correct position,
// immediately after all existing non-inherited ACEs.
//
_AddAccessAllowedAceEx =
(AddAccessAllowedAceExFnPtr)GetProcAddress(GetModuleHandle(TEXT("advapi32.dll")),"AddAccessAllowedAceEx");
if (_AddAccessAllowedAceEx)
{
fprintf(stderr, "new API\n");
if (!_AddAccessAllowedAceEx(pNewACL, ACL_REVISION2,
CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, dwAccessMask, pUserSID))
{
err_msg();
fResult = 8;
goto EXITFUNC;
}
}
else
{
if (!AddAccessAllowedAce(pNewACL, ACL_REVISION2, dwAccessMask,
pUserSID))
{
err_msg();
fResult = 8;
goto EXITFUNC;
}
}

//
// STEP 15: To conform to the new Windows 2000 preferred order,
// we will now copy the rest of inherited ACEs from the
// old DACL to the new DACL.
//
if (fDaclPresent && AclInfo.AceCount)
{
for (; CurrentAceIndex < AclInfo.AceCount; CurrentAceIndex++)
{
//
// STEP 16: Get an ACE.
//
if (!GetAce(pACL, CurrentAceIndex, &pTempAce))
{
err_msg();
fResult = 8;
goto EXITFUNC;
}

//
// STEP 17: Add the ACE to the new ACL.
//
if (!AddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce,
((PACE_HEADER) pTempAce)->AceSize))
{
err_msg();
fResult = 9;
goto EXITFUNC;
}
}
}

//
// STEP 18: Set the new DACL to the new SD.
//
if (!SetSecurityDescriptorDacl(&newSD, TRUE, pNewACL, FALSE))
{
err_msg();
fResult = 10;
goto EXITFUNC;
}

//
// STEP 19: Copy the old security descriptor control flags
// regarding DACL automatic inheritance for Windows 2000 or
// later where SetSecurityDescriptorControl() API is available
// in advapi32.dll.
//
_SetSecurityDescriptorControl =
(SetSecurityDescriptorControlFnPtr)GetProcAddress(GetModuleHandle(TEXT("advapi32.dll")),"SetSecurityDescriptorControl");
if (_SetSecurityDescriptorControl)
{
SECURITY_DESCRIPTOR_CONTROL controlBitsOfInterest = 0;
SECURITY_DESCRIPTOR_CONTROL controlBitsToSet = 0;
SECURITY_DESCRIPTOR_CONTROL oldControlBits = 0;
DWORD dwRevision = 0;

if (!GetSecurityDescriptorControl(pFileSD, &oldControlBits,
&dwRevision))
{
err_msg();
fResult = 10;
goto EXITFUNC;
}

if (oldControlBits & SE_DACL_AUTO_INHERITED)
{
controlBitsOfInterest = SE_DACL_AUTO_INHERIT_REQ |
SE_DACL_AUTO_INHERITED;
controlBitsToSet = controlBitsOfInterest;
}
else if (oldControlBits & SE_DACL_PROTECTED)
{
controlBitsOfInterest = SE_DACL_PROTECTED;
controlBitsToSet = controlBitsOfInterest;
}

if (controlBitsOfInterest)
{
if (!_SetSecurityDescriptorControl(&newSD, controlBitsOfInterest,
controlBitsToSet))
{
err_msg();
fResult = 11;
goto EXITFUNC;
}
}
}

//
// STEP 20: Set the new SD to the File.
//
if (!SetFileSecurity(lpszFileName, secInfo, &newSD))
{
err_msg();
fResult = 12;
goto EXITFUNC;
}

fResult = 0;

EXITFUNC:
//
// STEP 21: Free allocated memory
//
if (pFileSD) free(pFileSD);
if (pNewACL) free(pNewACL);

return fResult;
}
4 answers Last reply
More about inheritable doesn inherit code included
  1. Archived from groups: microsoft.public.win2000.security (More info?)

    <clintp@gmail.com> wrote in message
    news:1115149495.351993.74060@z14g2000cwz.googlegroups.com...
    > I've got a function that I'm using to create an inheritable ACE. I
    > want to grant permission on a directory, and have it be inherited by
    > its children.
    >
    > The function was largely stolen from MSDN, and it almost works. If I
    > go into Explorer and pull up the directory, everyhing looks fine -- all
    > of the correct switches are set, etc... If I look at the children --
    > no permissions are inherited.

    Most people don't realize but there are actually
    two kinds (possible) of inheritable ACL sets on
    each directory: One for containers (other
    subdirectories) and one for non-containers.

    I would check that first -- you might need to post
    the code to a developer list; although some
    of us here are programmers that is not the primary
    focus here.

    You might look at the source from SetAcl which
    is on SourceForge.net.

    --
    Herb Martin, MCSE, MVP
    Accelerated MCSE
    http://www.LearnQuick.Com
    [phone number on web site]

    > Doing it manually using Explorer's Security tab works fine.
    >
    > And, in fact, if I take the "broken" ACL on the directory and modify it
    > in any way using the Security tab and apply the changes... voila, it
    > gets inherited by its children.
    >
    > The function follows.
    >
    > PS: in the if(){} block below, I'm sure that AddAccessAllowedAceEx is
    > being called. I've dumped the ACE using another tool and the flag bits
    > look the same in the header whether this function adjusts the
    > permissions, or the Security tab does it. I'm completely lost.
    >
    > BOOL AddAccessRights(TCHAR *lpszFileName, TCHAR *lpszAccountName, DWORD
    > dwAccessMask)
  2. Archived from groups: microsoft.public.win2000.security (More info?)

    The code seems to have hidden all that is most relevant in the
    unsupplied call parameter for the ACE flags. IIRC there is a
    newer flag, but I think it is a SD flag not an ACE flag called
    Inheritance Requested that may help.
    The main issue you are dealing with is that what you see is
    in fact how inheritance works, i.e. it is not guaranteed to be
    immediately recalculated/propagated. An change event to an
    ACL in the inheriting substructure will trigger recalculation
    on the path to it, etc. which you have confirmed in your post
    where you used Explorer to trigger the effective to be shown
    as expected.
    I would suggest that you post to an MSDN group (if not already)
    as someone there may know the C++ Api that would allow you
    to trigger the recalculation.
    --
    Roger Abell
    Microsoft MVP (Windows Security)
    MCSE (W2k3,W2k,Nt4) MCDBA
    <clintp@gmail.com> wrote in message
    news:1115149495.351993.74060@z14g2000cwz.googlegroups.com...
    > I've got a function that I'm using to create an inheritable ACE. I
    > want to grant permission on a directory, and have it be inherited by
    > its children.
    >
    > The function was largely stolen from MSDN, and it almost works. If I
    > go into Explorer and pull up the directory, everyhing looks fine -- all
    > of the correct switches are set, etc... If I look at the children --
    > no permissions are inherited.
    >
    > Doing it manually using Explorer's Security tab works fine.
    >
    > And, in fact, if I take the "broken" ACL on the directory and modify it
    > in any way using the Security tab and apply the changes... voila, it
    > gets inherited by its children.
    >
    > The function follows.
    >
    > PS: in the if(){} block below, I'm sure that AddAccessAllowedAceEx is
    > being called. I've dumped the ACE using another tool and the flag bits
    > look the same in the header whether this function adjusts the
    > permissions, or the Security tab does it. I'm completely lost.
    >
    > BOOL AddAccessRights(TCHAR *lpszFileName, TCHAR *lpszAccountName, DWORD
    > dwAccessMask)
    > {
    > // SID variables.
    > LPVOID pUserSID = NULL;
    >
    > // File SD variables.
    > PSECURITY_DESCRIPTOR pFileSD = NULL;
    > DWORD cbFileSD = 0;
    >
    > // New SD variables.
    > SECURITY_DESCRIPTOR newSD;
    >
    > // ACL variables.
    > PACL pACL = NULL;
    > BOOL fDaclPresent;
    > BOOL fDaclDefaulted;
    > ACL_SIZE_INFORMATION AclInfo;
    >
    > // New ACL variables.
    > PACL pNewACL = NULL;
    > DWORD cbNewACL = 0;
    >
    > // Temporary ACE.
    > LPVOID pTempAce = NULL;
    > UINT CurrentAceIndex = 0;
    >
    > UINT newAceIndex = 0;
    >
    > // Assume function will fail.
    > BOOL fResult = FALSE;
    >
    > SetSecurityDescriptorControlFnPtr _SetSecurityDescriptorControl;
    > AddAccessAllowedAceExFnPtr _AddAccessAllowedAceEx;
    >
    > SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION;
    >
    > //
    > // STEP 1: Get SID of the account name specified.
    > //
    > if (! (pUserSID = GetUserSid(lpszAccountName)))
    > {
    > fResult = 1;
    > goto EXITFUNC;
    > }
    >
    > //
    > // STEP 2: Get security descriptor (SD) of the file specified.
    > //
    > if (! GetFileSecurity(lpszFileName, secInfo, pFileSD, 0, &cbFileSD))
    > {
    > if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
    > {
    > err_msg();
    > fResult = 2;
    > goto EXITFUNC;
    > }
    > }
    >
    > if (! (pFileSD = malloc(cbFileSD)))
    > {
    > fResult = -1;
    > goto EXITFUNC;
    > }
    >
    > if (! GetFileSecurity(lpszFileName, secInfo, pFileSD, cbFileSD,
    > &cbFileSD))
    > {
    > err_msg();
    > fResult = 2;
    > goto EXITFUNC;
    > }
    >
    > //
    > // STEP 3: Initialize new SD.
    > //
    > if (!InitializeSecurityDescriptor(&newSD,
    > SECURITY_DESCRIPTOR_REVISION))
    > {
    > err_msg();
    > fResult = 3;
    > goto EXITFUNC;
    > }
    >
    > //
    > // STEP 4: Get DACL from the old SD.
    > //
    > if (!GetSecurityDescriptorDacl(pFileSD, &fDaclPresent, &pACL,
    > &fDaclDefaulted))
    > {
    > err_msg();
    > fResult = 4;
    > goto EXITFUNC;
    > }
    >
    > //
    > // STEP 5: Get size information for DACL.
    > //
    > AclInfo.AceCount = 0; // Assume NULL DACL.
    > AclInfo.AclBytesFree = 0;
    > AclInfo.AclBytesInUse = sizeof(ACL);
    >
    > if (pACL == NULL)
    > fDaclPresent = FALSE;
    >
    > // If not NULL DACL, gather size information from DACL.
    > if (fDaclPresent)
    > {
    > if (!GetAclInformation(pACL, &AclInfo, sizeof(ACL_SIZE_INFORMATION),
    > AclSizeInformation))
    > {
    > err_msg();
    > fResult = 5;
    > goto EXITFUNC;
    > }
    > }
    >
    > //
    > // STEP 6: Compute size needed for the new ACL.
    > //
    > cbNewACL = AclInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE) +
    > GetLengthSid(pUserSID) - sizeof(DWORD);
    >
    > //
    > // STEP 7: Allocate memory for new ACL.
    > //
    > if (! (pNewACL = (PACL) malloc(cbNewACL)))
    > {
    > fResult = -1;
    > goto EXITFUNC;
    > }
    >
    > //
    > // STEP 8: Initialize the new ACL.
    > //
    > if (!InitializeAcl(pNewACL, cbNewACL, ACL_REVISION2))
    > {
    > err_msg();
    > fResult = 6;
    > goto EXITFUNC;
    > }
    >
    > //
    > // STEP 9 If DACL is present, copy all the ACEs from the old DACL
    > // to the new DACL.
    > //
    > // The following code assumes that the old DACL is
    > // already in Windows 2000 preferred order. To conform
    > // to the new Windows 2000 preferred order, first we will
    > // copy all non-inherited ACEs from the old DACL to the
    > // new DACL, irrespective of the ACE type.
    > //
    > newAceIndex = 0;
    >
    > if (fDaclPresent && AclInfo.AceCount)
    > {
    > for (CurrentAceIndex = 0; CurrentAceIndex < AclInfo.AceCount;
    > CurrentAceIndex++)
    > {
    > //
    > // STEP 10: Get an ACE.
    > //
    > if (!GetAce(pACL, CurrentAceIndex, &pTempAce))
    > {
    > err_msg();
    > fResult = 7;
    > goto EXITFUNC;
    > }
    >
    > //
    > // STEP 11: Check if it is a non-inherited ACE.
    > // If it is an inherited ACE, break from the loop so
    > // that the new access allowed non-inherited ACE can
    > // be added in the correct position, immediately after
    > // all non-inherited ACEs.
    > //
    > if (((ACCESS_ALLOWED_ACE *)pTempAce)->Header.AceFlags &
    > INHERITED_ACE)
    > break;
    >
    > //
    > // STEP 12: Skip adding the ACE, if the SID matches
    > // with the account specified, as we are going to
    > // add an access allowed ACE with a different access
    > // mask.
    > //
    > if (EqualSid(pUserSID, &(((ACCESS_ALLOWED_ACE
    > *)pTempAce)->SidStart)))
    > continue;
    >
    > //
    > // STEP 13: Add the ACE to the new ACL.
    > //
    > if (!AddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce,
    > ((PACE_HEADER) pTempAce)->AceSize))
    > {
    > err_msg();
    > fResult = 7;
    > goto EXITFUNC;
    > }
    >
    > newAceIndex++;
    > }
    > }
    >
    > //
    > // STEP 14: Add the access-allowed ACE to the new DACL.
    > // The new ACE added here will be in the correct position,
    > // immediately after all existing non-inherited ACEs.
    > //
    > _AddAccessAllowedAceEx =
    >
    (AddAccessAllowedAceExFnPtr)GetProcAddress(GetModuleHandle(TEXT("advapi32.dl
    l")),"AddAccessAllowedAceEx");
    > if (_AddAccessAllowedAceEx)
    > {
    > fprintf(stderr, "new API\n");
    > if (!_AddAccessAllowedAceEx(pNewACL, ACL_REVISION2,
    > CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, dwAccessMask, pUserSID))
    > {
    > err_msg();
    > fResult = 8;
    > goto EXITFUNC;
    > }
    > }
    > else
    > {
    > if (!AddAccessAllowedAce(pNewACL, ACL_REVISION2, dwAccessMask,
    > pUserSID))
    > {
    > err_msg();
    > fResult = 8;
    > goto EXITFUNC;
    > }
    > }
    >
    > //
    > // STEP 15: To conform to the new Windows 2000 preferred order,
    > // we will now copy the rest of inherited ACEs from the
    > // old DACL to the new DACL.
    > //
    > if (fDaclPresent && AclInfo.AceCount)
    > {
    > for (; CurrentAceIndex < AclInfo.AceCount; CurrentAceIndex++)
    > {
    > //
    > // STEP 16: Get an ACE.
    > //
    > if (!GetAce(pACL, CurrentAceIndex, &pTempAce))
    > {
    > err_msg();
    > fResult = 8;
    > goto EXITFUNC;
    > }
    >
    > //
    > // STEP 17: Add the ACE to the new ACL.
    > //
    > if (!AddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce,
    > ((PACE_HEADER) pTempAce)->AceSize))
    > {
    > err_msg();
    > fResult = 9;
    > goto EXITFUNC;
    > }
    > }
    > }
    >
    > //
    > // STEP 18: Set the new DACL to the new SD.
    > //
    > if (!SetSecurityDescriptorDacl(&newSD, TRUE, pNewACL, FALSE))
    > {
    > err_msg();
    > fResult = 10;
    > goto EXITFUNC;
    > }
    >
    > //
    > // STEP 19: Copy the old security descriptor control flags
    > // regarding DACL automatic inheritance for Windows 2000 or
    > // later where SetSecurityDescriptorControl() API is available
    > // in advapi32.dll.
    > //
    > _SetSecurityDescriptorControl =
    >
    (SetSecurityDescriptorControlFnPtr)GetProcAddress(GetModuleHandle(TEXT("adva
    pi32.dll")),"SetSecurityDescriptorControl");
    > if (_SetSecurityDescriptorControl)
    > {
    > SECURITY_DESCRIPTOR_CONTROL controlBitsOfInterest = 0;
    > SECURITY_DESCRIPTOR_CONTROL controlBitsToSet = 0;
    > SECURITY_DESCRIPTOR_CONTROL oldControlBits = 0;
    > DWORD dwRevision = 0;
    >
    > if (!GetSecurityDescriptorControl(pFileSD, &oldControlBits,
    > &dwRevision))
    > {
    > err_msg();
    > fResult = 10;
    > goto EXITFUNC;
    > }
    >
    > if (oldControlBits & SE_DACL_AUTO_INHERITED)
    > {
    > controlBitsOfInterest = SE_DACL_AUTO_INHERIT_REQ |
    > SE_DACL_AUTO_INHERITED;
    > controlBitsToSet = controlBitsOfInterest;
    > }
    > else if (oldControlBits & SE_DACL_PROTECTED)
    > {
    > controlBitsOfInterest = SE_DACL_PROTECTED;
    > controlBitsToSet = controlBitsOfInterest;
    > }
    >
    > if (controlBitsOfInterest)
    > {
    > if (!_SetSecurityDescriptorControl(&newSD, controlBitsOfInterest,
    > controlBitsToSet))
    > {
    > err_msg();
    > fResult = 11;
    > goto EXITFUNC;
    > }
    > }
    > }
    >
    > //
    > // STEP 20: Set the new SD to the File.
    > //
    > if (!SetFileSecurity(lpszFileName, secInfo, &newSD))
    > {
    > err_msg();
    > fResult = 12;
    > goto EXITFUNC;
    > }
    >
    > fResult = 0;
    >
    > EXITFUNC:
    > //
    > // STEP 21: Free allocated memory
    > //
    > if (pFileSD) free(pFileSD);
    > if (pNewACL) free(pNewACL);
    >
    > return fResult;
    > }
    >
  3. Archived from groups: microsoft.public.win2000.security (More info?)

    I didn't look at your code, sorry. I hate looking at other people's code.

    However I have often found the issue with doing this stuff is that the flags
    aren't set quite the way they should be. Do not use explorer to see if what you
    did matches what Explorer does, it hides a lot of the detail. You will want to
    dump the ACL of what you did and one you are trying to mimic and look at all of
    the specific fields to verify they are all identical.

    If you don't want to write the code to do that dump from scratch, look at
    http://www.rallenhome.com/books/adcookbook/src/PerlChkSec.pls.txt which has a
    perl script for doing that for AD permissions which should give you a jump on
    how to do it with other permissions (they are all handled very similarly).

    joe

    --
    Joe Richards Microsoft MVP Windows Server Directory Services
    www.joeware.net


    clintp@gmail.com wrote:
    > I've got a function that I'm using to create an inheritable ACE. I
    > want to grant permission on a directory, and have it be inherited by
    > its children.
    >
    > The function was largely stolen from MSDN, and it almost works. If I
    > go into Explorer and pull up the directory, everyhing looks fine -- all
    > of the correct switches are set, etc... If I look at the children --
    > no permissions are inherited.
    >
    > Doing it manually using Explorer's Security tab works fine.
    >
    > And, in fact, if I take the "broken" ACL on the directory and modify it
    > in any way using the Security tab and apply the changes... voila, it
    > gets inherited by its children.
    >
    > The function follows.
    >
    > PS: in the if(){} block below, I'm sure that AddAccessAllowedAceEx is
    > being called. I've dumped the ACE using another tool and the flag bits
    > look the same in the header whether this function adjusts the
    > permissions, or the Security tab does it. I'm completely lost.
    >
    > BOOL AddAccessRights(TCHAR *lpszFileName, TCHAR *lpszAccountName, DWORD
    > dwAccessMask)
    > {
    > // SID variables.
    > LPVOID pUserSID = NULL;
    >
    > // File SD variables.
    > PSECURITY_DESCRIPTOR pFileSD = NULL;
    > DWORD cbFileSD = 0;
    >
    > // New SD variables.
    > SECURITY_DESCRIPTOR newSD;
    >
    > // ACL variables.
    > PACL pACL = NULL;
    > BOOL fDaclPresent;
    > BOOL fDaclDefaulted;
    > ACL_SIZE_INFORMATION AclInfo;
    >
    > // New ACL variables.
    > PACL pNewACL = NULL;
    > DWORD cbNewACL = 0;
    >
    > // Temporary ACE.
    > LPVOID pTempAce = NULL;
    > UINT CurrentAceIndex = 0;
    >
    > UINT newAceIndex = 0;
    >
    > // Assume function will fail.
    > BOOL fResult = FALSE;
    >
    > SetSecurityDescriptorControlFnPtr _SetSecurityDescriptorControl;
    > AddAccessAllowedAceExFnPtr _AddAccessAllowedAceEx;
    >
    > SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION;
    >
    > //
    > // STEP 1: Get SID of the account name specified.
    > //
    > if (! (pUserSID = GetUserSid(lpszAccountName)))
    > {
    > fResult = 1;
    > goto EXITFUNC;
    > }
    >
    > //
    > // STEP 2: Get security descriptor (SD) of the file specified.
    > //
    > if (! GetFileSecurity(lpszFileName, secInfo, pFileSD, 0, &cbFileSD))
    > {
    > if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
    > {
    > err_msg();
    > fResult = 2;
    > goto EXITFUNC;
    > }
    > }
    >
    > if (! (pFileSD = malloc(cbFileSD)))
    > {
    > fResult = -1;
    > goto EXITFUNC;
    > }
    >
    > if (! GetFileSecurity(lpszFileName, secInfo, pFileSD, cbFileSD,
    > &cbFileSD))
    > {
    > err_msg();
    > fResult = 2;
    > goto EXITFUNC;
    > }
    >
    > //
    > // STEP 3: Initialize new SD.
    > //
    > if (!InitializeSecurityDescriptor(&newSD,
    > SECURITY_DESCRIPTOR_REVISION))
    > {
    > err_msg();
    > fResult = 3;
    > goto EXITFUNC;
    > }
    >
    > //
    > // STEP 4: Get DACL from the old SD.
    > //
    > if (!GetSecurityDescriptorDacl(pFileSD, &fDaclPresent, &pACL,
    > &fDaclDefaulted))
    > {
    > err_msg();
    > fResult = 4;
    > goto EXITFUNC;
    > }
    >
    > //
    > // STEP 5: Get size information for DACL.
    > //
    > AclInfo.AceCount = 0; // Assume NULL DACL.
    > AclInfo.AclBytesFree = 0;
    > AclInfo.AclBytesInUse = sizeof(ACL);
    >
    > if (pACL == NULL)
    > fDaclPresent = FALSE;
    >
    > // If not NULL DACL, gather size information from DACL.
    > if (fDaclPresent)
    > {
    > if (!GetAclInformation(pACL, &AclInfo, sizeof(ACL_SIZE_INFORMATION),
    > AclSizeInformation))
    > {
    > err_msg();
    > fResult = 5;
    > goto EXITFUNC;
    > }
    > }
    >
    > //
    > // STEP 6: Compute size needed for the new ACL.
    > //
    > cbNewACL = AclInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE) +
    > GetLengthSid(pUserSID) - sizeof(DWORD);
    >
    > //
    > // STEP 7: Allocate memory for new ACL.
    > //
    > if (! (pNewACL = (PACL) malloc(cbNewACL)))
    > {
    > fResult = -1;
    > goto EXITFUNC;
    > }
    >
    > //
    > // STEP 8: Initialize the new ACL.
    > //
    > if (!InitializeAcl(pNewACL, cbNewACL, ACL_REVISION2))
    > {
    > err_msg();
    > fResult = 6;
    > goto EXITFUNC;
    > }
    >
    > //
    > // STEP 9 If DACL is present, copy all the ACEs from the old DACL
    > // to the new DACL.
    > //
    > // The following code assumes that the old DACL is
    > // already in Windows 2000 preferred order. To conform
    > // to the new Windows 2000 preferred order, first we will
    > // copy all non-inherited ACEs from the old DACL to the
    > // new DACL, irrespective of the ACE type.
    > //
    > newAceIndex = 0;
    >
    > if (fDaclPresent && AclInfo.AceCount)
    > {
    > for (CurrentAceIndex = 0; CurrentAceIndex < AclInfo.AceCount;
    > CurrentAceIndex++)
    > {
    > //
    > // STEP 10: Get an ACE.
    > //
    > if (!GetAce(pACL, CurrentAceIndex, &pTempAce))
    > {
    > err_msg();
    > fResult = 7;
    > goto EXITFUNC;
    > }
    >
    > //
    > // STEP 11: Check if it is a non-inherited ACE.
    > // If it is an inherited ACE, break from the loop so
    > // that the new access allowed non-inherited ACE can
    > // be added in the correct position, immediately after
    > // all non-inherited ACEs.
    > //
    > if (((ACCESS_ALLOWED_ACE *)pTempAce)->Header.AceFlags &
    > INHERITED_ACE)
    > break;
    >
    > //
    > // STEP 12: Skip adding the ACE, if the SID matches
    > // with the account specified, as we are going to
    > // add an access allowed ACE with a different access
    > // mask.
    > //
    > if (EqualSid(pUserSID, &(((ACCESS_ALLOWED_ACE
    > *)pTempAce)->SidStart)))
    > continue;
    >
    > //
    > // STEP 13: Add the ACE to the new ACL.
    > //
    > if (!AddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce,
    > ((PACE_HEADER) pTempAce)->AceSize))
    > {
    > err_msg();
    > fResult = 7;
    > goto EXITFUNC;
    > }
    >
    > newAceIndex++;
    > }
    > }
    >
    > //
    > // STEP 14: Add the access-allowed ACE to the new DACL.
    > // The new ACE added here will be in the correct position,
    > // immediately after all existing non-inherited ACEs.
    > //
    > _AddAccessAllowedAceEx =
    > (AddAccessAllowedAceExFnPtr)GetProcAddress(GetModuleHandle(TEXT("advapi32.dll")),"AddAccessAllowedAceEx");
    > if (_AddAccessAllowedAceEx)
    > {
    > fprintf(stderr, "new API\n");
    > if (!_AddAccessAllowedAceEx(pNewACL, ACL_REVISION2,
    > CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, dwAccessMask, pUserSID))
    > {
    > err_msg();
    > fResult = 8;
    > goto EXITFUNC;
    > }
    > }
    > else
    > {
    > if (!AddAccessAllowedAce(pNewACL, ACL_REVISION2, dwAccessMask,
    > pUserSID))
    > {
    > err_msg();
    > fResult = 8;
    > goto EXITFUNC;
    > }
    > }
    >
    > //
    > // STEP 15: To conform to the new Windows 2000 preferred order,
    > // we will now copy the rest of inherited ACEs from the
    > // old DACL to the new DACL.
    > //
    > if (fDaclPresent && AclInfo.AceCount)
    > {
    > for (; CurrentAceIndex < AclInfo.AceCount; CurrentAceIndex++)
    > {
    > //
    > // STEP 16: Get an ACE.
    > //
    > if (!GetAce(pACL, CurrentAceIndex, &pTempAce))
    > {
    > err_msg();
    > fResult = 8;
    > goto EXITFUNC;
    > }
    >
    > //
    > // STEP 17: Add the ACE to the new ACL.
    > //
    > if (!AddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce,
    > ((PACE_HEADER) pTempAce)->AceSize))
    > {
    > err_msg();
    > fResult = 9;
    > goto EXITFUNC;
    > }
    > }
    > }
    >
    > //
    > // STEP 18: Set the new DACL to the new SD.
    > //
    > if (!SetSecurityDescriptorDacl(&newSD, TRUE, pNewACL, FALSE))
    > {
    > err_msg();
    > fResult = 10;
    > goto EXITFUNC;
    > }
    >
    > //
    > // STEP 19: Copy the old security descriptor control flags
    > // regarding DACL automatic inheritance for Windows 2000 or
    > // later where SetSecurityDescriptorControl() API is available
    > // in advapi32.dll.
    > //
    > _SetSecurityDescriptorControl =
    > (SetSecurityDescriptorControlFnPtr)GetProcAddress(GetModuleHandle(TEXT("advapi32.dll")),"SetSecurityDescriptorControl");
    > if (_SetSecurityDescriptorControl)
    > {
    > SECURITY_DESCRIPTOR_CONTROL controlBitsOfInterest = 0;
    > SECURITY_DESCRIPTOR_CONTROL controlBitsToSet = 0;
    > SECURITY_DESCRIPTOR_CONTROL oldControlBits = 0;
    > DWORD dwRevision = 0;
    >
    > if (!GetSecurityDescriptorControl(pFileSD, &oldControlBits,
    > &dwRevision))
    > {
    > err_msg();
    > fResult = 10;
    > goto EXITFUNC;
    > }
    >
    > if (oldControlBits & SE_DACL_AUTO_INHERITED)
    > {
    > controlBitsOfInterest = SE_DACL_AUTO_INHERIT_REQ |
    > SE_DACL_AUTO_INHERITED;
    > controlBitsToSet = controlBitsOfInterest;
    > }
    > else if (oldControlBits & SE_DACL_PROTECTED)
    > {
    > controlBitsOfInterest = SE_DACL_PROTECTED;
    > controlBitsToSet = controlBitsOfInterest;
    > }
    >
    > if (controlBitsOfInterest)
    > {
    > if (!_SetSecurityDescriptorControl(&newSD, controlBitsOfInterest,
    > controlBitsToSet))
    > {
    > err_msg();
    > fResult = 11;
    > goto EXITFUNC;
    > }
    > }
    > }
    >
    > //
    > // STEP 20: Set the new SD to the File.
    > //
    > if (!SetFileSecurity(lpszFileName, secInfo, &newSD))
    > {
    > err_msg();
    > fResult = 12;
    > goto EXITFUNC;
    > }
    >
    > fResult = 0;
    >
    > EXITFUNC:
    > //
    > // STEP 21: Free allocated memory
    > //
    > if (pFileSD) free(pFileSD);
    > if (pNewACL) free(pNewACL);
    >
    > return fResult;
    > }
    >
  4. Archived from groups: microsoft.public.win2000.security (More info?)

    It is not just that the ACL editor accessed from Explorer hides
    detail of the SD, ACL, and ACE headers and flags, it also will
    alter them to what is believed equivalent but more "simple",
    whatever the criteria are for that . . .

    --
    Roger
    "Joe Richards [MVP]" <humorexpress@hotmail.com> wrote in message
    news:eW5Zet9UFHA.2128@TK2MSFTNGP15.phx.gbl...
    > I didn't look at your code, sorry. I hate looking at other people's code.
    >
    > However I have often found the issue with doing this stuff is that the
    flags
    > aren't set quite the way they should be. Do not use explorer to see if
    what you
    > did matches what Explorer does, it hides a lot of the detail. You will
    want to
    > dump the ACL of what you did and one you are trying to mimic and look at
    all of
    > the specific fields to verify they are all identical.
    >
    > If you don't want to write the code to do that dump from scratch, look at
    > http://www.rallenhome.com/books/adcookbook/src/PerlChkSec.pls.txt which
    has a
    > perl script for doing that for AD permissions which should give you a jump
    on
    > how to do it with other permissions (they are all handled very similarly).
    >
    > joe
    >
    > --
    > Joe Richards Microsoft MVP Windows Server Directory Services
    > www.joeware.net
    >
    >
    > clintp@gmail.com wrote:
    > > I've got a function that I'm using to create an inheritable ACE. I
    > > want to grant permission on a directory, and have it be inherited by
    > > its children.
    > >
    > > The function was largely stolen from MSDN, and it almost works. If I
    > > go into Explorer and pull up the directory, everyhing looks fine -- all
    > > of the correct switches are set, etc... If I look at the children --
    > > no permissions are inherited.
    > >
    > > Doing it manually using Explorer's Security tab works fine.
    > >
    > > And, in fact, if I take the "broken" ACL on the directory and modify it
    > > in any way using the Security tab and apply the changes... voila, it
    > > gets inherited by its children.
    > >
    > > The function follows.
    > >
    > > PS: in the if(){} block below, I'm sure that AddAccessAllowedAceEx is
    > > being called. I've dumped the ACE using another tool and the flag bits
    > > look the same in the header whether this function adjusts the
    > > permissions, or the Security tab does it. I'm completely lost.
    > >
    > > BOOL AddAccessRights(TCHAR *lpszFileName, TCHAR *lpszAccountName, DWORD
    > > dwAccessMask)
    > > {
    > > // SID variables.
    > > LPVOID pUserSID = NULL;
    > >
    > > // File SD variables.
    > > PSECURITY_DESCRIPTOR pFileSD = NULL;
    > > DWORD cbFileSD = 0;
    > >
    > > // New SD variables.
    > > SECURITY_DESCRIPTOR newSD;
    > >
    > > // ACL variables.
    > > PACL pACL = NULL;
    > > BOOL fDaclPresent;
    > > BOOL fDaclDefaulted;
    > > ACL_SIZE_INFORMATION AclInfo;
    > >
    > > // New ACL variables.
    > > PACL pNewACL = NULL;
    > > DWORD cbNewACL = 0;
    > >
    > > // Temporary ACE.
    > > LPVOID pTempAce = NULL;
    > > UINT CurrentAceIndex = 0;
    > >
    > > UINT newAceIndex = 0;
    > >
    > > // Assume function will fail.
    > > BOOL fResult = FALSE;
    > >
    > > SetSecurityDescriptorControlFnPtr _SetSecurityDescriptorControl;
    > > AddAccessAllowedAceExFnPtr _AddAccessAllowedAceEx;
    > >
    > > SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION;
    > >
    > > //
    > > // STEP 1: Get SID of the account name specified.
    > > //
    > > if (! (pUserSID = GetUserSid(lpszAccountName)))
    > > {
    > > fResult = 1;
    > > goto EXITFUNC;
    > > }
    > >
    > > //
    > > // STEP 2: Get security descriptor (SD) of the file specified.
    > > //
    > > if (! GetFileSecurity(lpszFileName, secInfo, pFileSD, 0, &cbFileSD))
    > > {
    > > if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
    > > {
    > > err_msg();
    > > fResult = 2;
    > > goto EXITFUNC;
    > > }
    > > }
    > >
    > > if (! (pFileSD = malloc(cbFileSD)))
    > > {
    > > fResult = -1;
    > > goto EXITFUNC;
    > > }
    > >
    > > if (! GetFileSecurity(lpszFileName, secInfo, pFileSD, cbFileSD,
    > > &cbFileSD))
    > > {
    > > err_msg();
    > > fResult = 2;
    > > goto EXITFUNC;
    > > }
    > >
    > > //
    > > // STEP 3: Initialize new SD.
    > > //
    > > if (!InitializeSecurityDescriptor(&newSD,
    > > SECURITY_DESCRIPTOR_REVISION))
    > > {
    > > err_msg();
    > > fResult = 3;
    > > goto EXITFUNC;
    > > }
    > >
    > > //
    > > // STEP 4: Get DACL from the old SD.
    > > //
    > > if (!GetSecurityDescriptorDacl(pFileSD, &fDaclPresent, &pACL,
    > > &fDaclDefaulted))
    > > {
    > > err_msg();
    > > fResult = 4;
    > > goto EXITFUNC;
    > > }
    > >
    > > //
    > > // STEP 5: Get size information for DACL.
    > > //
    > > AclInfo.AceCount = 0; // Assume NULL DACL.
    > > AclInfo.AclBytesFree = 0;
    > > AclInfo.AclBytesInUse = sizeof(ACL);
    > >
    > > if (pACL == NULL)
    > > fDaclPresent = FALSE;
    > >
    > > // If not NULL DACL, gather size information from DACL.
    > > if (fDaclPresent)
    > > {
    > > if (!GetAclInformation(pACL, &AclInfo, sizeof(ACL_SIZE_INFORMATION),
    > > AclSizeInformation))
    > > {
    > > err_msg();
    > > fResult = 5;
    > > goto EXITFUNC;
    > > }
    > > }
    > >
    > > //
    > > // STEP 6: Compute size needed for the new ACL.
    > > //
    > > cbNewACL = AclInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE) +
    > > GetLengthSid(pUserSID) - sizeof(DWORD);
    > >
    > > //
    > > // STEP 7: Allocate memory for new ACL.
    > > //
    > > if (! (pNewACL = (PACL) malloc(cbNewACL)))
    > > {
    > > fResult = -1;
    > > goto EXITFUNC;
    > > }
    > >
    > > //
    > > // STEP 8: Initialize the new ACL.
    > > //
    > > if (!InitializeAcl(pNewACL, cbNewACL, ACL_REVISION2))
    > > {
    > > err_msg();
    > > fResult = 6;
    > > goto EXITFUNC;
    > > }
    > >
    > > //
    > > // STEP 9 If DACL is present, copy all the ACEs from the old DACL
    > > // to the new DACL.
    > > //
    > > // The following code assumes that the old DACL is
    > > // already in Windows 2000 preferred order. To conform
    > > // to the new Windows 2000 preferred order, first we will
    > > // copy all non-inherited ACEs from the old DACL to the
    > > // new DACL, irrespective of the ACE type.
    > > //
    > > newAceIndex = 0;
    > >
    > > if (fDaclPresent && AclInfo.AceCount)
    > > {
    > > for (CurrentAceIndex = 0; CurrentAceIndex < AclInfo.AceCount;
    > > CurrentAceIndex++)
    > > {
    > > //
    > > // STEP 10: Get an ACE.
    > > //
    > > if (!GetAce(pACL, CurrentAceIndex, &pTempAce))
    > > {
    > > err_msg();
    > > fResult = 7;
    > > goto EXITFUNC;
    > > }
    > >
    > > //
    > > // STEP 11: Check if it is a non-inherited ACE.
    > > // If it is an inherited ACE, break from the loop so
    > > // that the new access allowed non-inherited ACE can
    > > // be added in the correct position, immediately after
    > > // all non-inherited ACEs.
    > > //
    > > if (((ACCESS_ALLOWED_ACE *)pTempAce)->Header.AceFlags &
    > > INHERITED_ACE)
    > > break;
    > >
    > > //
    > > // STEP 12: Skip adding the ACE, if the SID matches
    > > // with the account specified, as we are going to
    > > // add an access allowed ACE with a different access
    > > // mask.
    > > //
    > > if (EqualSid(pUserSID, &(((ACCESS_ALLOWED_ACE
    > > *)pTempAce)->SidStart)))
    > > continue;
    > >
    > > //
    > > // STEP 13: Add the ACE to the new ACL.
    > > //
    > > if (!AddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce,
    > > ((PACE_HEADER) pTempAce)->AceSize))
    > > {
    > > err_msg();
    > > fResult = 7;
    > > goto EXITFUNC;
    > > }
    > >
    > > newAceIndex++;
    > > }
    > > }
    > >
    > > //
    > > // STEP 14: Add the access-allowed ACE to the new DACL.
    > > // The new ACE added here will be in the correct position,
    > > // immediately after all existing non-inherited ACEs.
    > > //
    > > _AddAccessAllowedAceEx =
    > >
    (AddAccessAllowedAceExFnPtr)GetProcAddress(GetModuleHandle(TEXT("advapi32.dl
    l")),"AddAccessAllowedAceEx");
    > > if (_AddAccessAllowedAceEx)
    > > {
    > > fprintf(stderr, "new API\n");
    > > if (!_AddAccessAllowedAceEx(pNewACL, ACL_REVISION2,
    > > CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, dwAccessMask, pUserSID))
    > > {
    > > err_msg();
    > > fResult = 8;
    > > goto EXITFUNC;
    > > }
    > > }
    > > else
    > > {
    > > if (!AddAccessAllowedAce(pNewACL, ACL_REVISION2, dwAccessMask,
    > > pUserSID))
    > > {
    > > err_msg();
    > > fResult = 8;
    > > goto EXITFUNC;
    > > }
    > > }
    > >
    > > //
    > > // STEP 15: To conform to the new Windows 2000 preferred order,
    > > // we will now copy the rest of inherited ACEs from the
    > > // old DACL to the new DACL.
    > > //
    > > if (fDaclPresent && AclInfo.AceCount)
    > > {
    > > for (; CurrentAceIndex < AclInfo.AceCount; CurrentAceIndex++)
    > > {
    > > //
    > > // STEP 16: Get an ACE.
    > > //
    > > if (!GetAce(pACL, CurrentAceIndex, &pTempAce))
    > > {
    > > err_msg();
    > > fResult = 8;
    > > goto EXITFUNC;
    > > }
    > >
    > > //
    > > // STEP 17: Add the ACE to the new ACL.
    > > //
    > > if (!AddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce,
    > > ((PACE_HEADER) pTempAce)->AceSize))
    > > {
    > > err_msg();
    > > fResult = 9;
    > > goto EXITFUNC;
    > > }
    > > }
    > > }
    > >
    > > //
    > > // STEP 18: Set the new DACL to the new SD.
    > > //
    > > if (!SetSecurityDescriptorDacl(&newSD, TRUE, pNewACL, FALSE))
    > > {
    > > err_msg();
    > > fResult = 10;
    > > goto EXITFUNC;
    > > }
    > >
    > > //
    > > // STEP 19: Copy the old security descriptor control flags
    > > // regarding DACL automatic inheritance for Windows 2000 or
    > > // later where SetSecurityDescriptorControl() API is available
    > > // in advapi32.dll.
    > > //
    > > _SetSecurityDescriptorControl =
    > >
    (SetSecurityDescriptorControlFnPtr)GetProcAddress(GetModuleHandle(TEXT("adva
    pi32.dll")),"SetSecurityDescriptorControl");
    > > if (_SetSecurityDescriptorControl)
    > > {
    > > SECURITY_DESCRIPTOR_CONTROL controlBitsOfInterest = 0;
    > > SECURITY_DESCRIPTOR_CONTROL controlBitsToSet = 0;
    > > SECURITY_DESCRIPTOR_CONTROL oldControlBits = 0;
    > > DWORD dwRevision = 0;
    > >
    > > if (!GetSecurityDescriptorControl(pFileSD, &oldControlBits,
    > > &dwRevision))
    > > {
    > > err_msg();
    > > fResult = 10;
    > > goto EXITFUNC;
    > > }
    > >
    > > if (oldControlBits & SE_DACL_AUTO_INHERITED)
    > > {
    > > controlBitsOfInterest = SE_DACL_AUTO_INHERIT_REQ |
    > > SE_DACL_AUTO_INHERITED;
    > > controlBitsToSet = controlBitsOfInterest;
    > > }
    > > else if (oldControlBits & SE_DACL_PROTECTED)
    > > {
    > > controlBitsOfInterest = SE_DACL_PROTECTED;
    > > controlBitsToSet = controlBitsOfInterest;
    > > }
    > >
    > > if (controlBitsOfInterest)
    > > {
    > > if (!_SetSecurityDescriptorControl(&newSD, controlBitsOfInterest,
    > > controlBitsToSet))
    > > {
    > > err_msg();
    > > fResult = 11;
    > > goto EXITFUNC;
    > > }
    > > }
    > > }
    > >
    > > //
    > > // STEP 20: Set the new SD to the File.
    > > //
    > > if (!SetFileSecurity(lpszFileName, secInfo, &newSD))
    > > {
    > > err_msg();
    > > fResult = 12;
    > > goto EXITFUNC;
    > > }
    > >
    > > fResult = 0;
    > >
    > > EXITFUNC:
    > > //
    > > // STEP 21: Free allocated memory
    > > //
    > > if (pFileSD) free(pFileSD);
    > > if (pNewACL) free(pNewACL);
    > >
    > > return fResult;
    > > }
    > >
Ask a new question

Read More

Security Windows