Я пытаюсь написать простую функцию для окон, которая отвечает на следующий вопрос.
Имеет ли пользователь (U) права (R) на файл (F)?
Где,
R - это некоторая комбинация (GENERIC_READ, GENERIC_WRITE, GENERIC_EXECUTE)
Вы не должны входить в систему или олицетворять
Код, который я написал, показан ниже. Приложение вызывает первую отображаемую UserHasPermission.
Права доступа, возвращаемые GetEffectiveRightsFromAcl, одинаковы для всех протестированных мной комбинаций пользователь / файл ($ 001200A9). Я дважды проверил, и $ 001200A9 - это не просто указатель на место, где фактически хранятся права доступа.
У меня двоякий вопрос:
1. Есть ли лучший способ сделать это?
2. Может кто-нибудь сказать мне, где я иду не так?
function UserHasPermission(APermission: Longword; out HasPermission: Boolean; AFileName: WideString; AUserName: String; ADomainName: String): Boolean;
var
SID: PSID;
ACL: PACL;
begin
SID := nil;
ACL := nil;
try
Result := GetUserSID(SID, AUserNAme, ADomainName);
Result := Result and GetFileDACL(AFileName, ACL);
Result := Result and UserHasPermission(APermission, HasPermission, ACL, SID);
finally
Dispose(SID);
end;
end;
function UserHasPermission(APermission: Longword; out HasPermission: Boolean; AACL: PACL; AUserSID: PSID): Boolean;
var
T: TRUSTEE;
Rights: ACCESS_MASK;
begin
BuildTrusteeWithSid(@T, AUserSID);
Result := GetEffectiveRightsFromAcl(AACL, @T, @Rights) = ERROR_SUCCESS;
HasPermission := (Rights and APermission) = APermission;
end;
function GetUserSID(out ASID: PSID; AUserName: WideString; const ADomainName: WideString): Boolean;
var
NSID, NDomain: Longword;
Use: SID_NAME_USE;
DomainName: WideString;
begin
Result := False;
if Length(AUserName) > 0 then
begin
if Length(ADomainName) > 0 then
AUserName := ADomainName + '\' + AUserName;
// determine memory requirements
NSID := 0;
NDomain := 0;
LookupAccountNameW(nil, PWideChar(AUserName), nil, NSID, nil, NDomain, Use);
// allocate memory
GetMem(ASID, NSID);
SetLength(DomainName, NDomain);
Result := LookupAccountNameW(nil, PWideChar(AUserName), ASID, NSID, PWideChar(DomainName), NDomain, Use);
end;
end;
function GetFileDACL(AFileName: WideString; out AACL: PACL): Boolean;
var
SD: PSecurityDescriptor;
NSD, NNeeded: Longword;
Present, Defualted: Longbool;
begin
GetFileSecurityW(PWideChar(AFileName), DACL_SECURITY_INFORMATION, nil, 0, NNeeded);
GetMem(SD, NNeeded);
try
NSD := NNeeded;
Result := GetFileSecurityW(PWideChar(AFileName), DACL_SECURITY_INFORMATION, SD, NSD, NNeeded);
Result := Result and GetSecurityDescriptorDacl(SD, Present, AACL, Defualted);
Result := Result and Present;
finally
Dispose(SD);
end;
end;