【问题标题】:How to get permission level of a folder?如何获取文件夹的权限级别?
【发布时间】:2011-10-17 23:59:43
【问题描述】:

如果需要管理员权限级别(使用Delphi),我想检测一个文件夹。有可能吗?

我写了这段代码。这正是我想要的。但我想使用 Windows 标准函数来做到这一点。

// 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');

【问题讨论】:

  • 为什么投反对票?我的问题有什么问题吗?请帮我解决它:)
  • 这个问题无法回答。它太不精确了。 “需要管理员权限级别”做什么?阅读?来写?删除?等等。您能否解释一下为什么需要检测这一点,因为可能有更好的解决方案。
  • 我猜这在非英语操作系统上会失败。最好测试GetLastError=ERROR_ACCESS_DENIED
  • 您如何理解需要管理员权限的结论?失败可能还有其他原因。
  • 您必须使用GetFileSecurity 函数来检索有关目录安全性的信息msdn.microsoft.com/en-us/library/aa446639%28VS.85%29.aspx

标签: delphi permissions windows-7 administrator


【解决方案1】:

以下示例翻译自this article。它可用于确定文件或目录是否具有每个用户在that article 中注意到的访问权限,因此如果我要求 FILE_ALL_ACCESS 则意味着每个人都具有对所需文件或目录的完全访问权限。请注意,在下面的代码中没有异常处理,我什至不记得我上次使用 VB 是什么时候,所以可能是错误的,所以以此为灵感,随时修改这篇文章。

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;


在 64 位 Windows 7 Enterprise SP 1 上使用 Delphi 2007


无论如何,下载JEDI Windows Security Code Library 并按照this one 之类的示例会更容易(我希望它也适用于目录,但我很确定它会)。

【讨论】:

    【解决方案2】:

    上面例子的小改动,对于那些已经迁移到 Delphi XE2 及更高版本的人(Token 不再与 Cardinal 一起使用,必须是 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;
    

    【讨论】:

      猜你喜欢
      • 2021-09-05
      • 1970-01-01
      • 2020-09-06
      • 2014-05-04
      • 1970-01-01
      • 2011-12-27
      • 2011-08-11
      • 2016-04-14
      • 2013-10-17
      相关资源
      最近更新 更多