这段代码怎么解释

Jack_xiao 2009-12-04 03:38:03
如题,不求每句代码都有解释,只是希望了解函数调用的作用,请尽可能详细些


BOOL Func()
{
#define ACCESS_READ 1
#define ACCESS_WRITE 2

HANDLE hToken;
DWORD dwStatus;
DWORD dwAccessMask;
DWORD dwAccessDesired;
DWORD dwACLSize;
DWORD dwStructureSize = sizeof(PRIVILEGE_SET);
PACL pACL = NULL;
PSID psidAdmin = NULL;
BOOL bReturn = FALSE;
PRIVILEGE_SET ps;
GENERIC_MAPPING GenericMapping;
PSECURITY_DESCRIPTOR psdAdmin = NULL;
SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;

if(!ImpersonateSelf(SecurityImpersonation))
goto LeaveIsAdmin;

if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken)) //?Token怎么解释
{
if (GetLastError() != ERROR_NO_TOKEN)
goto LeaveIsAdmin;

if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) //?
goto LeaveIsAdmin;

if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) //为什么要重复一遍
goto LeaveIsAdmin;
}

if (!AllocateAndInitializeSid(&SystemSidAuthority, 2,
SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0, &psidAdmin)) //?
goto LeaveIsAdmin;

psdAdmin = LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); //?分配空间做什么?
if (psdAdmin == NULL)
goto LeaveIsAdmin;

if (!InitializeSecurityDescriptor(psdAdmin,
SECURITY_DESCRIPTOR_REVISION)) //?
goto LeaveIsAdmin;

dwACLSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) +
GetLengthSid(psidAdmin) - sizeof(DWORD);

pACL = (PACL)LocalAlloc(LPTR, dwACLSize); //? pACL是做什么的?
if (pACL == NULL)
goto LeaveIsAdmin;

if (!InitializeAcl(pACL, dwACLSize, ACL_REVISION2))
goto LeaveIsAdmin;

dwAccessMask= ACCESS_READ | ACCESS_WRITE;

if (!AddAccessAllowedAce(pACL, ACL_REVISION2, dwAccessMask, psidAdmin)) //?
goto LeaveIsAdmin;

if (!SetSecurityDescriptorDacl(psdAdmin, TRUE, pACL, FALSE)) //?
goto LeaveIsAdmin;

if(!SetSecurityDescriptorGroup(psdAdmin, psidAdmin, FALSE)) //?
goto LeaveIsAdmin;
if(!SetSecurityDescriptorOwner(psdAdmin, psidAdmin, FALSE)) //为什么要重复一遍?
goto LeaveIsAdmin;

if (!IsValidSecurityDescriptor(psdAdmin)) // 有效or无效的判断依据是什么?
goto LeaveIsAdmin;

dwAccessDesired = ACCESS_READ;

GenericMapping.GenericRead = ACCESS_READ;
GenericMapping.GenericWrite = ACCESS_WRITE;
GenericMapping.GenericExecute = 0;
GenericMapping.GenericAll = ACCESS_READ | ACCESS_WRITE;

if (!AccessCheck(psdAdmin, hToken, dwAccessDesired,
&GenericMapping, &ps, &dwStructureSize, &dwStatus, &bReturn))
goto LeaveIsAdmin;

if(!RevertToSelf())
bReturn = FALSE;

LeaveIsAdmin:

if (pACL) LocalFree(pACL);
if (psdAdmin) LocalFree(psdAdmin);
if (psidAdmin) FreeSid(psidAdmin);

return bReturn;

}
...全文
304 21 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
Jack_xiao 2009-12-08
  • 打赏
  • 举报
回复
而且非管理员也有很多种:Guest, Power User, User, Debugger User
这个函数只能判断是否管理员,其他权限的用户怎么判断呢,能否从这个函数扩展?
Jack_xiao 2009-12-08
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 loaden 的回复:]
引用 3 楼 jack_xiao 的回复:
如果要求稍加改变,如判断是否标准用户或
超级管理员,需要修改那些代码?
另外,这段代码是否有冗余?是否有漏洞?

这个函数的功能是:如果是超级管理员,返回TRUE,受限用户就返回FALSE。

[/Quote]

超级管理员和管理员是不同的概念吧?
sanmao3 2009-12-08
  • 打赏
  • 举报
回复
学习了啊!这个管理员判断的函数我最近刚要用的哦。。。谢谢了啊。。
Jack_xiao 2009-12-07
  • 打赏
  • 举报
回复
在此声明,这段代码来源于网络,非本人所写
do_fork 2009-12-07
  • 打赏
  • 举报
回复
LZ的goto用的恰到好处
Jack_xiao 2009-12-07
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 leechrockgames 的回复:]
goto早被淘汰了.不要用.
[/Quote]

有时候用goto确实能省却很多重复的代码,虽说可以用其他结构化的语句替代,但有时用goto反而能让人对代码的流程一目了然,我认为要看情况而言
Jack_xiao 2009-12-07
  • 打赏
  • 举报
回复
不可否认,7楼和16楼的代码确实很巧妙的去除了goto, 但是我并不像讨论代码中是否该用goto的问题,至于对代码的解释,我还是想听听各位的自己的理解,而不是人云亦云。

16楼的代码中添加了一条语句
bReturn = TRUE;
这是否必要?

对于代码的优化,我还是更看重性能,而不是漂亮的外观。

希望各位能够认真看看代码,然后说说自己的理解;
traceless 2009-12-07
  • 打赏
  • 举报
回复
像这种一层层的关系
不用goto的话可以考虑用

do{

}while(0)看起来更结构化

或者用try catch

解释上面已有人解释了
traceless 2009-12-07
  • 打赏
  • 举报
回复
代码的解释,上面已经有了,我来优化一下代码:

有一些程序如果没有了goto,代码将很冗余并且实现的过程容易出现泄露,上面的goto确实用得不错

BOOL Func() 
{
#define ACCESS_READ 1
#define ACCESS_WRITE 2

HANDLE hToken;
DWORD dwStatus;
DWORD dwAccessMask;
DWORD dwAccessDesired;
DWORD dwACLSize;
DWORD dwStructureSize = sizeof(PRIVILEGE_SET);
PACL pACL = NULL;
PSID psidAdmin = NULL;
BOOL bReturn = FALSE;
PRIVILEGE_SET ps;
GENERIC_MAPPING GenericMapping;
PSECURITY_DESCRIPTOR psdAdmin = NULL;
SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;

do
{
if(!ImpersonateSelf(SecurityImpersonation))
break;

if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken))
{
if (GetLastError() != ERROR_NO_TOKEN)
break;

if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
break;

if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
break;
}

if (!AllocateAndInitializeSid(&SystemSidAuthority, 2,
SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0, &psidAdmin))
break;

psdAdmin = LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); //
if (psdAdmin == NULL)
break;

if (!InitializeSecurityDescriptor(psdAdmin,
SECURITY_DESCRIPTOR_REVISION)) //?
break;

dwACLSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) +
GetLengthSid(psidAdmin) - sizeof(DWORD);

pACL = (PACL)LocalAlloc(LPTR, dwACLSize); //? pACL是做什么的?
if (pACL == NULL)
break;

if (!InitializeAcl(pACL, dwACLSize, ACL_REVISION2))
break;

dwAccessMask= ACCESS_READ | ACCESS_WRITE;

if (!AddAccessAllowedAce(pACL, ACL_REVISION2, dwAccessMask, psidAdmin)) //?
break;

if (!SetSecurityDescriptorDacl(psdAdmin, TRUE, pACL, FALSE)) //?
break;

if(!SetSecurityDescriptorGroup(psdAdmin, psidAdmin, FALSE)) //?
break;
if(!SetSecurityDescriptorOwner(psdAdmin, psidAdmin, FALSE)) //为什么要重复一遍?
break;

if (!IsValidSecurityDescriptor(psdAdmin)) // 有效or无效的判断依据是什么?
break;

dwAccessDesired = ACCESS_READ;
GenericMapping.GenericRead = ACCESS_READ;
GenericMapping.GenericWrite = ACCESS_WRITE;
GenericMapping.GenericExecute = 0;
GenericMapping.GenericAll = ACCESS_READ | ACCESS_WRITE;

if (!AccessCheck(psdAdmin, hToken, dwAccessDesired,
&GenericMapping, &ps, &dwStructureSize, &dwStatus, &bReturn))
break;

if(!RevertToSelf())
break;
bReturn = TRUE;
} while (0);
//以下三个函数都是安全释放函数
if (pACL) LocalFree(pACL);
if (psdAdmin) LocalFree(psdAdmin);
if (psidAdmin) FreeSid(psidAdmin);

return bReturn;
}




shenzhiwanghz 2009-12-07
  • 打赏
  • 举报
回复
有人说lz的goto太多,不过我觉得这个goto还是可以接受的,保证了单入口单出口。
相反都用return的话,反而使函数出口太多,各有利弊。

另外,个人以为,适当的用向下的goto可以简化代码,
但是向上的goto是不太好的习惯,容易引起泄露等错误。
yzm365487848 2009-12-07
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 do_fork 的回复:]
LZ的goto用的恰到好处
[/Quote]

顶!

这里goto,没用错
lhslktg 2009-12-07
  • 打赏
  • 举报
回复
接分!
leechrockgames 2009-12-04
  • 打赏
  • 举报
回复
goto早被淘汰了.不要用.
z569362161 2009-12-04
  • 打赏
  • 举报
回复
goto
应该尽量避免少用。
「已注销」 2009-12-04
  • 打赏
  • 举报
回复
改成非goto的版本:

BOOL Func()
{
#define ACCESS_READ 1
#define ACCESS_WRITE 2

HANDLE hToken;
DWORD dwStatus;
DWORD dwAccessMask;
DWORD dwAccessDesired;
DWORD dwACLSize;
DWORD dwStructureSize = sizeof(PRIVILEGE_SET);
PACL pACL = NULL;
PSID psidAdmin = NULL;
BOOL bReturn = FALSE;
PRIVILEGE_SET ps;
GENERIC_MAPPING GenericMapping;
PSECURITY_DESCRIPTOR psdAdmin = NULL;
SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;

for (;;)
{
if (!ImpersonateSelf(SecurityImpersonation)) break;

if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken)) //?Token怎么解释
{
if (GetLastError() != ERROR_NO_TOKEN) break;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) //?
break;
}

if (!AllocateAndInitializeSid(&SystemSidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &psidAdmin)) //?
break;

psdAdmin = LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); //?分配空间做什么?
if (psdAdmin == NULL) break;

if (!InitializeSecurityDescriptor(psdAdmin, SECURITY_DESCRIPTOR_REVISION)) //?
break;

dwACLSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psidAdmin) - sizeof(DWORD);

pACL = (PACL)LocalAlloc(LPTR, dwACLSize); //? pACL是做什么的?
if (pACL == NULL) break;

if (!InitializeAcl(pACL, dwACLSize, ACL_REVISION2)) break;

dwAccessMask = ACCESS_READ | ACCESS_WRITE;

if (!AddAccessAllowedAce(pACL, ACL_REVISION2, dwAccessMask, psidAdmin)) //?
break;

if (!SetSecurityDescriptorDacl(psdAdmin, TRUE, pACL, FALSE)) //?
break;

if (!SetSecurityDescriptorGroup(psdAdmin, psidAdmin, FALSE)) //?
break;
if (!SetSecurityDescriptorOwner(psdAdmin, psidAdmin, FALSE)) //为什么要重复一遍?
break;
if (!IsValidSecurityDescriptor(psdAdmin)) // 有效or无效的判断依据是什么?
break;

dwAccessDesired = ACCESS_READ;
GenericMapping.GenericRead = ACCESS_READ;
GenericMapping.GenericWrite = ACCESS_WRITE;
GenericMapping.GenericExecute = 0;
GenericMapping.GenericAll = ACCESS_READ | ACCESS_WRITE;

if (!AccessCheck(psdAdmin, hToken, dwAccessDesired, &GenericMapping, &ps, &dwStructureSize,
&dwStatus, &bReturn)) break;

if (!RevertToSelf()) bReturn = FALSE;
break;
}

if (pACL) LocalFree(pACL);
if (psdAdmin) LocalFree(psdAdmin);
if (psidAdmin) FreeSid(psidAdmin);

return bReturn;
}

「已注销」 2009-12-04
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 jack_xiao 的回复:]
如果要求稍加改变,如判断是否标准用户或
超级管理员,需要修改那些代码?
另外,这段代码是否有冗余?是否有漏洞?
[/Quote]
这个函数的功能是:如果是超级管理员,返回TRUE,受限用户就返回FALSE。
「已注销」 2009-12-04
  • 打赏
  • 举报
回复
        if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) //为什么要重复一遍
goto LeaveIsAdmin;

没有必要重复!
去掉即可。

这个代码可能还需要考虑给C语言用户使用,所以在编码风格上不太优雅,太多的goto了。
如果不考虑C风格,可以在结构上调整下。
deng1243 2009-12-04
  • 打赏
  • 举报
回复
好多goto
Jack_xiao 2009-12-04
  • 打赏
  • 举报
回复
我并不是要得到每个API的解释,因为MSDN已经很清楚了。
这里只是想明白这个函数的工作原理,具体来说,各个函数之间的配合是什么样的,
前面的调用是为后面那步操作服务的,如果你面对一个从没用过这里所列的API的人,
如何讲能使他对这个函数有个较深的认识?如果要求稍加改变,如判断是否标准用户或
超级管理员,需要修改那些代码?
另外,这段代码是否有冗余?是否有漏洞?
「已注销」 2009-12-04
  • 打赏
  • 举报
回复
楼主如果要问每个API的用法,建议查证MSDN,那样会更详细,而且很多还有示例。

这是用于提取DEBUG权限的,里面的一些API和楼主代码相同,有注释,可参考下。

bool System::GetPrivileges()
{
// 取得当前进程的[Token](标识)句柄
Handle handle;
if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &handle.Get()))
return false;

// 取得关闭系统的[LUID](本地唯一的标识符)值
TOKEN_PRIVILEGES tokenPrivilege;
if (!::LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tokenPrivilege.Privileges[0].Luid))
return false;

// 设置特权数组的元素个数
tokenPrivilege.PrivilegeCount = 1;

// 设置[LUID]的属性值
tokenPrivilege.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

// 为当前进程取得DEBUG权限
if (!::AdjustTokenPrivileges(handle, FALSE, &tokenPrivilege, 0, NULL, NULL))
return false;

return true;
}
加载更多回复(1)

65,184

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧