2010-01-12 27 views
7

używam tego kodu, aby udostępnić folderu:Uprawnienia do folderu udostępnionego!

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 

Teraz to, co chcę jest zdefiniowanie użytkownika, który ma dostęp do tego folderu przez sieć? Jak mogę to zrobić?

Dzięki!

wpis
+1

To trochę skomplikowane, ale to powinno Ci zacząć: http://hamidshahid.blogspot.com/2009/03/adding-permissions-to- shared-folder.html – Heinzi

Odpowiedz

0

Poniżej znajduje się podobny kod NetShare, ale tym razem wszystko w języku C#. Obsługuje również poprawnie LocalFree() wskaźnika ACL; Użycie jest bardzo proste:

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."); 
     } 
    } 
} 
Powiązane problemy