首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >GetTokenInformation基础

GetTokenInformation基础
EN

Stack Overflow用户
提问于 2014-01-24 00:43:09
回答 2查看 2.4K关注 0票数 0

我一直想让这个电话合作,但没有成功。

我试图获取当前用户的SID值,以便获得用户的帐户权限(使用LsaEnumerateAccountRights)。虽然我不知道为什么我打给GetTokenInformation的电话是假的。检索进程令牌时没有错误。

到目前为止,我在这个问题上的工作如下:

代码语言:javascript
复制
    HANDLE h_Process;
HANDLE h_Token;
HANDLE h_retToken;

TOKEN_USER tp;
DWORD cb = sizeof(TOKEN_USER);
PDWORD ret;

DWORD dw_TokenLength;

h_Process = GetCurrentProcess();

if (OpenProcessToken(h_Process, TOKEN_READ, &h_Token) == FALSE)
{
    printf("Error: Couldn't open the process token\n");
    return -1;
}

if (GetTokenInformation(h_Token, TokenUser, &tp, cb, &dw_TokenLength) == FALSE)
{
    printf("Error: Could not retrieve Token User information");
    return -1;
}

同时,我还可以问一个我还没有遇到的后续问题,如何从形成的TOKEN_USER结构中检索SID?

我为这样一个简单的问题而提前道歉,我只是有点困惑,希望能继续一些帮助。与此相关的所有问题都要复杂得多,对我目前的问题几乎没有什么洞察力。

谢谢你,乔恩

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-01-24 01:01:42

根据GetTokenInformation文档,如果函数失败,您可以通过调用GetLastError检索更多信息。

返回值 如果函数成功,则返回值为非零。 如果函数失败,则返回值为零。要获得扩展的错误信息,请调用GetLastError

因此,您需要对扩展错误进行一些检查:

代码语言:javascript
复制
if (!GetTokenInformation(h_Token, TokenUser, &tp, cb, &dw_TokenLength))
{
    int lastError = GetLastError();

    // Should be a switch, of course. Omitted for brevity
    if (lastError == ERROR_INSUFFICIENT_BUFFER) 
    {
        //
    }
}  

在使用具有不同缓冲区需求的WinAPI函数时,通常使用的一般经验规则是

  • 使用空缓冲区调用函数以确定所需的缓冲区大小(在本例中,在ReturnLength参数中返回)
  • 分配指定大小的缓冲区
  • 再次调用函数,传递分配的缓冲区,以获取信息
票数 1
EN

Stack Overflow用户

发布于 2017-05-21 04:09:24

首先要理解的是,生成系统调用的Win32 UM (用户模式)API通常需要预先提供缓冲区。这与内核可以访问UM堆分配,而UM不能访问KM分配有关。

这些调用通常遵循一种约定,即调用一次以获得所需的缓冲区大小,然后使用足够大的分配缓冲区再次调用。不过,如果您可以预先创建一个大小合理的缓冲区,情况就更好了。系统调用可能会很昂贵,因为它会导致上下文切换,因此,如果系统调用是一条热门路径,那么从2个调用切换到1个调用将是一个很大的性能改进。

这是你需要的一个例子。这有一个将永远尝试的循环,但也通常只尝试两次。如果需要的缓冲区是<= 128,它将只调用一次。

代码语言:javascript
复制
DWORD bytesReturned = 128;
LPVOID tokenUser = nullptr;
auto cleanup = ScopeExit([&]() 
{
    LocalFree(tokenUser);
});
for (;;) {
    tokenUser = LocalAlloc(LMEM_FIXED, bytesReturned);
    THROW_HR_IF_NULL(E_OUTOFMEMORY, tokenUser);
    if (!GetTokenInformation(token.get(), TokenUser, &tokenUser, bytesReturned, &bytesReturned))
    {
        if (ERROR_INSUFFICIENT_BUFFER == GetLastError())
        {
            LocalFree(tokenUser);
            tokenUser = nullptr;
            continue;
        }
        THROW_HR(HRESULT_FROM_WIN32(GetLastError()));
    }
    break;
}

代码的另一个大问题是,您正在传递对TOKEN_USER tp的引用。API实际上只需要一个PVOID。SID的缓冲区将只位于tokenUser的缓冲区中。您需要将其转换为TOKEN_USER*才能正确访问内存。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21322307

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档