Following incomplete snippet removes write access and leaves any other permissions in the access mask unchanged.
err = GetExplicitEntriesFromAcl(pDacl, &nEntries, &pExplicit);
if (!err)
{
for (ULONG i = 0; i < nEntries; i++)
{
PEXPLICIT_ACCESS pea = &pExplicit[i];
if (pea->Trustee.TrusteeForm != TRUSTEE_IS_SID)
{
_tprintf(_T("Trustee form was not a SID\n"));
continue;
}
if (pea->Trustee.TrusteeForm == TRUSTEE_IS_SID)
{
if (EqualSid((PSID)pea->Trustee.ptstrName, pts2->Sid))
{
PACL pNewDacl{};
pea->grfAccessMode = SET_ACCESS;
// Remove permissions from access mask
pea->grfAccessPermissions &= ~(WRITE_DAC | WRITE_OWNER | DELETE); // Standard rights
pea->grfAccessPermissions &= ~(FILE_ADD_FILE | FILE_ADD_SUBDIRECTORY | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_DELETE_CHILD); // specific rights
err = SetEntriesInAcl(1, pea, pDacl, &pNewDacl);
if (!err)
{
err = SetNamedSecurityInfo(szFolder, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
nullptr, nullptr, pNewDacl, nullptr);
if (err)
ShowLastError(_T("SetNamedSecurityInfo"), err);
LocalFree(pNewDacl);
}
else
ShowLastError(_T("SetEntriesInAcl"), err);
break;
}
}
}
LocalFree(pExplicit);
}
else
ShowLastError(_T("GetExplicitEntriesFromAcl"), err);
The assumption used is that its OK to let SetNamedSecurityInfo handle propagation of permissions to subfolders/files based on the existing settings in the security descriptor.