在Lazarus/Delphi中修改文件ACL

在Lazarus/Delphi中修改文件ACL,delphi,winapi,acl,lazarus,Delphi,Winapi,Acl,Lazarus,我正在尝试在Lazarus中使用一个函数,该函数应该向该对象的现有ACL添加一个文件ACL。显然我做错了什么:当程序到达BuildExplicitAccessWithName时,程序会因SIGSEGV而崩溃。关于调试器,此函数调用buildTrusteeWithObjects和Name Iternaly,这将导致SIGSEGV。 我做错了什么?这是我的密码: program acltest; uses JwaWindows; function AddFileACL(Filename, Tru

我正在尝试在Lazarus中使用一个函数,该函数应该向该对象的现有ACL添加一个文件ACL。显然我做错了什么:当程序到达BuildExplicitAccessWithName时,程序会因SIGSEGV而崩溃。关于调试器,此函数调用buildTrusteeWithObjects和Name Iternaly,这将导致SIGSEGV。 我做错了什么?这是我的密码:

program acltest;

uses JwaWindows;

function AddFileACL(Filename, TrusteeName: AnsiString; AccessMode: ACCESS_MODE; Inheritance: dWord): Boolean; stdcall;
var
  pExplicitAccess : PEXPLICIT_ACCESS;
  ExistingDacl : PACL;
  pExistingDacl : PPACL;
  NewAcl : PACL;
  psd : PSECURITY_DESCRIPTOR;
begin
  NewAcl := nil;
  psd := nil;
  pExistingDacl := nil;
  Result := false;
  try
    if ERROR_SUCCESS = GetNamedSecurityInfo(pAnsiChar(Filename), SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, nil, nil, pExistingDacl, nil, psd) then
    begin
      try
        BuildExplicitAccessWithName(pExplicitAccess, PAnsiChar(TrusteeName), GENERIC_ALL, AccessMode, Inheritance);
        ExistingDacl := pExistingDacl^;
        if ERROR_SUCCESS = SetEntriesInAcl(1, pExplicitAccess, ExistingDacl, NewAcl) then
        begin
          if ERROR_SUCCESS = SetNamedSecurityInfo(pAnsiChar(Filename), SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, nil, nil, NewAcl, nil) then
          begin
            Result := true;
          end;
        end;
      finally
      end;
    end;
  finally
  end;
end;

begin
  if AddFileACL('C:\Users\keckc\Desktop\test.txt', 'Everyone', GRANT_ACCESS, SUB_CONTAINERS_AND_OBJECTS_INHERIT) = true then
  begin
    writeln('Yep, it works!');
  end
  else begin
    writeln('Nope, try again!');
  end;
end.

您传递
pExplicitAccess
,它是一个类型为
PEXPLICIT\u ACCESS
的未初始化指针变量。相反,您需要分配一个
显式访问
结构,并传递其地址

var
  ExplicitAccess: EXPLICIT_ACCESS;
....
BuildExplicitAccessWithName(@ExplicitAccess, ...);
在对
GetNamedSecurityInfo
的调用中,传递
psd
有些毫无意义。由于它的值为
nil
,您也可以删除pass
nil
。此时您可以删除
psd
变量

对于
pExistingDacl
,再次将其初始化为
nil
。因此,
pExistingDacl^
将成为另一个标志。相反,您应该删除
pExistingDacl
变量,并传递
@ExistingDacl

似乎您在调用
SetEntriesInAcl
SetNamedSecurityInfo
时遇到了类似的问题,但希望到现在为止,您能够理解模式并能够解决问题


最后,我还想知道为什么您使用的是ANSI版本的函数,而不是Unicode版本。

在XE8和其他版本的Delphi GetNamedSecurityInfo中被声明为错误

有两种解决方法:

1) 重新申报为:

   function FixedGetNamedSecurityInfo(pObjectName: LPWSTR; ObjectType: SE_OBJECT_TYPE;
         SecurityInfo: SECURITY_INFORMATION; ppsidOwner, ppsidGroup: PPSID; ppDacl, ppSacl: PPACL;
         var ppSecurityDescriptor: PSECURITY_DESCRIPTOR): DWORD; stdcall;
         external 'ADVAPI32.DLL' name 'GetNamedSecurityInfoW'; 
另一个是对使用的指针进行类型转换:

GetNamedSecurityInfo(FileObject.ToPchar, SE_OBJECT_TYPE.SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, nil, nil, PACL(@pExistingDacl), nil, pSD);

您使用的
try…finally
看起来毫无意义。另外,最后一个
if…then
可以转换为简单的赋值语句。谢谢您的回复。是的,它们有点毫无意义。我将在解决其他问题后尽快改进错误处理;-)谢谢你的回复。我已经按照你的建议修正了参数。此处需要psd,即使未使用它,因为它是函数中的强制参数。然而,它仍然拒绝工作。我已经更新了源代码以反映更改。当我运行它时,它抱怨SetEntriesInCl中的“错误参数”。您询问了SIGSEV。我没有回答吗?还是你想让我也回答这个新问题?或者,换一种说法,也许你最好就新问题问一个新问题不仅仅是因为我个人不是安全API的专家,所以虽然我可以回答SIGSEV问题,但我肯定是回答新问题的错误人选。是的,我问了为什么我有SIGSEV,是的,你回答了这个问题。非常感谢你。但我还是无法运行那个该死的东西,所以如果你也能帮我解决这个问题,那就太好了。好吧,我没注意到你在我打字时编辑了你的最后一条评论;-)我想我会编辑我的问题,这样它也会反映“新问题”。无论如何,谢谢你的努力!老实说,这不是我的专长。如果我是你,我会问一个新问题。我真的认为你不应该在这里问这个新问题。为它提出一个新问题。请