Тут тема, я скажу...
Когда нибудь работал cо стандартным SecurityDescriptor? Если просто, он состоит из двух списков - SACL и DACL. Каждая строка такого списка называется ACE. Начнем с ACE.
Это может быть разрешающая или запрещающая доступ строка, или строка аудита.
Создадим union, т.к. это удобно.
//---------------------------------------------------------------------------
typedef union STANDARD_ACE
{
ACE_HEADER aceHeader;
ACCESS_ALLOWED_ACE aceAllowed;
ACCESS_DENIED_ACE aceDenied;
SYSTEM_AUDIT_ACE aceAudit;
} *PSTANDARD_ACE;
#define ACESIDOFFSET (DWORD)(&((ACCESS_ALLOWED_ACE*) 0)->SidStart)
#define ACESTRUCTSIZE (DWORD)(sizeof(ACCESS_ALLOWED_ACE) - sizeof(((ACCESS_ALLOWED_ACE*) 0)->SidStart))
Дальше создадим класс:
//***************************************************************************
//* CAce
//***************************************************************************
class CAce
{
private:
PSTANDARD_ACE FPAce;
public:
CAce();
CAce& New(DWORD dwType, DWORD dwFlags, DWORD dwMask, PSID psid);
CAce& NewAllowed(DWORD dwFlags, DWORD dwMask, PSID psid)
{return New(ACCESS_ALLOWED_ACE_TYPE, dwFlags, dwMask, psid);};
CAce& NewDenied(DWORD dwFlags, DWORD dwMask, PSID psid)
{return New(ACCESS_DENIED_ACE_TYPE, dwFlags, dwMask, psid);};
CAce& NewAudit(DWORD dwFlags, DWORD dwMask, PSID psid)
{return New(SYSTEM_AUDIT_ACE_TYPE, dwFlags, dwMask, psid);};
~CAce();
operator PSTANDARD_ACE () {return FPAce;};
};
//***************************************************************************
//* CAce
//***************************************************************************
CAce::CAce()
{
FPAce = NULL;
}
//---------------------------------------------------------------------------
CAce::~CAce()
{
if (FPAce) LocalFree(FPAce);
}
//---------------------------------------------------------------------------
CAce& CAce::New(DWORD dwType, DWORD dwFlags, DWORD dwMask, PSID psid)
{
if (FPAce) LocalFree(FPAce);
FPAce = NewAce(dwType, dwFlags, dwMask, psid);
return *this;
}
//---------------------------------------------------------------------------
PSTANDARD_ACE NewAce(DWORD dwType, DWORD dwFlags, DWORD dwMask, PSID psid)
{
PSTANDARD_ACE pace = NULL;
PBYTE buf = NULL;
try
{
DWORD dwSidSize = GetLengthSid(psid);
buf = (PBYTE) LocalAlloc(LPTR, ACESTRUCTSIZE + dwSidSize);
if (buf)
{
if (CopySid(dwSidSize, (PSID) (buf + ACESIDOFFSET), psid))
{
pace = (PSTANDARD_ACE) buf;
pace->aceHeader.AceSize = (USHORT) (ACESTRUCTSIZE + dwSidSize);
pace->aceHeader.AceFlags = (BYTE) dwFlags;
pace->aceHeader.AceType = (BYTE) dwType;
pace->aceAllowed.Mask = dwMask;
}
}
}
catch(...) { }
if (buf != (PBYTE) pace) LocalFree(buf);
return pace;
}
Теперь ACL
#define ACLINITSIZE 0x0400
#define ACLSIZEDELTA 0x0040
class CAcl
{
private:
PACL FPAcl;
BOOL FCanonical;
BOOL CreateAcl(DWORD dwSize = ACLINITSIZE);
BOOL TuningAclSize(PACL pAddAcl);
BOOL TuningAclSize(DWORD dwAddSize);
// Затирает старый
BOOL RewriteAcl(PACL pSrcAcl);
// Добавляет
BOOL AddAcl(PACL pSrcAcl);
// Возвращает индекс эквивалентного Ace
int EqualAceIdx(PSTANDARD_ACE pAce);
public:
void clear();
public:
CAcl();
~CAcl() {clear();};
CAcl& operator += (PSTANDARD_ACE);
PSTANDARD_ACE operator [] (DWORD idx);
operator PACL () {return FPAcl;};
DWORD count();
};
//***************************************************************************
//* CAcl
//***************************************************************************
CAcl::CAcl()
{
FPAcl = NULL;
FCanonical = TRUE;
}
//---------------------------------------------------------------------------
void CAcl::clear()
{
if (FPAcl)
{
LocalFree(FPAcl);
FPAcl = NULL;
}
}
//---------------------------------------------------------------------------
BOOL CAcl::CreateAcl(DWORD dwSize)
{
clear();
if (dwSize < ACLINITSIZE) dwSize = ACLINITSIZE;
FPAcl = (PACL) LocalAlloc(LPTR, dwSize);
if (!FPAcl)
{
SetLastError(ERROR_OUTOFMEMORY);
return FALSE;
}
else
if (InitializeAcl(FPAcl, dwSize, ACL_REVISION)) return TRUE;
else
{
LocalFree(FPAcl);
FPAcl = NULL;
return FALSE;
}
}
//---------------------------------------------------------------------------
BOOL CAcl::TuningAclSize(DWORD dwAddSize)
{
BOOL fRes = FALSE;
try
{
if (FPAcl == NULL) return CreateAcl(dwAddSize);
ACL_SIZE_INFORMATION dstasi;
if (GetAclInformation(FPAcl, &dstasi, sizeof(dstasi), AclSizeInformation))
{
if (dstasi.AclBytesFree <= dwAddSize)
{
DWORD dwSize = dstasi.AclBytesInUse + dwAddSize;
dwSize = ((dwSize / ACLSIZEDELTA) + 1) * ACLSIZEDELTA;
PACL FTempAcl = (PACL) LocalAlloc(LPTR, dwSize);
if (!FTempAcl) return FALSE;
if (!InitializeAcl(FTempAcl, dwSize, ACL_REVISION))
{
LocalFree(FTempAcl);
return FALSE;
}
if (CopyAcl(FTempAcl, FPAcl))
{
LocalFree(FPAcl);
FPAcl = FTempAcl;
fRes = TRUE;
}
else LocalFree(FTempAcl);
}
else fRes = TRUE;
}
}
catch(...) { }
return fRes;
}
//---------------------------------------------------------------------------
BOOL CAcl::TuningAclSize(PACL pAddAcl)
{
BOOL fRes = FALSE;
try
{
ACL_SIZE_INFORMATION addasi;
if (GetAclInformation(pAddAcl, &addasi, sizeof(addasi), AclSizeInformation))
{
fRes = TuningAclSize(addasi.AclBytesInUse);
}
}
catch(...) { }
return fRes;
}
//---------------------------------------------------------------------------
BOOL CAcl::RewriteAcl(PACL pSrcAcl)
{
clear();
if (TuningAclSize(pSrcAcl)) return (CopyAcl(FPAcl, pSrcAcl));
else return FALSE;
}
//---------------------------------------------------------------------------
// Возвращает индекс эквивалентного Ace
int CAcl::EqualAceIdx(PSTANDARD_ACE pAce)
{
return FindAceInAcl(FPAcl, pAce);
}
//---------------------------------------------------------------------------
DWORD CAcl::count()
{
DWORD dwRes = 0;
try
{
if (FPAcl)
{
ACL_SIZE_INFORMATION asi;
if (GetAclInformation(FPAcl, &asi, sizeof(asi), AclSizeInformation))
dwRes = asi.AceCount;
}
}
catch(...) {}
return dwRes;
}
//---------------------------------------------------------------------------
PSTANDARD_ACE CAcl::operator [] (DWORD idx)
{
PSTANDARD_ACE pRes = NULL;
try
{
PACE_HEADER pAce;
if (GetAce(FPAcl, idx, (PVOID*) &pAce)) pRes = (PSTANDARD_ACE) pAce;
}
catch(...) {}
return pRes;
}
//---------------------------------------------------------------------------
CAcl& CAcl::operator +=(PSTANDARD_ACE pAce)
{
if (pAce && TuningAclSize(pAce->aceHeader.AceSize))
{
DWORD idx = EqualAceIdx(pAce); //MAXDWORD; // В конец ACL
switch (idx)
{
case MAXDWORD:
if (FCanonical) idx = GetCanonicalIndex(FPAcl, pAce);
AddAce(FPAcl, ACL_REVISION, idx, (PVOID) pAce, pAce->aceHeader.AceSize);
break;
default:
if (FCanonical)
(*this)[idx]->aceAllowed.Mask = pAce->aceAllowed.Mask;
}
}
return *this;
}
//---------------------------------------------------------------------------
// Добавляет
BOOL CAcl::AddAcl(PACL pSrcAcl)
{
BOOL fRes = FALSE;
try
{
if (TuningAclSize(pSrcAcl))
{
ACL_SIZE_INFORMATION srcasi;
if (GetAclInformation(pSrcAcl, &srcasi, sizeof(srcasi), AclSizeInformation))
{
PACE_HEADER pAce;
for (DWORD idx = 0; idx < srcasi.AceCount; idx++)
{
if (GetAce(pSrcAcl, idx, (PVOID*) &pAce))
{
*this += (PSTANDARD_ACE) pAce;
}
else return FALSE;
}
fRes = TRUE;
}
}
}
catch(...){}
return fRes;
}
//---------------------------------------------------------------------------
DWORD CalculateAclSize(PACL pOldAcl, PSID* ppSidArray, DWORD dwNumSids,
PSTANDARD_ACE* ppAces, DWORD dwNumAces)
{
DWORD res = 0;
BOOL fOk = TRUE;
try
{
if (pOldAcl)
{
ACL_SIZE_INFORMATION asi;
fOk = GetAclInformation(pOldAcl, &asi, sizeof(asi), AclSizeInformation);
if (fOk) res = asi.AclBytesInUse;
}
if (fOk && ppSidArray)
{
while (dwNumSids--)
{
fOk = IsValidSid(ppSidArray[dwNumSids]);
if (fOk)
{
res += GetLengthSid(ppSidArray[dwNumSids]);
res += sizeof(ACCESS_ALLOWED_ACE) - sizeof(((ACCESS_ALLOWED_ACE*) 0)->SidStart);
}
else break;
}
}
if (fOk && ppAces)
{
while (dwNumAces--)
{
res += ppAces[dwNumAces]->aceHeader.AceSize;
}
}
}
catch(...) { fOk = FALSE;}
if (fOk) return res;
else return 0;
}
//---------------------------------------------------------------------------
BOOL IsEqualAce(PSTANDARD_ACE pAce1, PSTANDARD_ACE pAce2)
{
BOOL fRes = FALSE;
try
{
if (pAce1->aceHeader.AceType != pAce2->aceHeader.AceType) return FALSE;
PBYTE pbAce1 = (PBYTE) pAce1;
PBYTE pbAce2 = (PBYTE) pAce2;
DWORD dwAceStructSize = ACESTRUCTSIZE;
fRes = TRUE;
// Жираф большой.... [1] стр.381
while (dwAceStructSize--)
fRes = (fRes && (pbAce1[dwAceStructSize] == pbAce2[dwAceStructSize]));
fRes = fRes && EqualSid((PSID)(pbAce1 + ACESIDOFFSET), (PSID)(pbAce2 + ACESIDOFFSET));
}
catch(...)
{
}
return fRes;
}
//---------------------------------------------------------------------------
int FindAceInAcl(PACL pAcl, PSTANDARD_ACE pAce)
{
int idx = -1;
try
{
ACL_SIZE_INFORMATION asi;
if (GetAclInformation(pAcl, &asi, sizeof(asi), AclSizeInformation))
{
PSTANDARD_ACE pAce2;
while (asi.AceCount--)
{
if (!GetAce(pAcl, asi.AceCount, (PVOID*) &pAce2)) break;
if (IsEqualAce(pAce, pAce2))
{
idx = (int) asi.AceCount;
break;
}
}
}
}
catch(...)
{
}
return (idx);
}
//---------------------------------------------------------------------------
// Возвращает положенный по каноническом стандарту индекс Ace в DACL
DWORD GetCanonicalIndex(PACL pDacl, PSTANDARD_ACE pNewAce)
{
DWORD idx = - 1;
try
{
BYTE dwOrderFilterType [] =
{ACCESS_DENIED_ACE_TYPE, ACCESS_DENIED_OBJECT_ACE_TYPE,
ACCESS_ALLOWED_ACE_TYPE, ACCESS_ALLOWED_OBJECT_ACE_TYPE};
DWORD dwNewAceGroup = 0;
for (dwNewAceGroup; dwNewAceGroup < 4; dwNewAceGroup++)
{
if (pNewAce->aceHeader.AceType == dwOrderFilterType[dwNewAceGroup])
break;
}
// Если недопустимый тип нового Ace
if (dwNewAceGroup == 4) return idx;
// Если унаследованный то идет последним
if ((pNewAce->aceHeader.AceFlags & INHERITED_ACE) != 0)
dwNewAceGroup += 4;
ACL_SIZE_INFORMATION asi;
if (GetAclInformation(pDacl, &asi, sizeof(asi), AclSizeInformation))
{
PACE_HEADER pAce;
idx = 0;
for (idx; idx < asi.AceCount; idx++)
{
if (GetAce(pDacl, idx, (PVOID*) &pAce))
{
DWORD dwAceGroup = 0;
for (dwAceGroup; dwAceGroup < 4; dwAceGroup++)
{
if (pAce->AceType == dwOrderFilterType[dwAceGroup])
break;
}
if (dwAceGroup == 4)
{
idx = - 1;
return idx; // недопустимый ACE в DACL
}
// Если унаследованный то внесем поправку
if ((pAce->AceFlags & INHERITED_ACE) != 0)
dwAceGroup += 4;
if (dwAceGroup >= dwNewAceGroup) break;
}
} // for idx
}
}
catch(...) { }
return idx;
}
//---------------------------------------------------------------------------
// Копирует ACL
BOOL CopyAcl(PACL pDestAcl, PACL pSrcAcl)
{
BOOL fRes = FALSE;
try
{
ACL_SIZE_INFORMATION asi;
if (GetAclInformation(pSrcAcl, &asi, sizeof(asi), AclSizeInformation))
{
PACE_HEADER pAce;
for (DWORD idx = 0; idx < asi.AceCount; idx++)
{
if (!GetAce(pSrcAcl, idx, (PVOID*) &pAce)) return FALSE;
if (!AddAce(pDestAcl, ACL_REVISION, MAXDWORD, (PVOID*) pAce, pAce->AceSize))
return FALSE;
}
}
fRes = TRUE;
}
catch(...) { }
return (fRes);
}
Ну и в итоге используем:
FObjHandle - Хэндл защищаемого процесса, открытого OpenProcess( PROCESS_ALL_ACCESS)
pDacl - PACL ( см. CAcl.operator PACL)
SetSecurityInfo( FObjHandle, FObjType,
DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
NULL, NULL,
pDacl, NULL);
Удачи. Попробуй разобраться...