Узнать SID пользователя [решено] Программа :)

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Узнать SID пользователя [решено] Программа :)

Сообщение shraibikus » 18.11.2010 18:29:19

Под Делфи есть юнит
Код: Выделить всё
(******************************************************************************)
(* SPGetSid - Retrieve the current user''s SID in text format                  *)
(*                                                                            *)
(* Copyright (c) 2004 Shorter Path Software                                   *)
(* http://www.shorterpath.com                                                 *)
(******************************************************************************)


{
  SID is a data structure of variable length that identifies user, group,
  and computer accounts.
  Every account on a network is issued a unique SID when the account is first created.
  Internal processes in Windows refer to an account''s SID
  rather than the account''s user or group name.
}


unit SPGetSid;

interface

uses
   Windows, SysUtils;

function GetCurrentUserSid: string;

implementation

const
   HEAP_ZERO_MEMORY = $00000008;
   SID_REVISION     = 1; // Current revision level

type
   PTokenUser = ^TTokenUser;
   TTokenUser = packed record
     User: TSidAndAttributes;
   end;

function ConvertSid(Sid: PSID; pszSidText: PChar; var dwBufferLen: DWORD): BOOL;
var
   psia: PSIDIdentifierAuthority;
   dwSubAuthorities: DWORD;
   dwSidRev: DWORD;
   dwCounter: DWORD;
   dwSidSize: DWORD;
begin
   Result := False;

   dwSidRev := SID_REVISION;

   if not IsValidSid(Sid) then Exit;

   psia := GetSidIdentifierAuthority(Sid);

   dwSubAuthorities := GetSidSubAuthorityCount(Sid)^;

   dwSidSize := (15 + 12 + (12 * dwSubAuthorities) + 1) * SizeOf(Char);

   if (dwBufferLen < dwSidSize) then
   begin
     dwBufferLen := dwSidSize;
     SetLastError(ERROR_INSUFFICIENT_BUFFER);
     Exit;
   end;

   StrFmt(pszSidText, 'S-%u-', [dwSidRev]);

   if (psia.Value[0] <> 0) or (psia.Value[1] <> 0) then
     StrFmt(pszSidText + StrLen(pszSidText),
       '0x%.2x%.2x%.2x%.2x%.2x%.2x',
       [psia.Value[0], psia.Value[1], psia.Value[2],
       psia.Value[3], psia.Value[4], psia.Value[5]])
   else
     StrFmt(pszSidText + StrLen(pszSidText),
       '%u',
       [DWORD(psia.Value[5]) +
       DWORD(psia.Value[4] shl 8) +
       DWORD(psia.Value[3] shl 16) +
       DWORD(psia.Value[2] shl 24)]);

   dwSidSize := StrLen(pszSidText);

   for dwCounter := 0 to dwSubAuthorities - 1 do
   begin
     StrFmt(pszSidText + dwSidSize, '-%u',
       [GetSidSubAuthority(Sid, dwCounter)^]);
     dwSidSize := StrLen(pszSidText);
   end;

   Result := True;
end;

function ObtainTextSid(hToken: THandle; pszSid: PChar;
   var dwBufferLen: DWORD): BOOL;
var
   dwReturnLength: DWORD;
   dwTokenUserLength: DWORD;
   tic: TTokenInformationClass;
   ptu: Pointer;
begin
   Result := False;
   dwReturnLength := 0;
   dwTokenUserLength := 0;
   tic := TokenUser;
   ptu := nil;

   if not GetTokenInformation(hToken, tic, ptu, dwTokenUserLength,
     dwReturnLength) then
   begin
     if GetLastError = ERROR_INSUFFICIENT_BUFFER then
     begin
       ptu := HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, dwReturnLength);
       if ptu = nil then Exit;
       dwTokenUserLength := dwReturnLength;
       dwReturnLength    := 0;

       if not GetTokenInformation(hToken, tic, ptu, dwTokenUserLength,
         dwReturnLength) then Exit;
     end
      else
        Exit;
   end;

   if not ConvertSid((PTokenUser(ptu).User).Sid, pszSid, dwBufferLen) then Exit;

   if not HeapFree(GetProcessHeap, 0, ptu) then Exit;

   Result := True;
end;

function GetCurrentUserSid: string;
var
   hAccessToken: THandle;
   bSuccess: BOOL;
   dwBufferLen: DWORD;
   szSid: array[0..260] of Char;
begin
   Result := '';

   bSuccess := OpenThreadToken(GetCurrentThread, TOKEN_QUERY, True,
     hAccessToken);
   if not bSuccess then
   begin
     if GetLastError = ERROR_NO_TOKEN then
       bSuccess := OpenProcessToken(GetCurrentProcess, TOKEN_QUERY,
         hAccessToken);
   end;
   if bSuccess then
   begin
     ZeroMemory(@szSid, SizeOf(szSid));
     dwBufferLen := SizeOf(szSid);

     if ObtainTextSid(hAccessToken, szSid, dwBufferLen) then
       Result := szSid;
     CloseHandle(hAccessToken);
   end;
end;

end.


Работает под Delphi.
Под lazarus 0.9.28.2 бета (на sf.com это последняя версия для конечного пользователя, на данный момент) получаем ошибку:
quickcleantemp.lpr(107,13) Error: Illegal qualifier
quickcleantemp.lpr(107,13) Hint: may be pointer dereference is missing
quickcleantemp.lpr(107,13) Fatal: Syntax error, ")" expected but "identifier VALUE" found


И как быть? =)
Я всего-лишь хочу зная сид чистить корзину из под пользователя (не Админ).
Последний раз редактировалось shraibikus 25.11.2010 12:54:18, всего редактировалось 2 раз(а).
Аватара пользователя
shraibikus
новенький
 
Сообщения: 36
Зарегистрирован: 22.09.2009 16:22:42
Откуда: Столица деревень

Re: Узнать SID пользователя (Windows)

Сообщение Padre_Mortius » 18.11.2010 18:55:22

Может стоит посмотреть на функцию SHEmptyRecycleBin из библиотеки shell32.dll?
Padre_Mortius
энтузиаст
 
Сообщения: 1265
Зарегистрирован: 29.05.2007 17:38:07
Откуда: Спб

Re: Узнать SID пользователя (Windows)

Сообщение shraibikus » 18.11.2010 18:58:25

Padre_Mortius писал(а):Может стоит посмотреть на функцию SHEmptyRecycleBin из библиотеки shell32.dll?

Спасибо за вариант, в текущей задаче наверное так и решу.

Однако, чисто из спортивных соображений все-же САБЖ по прежнему интересен! :roll:
Аватара пользователя
shraibikus
новенький
 
Сообщения: 36
Зарегистрирован: 22.09.2009 16:22:42
Откуда: Столица деревень

Re: Узнать SID пользователя (Windows)

Сообщение Sergei I. Gorelkin » 18.11.2010 19:20:10

Код от Дельфи нужно компилировать с ключом -Sdh. Или {$mode delphi}{$h+} в начале модуля.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1405
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Узнать SID пользователя (Windows)

Сообщение shraibikus » 18.11.2010 20:09:25

Sergei I. Gorelkin писал(а):Код от Дельфи нужно компилировать с ключом -Sdh. Или {$mode delphi}{$h+} в начале модуля.

А если принципиально на FreePascal?
Возможно существуют иные способы узнать user-sid, кроме перебора HKEY_USERS?

Спасибо Padre_Mortius. Результат:
Код: Выделить всё
{...}
procedure EmptyRecycleBin;
const
   SHERB_NOCONFIRMATION = $00000001;
   SHERB_NOPROGRESSUI = $00000002;
   SHERB_NOSOUND = $00000004;
type
   TSHEmptyRecycleBin = function(Wnd: HWND;
                                 pszRootPath: PChar;
                                 dwFlags: DWORD): HRESULT;  stdcall;
var
   SHEmptyRecycleBin: TSHEmptyRecycleBin;
   LibHandle: THandle;
   Handle: HWND;
begin  { EmptyRecycleBin }
   LibHandle := LoadLibrary(PChar('Shell32.dll'));
   if LibHandle <> 0 then pointer(SHEmptyRecycleBin) :=
       GetProcAddress(LibHandle, 'SHEmptyRecycleBinA')
   else
   begin
     WriteLn('Failed to load Shell32.dll.');
   end;

   Handle:= GetForegroundWindow;
   writeLn(IntToStr(Handle));

   if @SHEmptyRecycleBin <> nil then
     SHEmptyRecycleBin(Handle,
                       nil,
                       SHERB_NOCONFIRMATION or SHERB_NOPROGRESSUI or SHERB_NOSOUND);
   FreeLibrary(LibHandle); SHEmptyRecycleBin := nil;
end;
{...}
EmptyRecycleBin;
Аватара пользователя
shraibikus
новенький
 
Сообщения: 36
Зарегистрирован: 22.09.2009 16:22:42
Откуда: Столица деревень

Re: Узнать SID пользователя (Windows)

Сообщение Sergei I. Gorelkin » 18.11.2010 20:38:33

Если принципиально на FreePascal, то надо везде после psia добавить символ '^'. О чем в сообщениях об ошибке говорится, в общем-то, прямым текстом.
После исправления оно будет по-прежнему компилироваться в Дельфи.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1405
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Узнать SID пользователя (Windows)

Сообщение shraibikus » 18.11.2010 21:15:19

Sergei I. Gorelkin
спасибо!
Рабочий вариант:
Код: Выделить всё
{...}
uses
   Windows, SysUtils;
{...}
const
     HEAP_ZERO_MEMORY = $00000008;
     SID_REVISION     = 1; // Current revision level
{...}
function ConvertSid(Sid: PSID; pszSidText: PChar; var dwBufferLen: DWORD): BOOL;
var
   psia: PSIDIdentifierAuthority;
   dwSubAuthorities: DWORD;
   dwSidRev: DWORD;
   dwCounter: DWORD;
   dwSidSize: DWORD;
begin
   Result := False;

   dwSidRev := SID_REVISION;

   if not IsValidSid(Sid) then Exit;

   psia := GetSidIdentifierAuthority(Sid);

   dwSubAuthorities := GetSidSubAuthorityCount(Sid)^;

   dwSidSize := (15 + 12 + (12 * dwSubAuthorities) + 1) * SizeOf(Char);

   if (dwBufferLen < dwSidSize) then
   begin
     dwBufferLen := dwSidSize;
     SetLastError(ERROR_INSUFFICIENT_BUFFER);
     Exit;
   end;

   StrFmt(pszSidText, 'S-%u-', [dwSidRev]);

   if (psia^.Value[0] <> 0) or (psia^.Value[1] <> 0) then
     StrFmt(pszSidText + StrLen(pszSidText),
       '0x%.2x%.2x%.2x%.2x%.2x%.2x',
       [psia^.Value[0], psia^.Value[1], psia^.Value[2],
       psia^.Value[3], psia^.Value[4], psia^.Value[5]])
   else
     StrFmt(pszSidText + StrLen(pszSidText),
       '%u',
       [DWORD(psia^.Value[5]) +
       DWORD(psia^.Value[4] shl 8) +
       DWORD(psia^.Value[3] shl 16) +
       DWORD(psia^.Value[2] shl 24)]);

   dwSidSize := StrLen(pszSidText);

   for dwCounter := 0 to dwSubAuthorities - 1 do
   begin
     StrFmt(pszSidText + dwSidSize, '-%u',
       [GetSidSubAuthority(Sid, dwCounter)^]);
     dwSidSize := StrLen(pszSidText);
   end;

   Result := True;
end;

function ObtainTextSid(hToken: THandle; pszSid: PChar;
   var dwBufferLen: DWORD): BOOL;
var
   dwReturnLength: DWORD;
   dwTokenUserLength: DWORD;
   tic: TTokenInformationClass;
   ptu: Pointer;
begin
   Result := False;
   dwReturnLength := 0;
   dwTokenUserLength := 0;
   tic := TokenUser;
   ptu := nil;

   if not GetTokenInformation(hToken, tic, ptu, dwTokenUserLength,
     dwReturnLength) then
   begin
     if GetLastError = ERROR_INSUFFICIENT_BUFFER then
     begin
       ptu := HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, dwReturnLength);
       if ptu = nil then Exit;
       dwTokenUserLength := dwReturnLength;
       dwReturnLength    := 0;

       if not GetTokenInformation(hToken, tic, ptu, dwTokenUserLength,
         dwReturnLength) then Exit;
     end
      else
        Exit;
   end;

   if not ConvertSid((PTokenUser(ptu)^.User).Sid, pszSid, dwBufferLen) then Exit;

   if not HeapFree(GetProcessHeap, 0, ptu) then Exit;

   Result := True;
end;

function GetCurrentUserSid: string;
var
   hAccessToken: THandle;
   bSuccess: BOOL;
   dwBufferLen: DWORD;
   szSid: array[0..260] of Char;
begin
   Result := '';

   bSuccess := OpenThreadToken(GetCurrentThread, TOKEN_QUERY, True,
     hAccessToken);
   if not bSuccess then
   begin
     if GetLastError = ERROR_NO_TOKEN then
       bSuccess := OpenProcessToken(GetCurrentProcess, TOKEN_QUERY,
         hAccessToken);
   end;
   if bSuccess then
   begin
     ZeroMemory(@szSid, SizeOf(szSid));
     dwBufferLen := SizeOf(szSid);

     if ObtainTextSid(hAccessToken, szSid, dwBufferLen) then
       Result := szSid;
     CloseHandle(hAccessToken);
   end;
end;               
{...}
WriteLn(GetCurrentUserSid);
Аватара пользователя
shraibikus
новенький
 
Сообщения: 36
Зарегистрирован: 22.09.2009 16:22:42
Откуда: Столица деревень

Re: Узнать SID пользователя (Windows) [решено]

Сообщение shraibikus » 25.11.2010 04:01:47

Результат моих трудов, это первое что я собрал под Lazarus :oops:

Мультипользовательский клинер темпов и прочего мусора (windows. Обкатывал пока только на 2к, 2к3 и ХР).
Проверил на себе и на еще с пяток компьютеров.
Один из них был удивлен очистке 12гб :lol:

По умолчанию чистит только кеши, темпы.
Но умеет так-же чистить Prefetch и прочее.

Списки очистки настраиваемые. Пользователе-независимые (очень хорошо знаете-ли на терминальных серверах чистку проводить).
quicktempcleaner

Ругайтесь :roll:
Аватара пользователя
shraibikus
новенький
 
Сообщения: 36
Зарегистрирован: 22.09.2009 16:22:42
Откуда: Столица деревень

Re: Узнать SID пользователя (Windows) [решено]

Сообщение kosteek » 25.11.2010 11:49:42

Необходимо результат сохранять в лог.
kosteek
постоялец
 
Сообщения: 203
Зарегистрирован: 24.07.2008 14:57:09
Откуда: Украина, г.Славянск

Re: Узнать SID пользователя (Windows) [решено]

Сообщение shraibikus » 25.11.2010 12:51:38

kosteek писал(а):Необходимо результат сохранять в лог.

А разве
quicktempcleaner.exe /start >log.txt
или
quicktempcleaner.exe /start >>log.txt если нужно добавлять
не устраивает?
Аватара пользователя
shraibikus
новенький
 
Сообщения: 36
Зарегистрирован: 22.09.2009 16:22:42
Откуда: Столица деревень


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 13

Рейтинг@Mail.ru