Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > ОС и железо
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 29.10.2011, 23:45
Asmoday74 Asmoday74 вне форума
Прохожий
 
Регистрация: 12.10.2010
Адрес: Челябинск
Сообщения: 22
Версия Delphi: XE2
Репутация: 893
По умолчанию Установка прав доступа к объекту в реестре

Столкнулся с такой задачей: В реестре имеется ключ, который нужно удалить. Права доступа следующие: система - read, Администраторы - read, Пользователи - read, TrustedInstaller - Full. Как я понимаю нужно стать владельцем объекта, затем установить для своего пользователя права на запись и лишь после этого удалить нужный объект. Однако столкнулся с тем что при попытке выполнения следующего кода получаю сообщение об ошибке.
Код:
function ChangeRegKeySecurity(AUser, ADomain: String; AKey: HKEY;
  APatch: String; AHideMessage: Boolean = True): Boolean;
var
  Key: HKEY;
  test: integer;
  pOwnerSid: PSid;
  lpDomain: PWideChar;
  cbDomain, cbSid: Cardinal;
  peUse: Cardinal;
  pSecDescr: PSECURITY_DESCRIPTOR;
  r: integer;
  mybuff: PWideChar;
begin
  Result := False;
  pSecDescr := PSECURITY_DESCRIPTOR
    (LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH));
  LookupAccountName(PChar(ADomain), PChar(AUser), nil, cbSid, nil,
    cbDomain, peUse);
  GetMem(pOwnerSid, cbSid);
  GetMem(lpDomain, cbDomain * SizeOf(WideChar));
  if not LookupAccountNameW(PChar(ADomain), PChar(AUser), pOwnerSid, cbSid,
    lpDomain, cbDomain, peUse) then
  begin
    if not AHideMessage then
      MessageDlg('Указанный пользователь не найден!', mtError, [mbOK], 0);
    Exit;
  end;
  if InitializeSecurityDescriptor(@pSecDescr, SECURITY_DESCRIPTOR_REVISION) then
  begin
    if SetSecurityDescriptorOwner(@pSecDescr, pOwnerSid, True) then
    begin
      //Вот тут получаем ошибку об Access Denied      
      r := RegOpenKeyEx(AKey, PWideChar(APatch), 1, KEY_ALL_ACCESS, Key); 
      if r = ERROR_SUCCESS then
      begin
        r := RegSetKeySecurity(Key, OWNER_SECURITY_INFORMATION, @pSecDescr);
        if r <> ERROR_SUCCESS then
        begin
          if not AHideMessage then
            MessageDlg(SysErrorMessage(r), mtError, [mbOK], 0);
          Exit;
        end;
        RegCloseKey(Key);
        Result := True;
      end
      else
      begin
        if not AHideMessage then
          MessageDlg(SysErrorMessage(r), mtError, [mbOK], 0);
        Exit;
      end;
    end;
  end
  else
  begin
    if not AHideMessage then
      MessageDlg('Не могу инициализировать дескриптор безопасности!', mtError,
        [mbOK], 0);
  end;
end;
.....
  ChangeRegKeySecurity('TestUser','TEST-PC',HKEY_CLASSES_ROOT,'AppID\{CDCBCFCA-3CDC-436f-A4E2-0E02075250C2}',False);

TestUser - является администратором.

Собственно вопрос с каким ключем прав доступа выполнить RegOpenKeyEx.

Последний раз редактировалось Asmoday74, 29.10.2011 в 23:48.
Ответить с цитированием
  #2  
Старый 30.10.2011, 00:13
Asmoday74 Asmoday74 вне форума
Прохожий
 
Регистрация: 12.10.2010
Адрес: Челябинск
Сообщения: 22
Версия Delphi: XE2
Репутация: 893
По умолчанию

Почитал справку от мелкософта нашел следующее:
When you call the RegOpenKeyEx function, the system checks the requested access rights against the key's security descriptor. If the user does not have the correct access to the registry key, the open operation fails. If an administrator needs access to the key, the solution is to enable the SE_TAKE_OWNERSHIP_NAME privilege and open the registry key with WRITE_OWNER access. For more information, see Enabling and Disabling Privileges.

Пробую открыть нужный раздел с правами на смену владельца, все проходит удачно.
Код:
      
r := RegOpenKeyEx(AKey, PWideChar(APatch), 1,WRITE_OWNER, Key);
Однако права владельца остаются прежними.

Функцию для установки SE_TAKE_OWNERSHIP_NAME использую такую:
Код:
function SetPrivilege(privilegeName: string; enable: boolean): boolean;
var
  tpPrev, tp: TTokenPrivileges;
  token: THandle;
  dwRetLen: DWord;
begin
  result := False;
  try
    OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,
      token); // ïполучаем маркер безопасности процесс- токен
    tp.PrivilegeCount := 1;
    if LookupPrivilegeValue(nil, pchar(privilegeName), tp.Privileges[0].LUID)
    then // получаем идентификатор привилегии - LUID
    begin
      if enable then
        tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED
        // устанавливаем атрибуты привилегии
      else
        tp.Privileges[0].Attributes := 0;
      dwRetLen := 0;
      result := AdjustTokenPrivileges(token, False, tp, SizeOf(tpPrev), tpPrev,
        dwRetLen); // включаем или отключаем привилегию
    end;
  finally
    try
      CloseHandle(token);
    except
    end;
  end;
end;
Ответить с цитированием
  #3  
Старый 30.10.2011, 00:54
Asmoday74 Asmoday74 вне форума
Прохожий
 
Регистрация: 12.10.2010
Адрес: Челябинск
Сообщения: 22
Версия Delphi: XE2
Репутация: 893
По умолчанию

Вобщем вопрос решил сам, выкладываю полностью рабочий код функций для смены прав доступа к ветке реестра. Поддержка начиная с Windows 2000.

Код:
function SetPrivilege(privilegeName: string; enable: boolean): boolean;
var
  tpPrev, tp: TTokenPrivileges;
  token: THandle;
  dwRetLen: DWord;
begin
  result := False;
  try
    OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,
      token); // пполучаем маркер безопасности процесс- токен
    tp.PrivilegeCount := 1;
    if LookupPrivilegeValue(nil, pchar(privilegeName), tp.Privileges[0].LUID)
    then // получаем идентификатор привилегии - LUID
    begin
      if enable then
        tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED
        // устанавливаем атрибуты привилегии
      else
        tp.Privileges[0].Attributes := 0;
      dwRetLen := 0;
      result := AdjustTokenPrivileges(token, False, tp, SizeOf(tpPrev), tpPrev,
        dwRetLen); // включаем или отключаем привилегию
    end;
  finally
    try
      CloseHandle(token);
    except
    end;
  end;
end;

function ChangeRegKeySecurity(AUser, ADomain: String; AKey: HKEY;
  APatch: String; AHideMessage: boolean = True): boolean;
var
  Key: HKEY;
  pOwnerSid: PSid;
  lpDomain: PWideChar;
  cbDomain, cbSid: Cardinal;
  peUse: Cardinal;
  pSecDescr: PSECURITY_DESCRIPTOR;
  r: integer;
begin
  result := False;
  pSecDescr := PSECURITY_DESCRIPTOR
    (LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH));
  LookupAccountName(pchar(ADomain), pchar(AUser), nil, cbSid, nil,
    cbDomain, peUse);
  GetMem(pOwnerSid, cbSid);
  GetMem(lpDomain, cbDomain * SizeOf(WideChar));
  if not LookupAccountNameW(pchar(ADomain), pchar(AUser), pOwnerSid, cbSid,
    lpDomain, cbDomain, peUse) then
  begin
    if not AHideMessage then
      MessageDlg('Указанный пользователь не найден!', mtError, [mbOK], 0);
    Exit;
  end;
  if InitializeSecurityDescriptor(@pSecDescr, SECURITY_DESCRIPTOR_REVISION) then
  begin
    if SetSecurityDescriptorOwner(@pSecDescr, pOwnerSid, True) then
    begin
      r := RegOpenKeyEx(AKey, PWideChar(APatch), 1,WRITE_OWNER, Key);
      if r = ERROR_SUCCESS then
      begin
        r := RegSetKeySecurity(Key, OWNER_SECURITY_INFORMATION, @pSecDescr);
        if r <> ERROR_SUCCESS then
        begin
          if not AHideMessage then
            MessageDlg(SysErrorMessage(r), mtError, [mbOK], 0);
          Exit;
        end;
        RegCloseKey(Key);
        result := True;
      end
      else
      begin
        if not AHideMessage then
          MessageDlg(SysErrorMessage(r), mtError, [mbOK], 0);
        Exit;
      end;
    end;
  end
  else
  begin
    if not AHideMessage then
      MessageDlg('Не могу инициализировать дескриптор безопасности!', mtError,
        [mbOK], 0);
  end;
end;

//Использование
procedure TForm1.Button1Click(Sender: TObject);
begin
  if not SetPrivilege('SeTakeOwnershipPrivilege', True) then
  begin
    MessageDlg('Не могу установить привилегию смены владельца!', mtError,
      [mbOK], 0);
    Exit;
  end;
  ChangeRegKeySecurity(
    'user', //Имя влядельца объекта
    'domain', //Домен или имя локального компьютера
    HKEY_CLASSES_ROOT, //Ветка рееестра
    'test', //Дополнительный путь
    False //Скрыть сообщения об ошибках
    );
end;
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 12:50.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter