如何判断当前用户对文件有无写权限
前一段时间项目要求判断用户对文件有无写权限,于是查了相关资料,拜读了很多大牛的著作写下了一下代码(代码写的杂乱,有很多不足之处,还请各位大牛多多批评):
代码思路:1.获取当前用户名GetUserName
2.获取当前用户名所属的组NetUserGetLocalGroups
3.获取用户和用户组的sid(安全标识符,表示一个用户,一个用户组,一台计算机,一个域等,计算机可以通过这个识别用户;注册表对应位置:HESY_USERS下)
4.通过文件名获取文件的acl列表
5.遍历acl列表中的ace,比对sid,判断相应权限
代码缺陷:1.不针对域用户,如果是域用户可在NetUserGetLocalGroups函数之前,获取域名和用户名拼接wstrName,再传参给NetUserGetLocalGroups
2.仅针对ntfs,对fat32或fat16仅仅做简单处理
代码参考:http://pnig0s1992.blog.51cto.com/393390/908495
#define AllocMem(x) (HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, x))
#define FreeMem(x) (HeapFree(GetProcessHeap(),HEAP_ZERO_MEMORY, x))
bool hasWritePrivilege(const char* path)
{
//获得文件的安全描述符
BOOL bRs = FALSE;
DWORD dwSizeNeeded = 0;
PISECURITY_DESCRIPTOR psd = NULL;
SECURITY_INFORMATION si = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;
WCHAR wstr[256] = {0};
c2w(wstr, 256, path);
//获取当前用户名
WCHAR wstrName[256] = {0};
DWORD dwSize = 256;
GetUserName(wstrName,&dwSize);
//用户sid
LPVOID pUserSid = NULL;
DWORD cbUserSid = 0;
//组sid
TCHAR *szDomain = NULL;
DWORD cbDomain = 0;
SID_NAME_USE snuType;
DWORD dwLevel = 0;
DWORD dwPrefMaxLen = MAX_PREFERRED_LENGTH;
DWORD dwEntriesRead = 0;
DWORD dwTotalEntries = 0;
NET_API_STATUS nStatus;
LPLOCALGROUP_USERS_INFO_0 pBuf = NULL;
LPLOCALGROUP_USERS_INFO_0 pImpBuf;
LPVOID pDomainSid = NULL;
DWORD cbDomainSid = 0;
TCHAR *szDomainnew = NULL;
DWORD cbDomainnew = 0;
//获取当前用户所属的用户组
nStatus = NetUserGetLocalGroups(NULL,wstrName,0,LG_INCLUDE_INDIRECT,(LPBYTE*)&pBuf,dwPrefMaxLen,&dwEntriesRead,&dwTotalEntries);
if (nStatus == NERR_Success)
{
//遍历用户组
if ((pImpBuf = pBuf) != NULL)
{
for (int i = 0;i<dwEntriesRead;i++)
{
assert(pImpBuf != NULL);
if (pImpBuf == NULL)
{
break;
}
//获取用户组的sid,第一次获取可能失败 重新分配buffer后获取
if (!LookupAccountName(NULL,pImpBuf->lgrui0_name,pDomainSid,&cbDomainSid,szDomainnew,&cbDomainnew,&snuType))
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
pDomainSid = AllocMem(cbDomainSid);
szDomainnew = (TCHAR*)AllocMem(cbDomainnew*sizeof(TCHAR));
}
}
if (!LookupAccountName(NULL,pImpBuf->lgrui0_name,pDomainSid,&cbDomainSid,szDomainnew,&cbDomainnew,&snuType))
{
return true;
}
else
{
//获取用户的sid
if (!LookupAccountName(NULL,wstrName,pUserSid,&cbUserSid,szDomain,&cbDomain,&snuType))
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
pUserSid = AllocMem(cbUserSid);
szDomain = (TCHAR*)AllocMem(cbDomain*sizeof(TCHAR));
}
}
if (!LookupAccountName(NULL,wstrName,pUserSid,&cbUserSid,szDomain,&cbDomain,&snuType))
{
return true;
}
BOOL bSuccess = TRUE;
PACL pDacl = NULL;
ACCESS_ALLOWED_ACE *pAce = NULL;
//根据文件名获取dacl
if(ERROR_SUCCESS != GetNamedSecurityInfo(wstr,SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,&pDacl,NULL,NULL))
{
return true;
}
else
{
//Dacl不存在话,调用QFile和QDir来判断,这是Qt的类
if (!pDacl)
{
//Fat32系统
QFile file(QString::fromWCharArray(wstr));
QDir dir(QString::fromWCharArray(wstr));
if (file.isWritable())
{
return true;
}
else if (dir.isReadable())
{
return true;
}
else
{
return false;
}
}
//DACL存在的话遍历其中的ace
for (int i = 0; i<pDacl->AceCount;i++)
{
//获取ACE
if (GetAce(pDacl,i,(LPVOID*)&pAce))
{
qDebug()<<pAce->SidStart;
//判断ACE的sid和用户或用户组的sid是否相同
if (EqualSid(pUserSid,&pAce->SidStart) || EqualSid(pDomainSid,&pAce->SidStart))
{
qDebug()<<"pAce->Mask"<<pAce->Mask;
//判断当前用户或组对文件有无写权限
if ((pAce->Mask & FILE_WRITE_DATA) == FILE_WRITE_DATA)
{
qDebug()<<"可写!!!!!";
return true;
}
}
}
}
}
}
qDebug()<<"用户组:"<<QString::fromWCharArray(pImpBuf->lgrui0_name)<<snuType;
pImpBuf++;
}
}
if (pBuf != NULL)
{
NetApiBufferFree(pBuf);
pBuf = NULL;
}
}
//end
}