I want to detect a folder, if needs Administrator privilege level (using Delphi
). Is it possible?
I wrote this Code. This is what exactly I 开发者_开发知识库want. But I want to do this using Windows standard functions.
// Check if You need Administrator-level access to create a folder
try
mkdir(SDirectory + '\~TEST');
except
on E: exception do
begin
if E.message = 'File access denied' then
begin
MessageBox(self.Handle,
'You need Administrator-level access to create this folder', '', MB_ICONERROR);
exit;
end;
end;
end;
RmDir(SDirectory + '\~TEST');
The following example is translated from this article. It can be used for determination if the file or directory has the access rights noticed in that article for every user, so if I ask for FILE_ALL_ACCESS then it means that everyone has the full access to the desired file or directory. Note that in the following code there's no exception handling and that I can't even remember when I've used VB last time so it might be wrong so take this as an inspiration and feel free to modify this post.
const
FILE_READ_DATA = $0001;
FILE_WRITE_DATA = $0002;
FILE_APPEND_DATA = $0004;
FILE_READ_EA = $0008;
FILE_WRITE_EA = $0010;
FILE_EXECUTE = $0020;
FILE_READ_ATTRIBUTES = $0080;
FILE_WRITE_ATTRIBUTES = $0100;
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);
FILE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED or SYNCHRONIZE or $1FF;
function CheckFileAccess(const FileName: string; const CheckedAccess: Cardinal): Cardinal;
var Token: Cardinal;
Status: LongBool;
Access: Cardinal;
SecDescSize: Cardinal;
PrivSetSize: Cardinal;
PrivSet: PRIVILEGE_SET;
Mapping: GENERIC_MAPPING;
SecDesc: PSECURITY_DESCRIPTOR;
begin
Result := 0;
GetFileSecurity(PChar(Filename), OWNER_SECURITY_INFORMATION or GROUP_SECURITY_INFORMATION or DACL_SECURITY_INFORMATION, nil, 0, SecDescSize);
SecDesc := GetMemory(SecDescSize);
if GetFileSecurity(PChar(Filename), OWNER_SECURITY_INFORMATION or GROUP_SECURITY_INFORMATION or DACL_SECURITY_INFORMATION, SecDesc, SecDescSize, SecDescSize) then
begin
ImpersonateSelf(SecurityImpersonation);
OpenThreadToken(GetCurrentThread, TOKEN_QUERY, False, Token);
if Token <> 0 then
begin
Mapping.GenericRead := FILE_GENERIC_READ;
Mapping.GenericWrite := FILE_GENERIC_WRITE;
Mapping.GenericExecute := FILE_GENERIC_EXECUTE;
Mapping.GenericAll := FILE_ALL_ACCESS;
MapGenericMask(Access, Mapping);
PrivSetSize := SizeOf(PrivSet);
AccessCheck(SecDesc, Token, CheckedAccess, Mapping, PrivSet, PrivSetSize, Access, Status);
CloseHandle(Token);
if Status then
Result := Access;
end;
end;
FreeMem(SecDesc, SecDescSize);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if CheckFileAccess('C:\Windows', FILE_ALL_ACCESS) = FILE_ALL_ACCESS then
ShowMessage('C:\Windows has full access for everyone')
else
ShowMessage('Someone has no full access to C:\Windows');
end;
with Delphi 2007 on 64-bit Windows 7 Enterprise SP 1
Anyway much more easier would be to download JEDI Windows Security Code Library and follow the example like this one (I hope it works also for directories but I'm pretty sure it will).
Small change on the example above, for those who have moved to Delphi XE2 and up (Token no longer works with Cardinal, has to be THandle).
function getFileAccess(...):Cardinal;
var
Token: THandle;//No longer Cardinal
begin
{ ... code ...}
if GetFileSecurity({...params...}) then
begin
//... more stuff
OpenThreadToken(GetCurrentThread,TOKEN_QUERY,false,Token);
if Token<>0 then
begin
//... more stuff
AccessCheck(SecDesc,Token,CheckedAccess,Mapping,PrivSet,PrivSetSize,Access,Status);
CloseHandle(Token);
//... more stuff
end;
end;
//....more stuff
end;
精彩评论