【问题标题】:Shared folder permission!共享文件夹权限!
【发布时间】:2010-01-12 14:52:47
【问题描述】:

我使用此代码共享文件夹:

 Public Sub Share()
        Dim managementClass As New ManagementClass("Win32_Share")
        Dim inParams As ManagementBaseObject = managementClass.GetMethodParameters("Create")
        inParams("Description") = "My Description"
        inParams("Name") = "Share Name"
        inParams("Path") = "D:\Folder"
        inParams("Type") = &H0
        Dim outParams As ManagementBaseObject = managementClass.InvokeMethod("Create", inParams, Nothing)
        If Convert.ToUInt32(outParams.Properties("ReturnValue").Value) <> 0 Then MessageBox.Show("Unable to share directory.")
        MessageBox.Show("Shared folder successfully!")
    End 
Sub

现在我想要定义可以通过网络访问此文件夹的用户? 我怎么能这样做?

谢谢!

【问题讨论】:

标签: .net vb.net wmi


【解决方案1】:

这篇博文介绍了如何设置共享权限:

http://blogs.msdn.com/helloworld/archive/2008/06/06/programmatically-configuring-permissions-on-a-share-in-c.aspx

代码是C#,所以移植到VB没有问题。

【讨论】:

    【解决方案2】:

    请在下面找到类似的 NetShare 代码,但这次都是用 C# 编写的。 它还正确处理 ACL 指针的 LocalFree(); 用法很简单:

    NetShare.Add(pathToShare, shareName, description, sharePermissions);
    NetShare.DeleteIfExist(shareName);
    

    public class NetShare
    {
        #region PInvoke functions, enums and structs
    
        [DllImport("netapi32.dll")]
        private static extern NET_API_STATUS NetShareAdd(
            [In, MarshalAs(UnmanagedType.LPWStr)] string strServer,
            [In] Int32 dwLevel,
            [In] ref SHARE_INFO_502 buf,
            [Out] out uint parm_err);
    
        [DllImport("netapi32.dll")]
        private static extern NET_API_STATUS NetShareDel(
            [In, MarshalAs(UnmanagedType.LPWStr)] string strServer,
            [In, MarshalAs(UnmanagedType.LPWStr)] string netName,
            Int32 dwReserved);
    
        [DllImport("advapi32.dll", SetLastError = true)]
        private static extern bool InitializeSecurityDescriptor(
            [Out] out SECURITY_DESCRIPTOR SecurityDescriptor,
            [In] uint dwRevision);
    
        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern uint SetEntriesInAcl(
            int cCountOfExplicitEntries,
            [In] ref EXPLICIT_ACCESS pListOfExplicitEntries,
            [In] IntPtr OldAcl,
            out IntPtr NewAcl);
    
        [DllImport("advapi32.dll", SetLastError = true)]
        private static extern bool SetSecurityDescriptorDacl(
            [In] ref SECURITY_DESCRIPTOR sd, 
            [In] bool daclPresent, 
            IntPtr dacl,
            [In] bool daclDefaulted);
    
        [DllImport("advapi32.dll", SetLastError = true)]
        private static extern bool IsValidSecurityDescriptor(
            [In] ref SECURITY_DESCRIPTOR sd);
    
        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern IntPtr LocalFree(IntPtr hMem);
    
        private enum NET_API_STATUS : uint
        {
            NERR_Success = 0,
            ERROR_ACCESS_DENIED = 5,
            ERROR_NOT_ENOUGH_MEMORY = 8,
            ERROR_INVALID_PARAMETER = 87,
            ERROR_INVALID_NAME = 123,
            ERROR_INVALID_LEVEL = 124,
            ERROR_MORE_DATA = 234,
            NERR_BASE = 2100,
            NERR_UnknownDevDir = (NERR_BASE + 16),
            NERR_RedirectedPath = (NERR_BASE + 17),
            NERR_DuplicateShare = (NERR_BASE + 18),
            NERR_BufTooSmall = (NERR_BASE + 23),
            NERR_NetNameNotFound = (NERR_BASE + 210)  // Sharename not found
        }
    
        private enum SHARE_TYPE : uint
        {
            STYPE_DISKTREE = 0,
            STYPE_PRINTQ = 1,
            STYPE_DEVICE = 2,
            STYPE_IPC = 3,
            STYPE_TEMPORARY = 0x40000000,
            STYPE_SPECIAL = 0x80000000,
        }
    
        private enum SHARE_PERMISSIONS : uint
        {
            ACCESS_NONE = 0,
            ACCESS_READ = 1,
            ACCESS_WRITE = 2,
            ACCESS_CREATE = 4,
            ACCESS_EXEC = 8,
            ACCESS_DELETE = 0x10,
            ACCESS_ATRIB = 0x20,
            ACCESS_PERM = 0x40,
            ACCESS_ALL = ACCESS_READ | ACCESS_WRITE |  ACCESS_CREATE | ACCESS_EXEC | ACCESS_DELETE | ACCESS_ATRIB | ACCESS_PERM,
            ACCESS_GROUP = 0x8000
        }
    
        [StructLayout(LayoutKind.Sequential)]
        private struct SHARE_INFO_502
        {
            [MarshalAs(UnmanagedType.LPWStr)]
            public string shi502_netname;
            public SHARE_TYPE shi502_type;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string shi502_remark;
            public SHARE_PERMISSIONS shi502_permissions;
            public Int32 shi502_max_uses;
            public Int32 shi502_current_uses;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string shi502_path;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string shi502_passwd;
            public Int32 shi502_reserved;
            public IntPtr shi502_security_descriptor;
        }
    
        [Flags]
        private enum ACCESS_MASK : uint
        {
            DELETE = 0x00010000,
            READ_CONTROL = 0x00020000,
            WRITE_DAC = 0x00040000,
            WRITE_OWNER = 0x00080000,
            SYNCHRONIZE = 0x00100000,
    
            STANDARD_RIGHTS_REQUIRED = 0x000F0000,
    
            STANDARD_RIGHTS_READ = 0x00020000,
            STANDARD_RIGHTS_WRITE = 0x00020000,
            STANDARD_RIGHTS_EXECUTE = 0x00020000,
    
            STANDARD_RIGHTS_ALL = 0x001F0000,
    
            SPECIFIC_RIGHTS_ALL = 0x0000FFFF,
    
            ACCESS_SYSTEM_SECURITY = 0x01000000,
    
            MAXIMUM_ALLOWED = 0x02000000,
    
            GENERIC_READ = 0x80000000,
            GENERIC_WRITE = 0x40000000,
            GENERIC_EXECUTE = 0x20000000,
            GENERIC_ALL = 0x10000000,
    
            DESKTOP_READOBJECTS = 0x00000001,
            DESKTOP_CREATEWINDOW = 0x00000002,
            DESKTOP_CREATEMENU = 0x00000004,
            DESKTOP_HOOKCONTROL = 0x00000008,
            DESKTOP_JOURNALRECORD = 0x00000010,
            DESKTOP_JOURNALPLAYBACK = 0x00000020,
            DESKTOP_ENUMERATE = 0x00000040,
            DESKTOP_WRITEOBJECTS = 0x00000080,
            DESKTOP_SWITCHDESKTOP = 0x00000100,
    
            WINSTA_ENUMDESKTOPS = 0x00000001,
            WINSTA_READATTRIBUTES = 0x00000002,
            WINSTA_ACCESSCLIPBOARD = 0x00000004,
            WINSTA_CREATEDESKTOP = 0x00000008,
            WINSTA_WRITEATTRIBUTES = 0x00000010,
            WINSTA_ACCESSGLOBALATOMS = 0x00000020,
            WINSTA_EXITWINDOWS = 0x00000040,
            WINSTA_ENUMERATE = 0x00000100,
            WINSTA_READSCREEN = 0x00000200,
    
            WINSTA_ALL_ACCESS = 0x0000037F
        }
    
        private enum ACCESS_MODE : uint
        {
            NOT_USED_ACCESS,
            GRANT_ACCESS,
            SET_ACCESS,
            DENY_ACCESS,
            REVOKE_ACCESS,
            SET_AUDIT_SUCCESS,
            SET_AUDIT_FAILURE
        }
    
        private enum MULTIPLE_TRUSTEE_OPERATION : uint
        {
            NO_MULTIPLE_TRUSTEE,
            TRUSTEE_IS_IMPERSONATE
        }
    
        private enum TRUSTEE_FORM : uint
        {
            TRUSTEE_IS_SID,
            TRUSTEE_IS_NAME,
            TRUSTEE_BAD_FORM,
            TRUSTEE_IS_OBJECTS_AND_SID,
            TRUSTEE_IS_OBJECTS_AND_NAME
        }
    
        private enum TRUSTEE_TYPE : uint
        {
            TRUSTEE_IS_UNKNOWN,
            TRUSTEE_IS_USER,
            TRUSTEE_IS_GROUP,
            TRUSTEE_IS_DOMAIN,
            TRUSTEE_IS_ALIAS,
            TRUSTEE_IS_WELL_KNOWN_GROUP,
            TRUSTEE_IS_DELETED,
            TRUSTEE_IS_INVALID,
            TRUSTEE_IS_COMPUTER
        }
    
        [StructLayout(LayoutKind.Sequential)]
        private struct TRUSTEE
        {
            public IntPtr pMultipleTrustee;
            public MULTIPLE_TRUSTEE_OPERATION MultipleTrusteeOperation;
            public TRUSTEE_FORM TrusteeForm;
            public TRUSTEE_TYPE TrusteeType;
            [MarshalAs(UnmanagedType.LPTStr)]
            public string ptstrName;
        }
    
        [StructLayoutAttribute(LayoutKind.Sequential)]
        private struct SECURITY_DESCRIPTOR
        {
            public byte Revision;
            public byte Size;
            public ushort Control;
            public IntPtr Owner;
            public IntPtr Group;
            public IntPtr Sacl;
            public IntPtr Dacl;
        }
    
        [StructLayoutAttribute(LayoutKind.Sequential)]
        private struct EXPLICIT_ACCESS
        {
            public ACCESS_MASK grfAccessPermissions;
            public ACCESS_MODE grfAccessMode;
            public UInt32 grfInheritance;
            public TRUSTEE Trustee;
        }
    
        private const byte SECURITY_DESCRIPTOR_REVISION = 1;
        private const uint NO_INHERITANCE = 0;
        private const uint ERROR_NONE_MAPPED = 1332;
    
        private class AclPtrSafeHandle : SafeHandle
        {
            public AclPtrSafeHandle() : base(IntPtr.Zero, true) { }
    
            public override bool IsInvalid
            {
                get
                {
                    return false;
                }
            }
    
            public void Replace(IntPtr newAclPtr)
            {
                ReleaseHandle();
                this.handle = newAclPtr;
            }
    
            protected override bool ReleaseHandle()
            {
                return (IntPtr.Zero == LocalFree(this.handle));
            }
        }
    
        #endregion
    
        #region SharePermissionEntry
    
        public enum SharePermissions : uint
        {
            Read = ACCESS_MASK.GENERIC_READ | ACCESS_MASK.STANDARD_RIGHTS_READ | ACCESS_MASK.GENERIC_EXECUTE,
            FullControl = ACCESS_MASK.GENERIC_ALL
        }
    
        public class SharePermissionEntry
        {
            /// <summary>
            /// The account name in the following format: [DomainName]\[UserOrGroupName]
            /// Where DomainName that the user/group in the UserOrGroupName belongs to
            /// Where UserOrGroupName the user or group that should be granted/denied permission
            /// Note: DomainName with backslash is optional
            /// </summary>
            /// <example>
            /// Everyone
            /// REDMOND\elize
            /// AV\AVSubmit Samples RW
            /// </example>
            public readonly string AccountName;
    
            /// <summary>
            /// The share permission to grant or deny for the account in UserOrGroupName
            /// </summary>
            public readonly SharePermissions Permission;
    
            /// <summary>
            /// Set to True to allow the rights specified in the Permission property and False to deny the rights specified in the Permission property. 
            /// </summary>
            public readonly bool AllowOrDeny;
    
            /// <summary>
            /// Creates a new instance of the SharePermissionEntry class and populates each of the properties within the instance
            /// </summary>
            /// <param name="AccountName">[DomainName]\[UserOrGroupName] of username or group name that this permission entry relates to
            /// You may just pass [UserOrGroupName] if you are specifying a 'well known' identity such as the Everyone group in the AccountName argument
            /// </param>
            /// <param name="DesiredPermission">The share permission to grant/deny</param>
            /// <param name="AlloworDenyPermission">True to allow the permission, False to deny the permission</param>
            public SharePermissionEntry(string accountName, SharePermissions desiredPermission, bool alloworDenyPermission)
            {
                Guard.ArgumentNotNullOrEmptyString(accountName, nameof(accountName));
                this.AccountName = accountName;
                this.Permission = desiredPermission;
                this.AllowOrDeny = alloworDenyPermission;
            }
        }
    
        #endregion
    
        /// <summary>
        /// Shares local path with specified share name, description and permissions
        /// </summary>
        /// <param name="pathToShare">Local path to folder to share</param>
        /// <param name="shareName">Name of a shared resource</param>
        /// <param name="shareDescription">Optional comment about the shared resource</param>
        /// <param name="sharePermissions">List of share permissions to apply</param>
        /// <exception cref="Win32Exception">Will throw Win32Exception with relevant error code in case of failure</exception>
        /// <remarks>
        /// Only members of the Administrators, System Operators, or Power Users local group can add file shares with a call to the NetShareAdd function.
        /// </remarks>
        public static void Add(string pathToShare, string shareName, string shareDescription, IEnumerable<SharePermissionEntry> sharePermissions)
        {
            Guard.ArgumentNotNullOrEmptyString(pathToShare, nameof(pathToShare));
            Guard.ArgumentNotNullOrEmptyString(shareName, nameof(shareName));
            Guard.ArgumentCollectionNotEmpty(sharePermissions, nameof(sharePermissions));
            DirectoryInfo di = new DirectoryInfo(pathToShare);
            if (!di.Exists)
            {
                throw new DirectoryNotFoundException(pathToShare);
            }
            pathToShare = di.FullName.TrimEnd(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); // Remove last / or \
    
            // This pointer will hold the full ACL (access control list) once the loop below has completed
            using (AclPtrSafeHandle aclPtr = new AclPtrSafeHandle())
            {
                // Loop through each entry in our list of explicit access rules, build each one and add it to the ACL
                foreach (SharePermissionEntry spe in sharePermissions)
                {
                    // Create a TRUSTEE structure and populate it with the user account details
                    TRUSTEE account = new TRUSTEE()
                    {
                        MultipleTrusteeOperation = MULTIPLE_TRUSTEE_OPERATION.NO_MULTIPLE_TRUSTEE,
                        pMultipleTrustee = IntPtr.Zero,
                        TrusteeForm = TRUSTEE_FORM.TRUSTEE_IS_NAME,
                        ptstrName = spe.AccountName,
                        TrusteeType = TRUSTEE_TYPE.TRUSTEE_IS_UNKNOWN
                    };
                    // Populate the explicit access rule for this user/permission specified in the SharePermissions argument
                    EXPLICIT_ACCESS explicitAccessRule = new EXPLICIT_ACCESS()
                    {
                        // Set this to an Allow or Deny entry based on what was specified in the AllowOrDeny property
                        grfAccessMode = (spe.AllowOrDeny) ? ACCESS_MODE.GRANT_ACCESS : ACCESS_MODE.DENY_ACCESS,
                        // Build the access mask for the share permission specified for this user
                        grfAccessPermissions = (ACCESS_MASK)spe.Permission,
                        // Not relevant for share permissions so just set to NO_INHERITANCE
                        grfInheritance = NetShare.NO_INHERITANCE,
                        // Set the Trustee to the TRUSTEE structure we created earlier in the loop
                        Trustee = account
                    };
                    // Add this explicit access rule to the ACL
                    IntPtr newAclPtr;
                    uint setEntriesResult = SetEntriesInAcl(1, ref explicitAccessRule, aclPtr.DangerousGetHandle(), out newAclPtr);
                    aclPtr.Replace(newAclPtr);
    
                    // Check the result of the SetEntriesInAcl API call
                    if (setEntriesResult == ERROR_NONE_MAPPED)
                    {
                        throw new Win32Exception(Marshal.GetLastWin32Error(), $"The account {spe.AccountName} could not be mapped to a security identifier (SID). Check that the account name is correct and that the domain where the account is held is contactable. The share has not been created.");
                    }
                    else if (setEntriesResult != 0)
                    {
                        throw new Win32Exception(Marshal.GetLastWin32Error(), $"The account {spe.AccountName} could not be added to the ACL as the follow error was encountered: {setEntriesResult}. The share has not been created.");
                    }
                }
                // Create a SECURITY_DESCRIPTOR structure and set the Revision number
                SECURITY_DESCRIPTOR secDesc = new SECURITY_DESCRIPTOR()
                {
                    Revision = NetShare.SECURITY_DESCRIPTOR_REVISION
                };
                // Initialise the SECURITY_DESCRIPTOR instance - returns False if an error was encountered
                if (!InitializeSecurityDescriptor(out secDesc, NetShare.SECURITY_DESCRIPTOR_REVISION))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error(), "An error was encountered during the call to the InitializeSecurityDescriptor API. The share has not been created.");
                }
                // Add the ACL to the SECURITY_DESCRIPTOR
                if (!SetSecurityDescriptorDacl(ref secDesc, true, aclPtr.DangerousGetHandle(), false))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error(), "An error was encountered during the call to the SetSecurityDescriptorDacl API. The share has not been created.");
                }
                // Check to make sure the SECURITY_DESCRIPTOR is valid
                if (!IsValidSecurityDescriptor(ref secDesc))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error(), "No errors were reported from previous API calls but the security descriptor is not valid. The share has not been created.");
                }
                // Create a pointer for the SECURITY_DESCRIPTOR so that we can pass this in to the SHARE_INFO_502 structure
                IntPtr secDescPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(secDesc));
                Marshal.StructureToPtr(secDesc, secDescPtr, false);
                // Create and populate the SHARE_INFO_502 structure that specifies all of the share settings
                SHARE_INFO_502 shareInfo = new SHARE_INFO_502()
                {
                    shi502_netname = shareName,
                    shi502_type = SHARE_TYPE.STYPE_DISKTREE,
                    shi502_remark = shareDescription,
                    shi502_permissions = SHARE_PERMISSIONS.ACCESS_NONE,
                    shi502_max_uses = -1,
                    shi502_current_uses = 0,
                    shi502_path = pathToShare,
                    shi502_passwd = null,
                    shi502_reserved = 0,
                    shi502_security_descriptor = secDescPtr
                };
                // Call the NetShareAdd API to create the share
                uint parm_error = 0;
                NET_API_STATUS r = NetShareAdd(null /*localhost*/, 502, ref shareInfo, out parm_error);
                // Clean up and return the result of NetShareAdd
                Marshal.FreeCoTaskMem(secDescPtr);
                if (r != NET_API_STATUS.NERR_Success)
                {
                    throw new Win32Exception((int)r, $"An error {r} was encountered during the call to the NetShareAdd API. The share has not been created.");
                }
            }
        }
    
        /// <summary>
        /// Deletes a share name from a server's list of shared resources, disconnecting all connections to the shared resource.
        /// </summary>
        /// <param name="shareName">Name of a shared resource</param>
        /// <exception cref="Win32Exception">Will throw Win32Exception with relevant error code in case of failure</exception>
        /// <remarks>
        /// Only members of the Administrators, Server Operators, or Power Users local group, or those with Server Operator group membership, 
        /// can successfully delete file shares with a call to the NetShareDel function. 
        /// </remarks>
        public static void DeleteIfExist(string shareName)
        {
            Guard.ArgumentNotNullOrEmptyString(shareName, nameof(shareName));
            var r = NetShareDel(null /* localhost */, shareName, 0);
            if ((r != NET_API_STATUS.NERR_Success) && (r != NET_API_STATUS.NERR_NetNameNotFound))
            {
                throw new Win32Exception((int)r, "An error was encountered during the call to the NetShareDel API. The share has not been deleted.");
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2022-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多