Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GetTokenInformation() first call. What for?

Looking at MSDN documentaion for GetTokenInformation() and the Getting the Logon SID example, GetTokenInformation() needs to be called twice. The first call is to get the buffer size.

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.

Thanks in advance

like image 404
Phantom Avatar asked Sep 08 '10 18:09

Phantom


4 Answers

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.

like image 99
Rob Kennedy Avatar answered Nov 14 '22 19:11

Rob Kennedy


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.

// 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;
   }
like image 24
Steve Townsend Avatar answered Nov 14 '22 18:11

Steve Townsend


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.

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.

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.

like image 4
dirkgently Avatar answered Nov 14 '22 18:11

dirkgently


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.

like image 3
Chris Taylor Avatar answered Nov 14 '22 18:11

Chris Taylor