// stuff Delphi might not know...
const
FILE_READ_DATA = $0001;
// file & pipe
FILE_LIST_DIRECTORY = $0001;
// directory
FILE_WRITE_DATA = $0002;
// file & pipe
FILE_ADD_FILE = $0002;
// directory
FILE_APPEND_DATA = $0004;
// file
FILE_ADD_SUBDIRECTORY = $0004;
// directory
FILE_CREATE_PIPE_INSTANCE = $0004;
// named pipe
FILE_READ_EA = $0008;
// file & directory
FILE_WRITE_EA = $0010;
// file & directory
FILE_EXECUTE = $0020;
// file
FILE_TRAVERSE = $0020;
// directory
FILE_DELETE_CHILD = $0040;
// directory
FILE_READ_ATTRIBUTES = $0080;
// all
FILE_WRITE_ATTRIBUTES = $0100;
// all
FILE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED
or SYNCHRONIZE
or $1FF;
FILE_GENERIC_READ = STANDARD_RIGHTS_READ
or FILE_READ_DATA
or FILE_READ_ATTRIBUTES
or FILE_READ_EA
or SYNCHRONIZE;
FILE_GENERIC_WRITE = STANDARD_RIGHTS_WRITE
or FILE_WRITE_DATA
or FILE_WRITE_ATTRIBUTES
or FILE_WRITE_EA
or
FILE_APPEND_DATA
or SYNCHRONIZE;
FILE_GENERIC_EXECUTE = STANDARD_RIGHTS_EXECUTE
or FILE_READ_ATTRIBUTES
or FILE_EXECUTE
or SYNCHRONIZE;
(**)
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;
end;
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;