windows-nt/Source/XPSP1/NT/ds/security/ntmarta/newsrc/seia.cxx
2020-09-26 16:20:57 +08:00

1678 lines
56 KiB
C++

////////////////////////////////////////////////////////////////////////////////
// //
// Microsoft Windows //
// Copyright (C) Microsoft Corporation, 1999. //
// //
// File: seia.cxx //
// //
// Contents: New marta rewrite functions for SetEntriesInAcl //
// //
// History: 4/99 KedarD Created //
// //
////////////////////////////////////////////////////////////////////////////////
#include <aclpch.hxx>
#pragma hdrstop
extern "C"
{
#include <stdio.h>
#include <permit.h>
#include <dsgetdc.h>
#include <lmapibuf.h>
#include <wmistr.h>
#include <ntprov.hxx>
#include <strings.h>
#include <seopaque.h>
#include <sertlp.h>
#include <accctrl.h>
#include <guidtables.h>
}
////////////////////////////////////////////////////////////////////////////////
// //
// MACRO DEFINITIONS START HERE //
// //
////////////////////////////////////////////////////////////////////////////////
#define MARTA_SID_FOR_NAME \
{ \
((PKNOWN_ACE) *ppAcl)->Mask = pAccessInfo->Mask; \
AceSize = RtlLengthSid(pAccessInfo->pSid); \
memcpy( \
((PUCHAR) *ppAcl) + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK), \
(PUCHAR) pAccessInfo->pSid, \
AceSize \
); \
AceSize += sizeof(ACE_HEADER) + sizeof(ACCESS_MASK); \
}
#define MARTA_SID_FOR_SID \
{ \
((PKNOWN_ACE) *ppAcl)->Mask = pAccessInfo->Mask; \
AceSize = RtlLengthSid((PSID) pExplicitAccess->Trustee.ptstrName); \
memcpy( \
((PUCHAR) *ppAcl) + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK), \
(PUCHAR) pExplicitAccess->Trustee.ptstrName, \
AceSize \
); \
AceSize += sizeof(ACE_HEADER) + sizeof(ACCESS_MASK); \
}
#define MARTA_SID_AND_GUID_FOR_OBJECT_NAME \
{ \
pObjName = (POBJECTS_AND_NAME_W) pExplicitAccess->Trustee.ptstrName;\
((PKNOWN_OBJECT_ACE) *ppAcl)->Flags = pObjName->ObjectsPresent; \
((PKNOWN_OBJECT_ACE) *ppAcl)->Mask = pAccessInfo->Mask; \
AceSize = RtlLengthSid(pAccessInfo->pSid); \
memcpy( \
(PUCHAR) RtlObjectAceSid(*ppAcl), \
(PUCHAR) pAccessInfo->pSid, \
AceSize \
); \
pGuid = RtlObjectAceObjectType(*ppAcl); \
if (NULL != pGuid) \
{ \
memcpy( \
(PUCHAR) pGuid, \
(PUCHAR) pAccessInfo->pObjectTypeGuid, \
sizeof(GUID) \
); \
AceSize += sizeof(GUID); \
} \
pGuid = RtlObjectAceInheritedObjectType(*ppAcl); \
if (NULL != pGuid) \
{ \
memcpy( \
(PUCHAR) pGuid, \
(PUCHAR) pAccessInfo->pInheritedObjectTypeGuid, \
sizeof(GUID) \
); \
AceSize += sizeof(GUID); \
} \
AceSize += sizeof(ACE_HEADER) + sizeof(ACCESS_MASK) + sizeof(ULONG);\
}
#define MARTA_SID_AND_GUID_FOR_OBJECT_SID \
{ \
pObjSid = (POBJECTS_AND_SID) pExplicitAccess->Trustee.ptstrName; \
((PKNOWN_OBJECT_ACE) *ppAcl)->Flags = pObjSid->ObjectsPresent; \
((PKNOWN_OBJECT_ACE) *ppAcl)->Mask = pAccessInfo->Mask; \
AceSize = RtlLengthSid(pObjSid->pSid); \
memcpy( \
(PUCHAR) RtlObjectAceSid(*ppAcl), \
(PUCHAR) pObjSid->pSid, \
AceSize \
); \
pGuid = RtlObjectAceObjectType(*ppAcl); \
if (NULL != pGuid) \
{ \
memcpy( \
(PUCHAR) pGuid, \
(PUCHAR) &(pObjSid->ObjectTypeGuid), \
sizeof(GUID) \
); \
AceSize += sizeof(GUID); \
} \
pGuid = RtlObjectAceInheritedObjectType(*ppAcl); \
if (NULL != pGuid) \
{ \
memcpy( \
(PUCHAR) pGuid, \
(PUCHAR) &(pObjSid->InheritedObjectTypeGuid), \
sizeof(GUID) \
); \
AceSize += sizeof(GUID); \
} \
AceSize += sizeof(ACE_HEADER) + sizeof(ACCESS_MASK) + sizeof(ULONG);\
}
typedef struct _MARTA_ACCESS_INFO
{
ACCESS_MASK Mask;
ULONG Size;
PSID pSid;
PSID pServerSid;
GUID * pObjectTypeGuid;
GUID * pInheritedObjectTypeGuid;
} MARTA_ACCESS_INFO, *PMARTA_ACCESS_INFO;
////////////////////////////////////////////////////////////////////////////////
// //
// FUNCTION PROTOTYPES START HERE //
// //
////////////////////////////////////////////////////////////////////////////////
DWORD
WINAPI
AccRewriteSetEntriesInAcl(
IN ULONG cCountOfExplicitEntries,
IN PEXPLICIT_ACCESS_W pListOfExplicitEntries,
IN PACL OldAcl,
OUT PACL * pNewAcl
);
BOOL
MartaIsExplicitAclCanonical(
IN PACL pAcl,
OUT PULONG pExplicitAceCnt
);
DWORD
MartaTrusteeSidAndGuidSize(
IN PTRUSTEE_W pTrustee,
IN BOOL bComputeGuidSize,
OUT PSID * ppSid,
OUT PULONG pSize,
OUT PULONG pGuidCnt OPTIONAL
);
DWORD
MartaAddExplicitEntryToAcl(
IN OUT PUCHAR * ppAcl,
IN PEXPLICIT_ACCESS_W pExplicitAccess,
IN PMARTA_ACCESS_INFO pAccessInfo
);
DWORD
MartaGetSidFromName(
IN LPWSTR pName,
OUT PSID * ppSid
);
DWORD
MartaGetGuid(
IN LPWSTR pObjectName,
IN SE_OBJECT_TYPE ObjectType,
OUT GUID * pGuid
);
DWORD
MartaGetExplicitAccessEntrySize(
IN PEXPLICIT_ACCESS_W pExplicitAccess,
OUT PMARTA_ACCESS_INFO pAccessInfo,
OUT PULONG pGuidCnt,
OUT PUCHAR pAclRevision
);
DWORD
MartaCompareAcesAndMarkMasks(
IN PUCHAR pAce,
IN PACCESS_MASK pAceMask,
IN PEXPLICIT_ACCESS_W pExplicitAccess,
IN PMARTA_ACCESS_INFO pAccessInfo,
IN BOOL bCanonical
);
////////////////////////////////////////////////////////////////////////////////
// //
// Function: MartaAddExplicitEntryToAcl //
// //
// Description: Convert an explicit entry into an ace and store it in the //
// acl. Update the acl pointer to the end. //
// //
// Arguments: //
// //
// [IN OUT ppAcl] Acl pointer where the ace should be stored //
// //
// [IN pExplicitAccess] Explicit entry to convert into an ace //
// [IN pAccessInfo] Temp info associated with the explicit entry //
// //
// Returns: ERROR_SUCCESS if the entry could be converted into an ACE //
// Appropriate failure otherwise //
// //
////////////////////////////////////////////////////////////////////////////////
DWORD
MartaAddExplicitEntryToAcl(
IN OUT PUCHAR * ppAcl,
IN PEXPLICIT_ACCESS_W pExplicitAccess,
IN PMARTA_ACCESS_INFO pAccessInfo
)
{
DWORD dwErr = ERROR_SUCCESS;
ULONG AceSize = 0;
ULONG SidSize = 0;
UCHAR AceType = 0;
UCHAR AceFlags = 0;
PSID pSid = NULL;
GUID * pGuid = NULL;
POBJECTS_AND_SID pObjSid = NULL;
POBJECTS_AND_NAME_W pObjName = NULL;
if (REVOKE_ACCESS == pExplicitAccess->grfAccessMode)
{
return ERROR_SUCCESS;
}
if (FLAG_ON(pExplicitAccess->grfInheritance, INHERITED_ACE))
{
return ERROR_SUCCESS;
}
if (0 == pAccessInfo->Size)
{
return ERROR_SUCCESS;
}
if (TRUSTEE_IS_IMPERSONATE == pExplicitAccess->Trustee.MultipleTrusteeOperation)
{
((PKNOWN_COMPOUND_ACE) *ppAcl)->CompoundAceType = COMPOUND_ACE_IMPERSONATION;
((PKNOWN_COMPOUND_ACE) *ppAcl)->Mask = pAccessInfo->Mask;
((PKNOWN_COMPOUND_ACE) *ppAcl)->Reserved = 0;
AceSize = sizeof(ACE_HEADER) + sizeof(ACCESS_MASK) + sizeof(LONG);
pSid = pAccessInfo->pServerSid ?
pAccessInfo->pServerSid :
(PSID) pExplicitAccess->Trustee.ptstrName;
SidSize = RtlLengthSid(pSid);
memcpy(
((PUCHAR) *ppAcl) + AceSize,
(PUCHAR) pSid,
SidSize
);
AceSize += SidSize;
pSid = pAccessInfo->pSid ?
pAccessInfo->pSid :
(PSID) (pExplicitAccess->Trustee.pMultipleTrustee->ptstrName);
SidSize = RtlLengthSid(pSid);
memcpy(
((PUCHAR) *ppAcl) + AceSize,
(PUCHAR) pSid,
SidSize
);
AceSize += SidSize;
CONDITIONAL_ACE_SIZE_ERROR(AceSize);
((PACE_HEADER) *ppAcl)->AceType = ACCESS_ALLOWED_COMPOUND_ACE_TYPE;
((PACE_HEADER) *ppAcl)->AceFlags = (UCHAR) pExplicitAccess->grfInheritance;
((PACE_HEADER) *ppAcl)->AceSize = (USHORT) AceSize;
*ppAcl += AceSize;
return ERROR_SUCCESS;
}
switch (pExplicitAccess->grfAccessMode)
{
case GRANT_ACCESS:
case SET_ACCESS:
AceFlags = (UCHAR) pExplicitAccess->grfInheritance;
switch (pExplicitAccess->Trustee.TrusteeForm)
{
case TRUSTEE_IS_NAME:
AceType = ACCESS_ALLOWED_ACE_TYPE;
MARTA_SID_FOR_NAME
break;
case TRUSTEE_IS_SID:
AceType = ACCESS_ALLOWED_ACE_TYPE;
MARTA_SID_FOR_SID
break;
case TRUSTEE_IS_OBJECTS_AND_SID:
AceType = ACCESS_ALLOWED_OBJECT_ACE_TYPE;
MARTA_SID_AND_GUID_FOR_OBJECT_SID
break;
case TRUSTEE_IS_OBJECTS_AND_NAME:
AceType = ACCESS_ALLOWED_OBJECT_ACE_TYPE;
MARTA_SID_AND_GUID_FOR_OBJECT_NAME
break;
default:
break;
}
break;
case DENY_ACCESS:
AceFlags = (UCHAR) pExplicitAccess->grfInheritance;
switch (pExplicitAccess->Trustee.TrusteeForm)
{
case TRUSTEE_IS_NAME:
AceType = ACCESS_DENIED_ACE_TYPE;
MARTA_SID_FOR_NAME
break;
case TRUSTEE_IS_SID:
AceType = ACCESS_DENIED_ACE_TYPE;
MARTA_SID_FOR_SID
break;
case TRUSTEE_IS_OBJECTS_AND_SID:
AceType = ACCESS_DENIED_OBJECT_ACE_TYPE;
MARTA_SID_AND_GUID_FOR_OBJECT_SID
break;
case TRUSTEE_IS_OBJECTS_AND_NAME:
AceType = ACCESS_DENIED_OBJECT_ACE_TYPE;
MARTA_SID_AND_GUID_FOR_OBJECT_NAME
break;
default:
break;
}
break;
case SET_AUDIT_SUCCESS:
AceFlags = (UCHAR) (pExplicitAccess->grfInheritance | SUCCESSFUL_ACCESS_ACE_FLAG);
switch (pExplicitAccess->Trustee.TrusteeForm)
{
case TRUSTEE_IS_NAME:
AceType = SYSTEM_AUDIT_ACE_TYPE;
MARTA_SID_FOR_NAME
break;
case TRUSTEE_IS_SID:
AceType = SYSTEM_AUDIT_ACE_TYPE;
MARTA_SID_FOR_SID
break;
case TRUSTEE_IS_OBJECTS_AND_SID:
AceType = SYSTEM_AUDIT_OBJECT_ACE_TYPE;
MARTA_SID_AND_GUID_FOR_OBJECT_SID
break;
case TRUSTEE_IS_OBJECTS_AND_NAME:
AceType = SYSTEM_AUDIT_OBJECT_ACE_TYPE;
MARTA_SID_AND_GUID_FOR_OBJECT_NAME
break;
default:
break;
}
break;
case SET_AUDIT_FAILURE:
AceFlags = (UCHAR) (pExplicitAccess->grfInheritance | FAILED_ACCESS_ACE_FLAG);
switch (pExplicitAccess->Trustee.TrusteeForm)
{
case TRUSTEE_IS_NAME:
AceType = SYSTEM_AUDIT_ACE_TYPE;
MARTA_SID_FOR_NAME
break;
case TRUSTEE_IS_SID:
AceType = SYSTEM_AUDIT_ACE_TYPE;
MARTA_SID_FOR_SID
break;
case TRUSTEE_IS_OBJECTS_AND_SID:
AceType = SYSTEM_AUDIT_OBJECT_ACE_TYPE;
MARTA_SID_AND_GUID_FOR_OBJECT_SID
break;
case TRUSTEE_IS_OBJECTS_AND_NAME:
AceType = SYSTEM_AUDIT_OBJECT_ACE_TYPE;
MARTA_SID_AND_GUID_FOR_OBJECT_NAME
break;
default:
break;
}
break;
case REVOKE_ACCESS:
return ERROR_SUCCESS;
default:
return ERROR_SUCCESS;
}
CONDITIONAL_ACE_SIZE_ERROR(AceSize);
((PACE_HEADER) *ppAcl)->AceType = AceType;
((PACE_HEADER) *ppAcl)->AceFlags = AceFlags;
((PACE_HEADER) *ppAcl)->AceSize = (USHORT) AceSize;
*ppAcl += AceSize;
return ERROR_SUCCESS;
}
////////////////////////////////////////////////////////////////////////////////
// //
// Function: MartaCompareAcesAndMarkMasks //
// //
// Description: Check if the explicit entry is supposed to make any changes //
// to the ace. If so, store the change into the temp structure //
// assoiciated with the ace. //
// //
// Arguments: //
// //
// [IN pAce] Ace to compare with the explict entry //
// [IN pAceMask] Temp info associated with the ace //
// [IN pExplicitAccess] Explicit entry //
// [IN pAccessInfo] Temp info associated with the explicit entry //
// [IN bCanonical] Whether the acl passed in is canonical //
// //
// Returns: ERROR_SUCCESS if the entry could be converted into an ACE //
// Appropriate failure otherwise //
// //
////////////////////////////////////////////////////////////////////////////////
DWORD
MartaCompareAcesAndMarkMasks(
IN PUCHAR pAce,
IN PACCESS_MASK pAceMask,
IN PEXPLICIT_ACCESS_W pExplicitAccess,
IN PMARTA_ACCESS_INFO pAccessInfo,
IN BOOL bCanonical
)
{
ULONG SidLength = 0;
DWORD ObjectsPresent = 0;
GUID * pGuid = NULL;
GUID * pObjectTypeGuid = NULL;
GUID * pInheritedObjectTypeGuid = NULL;
PSID pSid = NULL;
POBJECTS_AND_SID pObjSid = NULL;
POBJECTS_AND_NAME_W pObjName = NULL;
ULONG AuditFlag = FAILED_ACCESS_ACE_FLAG;
UCHAR AceFlags = 0;
if (FLAG_ON(pExplicitAccess->grfInheritance, INHERITED_ACE))
{
return ERROR_SUCCESS;
}
if (TRUSTEE_IS_IMPERSONATE == pExplicitAccess->Trustee.MultipleTrusteeOperation)
{
if (ACCESS_ALLOWED_COMPOUND_ACE_TYPE != ((PACE_HEADER) pAce)->AceType)
{
return ERROR_SUCCESS;
}
pSid = pAccessInfo->pServerSid ?
pAccessInfo->pServerSid :
(PSID) pExplicitAccess->Trustee.ptstrName;
if (!RtlEqualSid(
pSid,
(PSID) &(((PCOMPOUND_ACCESS_ALLOWED_ACE) pAce)->SidStart)
))
{
return ERROR_SUCCESS;
}
SidLength = RtlLengthSid(pSid);
pSid = pAccessInfo->pSid ?
pAccessInfo->pSid :
(PSID) (pExplicitAccess->Trustee.pMultipleTrustee->ptstrName);
if (!RtlEqualSid(
pSid,
(PSID) (((PUCHAR) &(((PCOMPOUND_ACCESS_ALLOWED_ACE) pAce)->SidStart)) + SidLength)
))
{
return ERROR_SUCCESS;
}
}
else
{
switch (((PACE_HEADER) pAce)->AceType)
{
case ACCESS_ALLOWED_ACE_TYPE:
case ACCESS_DENIED_ACE_TYPE:
case SYSTEM_AUDIT_ACE_TYPE:
case SYSTEM_ALARM_ACE_TYPE:
switch (pExplicitAccess->Trustee.TrusteeForm)
{
case TRUSTEE_IS_SID:
pSid = (PSID) pExplicitAccess->Trustee.ptstrName;
break;
case TRUSTEE_IS_NAME:
pSid = pAccessInfo->pSid;
break;
default:
return ERROR_SUCCESS;
}
if (!RtlEqualSid(
pSid,
(PSID) &(((PKNOWN_ACE) pAce)->SidStart)
))
{
return ERROR_SUCCESS;
}
break;
case ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
return ERROR_SUCCESS;
case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
case ACCESS_DENIED_OBJECT_ACE_TYPE:
case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
case SYSTEM_ALARM_OBJECT_ACE_TYPE:
switch (pExplicitAccess->Trustee.TrusteeForm)
{
case TRUSTEE_IS_OBJECTS_AND_SID:
pObjSid = (POBJECTS_AND_SID) pExplicitAccess->Trustee.ptstrName;
ObjectsPresent = pObjSid->ObjectsPresent;
pSid = pObjSid->pSid;
pObjectTypeGuid = &(pObjSid->ObjectTypeGuid);
pInheritedObjectTypeGuid = &(pObjSid->InheritedObjectTypeGuid);
break;
case TRUSTEE_IS_OBJECTS_AND_NAME:
pObjName = (POBJECTS_AND_NAME_W) pExplicitAccess->Trustee.ptstrName;
ObjectsPresent = pObjName->ObjectsPresent;
pSid = pAccessInfo->pSid;
pObjectTypeGuid = pAccessInfo->pObjectTypeGuid;
pInheritedObjectTypeGuid = pAccessInfo->pInheritedObjectTypeGuid;
break;
default:
return ERROR_SUCCESS;
}
if (ObjectsPresent != ((PKNOWN_OBJECT_ACE) pAce)->Flags)
{
return ERROR_SUCCESS;
}
if (!RtlEqualSid(pSid, RtlObjectAceSid(pAce)))
{
return ERROR_SUCCESS;
}
pGuid = RtlObjectAceObjectType(pAce);
if (NULL != pGuid)
{
if ((NULL == pObjectTypeGuid) ||
!RtlpIsEqualGuid(pGuid, pObjectTypeGuid))
{
return ERROR_SUCCESS;
}
}
pGuid = RtlObjectAceInheritedObjectType(pAce);
if (NULL != pGuid)
{
if ((NULL == pInheritedObjectTypeGuid) ||
!RtlpIsEqualGuid(pGuid, pInheritedObjectTypeGuid))
{
return ERROR_SUCCESS;
}
}
break;
}
}
AceFlags = (((PACE_HEADER) pAce)->AceFlags) & VALID_INHERIT_FLAGS;
if (pExplicitAccess->grfInheritance != AceFlags)
{
return ERROR_SUCCESS;
}
switch (pExplicitAccess->grfAccessMode)
{
case REVOKE_ACCESS:
switch (((PACE_HEADER) pAce)->AceType)
{
case ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
case ACCESS_ALLOWED_ACE_TYPE:
*pAceMask = 0;
break;
default:
break;
}
break;
case GRANT_ACCESS:
switch (((PACE_HEADER) pAce)->AceType)
{
case ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
case ACCESS_ALLOWED_ACE_TYPE:
if (TRUE == bCanonical)
{
*pAceMask |= pAccessInfo->Mask;
pAccessInfo->Size = 0;
}
break;
case ACCESS_DENIED_OBJECT_ACE_TYPE:
case ACCESS_DENIED_ACE_TYPE:
*pAceMask &= ~pAccessInfo->Mask;
break;
default:
return ERROR_SUCCESS;
}
break;
case DENY_ACCESS:
switch (((PACE_HEADER) pAce)->AceType)
{
case ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
case ACCESS_ALLOWED_ACE_TYPE:
//
// Do not delete existing Allow aces!
//
// *pAceMask &= ~pAccessInfo->Mask;
//
break;
case ACCESS_DENIED_OBJECT_ACE_TYPE:
case ACCESS_DENIED_ACE_TYPE:
if (TRUE == bCanonical)
{
*pAceMask |= pAccessInfo->Mask;
pAccessInfo->Size = 0;
}
break;
default:
return ERROR_SUCCESS;
}
break;
case SET_ACCESS:
switch (((PACE_HEADER) pAce)->AceType)
{
case ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
case ACCESS_ALLOWED_ACE_TYPE:
case ACCESS_DENIED_OBJECT_ACE_TYPE:
case ACCESS_DENIED_ACE_TYPE:
*pAceMask = 0;
break;
default:
return ERROR_SUCCESS;
}
break;
case SET_AUDIT_SUCCESS:
AuditFlag = SUCCESSFUL_ACCESS_ACE_FLAG;
case SET_AUDIT_FAILURE:
switch (((PACE_HEADER) pAce)->AceType)
{
case SYSTEM_AUDIT_ACE_TYPE:
case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
case SYSTEM_ALARM_ACE_TYPE:
case SYSTEM_ALARM_OBJECT_ACE_TYPE:
if (!FLAG_ON(((PACE_HEADER) pAce)->AceFlags, AuditFlag))
{
return ERROR_SUCCESS;
}
*pAceMask |= pAccessInfo->Mask;
pAccessInfo->Size = 0;
break;
default:
return ERROR_SUCCESS;
}
}
return ERROR_SUCCESS;
}
////////////////////////////////////////////////////////////////////////////////
// //
// Function: MartaGetExplicitAccessEntrySize //
// //
// Description: Computes the memory size in bytes for the ace for the //
// explicit entry. //
// //
// Arguments: //
// //
// [IN pExplicitAccess] Explicit entry to convert into an ace //
// [IN pAccessInfo] Temp info associated with the explicit entry //
// //
// [IN OUT pGuidCnt] Number of guid-names that have to be convrted //
// to guid structs. //
// //
// Returns: ERROR_SUCCESS if the entry could be converted into an ACE //
// Appropriate failure otherwise //
// //
////////////////////////////////////////////////////////////////////////////////
DWORD
MartaGetExplicitAccessEntrySize(
IN PEXPLICIT_ACCESS_W pExplicitAccess,
OUT PMARTA_ACCESS_INFO pAccessInfo,
OUT PULONG pGuidCnt,
OUT PUCHAR pAclRevision
)
{
DWORD dwErr = ERROR_SUCCESS;
ULONG SidAndGuidSize = 0;
if (FLAG_ON(pExplicitAccess->grfInheritance, ~VALID_INHERIT_FLAGS))
{
return ERROR_INVALID_PARAMETER;
}
switch (pExplicitAccess->grfAccessMode)
{
case REVOKE_ACCESS:
case DENY_ACCESS:
case GRANT_ACCESS:
case SET_ACCESS:
case SET_AUDIT_SUCCESS:
case SET_AUDIT_FAILURE:
break;
default:
return ERROR_INVALID_PARAMETER;
}
if (FLAG_ON(pExplicitAccess->grfInheritance, INHERITED_ACE))
{
pAccessInfo->Size = 0;
return ERROR_SUCCESS;
}
//
// For an impersonate trustee, two sids contribute to the size.
//
if (TRUSTEE_IS_IMPERSONATE == pExplicitAccess->Trustee.MultipleTrusteeOperation)
{
pAccessInfo->Size = sizeof(ACE_HEADER) + sizeof(ACCESS_MASK) + sizeof(ULONG);
dwErr = MartaTrusteeSidAndGuidSize(
&(pExplicitAccess->Trustee),
FALSE,
&(pAccessInfo->pServerSid),
&SidAndGuidSize,
NULL
);
if (ERROR_SUCCESS != dwErr)
{
return dwErr;
}
pAccessInfo->Size += SidAndGuidSize;
if (NULL == pExplicitAccess->Trustee.pMultipleTrustee)
{
return ERROR_INVALID_PARAMETER;
}
dwErr = MartaTrusteeSidAndGuidSize(
pExplicitAccess->Trustee.pMultipleTrustee,
FALSE,
&(pAccessInfo->pSid),
&SidAndGuidSize,
NULL
);
if (ERROR_SUCCESS != dwErr)
{
return dwErr;
}
pAccessInfo->Size += SidAndGuidSize;
if (*pAclRevision < ACL_REVISION3)
{
*pAclRevision = ACL_REVISION3;
}
return ERROR_SUCCESS;
}
//
// For any other type of trustee, compute the space required for the SID as
// well as Guids, if any.
//
switch (pExplicitAccess->Trustee.TrusteeForm)
{
case TRUSTEE_IS_OBJECTS_AND_SID:
case TRUSTEE_IS_OBJECTS_AND_NAME:
pAccessInfo->Size = sizeof(ACE_HEADER) + sizeof(ACCESS_MASK) + sizeof(ULONG);
*pAclRevision = ACL_REVISION_DS;
break;
case TRUSTEE_IS_SID:
case TRUSTEE_IS_NAME:
pAccessInfo->Size = sizeof(ACE_HEADER) + sizeof(ACCESS_MASK);
break;
default:
return ERROR_INVALID_PARAMETER;
}
dwErr = MartaTrusteeSidAndGuidSize(
&(pExplicitAccess->Trustee),
TRUE,
&(pAccessInfo->pSid),
&SidAndGuidSize,
pGuidCnt
);
if (ERROR_SUCCESS != dwErr)
{
return dwErr;
}
if (REVOKE_ACCESS == pExplicitAccess->grfAccessMode)
{
pAccessInfo->Size = 0;
}
else
{
pAccessInfo->Size += SidAndGuidSize;
}
return ERROR_SUCCESS;
}
////////////////////////////////////////////////////////////////////////////////
// //
// Function: MartaIsExplicitAclCanonical //
// //
// Description: Determines whether the explicit part of the acl is canonical. //
// Finds the first explicit allow ace. //
// //
// Arguments: //
// //
// [IN pAcl] Acl //
// [OUT pExplicitAceCnt] To return the first allow explicit ace //
// //
// Returns: TRUE if the acl is canonical //
// FALSE otherwise //
// //
////////////////////////////////////////////////////////////////////////////////
BOOL
MartaIsExplicitAclCanonical(
IN PACL pAcl,
OUT PULONG pExplicitAceCnt
)
{
USHORT j;
USHORT AceCnt;
PACE_HEADER pAce;
*pExplicitAceCnt = 0;
if ((NULL == pAcl) || (0 == pAcl->AceCount))
{
return TRUE;
}
AceCnt = pAcl->AceCount;
pAce = (PACE_HEADER) FirstAce(pAcl);
for (j = 0; j < AceCnt; pAce = (PACE_HEADER) NextAce(pAce))
{
if (FLAG_ON(pAce->AceFlags, INHERITED_ACE))
{
j++;
continue;
}
if ((ACCESS_ALLOWED_ACE_TYPE == pAce->AceType) ||
(ACCESS_ALLOWED_OBJECT_ACE_TYPE == pAce->AceType) ||
(ACCESS_ALLOWED_COMPOUND_ACE_TYPE == pAce->AceType))
{
break;
}
*pExplicitAceCnt = ++j;
}
for (; j < AceCnt; j++, pAce = (PACE_HEADER) NextAce(pAce))
{
if (FLAG_ON(pAce->AceFlags, INHERITED_ACE))
{
continue;
}
if ((ACCESS_DENIED_ACE_TYPE == pAce->AceType) ||
(ACCESS_DENIED_OBJECT_ACE_TYPE == pAce->AceType))
{
return FALSE;
}
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////
// //
// Function: MartaTrusteeSidAndGuidSize //
// //
// Description: Compute the size for the Sid(s) and Guid(s) for the trustee. //
// //
// Arguments: //
// //
// [IN pTrustee] Trsutee for which the size has to be computed //
// [IN bComputeGuidSize] Whether Guidsize should be computed //
// //
// [OUT ppSid] To return the Sid if trustee is "named" //
// [OUT pSize] To return the size computed //
// [OUT pGuidCnt] To return the number of guids //
// //
// Returns: ERROR_SUCCESS if Name to Sid resolution passed //
// Appropriate failure otherwise //
// //
////////////////////////////////////////////////////////////////////////////////
DWORD
MartaTrusteeSidAndGuidSize(
IN PTRUSTEE_W pTrustee,
IN BOOL bComputeGuidSize,
OUT PSID * ppSid,
OUT PULONG pSize,
OUT PULONG pGuidCnt OPTIONAL
)
{
PSID pSid = NULL;
SID_NAME_USE SidType = SidTypeUnknown;
DWORD dwErr = ERROR_SUCCESS;
switch (pTrustee->TrusteeForm)
{
case TRUSTEE_IS_SID:
pSid = (PSID) pTrustee->ptstrName;
if ((NULL == pSid) || (!RtlValidSid(pSid)))
{
return ERROR_INVALID_PARAMETER;
}
*pSize = RtlLengthSid(pSid);
break;
case TRUSTEE_IS_OBJECTS_AND_SID:
pSid = ((POBJECTS_AND_SID) pTrustee->ptstrName)->pSid;
if ((NULL == pSid) || (!RtlValidSid(pSid)))
{
return ERROR_INVALID_PARAMETER;
}
*pSize = RtlLengthSid(pSid);
if (TRUE == bComputeGuidSize)
{
if (FLAG_ON(((POBJECTS_AND_SID) pTrustee->ptstrName)->ObjectsPresent,
ACE_OBJECT_TYPE_PRESENT))
{
*pSize += sizeof(GUID);
}
if (FLAG_ON(((POBJECTS_AND_SID) pTrustee->ptstrName)->ObjectsPresent,
ACE_INHERITED_OBJECT_TYPE_PRESENT))
{
*pSize += sizeof(GUID);
}
}
break;
case TRUSTEE_IS_NAME:
dwErr = MartaGetSidFromName(pTrustee->ptstrName, ppSid);
CONDITIONAL_RETURN(dwErr);
*pSize = RtlLengthSid(*ppSid);
break;
case TRUSTEE_IS_OBJECTS_AND_NAME:
dwErr = MartaGetSidFromName(
((POBJECTS_AND_NAME_W) pTrustee->ptstrName)->ptstrName,
ppSid
);
CONDITIONAL_RETURN(dwErr);
*pSize = RtlLengthSid(*ppSid);
if (TRUE == bComputeGuidSize)
{
if (FLAG_ON(((POBJECTS_AND_NAME_W) pTrustee->ptstrName)->ObjectsPresent,
ACE_OBJECT_TYPE_PRESENT))
{
*pSize += sizeof(GUID);
(*pGuidCnt)++;
}
if (FLAG_ON(((POBJECTS_AND_NAME_W) pTrustee->ptstrName)->ObjectsPresent,
ACE_INHERITED_OBJECT_TYPE_PRESENT))
{
*pSize += sizeof(GUID);
(*pGuidCnt)++;
}
}
break;
default:
return ERROR_NONE_MAPPED;
}
return ERROR_SUCCESS;
}
////////////////////////////////////////////////////////////////////////////////
// //
// Function: MartaGetSidFromName //
// //
// Description: Resolves a given Name to Sid. //
// //
// Arguments: //
// //
// [IN pName] Name to be resolved //
// [OUT ppSid] To return the Sid for the trustee //
// //
// Returns: ERROR_SUCCESS if Name to Sid resolution passed //
// Appropriate failure otherwise //
// //
////////////////////////////////////////////////////////////////////////////////
DWORD
MartaGetSidFromName(
IN LPWSTR pName,
OUT PSID * ppSid
)
{
#define MARTA_DEFAULT_SID_SIZE 64
#define MARTA_DEFAULT_DOMAIN_SIZE 256
WCHAR DomainBuffer[MARTA_DEFAULT_DOMAIN_SIZE];
ULONG SidSize = MARTA_DEFAULT_SID_SIZE;
ULONG DomainSize = MARTA_DEFAULT_DOMAIN_SIZE;
LPWSTR Domain = (LPWSTR) DomainBuffer;
SID_NAME_USE SidNameUse = SidTypeUnknown;
DWORD dwErr = ERROR_SUCCESS;
if (NULL == ppSid)
{
return ERROR_INVALID_PARAMETER;
}
if(0 == _wcsicmp(pName, L"CURRENT_USER"))
{
HANDLE TokenHandle;
dwErr = GetCurrentToken(&TokenHandle);
if(dwErr != ERROR_SUCCESS)
{
return dwErr;
}
dwErr = AccGetSidFromToken(
NULL,
TokenHandle,
TokenUser,
ppSid
);
CloseHandle(TokenHandle);
return dwErr;
}
*ppSid = (PSID) AccAlloc(SidSize);
if(NULL == *ppSid)
{
return ERROR_NOT_ENOUGH_MEMORY;
}
if(!LookupAccountName(
NULL,
pName,
*ppSid,
&SidSize,
Domain,
&DomainSize,
&SidNameUse))
{
dwErr = GetLastError();
if(dwErr == ERROR_INSUFFICIENT_BUFFER)
{
dwErr = ERROR_SUCCESS;
if (SidSize > MARTA_DEFAULT_SID_SIZE)
{
AccFree(*ppSid);
*ppSid = (PSID) AccAlloc(SidSize);
if (*ppSid == NULL)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto End;
}
}
if(DomainSize > MARTA_DEFAULT_DOMAIN_SIZE)
{
Domain = (LPWSTR) AccAlloc(DomainSize * sizeof(WCHAR));
if (NULL == Domain)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto End;
}
if(!LookupAccountName(
NULL,
pName,
*ppSid,
&SidSize,
Domain,
&DomainSize,
&SidNameUse))
{
dwErr = GetLastError();
goto End;
}
}
}
}
End:
if (Domain != (LPWSTR) DomainBuffer)
{
AccFree(Domain);
}
if (ERROR_SUCCESS != dwErr)
{
if (NULL != *ppSid)
{
AccFree(*ppSid);
*ppSid = NULL;
}
}
return dwErr;
}
////////////////////////////////////////////////////////////////////////////////
// //
// Function: MartaGetGuid //
// //
// Description: Resolves a given Guid Name to a Guid struct. //
// //
// Arguments: //
// //
// [IN pObjectName] Name to be resolved //
// [IN ObjectType] Object type of the name to be resolved //
// [OUT pGuid] To return the guid //
// //
// Returns: ERROR_SUCCESS if Name to guid resolution passed //
// Appropriate failure otherwise //
// //
////////////////////////////////////////////////////////////////////////////////
DWORD
MartaGetGuid(
IN LPWSTR pObjectName,
IN SE_OBJECT_TYPE ObjectType,
OUT GUID * pGuid
)
{
switch (ObjectType)
{
case SE_DS_OBJECT:
case SE_DS_OBJECT_ALL:
break;
default:
return ERROR_INVALID_PARAMETER;
}
return MartaConvertNameToGuid[ObjectType](
pObjectName,
pGuid
);
}
////////////////////////////////////////////////////////////////////////////////
// //
// Function: AccRewriteSetEntriesInAcl //
// //
// Description: Resolves a given Name to Sid. //
// //
// Arguments: //
// //
// [IN cCountOfExplicitEntries] Number of items in list //
// [IN pListOfExplicitEntries] List of entries to be added //
// [IN OldAcl] The old acl to add the entries to //
// [OUT pNewAcl] To return the new acl //
// //
// Returns: ERROR_SUCCESS if everything passed //
// Appropriate failure otherwise //
// //
////////////////////////////////////////////////////////////////////////////////
DWORD
WINAPI
AccRewriteSetEntriesInAcl(
IN ULONG cCountOfExplicitEntries,
IN PEXPLICIT_ACCESS_W pListOfExplicitEntries,
IN PACL OldAcl,
OUT PACL * pNewAcl
)
{
PMARTA_ACCESS_INFO pAccessInfo = NULL;
PACCESS_MASK pAceMaskInfo = NULL;
PACE_HEADER pAce = NULL;
GUID * pGuid = NULL;
GUID * pCurrentGuid = NULL;
POBJECTS_AND_NAME_W pObjName = NULL;
PUCHAR pAcl = NULL;
USHORT OldAceCnt = 0;
USHORT NewAceCnt = 0;
ULONG ExplicitAceCnt = 0;
ULONG NewAclSize = sizeof(ACL);
BOOL bCanonical = TRUE;
DWORD dwErr = ERROR_SUCCESS;
ULONG i = 0;
ULONG j = 0;
ULONG GuidCnt = 0;
ULONG ObjectsPresent = 0;
UCHAR AclRevision = ACL_REVISION;
if ((NULL == pNewAcl) || ((NULL != OldAcl) && (!RtlValidAcl(OldAcl))))
{
return ERROR_INVALID_PARAMETER;
}
*pNewAcl = NULL;
//
// If the number of entries to be added is zero then make a copy of the Old
// Acl as it is. Do not try to convert it into Canonical form if it's not.
//
if (0 == cCountOfExplicitEntries)
{
if (NULL != OldAcl)
{
*pNewAcl = (PACL) AccAlloc(OldAcl->AclSize);
if (NULL == *pNewAcl)
{
return ERROR_NOT_ENOUGH_MEMORY;
}
memcpy((PUCHAR) *pNewAcl, (PUCHAR) OldAcl, OldAcl->AclSize);
}
return ERROR_SUCCESS;
}
//
// Canonical acls processing will be done as in the past.
// Note: We now support non-canonical acls as well..
//
bCanonical = MartaIsExplicitAclCanonical(OldAcl, &ExplicitAceCnt);
//
// The Mask for all the aces is stored in a pAceMaskInfo and modified as
// dictated by the ExplicitAccess entries.
//
if (NULL != OldAcl)
{
OldAceCnt = OldAcl->AceCount;
NewAclSize = OldAcl->AclSize;
NewAceCnt = OldAceCnt;
pAceMaskInfo = (PACCESS_MASK) AccAlloc(sizeof(ACCESS_MASK) * OldAceCnt);
if (NULL == pAceMaskInfo)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto End;
}
AclRevision = OldAcl->AclRevision;
}
//
// Note: cCountOfExplicitEntries is non-zero at this point.
//
pAccessInfo = (PMARTA_ACCESS_INFO) AccAlloc(sizeof(MARTA_ACCESS_INFO) * cCountOfExplicitEntries);
if (NULL == pAccessInfo)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto End;
}
//
// Initialize the temp structures for the acl and the explicit entries.
//
pAce = (PACE_HEADER) FirstAce(OldAcl);
for (j = 0; j < OldAceCnt; j++, pAce = (PACE_HEADER) NextAce(pAce))
{
pAceMaskInfo[j] = ((PKNOWN_ACE) pAce)->Mask;
}
for (i = 0; i < cCountOfExplicitEntries; i++)
{
pAccessInfo[i].pServerSid = NULL;
pAccessInfo[i].pSid = NULL;
pAccessInfo[i].pObjectTypeGuid = NULL;
pAccessInfo[i].pInheritedObjectTypeGuid = NULL;
pAccessInfo[i].Mask = pListOfExplicitEntries[i].grfAccessPermissions;
}
//
// Compute the size required to add this explicit entry to the acl.
//
for (i = 0; i < cCountOfExplicitEntries; i++)
{
dwErr = MartaGetExplicitAccessEntrySize(
pListOfExplicitEntries + i,
pAccessInfo + i,
&GuidCnt,
&AclRevision
);
CONDITIONAL_EXIT(dwErr, End);
}
//
// For TRUSTEE_IS_OBJECTS_AND_NAME, resolve the GuidNames to Guids and store
// them in the temp structure.
//
if (0 != GuidCnt)
{
pGuid = pCurrentGuid = (GUID *) AccAlloc(sizeof(GUID) * GuidCnt);
if (NULL == pGuid)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto End;
}
for (i = 0; i < cCountOfExplicitEntries; i++)
{
pObjName = (POBJECTS_AND_NAME_W) pListOfExplicitEntries[i].Trustee.ptstrName;
ObjectsPresent = pObjName->ObjectsPresent;
if (FLAG_ON(ObjectsPresent, ACE_OBJECT_TYPE_PRESENT))
{
dwErr = MartaGetGuid(
pObjName->ObjectTypeName,
pObjName->ObjectType,
pCurrentGuid
);
CONDITIONAL_EXIT(dwErr, End);
pAccessInfo[i].pObjectTypeGuid = pCurrentGuid++;
}
if (FLAG_ON(ObjectsPresent, ACE_INHERITED_OBJECT_TYPE_PRESENT))
{
dwErr = MartaGetGuid(
pObjName->InheritedObjectTypeName,
pObjName->ObjectType,
pCurrentGuid
);
CONDITIONAL_EXIT(dwErr, End);
pAccessInfo[i].pInheritedObjectTypeGuid = pCurrentGuid++;
}
}
}
//
// Compute the effect of explict entries added on the exisiting acl.
// The size of an explicit entry will be set to zero if the entry will be
// absorbed by some existing ace.
// The Mask for an ace will be set to zero if the AceMask flags have been
// nulled out by explicit entries.
//
for (i = 0; i < cCountOfExplicitEntries; i++)
{
pAce = (PACE_HEADER) FirstAce(OldAcl);
for (j = 0; j < OldAceCnt; j++, pAce = (PACE_HEADER) NextAce(pAce))
{
dwErr = MartaCompareAcesAndMarkMasks(
(PUCHAR) pAce,
pAceMaskInfo + j,
pListOfExplicitEntries + i,
pAccessInfo + i,
bCanonical
);
CONDITIONAL_EXIT(dwErr, End);
}
}
//
// Compute the size required for the new acl and the number of aces in it.
//
pAce = (PACE_HEADER) FirstAce(OldAcl);
for (j = 0; j < OldAceCnt; j++, pAce = (PACE_HEADER) NextAce(pAce))
{
if (0 == pAceMaskInfo[j])
{
NewAclSize -= pAce->AceSize;
NewAceCnt--;
}
}
for (i = 0; i < cCountOfExplicitEntries; i++)
{
if (0 != pAccessInfo[i].Size)
{
NewAclSize += pAccessInfo[i].Size;
NewAceCnt++;
}
}
*pNewAcl = (PACL) AccAlloc(NewAclSize);
if (NULL == *pNewAcl)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto End;
}
if (FALSE == InitializeAcl(*pNewAcl, NewAclSize, AclRevision))
{
dwErr = GetLastError();
goto End;
}
(*pNewAcl)->AceCount = NewAceCnt;
pAcl = ((PUCHAR) *pNewAcl) + sizeof(ACL);
for (i = 0; i < cCountOfExplicitEntries; i++)
{
//
// Add all the DENY ACES to the ACL.
//
switch (pListOfExplicitEntries[i].grfAccessMode)
{
case DENY_ACCESS:
case SET_AUDIT_SUCCESS:
case SET_AUDIT_FAILURE:
dwErr = MartaAddExplicitEntryToAcl(
&pAcl,
pListOfExplicitEntries + i,
pAccessInfo + i
);
CONDITIONAL_EXIT(dwErr, End);
break;
default:
break;
}
}
//
// Copy the explicit aces from the OldAcl that have not been invalidated by
// the new Aces added.
// Inherited aces will be copied afterthe explict ones have been copied.
//
pAce = (PACE_HEADER) FirstAce(OldAcl);
for (j = 0; j < ExplicitAceCnt; j++, pAce = (PACE_HEADER) NextAce(pAce))
{
if (FLAG_ON(pAce->AceFlags, INHERITED_ACE))
{
continue;
}
if (0 != pAceMaskInfo[j])
{
memcpy((PUCHAR) pAcl, (PUCHAR) pAce, pAce->AceSize);
((PKNOWN_ACE) pAcl)->Mask = pAceMaskInfo[j];
pAcl += pAce->AceSize;
}
}
//
// Add all the NON-DENY ACES to the ACL.
// DENY aces have already been added.
//
// If the ACL was canonical then follow the old behavior i.e. add the
// remaining explicit entries to the beginning of the "allowed" acl.
// Otherwise, add the ACEs to the end of the explicit part of the ACL.
//
if (FALSE == bCanonical)
{
for (; j < OldAceCnt; j++, pAce = (PACE_HEADER) NextAce(pAce))
{
if (FLAG_ON(pAce->AceFlags, INHERITED_ACE))
{
continue;
}
if (0 != pAceMaskInfo[j])
{
memcpy((PUCHAR) pAcl, (PUCHAR) pAce, pAce->AceSize);
((PKNOWN_ACE) pAcl)->Mask = pAceMaskInfo[j];
pAcl += pAce->AceSize;
}
}
for (i = 0; i < cCountOfExplicitEntries; i++)
{
switch (pListOfExplicitEntries[i].grfAccessMode)
{
case GRANT_ACCESS:
case SET_ACCESS:
dwErr = MartaAddExplicitEntryToAcl(
&pAcl,
pListOfExplicitEntries + i,
pAccessInfo + i
);
CONDITIONAL_EXIT(dwErr, End);
break;
default:
break;
}
}
}
else
{
for (i = 0; i < cCountOfExplicitEntries; i++)
{
switch (pListOfExplicitEntries[i].grfAccessMode)
{
case GRANT_ACCESS:
case SET_ACCESS:
dwErr = MartaAddExplicitEntryToAcl(
&pAcl,
pListOfExplicitEntries + i,
pAccessInfo + i
);
CONDITIONAL_EXIT(dwErr, End);
break;
default:
break;
}
}
for (; j < OldAceCnt; j++, pAce = (PACE_HEADER) NextAce(pAce))
{
if (FLAG_ON(pAce->AceFlags, INHERITED_ACE))
{
continue;
}
if (0 != pAceMaskInfo[j])
{
memcpy((PUCHAR) pAcl, (PUCHAR) pAce, pAce->AceSize);
((PKNOWN_ACE) pAcl)->Mask = pAceMaskInfo[j];
pAcl += pAce->AceSize;
}
}
}
//
// Add the inherited aces to the new ACL. This will reorder the ACEs so that
// the EXPLICIT ACEs precede the INHERITED ONES but will not arrange the ACL
// in canonical form if it was not to start with.
//
pAce = (PACE_HEADER) FirstAce(OldAcl);
for (j = 0; j < OldAceCnt; j++, pAce = (PACE_HEADER) NextAce(pAce))
{
if (FLAG_ON(pAce->AceFlags, INHERITED_ACE))
{
memcpy((PUCHAR) pAcl, (PUCHAR) pAce, pAce->AceSize);
pAcl += pAce->AceSize;
}
}
End:
if (NULL != pAccessInfo)
{
for (i = 0; i < cCountOfExplicitEntries; i++ )
{
if (NULL != pAccessInfo[i].pServerSid)
{
AccFree(pAccessInfo[i].pServerSid);
}
if (NULL != pAccessInfo[i].pSid)
{
AccFree(pAccessInfo[i].pSid);
}
}
AccFree(pAccessInfo);
}
if (NULL != pGuid)
{
AccFree(pGuid);
}
if (NULL != pAceMaskInfo)
{
AccFree(pAceMaskInfo);
}
if (ERROR_SUCCESS != dwErr)
{
if (NULL != *pNewAcl)
{
AccFree(*pNewAcl);
*pNewAcl = NULL;
}
}
return dwErr;
}