unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs,AclApi, AccCtrl, StdCtrls;
type PShareInfo2 = ^TShareInfo2; TShareInfo2 = packed record shi2_netname: PWideChar; shi2_type: DWORD; shi2_remark: PWideChar; shi2_permissions: DWORD; shi2_max_uses: DWORD; shi2_current_uses: DWORD; shi2_path: PWideChar; shi2_passwd: PWideChar; end;
const NERR_SUCCESS = 0; STYPE_DISKTREE = 0; STYPE_PRINTQ = 1; STYPE_DEVICE = 2; STYPE_IPC = 3; SHI_USES_UNLIMITED=20; ACCESS_READ = $01; //可读 ACCESS_WRITE = $02; //可写 ACCESS_CREATE = $04; //创建资源的一个实例的权限 ACCESS_EXEC = $08; //执行资源的权限 ACCESS_DELETE = $10;//删除资源的权限 ACCESS_ATRIB = $20; //修改资源属性的权限 ACCESS_PERM = $40; ACCESS_ALL = ACCESS_READ or ACCESS_WRITE or ACCESS_CREATE or ACCESS_EXEC or ACCESS_DELETE or ACCESS_ATRIB or ACCESS_PERM; //全部权限
type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end;
const SECURITY_WORLD_SID_AUTHORITY: TSidIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 1)); SECURITY_WORLD_RID = ($00000000);
const ACL_REVISION = 2; ACL_REVISION2 = 2;
advapi = 'advapi32.dll'; netapi = 'netapi32.dll';
Type ACE_HEADER = record AceType: Byte; AceFlags: Byte; AceSize: Word; end;
ACCESS_ALLOWED_ACE = record Header:ACE_HEADER; Mask:ACCESS_MASK; SidStart:DWORD; end;
ACL_SIZE_INFORMATION = record AceCount: DWORD; AclBytesInUse: DWORD; AclBytesFree: DWORD; end;
PACE_HEADER = ^ACE_HEADER;
var Form1: TForm1;
procedure BuildExplicitAccessWithNameW(pExplicitAccess: PEXPLICIT_ACCESS_W; pTrusteeName: PWideChar; AccessPermissions: DWORD; AccessMode: ACCESS_MODE; Ineritance: DWORD); stdcall; external advapi name 'BuildExplicitAccessWithNameW'; function GetNamedSecurityInfoW(pObjectName: PWideChar; ObjectType: SE_OBJECT_TYPE; SecurityInfo: SECURITY_INFORMATION; ppsidOwner, ppsidGroup: PPSID; ppDacl, ppSacl: PACL; var ppSecurityDescriptor: PSECURITY_DESCRIPTOR): DWORD; stdcall; external advapi name 'GetNamedSecurityInfoW'; function NetShareAdd(servername: PWideChar; level: DWORD; buf: Pointer; parm_err: LPDWORD): DWORD; stdcall; external netapi; function NetShareDel(servername, netname: PWideChar; reserved: DWORD): DWORD; stdcall; external netapi; function SetNamedSecurityInfoW(pObjectName: PWideChar; ObjectType: SE_OBJECT_TYPE; SecurityInfo: SECURITY_INFORMATION; ppsidOwner, ppsidGroup: PPSID; ppDacl, ppSacl: PACL): DWORD; stdcall; external advapi name 'SetNamedSecurityInfoW';
implementation
{$R *.dfm}
function SetFileAccesRights(const FileName, UserName: string; dwAccessMask: DWORD): boolean; var // SID variables snuType : SID_NAME_USE; szDomain : PChar; cbDomain: DWORD; pUserSID: Pointer; cbUserSID: DWORD; // File SD variables. pFileSD: PSECURITY_DESCRIPTOR; cbFileSD: DWORD; // New SD variables. pNewSD: PSECURITY_DESCRIPTOR; // ACL variables. p_ACL : PACL; fDaclPresent, fDaclDefaulted : LongBool; AclInfo: ACL_SIZE_INFORMATION; // New ACL variables. pNewACL : PACL; cbNewACL: DWORD; // Temporary ACE. pTempAce: Pointer; CurrentAceIndex : Cardinal; begin szDomain := nil; cbDomain := 0; pUserSID := nil; cbUserSID := 0; pFileSD := nil; cbFileSD := 0; pNewSD := nil; p_ACL := nil; pNewACL := nil; pTempAce := nil;
// // STEP 1: Get SID for given user. // Result := LookupAccountName(nil, PChar(UserName), pUserSID, cbUserSID, szDomain, cbDomain, snuType);
// API should have failed with insufficient buffer. if (not Result) and (GetLastError <> ERROR_INSUFFICIENT_BUFFER) then RaiseLastWin32Error;
pUserSID := AllocMem(cbUserSID); szDomain := AllocMem(cbDomain); try Result := LookupAccountName(nil, PChar(UserName), pUserSID, cbUserSID, szDomain, cbDomain, snuType);
if (not Result) then RaiseLastWin32Error;
// STEP 2: Get security descriptor (SD) for file. Result := GetFileSecurity(PChar(FileName), DACL_SECURITY_INFORMATION, pFileSD, 0, cbFileSD);
if (not Result) and (GetLastError <> ERROR_INSUFFICIENT_BUFFER) then RaiseLastWin32Error;
pFileSD := AllocMem(cbFileSD);
Result := GetFileSecurity(PChar(FileName), DACL_SECURITY_INFORMATION, pFileSD, cbFileSD, cbFileSD); if (not Result) then RaiseLastWin32Error;
// STEP 3: Initialize new SD. pNewSD := AllocMem(cbFileSD); // Should be same size as FileSD.
if (not InitializeSecurityDescriptor(pNewSD, SECURITY_DESCRIPTOR_REVISION)) then RaiseLastWin32Error;
// STEP 4: Get DACL from SD. if (not GetSecurityDescriptorDacl(pFileSD, fDaclPresent, p_ACL, fDaclDefaulted)) then RaiseLastWin32Error; // STEP 5: Get size information for DACL. AclInfo.AceCount := 0; // Assume NULL DACL. AclInfo.AclBytesFree := 0; AclInfo.AclBytesInUse := SizeOf(ACL);
if (fDaclPresent and Assigned(p_ACL)) then begin if (not GetAclInformation(p_ACL^, @AclInfo, SizeOf(ACL_SIZE_INFORMATION), AclSizeInformation)) then RaiseLastWin32Error;
// STEP 6: Compute size needed for the new ACL. cbNewACL := AclInfo.AclBytesInUse + SizeOf(ACCESS_ALLOWED_ACE) + GetLengthSid(pUserSID) - SizeOf(DWORD);
// STEP 7: Allocate memory for new ACL. pNewACL := AllocMem(cbNewACL);
// STEP 8: Initialize the new ACL. if (not InitializeAcl(pNewACL^, cbNewACL, ACL_REVISION2)) then RaiseLastWin32Error; // STEP 9: If DACL is present, copy it to a new DACL. if (fDaclPresent) then begin // STEP 10: Copy the file's ACEs to the new ACL. if (AclInfo.AceCount > 0) then begin for CurrentAceIndex := 0 to AclInfo.AceCount - 1 do begin // STEP 11: Get an ACE. if (not GetAce(p_ACL^, CurrentAceIndex, pTempAce)) then RaiseLastWin32Error; // STEP 12: Add the ACE to the new ACL. if (not AddAce(pNewACL^, ACL_REVISION, MAXDWORD, pTempAce, PACE_HEADER(pTempAce)^.AceSize)) then RaiseLastWin32Error; end end end;
// STEP 13: Add the access-allowed ACE to the new DACL. if (not AddAccessAllowedAce(pNewACL^, ACL_REVISION2, dwAccessMask, pUserSID)) then RaiseLastWin32Error;
// STEP 14: Set the new DACL to the file SD. if (not SetSecurityDescriptorDacl(pNewSD, True, pNewACL, False)) then RaiseLastWin32Error;
// STEP 15: Set the SD to the File. if (not SetFileSecurity(PChar(FileName), DACL_SECURITY_INFORMATION, pNewSD)) then RaiseLastWin32Error; Result := True; end; finally // STEP 16: Free allocated memory if Assigned(pUserSID) then FreeMem(pUserSID); if Assigned(szDomain) then FreeMem(szDomain); if Assigned(pFileSD) then FreeMem(pFileSD); if Assigned(pNewSD) then FreeMem(pNewSD); if Assigned(pNewACL) then FreeMem(pNewACL); end; end;
// procedure NetApiCheck(RetValue: Cardinal); begin if RetValue <> ERROR_SUCCESS then RaiseLastOSError(RetValue); end; //
function WideGetEveryoneName: WideString; var psid: PSECURITY_DESCRIPTOR; Dummy: WideString; NameLen, DomainNameLen: Cardinal; Use: SID_NAME_USE; begin Result := '';
if not AllocateAndInitializeSid(SECURITY_WORLD_SID_AUTHORITY, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, psid) then Exit; try NameLen := 0; DomainNameLen := 0; Use := 0; if LookupAccountSidW(nil, psid, nil, NameLen, nil, DomainNameLen, Use) or (GetLastError <> ERROR_INSUFFICIENT_BUFFER) then Exit;
if NameLen = 1 then Exit;
SetLength(Result, NameLen - 1); SetLength(Dummy, DomainNameLen);
if not LookupAccountSidW(nil, psid, PWideChar(Result), NameLen, PWideChar(Dummy), DomainNameLen, Use) then Result := ''; finally FreeSid(psid); end; end;
//
function DeleteShare(const ShareName: WideString): Boolean; begin Result := NetShareDel(nil, PWideChar(ShareName), 0) = NERR_Success; end;
procedure ShareDirectory(const Directory, ShareName, Description: WideString); var ShareInfo: TShareInfo2; OldAcl, NewAcl: PACL; psid: PSECURITY_DESCRIPTOR; ExplicitAccess: EXPLICIT_ACCESS_W; begin FillChar(ShareInfo, SizeOf(ShareInfo), 0); ShareInfo.shi2_netname := PWideChar(ShareName); ShareInfo.shi2_type := STYPE_DISKTREE; ShareInfo.shi2_remark := PWideChar(Description); ShareInfo.shi2_max_uses := SHI_USES_UNLIMITED; ShareInfo.shi2_path := PWideChar(Directory); NetApiCheck(NetShareAdd(nil, 2, @ShareInfo, nil));
///////////添加共享资源的访问权限,对应于对象属性页中"共享" 页中的设置
//为已共享对象分配权限
// 第1步:获取文件(夹)安全对象的DACL列表
NetApiCheck(GetNamedSecurityInfoW(PWideChar(ShareName), SE_LMSHARE, DACL_SECURITY_INFORMATION, nil, nil, @OldAcl, nil, psid)); try //第2步: 生成指定用户帐户的访问控制信息(这里指定赋予全部的访问权限)
////创建一个ACE,禁止 everyone 组成员完全控制对象,只读且不允许子对象继承此权限 FillChar(ExplicitAccess, SizeOf(ExplicitAccess), 0);
BuildExplicitAccessWithNameW(@ExplicitAccess, PWideChar(WideGetEveryoneName), GENERIC_ALL or STANDARD_RIGHTS_ALL or SPECIFIC_RIGHTS_ALL ,GRANT_ACCESS{SET_ACCESS}, SUB_CONTAINERS_AND_OBJECTS_INHERIT); //使用共享文件夹被everyone用户完全控制
//第3步: 创建新的ACL对象(合并已有的ACL对象和刚生成的用户帐户访问控制信息)
NetApiCheck(SetEntriesInAclW(1, @ExplicitAccess, OldAcl, NewAcl)); // 将新的ACE加入DACL
try //// 更新共享对象的DACL NetApiCheck(SetNamedSecurityInfoW(PWideChar(ShareName), SE_LMSHARE, DACL_SECURITY_INFORMATION, nil, nil, NewAcl, nil));
finally LocalFree(HLOCAL(NewAcl)); //释放 end;
////////////////添加文件、目录访问权限,对应于对象属性页中"安全" 页中的设置
SetFileAccesRights(Directory,'Everyone',GENERIC_ALL); SetFileAccesRights(Directory,'Guest',GENERIC_WRITE or STANDARD_RIGHTS_ALL);
finally LocalFree(HLOCAL(psid)); end;
end;
procedure TForm1.Button1Click(Sender: TObject); begin DeleteShare('test_folder2'); //取消共享 ShareDirectory('D:\test_folder2', 'test_folder2', ''); //共享文件夹 showmessage('share ok'); end;
end.
|
请发表评论