GetTokenInformation () первый вызов.Зачем? - PullRequest
5 голосов
/ 08 сентября 2010

При просмотре документации MSDN для GetTokenInformation () и Получение идентификатора входа в систему , GetTokenInformation () необходимо вызвать дважды. Первый вызов - получить размер буфера.

Итак, размер буфера чего? Просто скажите, что я использую TokenUser в качестве второго параметра, и я вижу, что dwReturnLength, возвращаемый первым вызовом, не является размером структуры TOKEN_USER.

Заранее спасибо

Ответы [ 5 ]

8 голосов
/ 08 сентября 2010

Структура TOKEN_USER содержит указатели (в частности, указатель на SID, который сам имеет переменную длину).Эти указатели должны указывать куда-то.Функция API будет ожидать достаточно большой буфер для размещения не только структуры TOKEN_USER, но и всех вещей, на которые указывает эта структура.Функция сообщает вам, сколько памяти ей нужно для всего .Все это будет находиться в смежной памяти.

4 голосов
/ 08 сентября 2010

Посмотрите на последние три параметра:

TokenInformation [out, необязательно]

Указатель на буфер, который заполняет функция запрошенной информацией.Структура, помещенная в этот буфер, зависит от типа информации, указанной параметром TokenInformationClass.

TokenInformationLength [in]

Указывает размер в байтах буфера, на который указывает параметр TokenInformation.Если TokenInformation равен NULL, этот параметр должен быть нулевым.

ReturnLength [out]

Указатель на переменную, которая получает количество байтов, необходимое для буфера, на который указывает параметр TokenInformation.Если это значение больше значения, указанного в параметре TokenInformationLength, функция завершается сбоем и не сохраняет никаких данных в буфере.

Если значение параметра TokenInformationClass равно TokenDefaultDacl и токен не имеет DACL по умолчанию, функцияустанавливает переменную, на которую указывает ReturnLength, в sizeof (TOKEN_DEFAULT_DACL) и устанавливает для элемента DefaultDacl структуры TOKEN_DEFAULT_DACL значение NULL.

Поскольку вы не знаете, какой размер буфера нужно передать для параметра #2, вам нужно запросить API для точного размера.А затем вы передаете достаточно большой буфер и получаете нужную информацию.

Вы всегда можете угадать размер буфера, и он может работать.

Обратите внимание, что это типично для Win32API-интерфейсы.Это помогает раз и навсегда решить эту идиому.

4 голосов
/ 08 сентября 2010

Полный пример вашего второго 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;
   }
3 голосов
/ 08 сентября 2010

В структуру встроен SID переменной длины, поэтому размер буфера будет зависеть от размера SID, который будет включен в результат.

1 голос
/ 08 сентября 2010

Вы можете сделать это при первом вызове, если ваш буфер достаточно велик.Большая часть кода, использующего эти методы, будет сначала пытаться использовать буфер фиксированного размера, а затем выделять больший буфер, если вызов указывает, что ему требуется больше памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...