windows GetTokenInformation() 第一次调用。做什么的?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3670984/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
GetTokenInformation() first call. What for?
提问by Phantom
Looking at MSDN documentaion for GetTokenInformation()and the Getting the Logon SIDexample, GetTokenInformation() needs to be called twice. The first call is to get the buffer size.
查看GetTokenInformation() 的MSDN 文档和获取登录 SID示例,GetTokenInformation() 需要调用两次。第一个调用是获取缓冲区大小。
So, buffer size of what? Just say I use TokenUser as its second parameter, I see that the dwReturnLength returned by first call is not the size of TOKEN_USER structure.
那么,缓冲区的大小是多少?只是说我使用 TokenUser 作为它的第二个参数,我看到第一次调用返回的 dwReturnLength 不是 TOKEN_USER 结构的大小。
Thanks in advance
提前致谢
回答by Rob Kennedy
The TOKEN_USER
structure contains pointers (in particular, a pointer to a SID
that itself has variable length). Those pointers have to point somewhere. The API function will expect a buffer big enough to hold not only the the TOKEN_USER
structure, but also all the things that structure points to. The function tells you how much memory it needs for everything. It will all reside in adjacent memory.
该TOKEN_USER
结构包含指针(特别是指向SID
本身具有可变长度的a 的指针)。这些指针必须指向某个地方。API 函数需要一个足够大的缓冲区,不仅可以容纳TOKEN_USER
结构,还可以容纳结构指向的所有内容。该函数会告诉您所有内容需要多少内存。它将全部驻留在相邻的内存中。
回答by Steve Townsend
The full example from your second URL should make it clear that how the length returned from the first call is used. You use this to allocate raw memory of that size - here this is the variable ptg
- and cast it to PTOKEN_GROUPS for use in the second call.
第二个 URL 中的完整示例应该清楚说明如何使用从第一次调用返回的长度。您使用它来分配该大小的原始内存 - 这里是变量ptg
- 并将其转换为 PTOKEN_GROUPS 以在第二次调用中使用。
// Get required buffer size and allocate the TOKEN_GROUPS buffer.
if (!GetTokenInformation(
hToken, // handle to the access token
TokenGroups, // get information about the token's groups
(LPVOID) ptg, // pointer to TOKEN_GROUPS buffer
0, // size of buffer
&dwLength // receives required buffer size
))
{
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
goto Cleanup;
ptg = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, dwLength);
if (ptg == NULL)
goto Cleanup;
}
// Get the token group information from the access token.
if (!GetTokenInformation(
hToken, // handle to the access token
TokenGroups, // get information about the token's groups
(LPVOID) ptg, // pointer to TOKEN_GROUPS buffer
dwLength, // size of buffer
&dwLength // receives required buffer size
))
{
goto Cleanup;
}
回答by dirkgently
Look at the last three parameters:
查看最后三个参数:
TokenInformation[out, optional]
A pointer to a buffer the function fills with the requested information. The structure put into this buffer depends upon the type of information specified by the TokenInformationClass parameter.
TokenInformationLength[in]
Specifies the size, in bytes, of the buffer pointed to by the TokenInformation parameter. If TokenInformation is NULL, this parameter must be zero.
ReturnLength[out]
A pointer to a variable that receives the number of bytes needed for the buffer pointed to by the TokenInformation parameter. If this value is larger than the value specified in the TokenInformationLength parameter, the function fails and stores no data in the buffer.
If the value of the TokenInformationClass parameter is TokenDefaultDacl and the token has no default DACL, the function sets the variable pointed to by ReturnLength to sizeof(TOKEN_DEFAULT_DACL) and sets the DefaultDacl member of the TOKEN_DEFAULT_DACL structure to NULL.
TokenInformation[输出,可选]
指向函数用请求的信息填充的缓冲区的指针。放入此缓冲区的结构取决于 TokenInformationClass 参数指定的信息类型。
TokenInformationLength[in]
指定 TokenInformation 参数指向的缓冲区的大小(以字节为单位)。如果 TokenInformation 为 NULL,则此参数必须为零。
返回长度[out]
一个指向变量的指针,该变量接收 TokenInformation 参数指向的缓冲区所需的字节数。如果此值大于 TokenInformationLength 参数中指定的值,则该函数将失败并且不会在缓冲区中存储任何数据。
如果 TokenInformationClass 参数的值为 TokenDefaultDacl 并且令牌没有默认 DACL,则该函数将 ReturnLength 指向的变量设置为 sizeof(TOKEN_DEFAULT_DACL) 并将 TOKEN_DEFAULT_DACL 结构的 DefaultDacl 成员设置为 NULL。
Since you don't know how big a buffer you need to pass for parameter #2, you need to query the API for the exact size. And then you pass-in a sufficiently large buffer and get back the information you want.
由于您不知道需要为参数 #2 传递多大的缓冲区,因此您需要查询 API 以获取确切大小。然后你传入一个足够大的缓冲区并取回你想要的信息。
You could always guess the buffer size and it may work.
您总是可以猜测缓冲区大小,它可能会起作用。
Note that this is a typical of Win32 APIs. It helps to get this idiom right once and for all.
请注意,这是典型的 Win32 API。它有助于一劳永逸地正确使用这个习语。
回答by Chris Taylor
Imbedded in the structure is a SID which is variable length, so the buffer size will depend on the size of the SID that will be included in the result.
嵌入在结构中的是可变长度的 SID,因此缓冲区大小将取决于将包含在结果中的 SID 的大小。
回答by Mike
You can make this work in the first call if your buffer is large enough. Most code that use these methods will try first with a fixed size buffer and then allocate a larger buffer if the call indicated that it needs more memory.
如果您的缓冲区足够大,您可以在第一次调用时完成这项工作。大多数使用这些方法的代码将首先尝试使用固定大小的缓冲区,然后如果调用表明它需要更多内存,则分配更大的缓冲区。