2013-03-27 82 views
1

我们面临的问题是,不同的用户组应该能够从公共数据目录(例如c:\ ProgramData \ xyz)读取和写入文件。检查是否每个人都可以读取/写入目录

数据是从不同的来源写入的,例如,一个服务将文件写入其中,用户可以稍后更改它的内容。

现在的问题是,这只有在允许“所有人”在该目录(和子目录)中读/写/更改 文件时才有效。

我想在安装程序中检查是否允许所有用户这样做。检查“每个用户”组(或德语中的“Jeder”组)是否在访问列表中。 我只有基本的关于ACL的知识,可以在资源管理器中改变它,但是我需要几行代码,这些代码将我推向了正确的方向(在Delphi中)。

千恩万谢 麦克

+0

点击链接Alexey Dynnikov的[网页](http://www.aldyn.ru/demos/0008/1.html)。它可能会给你一些提示。 – 2013-03-27 13:19:48

+0

你实际上想做什么。推荐的做法是让安装人员在应用程序的ProgramData子文件夹中设置ACL。您不检查安装程序中的任何内容。您只需创建一个新文件夹并使用适当的权限应用ACL。 – 2013-03-27 13:23:39

+0

@david:目录已经存在 - 服务/服务器基本上是现有安装的插件。安装程序不会创建任何数据目录。 – mrabat 2013-03-27 14:37:36

回答

1

我认为这不是一个Delphi但WinAPI的问题。德尔福没有任何特殊的设施来使这个更容易的AFAIK。

Getting information from an ACL说你需要在打开的句柄上做GetSecurityInfo,然后在你得到的ACL上使用GetEffectiveRightsFromACL

您指定一个trustee,它可以是名字,但更好地使用SID。 “每个人”的名称都可以更改,但是有一个特殊的SID可以在任何PC上使用,请在Google上查看。好的,这里是:“(S-1-1-0)”。或者你可以使用CreateWellKnownSid并给它WinWorldSid以获得相同的SID(更正确但更长的方式)。

所有这些从五分钟的谷歌搜索,所以要小心错误。

好的,这里有一些代码。

function ConvertStringSidToSid(StringSid: PWideChar; var Sid: PSID): boolean; stdcall; external advapi32 name 'ConvertStringSidToSidW'; 

function AclGetEffectiveRights(const path, sid: string): cardinal; 
var h: THandle; //handle to our directory 
    err: integer; 
    dacl: PACL; //access control list for the object 
    secdesc: pointer; 
    tr: TRUSTEE; 
    bsid: PSid; 
begin 
    Result := 0; 
//Open directory 
    h := CreateFile(PChar(path), GENERIC_READ, FILE_SHARE_READ, nil, 
    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_BACKUP_SEMANTICS, 0); 
    //we need FILE_FLAG_BACKUP_SEMANTICS to open a directory 
    if h=INVALID_HANDLE_VALUE then RaiseLastOsError(); 
    try 

    bsid := nil; 
    //Query access control list for a directory -- the list you see in the properties box 
    err := GetSecurityInfo(h, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, 
     nil, nil, @dacl, nil, secdesc); 
     //GetSecurityInfo can return many things but we only need DACL, 
     //and we are required to also get a security descriptor 
    if err<>ERROR_SUCCESS then 
     raise Exception.CreateFmt('Cannot retrieve DACL: error %d',[err]); 
    try 
    //Convert string sid to binary sid 
     if not ConvertStringSidToSid(PChar(sid), bsid) then 
     RaiseLastOsError(); 

    //Query effective rights for a trustee 
     BuildTrusteeWithSid(@tr, bsid); 
     err := GetEffectiveRightsFromAcl(dacl^, tr, Result); 
     if err<>ERROR_SUCCESS then 
     raise Exception.CreateFmt('Cannot calculate effective rights: error %d',[err]); 
    finally 
    //Documentation says to free some resources this way when we're done with it. 
     LocalFree(NativeUint(bsid)); 
     LocalFree(NativeUint(secdesc)); 
    end; 
    finally 
    CloseHandle(h); 
    end; 
end; 

它这样使用:

var rights,test: cardinal; 
rights := AclGetEffectiveRights('C:\My\Folder','S-1-1-0'); 
//List rights you want tested 
test := FILE_LIST_DIRECTORY + FILE_ADD_FILE + FILE_ADD_SUBDIRECTORY 
    + FILE_READ_EA + FILE_WRITE_EA + FILE_TRAVERSE + FILE_DELETE_CHILD; 
Result := (rights and test) = test; 

可能无法正常工作;给我的电脑ACCESS_DENIED,但这可能是因为我的complicated domain situation。无论如何,这是一个开始。

+0

这就是我所使用的Google搜索引擎。但是由于我没有使用这些知识的经验,因此微软在这方面做得非常好,这样做很复杂。 – mrabat 2013-03-27 14:41:09

+0

@mrabat:好的... – himself 2013-03-28 08:13:05

+0

非常感谢! – mrabat 2013-03-28 09:18:09