Получение списка привелегий пользователя
От: Аноним  
Дата: 13.05.03 10:23
Оценка:
Пытаюсь следующим способом:

(Слеплено из различных примеров, собранных в инете.)

Есть buffer, заполненный функцией GetTokenInformation();
Заполнен, вроде, правильно: buffer.PrivilegesCount = 17, есть какие-то атрибуты. Дальше:



buffer:=nil;
length:=0;
OpenProcessToken(GetCurrentProcess(),
   TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, token)
b:=GetTokenInformation(token, TokenPrivileges, buffer, length, length);
 while (not b) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) do
     begin
        ReallocMem(buffer, length);
        b:=GetTokenInformation(token, InformationClass, buffer, length, length);
 end;


for i:=0 to buffer.PrivilegeCount-1 do
  begin
   if not  LookupPrivilegeName( nil, buffer.Privileges[i].Luid, ucPrivilegeName, PrivilegeName) then
        raise Exception.Create(SysErrorMessage(GetLastError));
// Здесь выскакивает рантайм ошибка 

   if not LookupPrivilegeDisplayName( nil, ucPrivilegeName,
                  ucDisplayName, dwDisplayName, dwLangId ) then
        raise Exception.Create(SysErrorMessage(GetLastError));
   
   Тут идет вывод названий привелегий (там, в TMemo.Lines.Add() например)
.....................................
end;

Код вылетает на функции LookupPrivilegeName с ошибкой A specified privilege does not exist. То-есть, неверный buffer.Privileges[i].Luid??? Если ошибка да, то скажите как правильно пользоваться функцией GetTokenInformation()?
Re: Получение списка привелегий пользователя
От: Alex Fedotov США  
Дата: 13.05.03 17:39
Оценка:
Здравствуйте, Аноним, Вы писали:

Не знаю, насколько это будет полезно, но вот этот код на C(++) у меня работает без ошибок:

int main(void)
{
    PTOKEN_PRIVILEGES pBuffer = NULL;
    ULONG cbBuffer = 0;
    HANDLE hToken;

    if (!OpenProcessToken(GetCurrentProcess(), 
              TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES,
              &hToken))
    {
    _tprintf(_T("OpenProcessToken failed\n"));
    return 1;
    }

    if (!GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &cbBuffer))
    {
    if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
    {
        _tprintf(_T("GetTokenInformation failed\n"));
        return 1;
    }

    pBuffer = (PTOKEN_PRIVILEGES)_alloca(cbBuffer);

    if (!GetTokenInformation(hToken, TokenPrivileges, pBuffer, cbBuffer,
                 &cbBuffer))
    {
        _tprintf(_T("GetTokenInformation failed\n"));
        return 1;
    }
    }

    for (ULONG i = 0; i < pBuffer->PrivilegeCount; i++)
    {
    TCHAR szName[256];
    TCHAR szDisplayName[256];
    ULONG cbName;
    ULONG dwLangId;
        
    cbName = sizeof(szName) / sizeof(szName[0]);
    if (!LookupPrivilegeName(NULL, &pBuffer->Privileges[i].Luid, 
                 szName, &cbName))
    {
        _tprintf(_T("LookupPrivilegeName failed\n"));
        return 1;
    }

    cbName = sizeof(szDisplayName) / sizeof(szDisplayName[0]);
    if (!LookupPrivilegeDisplayName(NULL, szName, szDisplayName, 
                    &cbName, &dwLangId))
    {
        _tprintf(_T("LookupPrivilegeDisplayName failed\n"));
        return 1;
    }

    _tprintf(_T("%s - %s\n"), szName, szDisplayName);
    }

    return 0;
}


Паскалем уже давно не занимаюсь, поэтому какие-то мелочи в вашем коде мог просмотреть.

Обратите внимание, что размер выходного буфера для LookupPrivilegeName и LookupPrivilegeDisplayName (ucPrivilegeName в вашем коде) нужно инициализировать перед каждым вызовом этих функций, так как они модифицируют переданное им значение. В вашем коде этого не видно.
-- Alex Fedotov
Re[2]: Получение списка привелегий пользователя
От: bigdaddy  
Дата: 14.05.03 07:00
Оценка:
Здравствуйте, Alex Fedotov,

Спасибо за совет, сейчас попробую исправить.
Re[3]: Получение списка привелегий пользователя
От: bigdaddy  
Дата: 14.05.03 07:35
Оценка:
Здравствуйте, Alex Fedotov,

Ситуация такая — переделал я немного Ваш код под С++ билдер — супер, все работает.

Попробовал сделать так, как Вы сказали в дельфи:

PrivilegeNameSize: array[0..255] of char;

  PrivilegeNameSize:=sizeof(ucPrivilegeName);
  if not  LookupPrivilegeName( nil, buffer.Privileges[i].Luid, PChar(@ucPrivilegeName), PrivilegeNameSize) then
     begin
         raise Exception.Create(SysErrorMessage(GetLastError));
     end;


Получаю "Specified privilege does not exist". Очевидно, проблемы с приведением типов для дельфовской версии винапи. Может кто-нибуть подскажет, где можно нормальную доку увидеть по использованию винапи в дельфи?
Re[4]: Получение списка привелегий пользователя
От: Alex Fedotov США  
Дата: 14.05.03 15:22
Оценка:
Здравствуйте, bigdaddy, Вы писали:

B>Ситуация такая — переделал я немного Ваш код под С++ билдер — супер, все работает.


B>Попробовал сделать так, как Вы сказали в дельфи:


B>
B>PrivilegeNameSize: array[0..255] of char;

B>  PrivilegeNameSize:=sizeof(ucPrivilegeName);
B>  if not  LookupPrivilegeName( nil, buffer.Privileges[i].Luid, PChar(@ucPrivilegeName), PrivilegeNameSize) then
B>     begin
B>         raise Exception.Create(SysErrorMessage(GetLastError));
B>     end;

B>


B>Получаю "Specified privilege does not exist". Очевидно, проблемы с приведением типов для дельфовской версии винапи. Может кто-нибуть подскажет, где можно нормальную доку увидеть по использованию винапи в дельфи?


Ну а как LookupPrivilegeName объявлена в Delphi?
-- Alex Fedotov
Re[5]: Получение списка привелегий пользователя
От: bigdaddy  
Дата: 15.05.03 05:41
Оценка:
Здравствуйте, Alex Fedotov, Вы писали:

AF>Ну а как LookupPrivilegeName объявлена в Delphi?


Сорри, неправильно свой код привел:

  ucPrivilegeName:array[0..255] of char;
  PrivilegeNameSize:cardinal;

  PrivilegeNameSize:=sizeof(ucPrivilegeName);
  if not  LookupPrivilegeName( nil, buffer.Privileges[i].Luid, PChar(@ucPrivilegeName), PrivilegeNameSize) then
      begin
           raise Exception.Create(SysErrorMessage(GetLastError));
      end;


А функция объявлена так: LookupPrivilegeName(lpSystem Pchar; LUID Int64; var lpName Pchar; var cbName Cardinal);

пробовал и так:


ucPrivilegeName:   Pchar;
PrivilegeNameSize: cardinal;

PrivilegeNameSize:=0; //sizeof(PChar) - как-то не очень имеет смысл, по-моему... Хотя тоже пробовал :-)


  if not  LookupPrivilegeName( nil, buffer.Privileges[i].Luid, ucPrivilegeName, PrivilegeNameSize) then
      begin
           raise Exception.Create(SysErrorMessage(GetLastError));
      end;


Все время та же лабуда — "указанная привилегия не существует". Я нутром чуваствую, что проблема в типах, но как подобрать??? Хрен его знает...
Re[6]: Получение списка привелегий пользователя
От: Alex Fedotov США  
Дата: 15.05.03 06:23
Оценка:
Здравствуйте, bigdaddy, Вы писали:

B>А функция объявлена так: LookupPrivilegeName(lpSystem Pchar; LUID Int64; var lpName Pchar; var cbName Cardinal);


В C она объявлена как

BOOL LookupPrivilegeName(
    LPCTSTR lpSystemName, 
    PLUID lpLuid, 
    LPTSTR lpName, 
    LPDWORD cbName
    );


Обратите внимание, что второй параметр является указателем на LUID, а не непосредственным значением LUID. Это, кстати, объясняет, почему выдается ошибка о том, что привилегия не существует.

С другой стороны, третий параметр является указателем на строку, что эквивалентно просто Pchar (не var Pchar) в Delphi. Поэтому правильным объявлением функции в Delphi будет

LookupPrivilegeName(lpSystem:Pchar; var LUID:Int64; lpName:Pchar; var cbName:Cardinal);
-- Alex Fedotov
Re[7]: Получение списка привелегий пользователя
От: bigdaddy  
Дата: 15.05.03 07:29
Оценка:
Здравствуйте, Alex Fedotov, Вы писали:

Да, Вы правы, опять я неверно написал:
LookupPrivilegeName(lpSystem Pchar; var LUID Int64; lpName Pchar; var cbName Cardinal);

Огромное спасибо, более-менее разобрался, немного заработало. Проблема еще была и в том, что функция возвращает только те привелегии, которые установлены (я так понял) — оказалось, их всего четыре, всего GetTokenInformation возвращал информацию о 17 привелегиях. А на тех, которые не установлены, LookupPrivilegeName возвращал ошибку, при чем ошибку о несуществующей привелегии. Я просто убал exception.

А Ваш пример под С — показывает все привелегии. Я сравнил оба варианта — насколько мне позволяет знание обоих языков программирования — вроде те же способы вызова функций, за исключением обработки ошибок (почему я их убрал, я написал выше).

Теперь вопрос в том, как увидеть ВСЕ привелегии, а не только те, что разрешены?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.