在Lazarus / Delphi中修改文件ACL

时间:2014-07-30 09:46:23

标签: delphi winapi acl lazarus

我试图在Lazarus中运行一个函数,该函数应该将File-ACL添加到该对象的现有ACL中。显然我做错了一些:当程序到达BuildExplicitAccessWithName时程序与SIGSEGV崩溃。关于调试器,此函数直接调用BuildTrusteeWithObjectsAndName,然后导致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.

2 个答案:

答案 0 :(得分:2)

您传递pExplicitAccess,它是PEXPLICIT_ACCESS类型的未初始化指针变量。相反,您需要分配EXPLICIT_ACCESS结构,并传递其地址。

var
  ExplicitAccess: EXPLICIT_ACCESS;
....
BuildExplicitAccessWithName(@ExplicitAccess, ...);

在致电GetNamedSecurityInfo时,传递psd有点毫无意义。由于它的值为nil,因此您也可以删除传递nil。此时,您将能够删除psd变量。

对于pExistingDacl,再次将其初始化为nil。所以pExistingDacl^将成为另一个SIGSEV。相反,您应该删除pExistingDacl变量,然后传递@ExistingDacl

您对SetEntriesInAclSetNamedSecurityInfo的调用似乎有类似的问题,但希望到现在为止,您可以了解该模式并能够解决问题。

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

答案 1 :(得分:0)

在XE8中,很可能其他版本的Delphi GetNamedSecurityInfo声明错误。

解决这个问题的两种方法:

1)Redeclare as:

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