在Lazarus/Delphi中修改文件ACL
我正在尝试在Lazarus中使用一个函数,该函数应该向该对象的现有ACL添加一个文件ACL。显然我做错了什么:当程序到达BuildExplicitAccessWithName时,程序会因SIGSEGV而崩溃。关于调试器,此函数调用buildTrusteeWithObjects和Name Iternaly,这将导致SIGSEGV。 我做错了什么?这是我的密码:在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
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
,您也可以删除passnil
。此时您可以删除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,是的,你回答了这个问题。非常感谢你。但我还是无法运行那个该死的东西,所以如果你也能帮我解决这个问题,那就太好了。好吧,我没注意到你在我打字时编辑了你的最后一条评论;-)我想我会编辑我的问题,这样它也会反映“新问题”。无论如何,谢谢你的努力!老实说,这不是我的专长。如果我是你,我会问一个新问题。我真的认为你不应该在这里问这个新问题。为它提出一个新问题。请