Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Идентификация SID в Delphi: обход PsGetSid без использования SysInternals

Delphi , Синтаксис , Справочник по API-функциям

Идентификация SID в Delphi: обход PsGetSid без использования SysInternals

Введение

SID (Security Identifier) - это уникальный идентификатор, используемый в Windows для идентификации пользователей, групп и компьютеров. Для разработчиков, работающих с Delphi, может возникнуть необходимость извлечения SID компьютера для различных целей, например, для управления доступом или аутентификации.

Проблема

Пользователь ищет способ извлечения SID компьютера с помощью кода на Delphi. Существует утилита PsGetSid от SysInternals, которая выполняет эту задачу, но использование сторонних инструментов может быть нежелательно или невозможно в некоторых приложениях.

Решение

Для решения задачи можно использовать функцию LookupAccountName из WinAPI или WMI класс Win32_Account для извлечения SID. Ниже приведены примеры кода на Object Pascal, которые демонстрируют оба подхода.

Использование WinAPI LookupAccountName

program GetLocalComputerSID;
{$APPTYPE CONSOLE}
uses
  Windows,
  SysUtils;

function ConvertSidToStringSid(Sid: PSID; out StringSid: PChar): BOOL; stdcall; external 'ADVAPI32.DLL' name {$IFDEF UNICODE} 'ConvertSidToStringSidW'{$ELSE} 'ConvertSidToStringSidA'{$ENDIF};

function SIDToString(ASID: PSID): string;
var
  StringSid: PChar;
begin
  if not ConvertSidToStringSid(ASID, StringSid) then
    RaiseLastWin32Error;
  Result := string(StringSid);
  LocalFree(HLocal(StringSid));
end;

function GetLocalComputerName: string;
var
  nSize: DWORD;
begin
  nSize := MAX_COMPUTERNAME_LENGTH + 1;
  SetLength(Result, nSize);
  if not GetComputerName(PChar(Result), {var}nSize) then
  begin
    Result := '';
    Exit;
  end;
  SetLength(Result, nSize);
  SetLength(Result, Length(Result) - 1); // Убираем лишний символ в конце строки
end;

function GetComputerSID: string;
var
  Sid: PSID;
  cbSid: DWORD;
  cbReferencedDomainName: DWORD;
  ReferencedDomainName: string;
  peUse: SID_NAME_USE;
  Success: BOOL;
  lpSystemName, lpAccountName: string;
begin
  Sid := nil;
  try
    lpSystemName := '';
    lpAccountName := GetLocalComputerName;

    cbSid := 0;
    cbReferencedDomainName := 0;
    // Первый вызов к LookupAccountName для получения размеров буфера.
    Success := LookupAccountName(PChar(lpSystemName), PChar(lpAccountName), nil, cbSid, nil, cbReferencedDomainName, peUse);
    if (not Success) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) then
    begin
      SetLength(ReferencedDomainName, cbReferencedDomainName);
      Sid := AllocMem(cbSid);
      // Второй вызов к LookupAccountName для получения SID.
      Success := LookupAccountName(PChar(lpSystemName), PChar(lpAccountName), Sid, cbSid, PChar(ReferencedDomainName), cbReferencedDomainName, peUse);
      if not Success then
      begin
        FreeMem(Sid);
        Sid := nil;
        RaiseLastOSError;
      end
      else
        Result := SIDToString(Sid);
    end
    else
      RaiseLastOSError;
  finally
    if Assigned(Sid) then
      FreeMem(Sid);
  end;
end;

begin
  try
    Writeln(GetComputerSID);
  except
    on E: Exception do
      Writeln(E.Classname, ':', E.Message);
  end;
  Writeln('Нажмите Enter, чтобы выйти');
  Readln;
end.

Использование WMI класса Win32_Account

program GetWMI_Info;
{$APPTYPE CONSOLE}
uses
  SysUtils,
  ActiveX,
  ComObj,
  Variants;

function GetComputerSID: string;
const
  WbemUser := '';
  WbemPassword := '';
  WbemComputer := 'localhost';
  wbemFlagForwardOnly = $00000020;
var
  FSWbemLocator: OLEVariant;
  FWMIService: OLEVariant;
  FWbemObjectSet: OLEVariant;
  FWbemObject: OLEVariant;
  oEnum: IEnumvariant;
  iValue: LongWord;
begin
  FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
  FWMIService := FSWbemLocator.ConnectServer(WbemComputer, 'root\CIMV2', WbemUser, WbemPassword);
  FWbemObjectSet := FWMIService.ExecQuery('SELECT SID FROM Win32_Account Where SIDType=1', 'WQL', wbemFlagForwardOnly);
  oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
  if oEnum.Next(1, FWbemObject, iValue) = 0 then
  begin
    Result := FWbemObject.SID;
    Result := Copy(Result, 1, LastDelimiter('-', Result) - 1);
    FWbemObject := Unassigned;
  end;
end;

begin
  try
    CoInitialize(nil);
    try
      Writeln(GetComputerSID);
    finally
      CoUninitialize;
    end;
  except
    on E: EOleException do
      Writeln(Format('EOleException %s %x', [E.Message, E.ErrorCode]));
    on E: Exception do
      Writeln(E.Classname, ':', E.Message);
  end;
  Writeln('Нажмите Enter, чтобы выйти');
  Readln;
end.

Заключение

В данной статье были рассмотрены два способа извлечения SID компьютера в Delphi: с использованием WinAPI функции LookupAccountName и с использованием WMI класса Win32_Account. Оба подхода позволяют обойти необходимость использования стороннего инструмента PsGetSid от SysInternals. Выбор метода зависит от конкретных требований и предпочтений разработчика.

Создано по материалам из источника по ссылке.

Пользователь ищет способ идентификации SID в Delphi, избегая использования стороннего инструмента PsGetSid, и рассматривает два метода: использование функции WinAPI `LookupAccountName` и WMI класс `Win32_Account`.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Справочник по API-функциям ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2024-12-26 13:59:33/0.0033278465270996/0