Иногда возникает задача узнать, запущена ли программа под администраторской учеткой или же обычного пользователя. Для чего это нужно? Ну, например мы написали крутую софтину, выполняющую некие действия с системой (например свой собственный редактор реестра). Для редактирования некоторых веток (например HKEY_LOCAL_MACHINE), требуются права админа. А вдруг программа запущена без соответствующих привилегий, то тогда мы ничего не сможем сделать – это раз, система нам будет показывать непонятные на первый взгляд ошибки – это два. Одна из самых частых в такой ситуации – ошибка с кодом 5 (ERROR_ACCESS_DENIED). С проверкой на "вшивость” можно говорить пользователю, что нужно запустить программу с правами администратора и смело закрываться.
Погуглив, не нашел ничего подходящего. Может просто плохо искал? Обратившись к крутой справочной системе, входящей в состав Delphi 7, был обнаружен кусок кода, который как раз за это отвечает. Но… Он на Си. Ну ничего, попыхтев немного мне всетаки удалось переписать его на Delphi. Отступление: исходник функции на Си можно найти в Help -> Windows SDK -> Поиск. Если запускаете поиск первый раз, то нужно выбрать пункт "Обеспечить максимальные возможности поиска”. Если запускаете не первый раз, то нужно нажать на кнопку "Перестроить…” и выбрать пункт"Обеспечить максимальные возможности поиска”. После этого в поле поиска (1 поле) ввести "admin”, а в результатах поиска (2 поле) выбрать первый пункт "admin”. И в третьем поле, там где нас просят выбрать нужный раздел, выбираем раздел "Determining Whether the User is an Administrator”. Жмем "Показать” и копипастим код:) Код на Delphi:
function isAdmin: Boolean;
{ Объявление констант, которых в delphi я не нашел }
const
SECURITY_BUILTIN_DOMAIN_RID = $00000020;
DOMAIN_ALIAS_RID_ADMINS = $00000220;
var
hProcess, hAccessToken: Cardinal;
InfoBuffer: array [0..1023] of Char;
ptgGroups: PTokenGroups;
dwInfoBufferSize: DWORD;
psidAdmins: PSID;
siaNtAuthority: TSidIdentifierAuthority;
x: UINT;
begin
{ Получаем Token нашего приложения }
hProcess := GetCurrentProcess();
{
Обнуляем память и заносим в последний элемент 5.
Это нужно для того что бы "формат" данных выглядел так [0, 0, 0, 0, 0, 5]
тупым присваиванием не прокатило.
Откуда я это знаю? Подсмотрел в VC, как и те две константы, что объявлены
в начале:)
}
ZeroMemory(@siaNtAuthority.Value, sizeof(Char)*6);
siaNtAuthority.Value[5] := 5;
{ даем указатель ptgGroups на InfoBuffer }
ptgGroups := PTokenGroups(@InfoBuffer);
{ Попытка открыть процесс и получить инфу о нем }
if not OpenProcessToken(hProcess, TOKEN_READ, hAccessToken) then
begin
Result := false;
Exit;
end;
{ Пытаемся получить информаци о првах доступа, одновременно заполная все что
нужно }
if not (getTokenInformation(hAccessToken, TokenGroups, @InfoBuffer,
High(InfoBuffer) + 1, dwInfoBufferSize)) then
begin
Result := false;
Exit;
end;
{ Распределяем и инициализируем идентификатор безопасности (SID) с восьмью
полномочиями }
AllocateAndInitializeSid(siaNtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, psidAdmins);
{ Тут вроде происходит собственно проверка на то, является ли процесс запущенный
с правами админа }
for x := 0 to ptgGroups.GroupCount - 1 do
if EqualSid(psidAdmins, ptgGroups.Groups[x].Sid) then
begin
FreeSid(psidAdmins);
Result := true;
Exit;
end;
FreeSid(psidAdmins);
Result := false;
end;
Воть. За коменты сильно не бейте, писал от себя, так, как я это понимаю +переводы SDK, весьма скудными знаниями английского(( Надеюсь статейка будет полезна. (на форуме где то видел похожую тему).
|