На страже файлов Фленов Михаил Хакер, номер #094, стр. 094-126-2 // выделяем память sidValue := AllocMem(sidLength); domain1 := AllocMem(sidLengthDomain); // получаем SID if (LookupAccountName(nil, 'everyone', sidValue, sidLength, domain1, sidLengthDomain, sidType)=false) then exit; Все эти функции мы рассматривали в августе этого года. Сочувствую тем, кто в это время отдыхал на море и пропустил выпуск этого номера. Назад в будущее Теперь определяем текущую информацию безопасности файла с помощью GetNamedSecurityInfo и ACL-информацию с помощью GetAclInformation. Эти функции мы использовали в прошлом номере. Можешь взять код один к одному и даже оставить старую форму главного окна для выбора файла. Получив информацию о текущем списке, необходимо выделить память под новый список. Как рассчитать новый размер? Все достаточно просто. У нас есть размер текущего списка в поле AclBytesInUse структуры AclInfo. Эту структуру мы получили после вызова функции GetAclInformation. К этому размеру мы добавляем размер разрешающей структуры ACCESS_ACE и размер SID идентификатора пользователя, которого мы хотим внести в список: newSize:=AclInfo.AclBytesInUse + sizeof(ACCESS_ACE) + GetLengthSid(sidValue); В файле справки из этого результата еще вычитается размер DWORD, но я этого не делаю, и у меня пример прекрасно работает. Если будут проблемы, то попробуй изменить строку так: newSize:=AclInfo.AclBytesInUse + sizeof(ACCESS_ACE) + GetLengthSid(sidValue)-sizeof(DWORD); Теперь выделяем память для нового ACL-списка и инициализируем его: pNewDACL:=PACL(LocalAlloc(LPTR, newSize)); if not InitializeAcl(pNewDACL^, newSize, 2) then exit; Для инициализации используется функция InitializeAcl, которая выглядит следующим образом: function InitializeAcl( var pAcl: TACL; nAclLength, dwAclRevision: DWORD ): BOOL; stdcall; Функция получает в качестве параметра три значения: - указатель на выделенную для списка память; - размер списка; - ревизия, которая должна быть равна ACL_REVISION для данной версии Windows. Мы будем использовать последнюю ревизию ACL_REVISION, которая равна 2, но если указать 1, то ошибки не должно быть. В старых версиях окон лучше не экспериментировать, а сразу указывать первую версию, то есть единицу. Я не проверял, но, возможно, при других значениях работа примера окажется неверной. Заполняем список Теперь запускаем цикл перебора всех записей и копируем их в новый список, чтобы ничего не потерять: for i:=0 to aclInfo.AceCount-1 do begin // получаем текущую запись if not (GetAce(pDACL^, i, Pointer(ace))) then continue; // добавляем ее в новый список if not AddAce(pNewDACL^, 2, MAXWORD, ace, ace.Header.AceSize) then continue; end; Цикл очень прост. Сначала пытаемся получить текущую запись. Если неудачно, то плюем на нее и переходим на следующий шаг записи. Если ACE получена, то добавляем ее в новый список с помощью функции AddAce, которая в общем виде выглядит так: function AddAce( var pAcl: TACL; dwAceRevision, dwStartingAceIndex: DWORD; pAceList: Pointer; nAceListLength: DWORD ): BOOL; stdcall; Тут у нас 5 параметров: |