FUNCTION CheckAccessToFile(DesiredAccess: DWORD;
CONST FileName: WideString): BOOLEAN;
CONST
GenericFileMapping: TGenericMapping = (
GenericRead: FILE_GENERIC_READ;
GenericWrite: FILE_GENERIC_WRITE;
GenericExecute: FILE_GENERIC_EXECUTE;
GenericAll: FILE_ALL_ACCESS
);
VAR
LastError: DWORD;
LengthNeeded: DWORD;
SecurityDescriptor: PSecurityDescriptor;
ClientToken: THandle;
AccessMask: DWORD;
PrivilegeSet: TPrivilegeSet;
PrivilegeSetLength: DWORD;
GrantedAccess: DWORD;
AccessStatus: BOOL;
BEGIN
Result := False;
LastError := GetLastError;
IF NOT GetFileSecurityW(PWideChar(FileName), OWNER_SECURITY_INFORMATION
OR
GROUP_SECURITY_INFORMATION
OR DACL_SECURITY_INFORMATION,
nil, 0, LengthNeeded)
AND
(GetLastError <> ERROR_INSUFFICIENT_BUFFER)
THEN
Exit;
SetLastError(LastError);
Inc(LengthNeeded, $1000);
SecurityDescriptor := PSecurityDescriptor(LocalAlloc(LPTR, LengthNeeded));
IF NOT Assigned(SecurityDescriptor)
THEN
Exit;
TRY
IF NOT GetFileSecurityW(PWideChar(FileName), OWNER_SECURITY_INFORMATION
OR
GROUP_SECURITY_INFORMATION
OR DACL_SECURITY_INFORMATION,
SecurityDescriptor, LengthNeeded, LengthNeeded)
THEN
Exit;
IF NOT ImpersonateSelf(SecurityImpersonation)
THEN
Exit;
TRY
IF NOT OpenThreadToken(GetCurrentThread, TOKEN_QUERY
OR
TOKEN_IMPERSONATE
OR TOKEN_DUPLICATE, False, ClientToken)
THEN
Exit;
TRY
AccessMask := DesiredAccess;
MapGenericMask(AccessMask, GenericFileMapping);
PrivilegeSetLength := SizeOf(TPrivilegeSet);
IF AccessCheck(SecurityDescriptor, ClientToken, AccessMask,
GenericFileMapping, PrivilegeSet, PrivilegeSetLength,
GrantedAccess, AccessStatus)
THEN
Result := AccessStatus;
FINALLY
CloseHandle(ClientToken);
END;
FINALLY
RevertToSelf;
END;
FINALLY
LocalFree(HLOCAL(SecurityDescriptor));
END;
//Möglicher Aufruf
//procedure TForm1.Button1Click(Sender: TObject);
//begin
// if OpenDialog1.Execute then
// ShowMessage(BoolToStr(
// CheckAccessToFile(GENERIC_WRITE, // check for generic write access
// OpenDialog1.FileName), True) + ': ' + SysErrorMessage(GetLastError));
//end;
END;