• [原创]delphi在win7下创建共享文件夹源代码


    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: est_folder2', 'test_folder2', ''); //共享文件夹
    showmessage('share ok');
    end;

    end.

  • 相关阅读:
    树状数组&线段树
    8月7日小练
    8月6日小练
    LID&LDS 的另外一种算法
    LCS,LIS,LCIS
    8-11-Exercise
    8-10-Exercise
    线段树
    8-7-Exercise
    8-6-Exercise
  • 原文地址:https://www.cnblogs.com/yzryc/p/delphi_share_dir.html
Copyright © 2020-2023  润新知