本文的程序需在管理员的权限下运行
原文参考:http://m.myexception.cn/vc-mfc/120522.html
可以修改指定文件的或者文件夹的属性
TCHAR* lpFileName, TCHAR* lpAccountName, DWORD dw
lpFileName指定需要设置文件或者文件夹的路径,lpAccountName为需要设置的组的名字例如:Everyone,
dw为设置的属性的ACCESS_MASK具体的值有以下。参考:https://blogs.msdn.microsoft.com/openspecification/2010/04/01/about-the-access_mask-structure/
#define myHeapAlloc(x) (HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,x))
typedef BOOL(WINAPI *SetSecurityDescriptorControlFnPtr)(
IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
IN SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
IN SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet);
typedef BOOL(WINAPI *AddAccessAllowedAceExFnPtr)(
PACL pAcl,
DWORD dwAceRevision,
DWORD AceFlags,
DWORD AccessMask,
PSID pSid
);
BOOL AddRights(TCHAR* lpFileName, TCHAR* lpAccountName, DWORD dw)
{
//lookupAccountName相关变量
PSID pUserID = NULL;
DWORD dUserID = 0;
TCHAR* pDomainName = NULL;
DWORD dDomainName = 0;
SID_NAME_USE snuType;
//第一步,取得传入的用户或用户组的SID
BOOL check1 = LookupAccountName(NULL, lpAccountName, pUserID, &dUserID, pDomainName, &dDomainName, &snuType);
pUserID = (PSID)myHeapAlloc(dUserID);
pDomainName = (TCHAR*)myHeapAlloc(dDomainName * sizeof(TCHAR));
check1 = LookupAccountName(NULL, lpAccountName, pUserID, &dUserID, pDomainName, &dDomainName, &snuType);
//第二步,取得文件的安全描述符(SD)
PSECURITY_DESCRIPTOR pFileSD = NULL;
DWORD dFileSD = 0;
SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION;
check1 = GetFileSecurity(lpFileName, secInfo, pFileSD, 0, &dFileSD);
pFileSD = (PSECURITY_DESCRIPTOR)myHeapAlloc(dFileSD);
check1 = GetFileSecurity(lpFileName, secInfo, pFileSD, dFileSD, &dFileSD);
//第三步,初始一个新的SD
SECURITY_DESCRIPTOR newSD;
InitializeSecurityDescriptor(&newSD, SECURITY_DESCRIPTOR_REVISION);
//第四步,从SD中取出DACL
BOOL bPresent;
BOOL bDaclDefault;
PACL pACL = NULL;
GetSecurityDescriptorDacl(pFileSD, &bPresent, &pACL, &bDaclDefault);
//第五步,取DACL的内存大小
ACL_SIZE_INFORMATION aclInfo;
aclInfo.AceCount = 0;
aclInfo.AclBytesFree = 0;
aclInfo.AclBytesInUse = sizeof(ACL);
// 如果DACL不为空,则取其信息
if (bPresent) {
GetAclInformation(pACL, &aclInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation);
}
//第六步,计算新的ACL的size
DWORD dNewAcl = aclInfo.AclBytesInUse + sizeof(ACL_SIZE_INFORMATION) + GetLengthSid(pUserID) - 2;
//第七步,为新ACL分配内存
PACL pNewAcl = (PACL)myHeapAlloc(dNewAcl);
//第八步,初始化新的acl
InitializeAcl(pNewAcl, dNewAcl, ACL_REVISION2);
//第九步,如果文件(目录)的DACL有数据则拷贝数据到新的DACL
UINT newAclIndex = 0;
UINT curAclIndex = 0;
LPVOID pTempAce = NULL;
if (bPresent&&aclInfo.AceCount)
{
for (curAclIndex = 0; curAclIndex != aclInfo.AceCount; curAclIndex++)
{
GetAce(pACL, curAclIndex, &pTempAce);
if (((ACCESS_ALLOWED_ACE*)pTempAce)->Header.AceFlags == INHERITED_ACE)
break;
if (EqualSid(pUserID, &(((ACCESS_ALLOWED_ACE*)pTempAce)->SidStart)))
{
printf("suc");
continue;
}
AddAce(pNewAcl, ACL_REVISION, MAXDWORD, pTempAce, ((PACE_HEADER)pTempAce)->AceSize);
newAclIndex++;
}
}
SetSecurityDescriptorControlFnPtr _SetSecurityDescriptorControl = NULL;
AddAccessAllowedAceExFnPtr _AddAccessAllowedAceEx = NULL;
//动态装载函数
_AddAccessAllowedAceEx = (AddAccessAllowedAceExFnPtr)
GetProcAddress(GetModuleHandle(TEXT("advapi32.dll")),
"AddAccessAllowedAceEx");
_AddAccessAllowedAceEx(pNewAcl, ACL_REVISION2,
CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE,
dw, pUserID);
//拷贝继承的ACE
if (bPresent&&aclInfo.AceCount)
{
for (; curAclIndex != aclInfo.AceCount; curAclIndex++)
{
GetAce(pACL, curAclIndex, &pTempAce);
AddAce(pNewAcl, ACL_REVISION, MAXDWORD, pTempAce, ((PACE_HEADER)pTempAce)->AceSize);
}
}
//把新的acl设置到新的sd中
check1 = SetSecurityDescriptorDacl(&newSD, TRUE, pNewAcl, FALSE);
check1 = SetFileSecurity(lpFileName, secInfo, &newSD);
DWORD err = GetLastError();
return TRUE;
}