查看GetDokenInformation()的 MSDN文档和获取loginSID示例,GetTokenInformation()需要被调用两次。 第一个调用是获取缓冲区大小。
那么,缓冲区大小是什么? 只要说我使用TokenUser作为第二个参数,我看到由第一次调用返回的dwReturnLength不是TOKEN_USER结构的大小。
提前致谢
TOKEN_USER
结构包含指针(特别是指向本身具有可变长度的SID
的指针)。 这些指针必须指向某个地方。 API函数将期望一个足够大的缓冲区来存放不仅TOKEN_USER
结构,而且还包含所有结构指向的东西。 该函数告诉你它需要多少内存。 它将全部驻留在相邻的存储器中。
第二个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; }
看看最后三个参数:
TokenInformation [out,可选]
指向缓冲区的指针填充请求的信息。 放入此缓冲区的结构取决于TokenInformationClass参数指定的信息类型。
TokenInformationLength [in]
指定由TokenInformation参数指向的缓冲区的大小(以字节为单位)。 如果TokenInformation为NULL,则此参数必须为零。
ReturnLength [out]
指向一个变量的指针,该变量接收TokenInformation参数指向的缓冲区所需的字节数。 如果此值大于TokenInformationLength参数中指定的值,则该函数将失败并将任何数据存储在缓冲区中。
如果TokenInformationClass参数的值是TokenDefaultDacl并且该标记没有默认的DACL,则该函数将ReturnLength指向的变量设置为sizeof(TOKEN_DEFAULT_DACL),并将TOKEN_DEFAULT_DACL结构的DefaultDacl成员设置为NULL。
由于您不知道参数2需要传递多大的缓冲区,因此您需要查询API的确切大小。 然后你通过一个足够大的缓冲区并取回你想要的信息。
你总是可以猜测缓冲区的大小,它可能会工作。
请注意,这是一个典型的Win32 APIs。 它有助于一劳永逸地得到这个成语。
在结构中嵌入的是一个长度可变的SID,所以缓冲区的大小将取决于将被包含在结果中的SID的大小。
如果你的缓冲区足够大,你可以在第一个调用中做这个工作。 大多数使用这些方法的代码将首先尝试使用固定大小的缓冲区,然后在调用指示需要更多内存时分配更大的缓冲区。