# VBForums CodeBank > CodeBank - Visual Basic .NET >  Creating shared folders and specifying share permissions

## chris128

OK so I could not find a single example anywhere on the web for setting Share permissions (not NTFS permissions) from .NET code so I decided to post my own code here now that I have got it all working. There are plenty of examples for just creating shares and not specifying any permissions, and examples of how to set the permissions in C++ but not any working implementations of the relevant APIs in .NET (not that I could find anyway). Yes you can do it via WMI but personally I avoid using WMI whenever there is an alternative method so I've spent the last 2 days trying to get the various Windows APIs required to do this working from a VB.NET program... and I've finally finished it  :Smilie: 

Rather than just post the API definitions and leave it for you to figure out exactly how to use them to get the desired effect (ie to add multiple permissions, or deny permissions etc), I've created a method that you can call which will do all of the API work for you, so you can simply call this method and pass in the share name, comment, local path to the folder that is to be shared, and a list of users with the share permissions you want each of them to have  :Smilie: 

I will post the definitions in the next post but here is an example of how you can use it once you have got them:


vb Code:
'Create a list that will hold our permissions
        Dim PermissionsList As New List(Of SharePermissionEntry)
         'Create a new permission entry for the Everyone group and specify that we want to allow them Read access
        Dim PermEveryone As New SharePermissionEntry(String.Empty, "Everyone", SharedFolder.SharePermissions.Read, True)
        'Create a new permission entry for the currently logged on user and specify that we want to allow them Full Control
        Dim PermUser As New SharePermissionEntry(Environment.UserDomainName, Environment.UserName, SharedFolder.SharePermissions.FullControl, True)
         'Add the two entries declared above to our list
        PermissionsList.Add(PermUser)
        PermissionsList.Add(PermEveryone)
         'Share the folder as "Test Share" and pass in the desired permissions list
        Dim Result As SharedFolder.NET_API_STATUS = _
        SharedFolder.ShareExistingFolder("Test Share", "This is a test share", "C:\SomeFolder", PermissionsList)
         'Show the result
        If Result = SharedFolder.NET_API_STATUS.NERR_Success Then
            MessageBox.Show("Share created successfully!")
        Else
            MessageBox.Show("Share was not created as the following error was returned: " & Result.ToString)
        End If

So this example shares the folder C:\SomeFolder as "Test Share" and grants the Everyone group Read access and the currently logged on user Full Control.
*Note that this does not set NTFS permissions - just Share permissions.* If you want to set the NTFS permissions as well then look here: http://www.vbforums.com/showthread.php?p=3808272

Also note that these APIs do not seem to work on a 64 bit OS if your program is set to target 64 bit CPU - if you set your project to target x86 then it works fine on 64 bit and 32 bit OS but if you set to AnyCPU then it will only work correctly on a 32 bit OS.

----------


## chris128

_Could not post the contents here as it is too long for the post size limit, so I've attached the 2 vb files to this post._

See "Attached Files" section at the bottom of this post for my classes that make use of the NetShareAdd Windows API (and a couple of others) - just add them both to your project and then you can use my simple .NET wrapper as shown in the previous post  :Smilie:  Of course you can also just use them to see how the APIs are defined and used etc and make your own .NET versions.

*EDIT:* New version of SharedFolder class uploaded that now allows you to create a share on a remote machine. There is now an optional argument for the _SharedFolder.ShareExistingFolder_ method where you can specify the remote machine name - do not use "\\ServerName", just "ServerName" will do it.
If you want to create the share locally then just either miss this argument off or specify Nothing for it.

Here is an example of sharing the folder D:\Shared as "Shared Folder" on a remote server called TestServer:

vb Code:
SharedFolder.ShareExistingFolder("Shared Folder", "This is an example comment", "D:\Shared", PermissionsList, "TestServer")

*Note that I have included this functionality (along with a load of other Windows API based functions) in my Windows API library, which you can download for free here:*  http://cjwdev.wordpress.com/2010/07/...pack-released/

----------


## Dawg

It looks like the permission list is passed in when the folder is shared...

Any way to view/modify permissions to an existing share on a remote server?

I have about 300 users I need to add to 6 different folders. I cant do it to an upper level folder as sibling folders need different permissions, I can't create a group on the domain, I can't use "Everyone" - in fact that's what needs to be removed, and obviously I don't want to add them manually.

Thoughts?

----------


## chris128

I don't think you are talking about share permissions, it sounds like you mean NTFS permissions. Share permissions only get set on the root of the share not sub folders within the share, i.e "\\server\share" not "\\server\share\subfolder". If you want to work with NTFS permissions then see this thread: http://www.vbforums.com/showthread.php?p=3808272

----------


## Dawg

You are correct (and that application looks so much easier). Thanks.

----------


## Ginolard

Hi,

I think I was the original "inspiration" for this lovely piece of code as I was trying to figure out how to do it myself  :Wink: 

Anyway, I've finally had time to go back to the application I was creating that needed this code and I've hit a snag.

It works brilliantly if the permissions you are trying to set are for a pre-existing user.  However, my application creates a user in AD, creates the folders and then tries to share them and set the permissions.  Fairly often, this fails because AD replication hasn't taken place yet and I get the error thrown by this bit of code



```
      If SetEntriesResult = ERROR_NONE_MAPPED Then
                Throw New ApplicationException("The account " & FullAccountName & " 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")
            ElseIf SetEntriesResult <> 0 Then
                Throw New ApplicationException("The account " & FullAccountName & " could not be added to the ACL as the follow error was encountered: " & SetEntriesResult & ". The share has not been created")
            End If
```

Is there anyway of using the user's SID instead of the domain\username?  This would mean you don't have to wait for replication

----------


## Ginolard

Also...seen this?

http://blogs.msdn.com/b/helloworld/a...hare-in-c.aspx

----------


## chris128

> Also...seen this?
> 
> http://blogs.msdn.com/b/helloworld/a...hare-in-c.aspx


Yeah, that uses WMI, and I hate WMI due to its performance and reliability issues so I always choose to use Windows APIs instead if possible  :Smilie:

----------


## chris128

> Hi,
> 
> I think I was the original "inspiration" for this lovely piece of code as I was trying to figure out how to do it myself 
> 
> Anyway, I've finally had time to go back to the application I was creating that needed this code and I've hit a snag.
> 
> It works brilliantly if the permissions you are trying to set are for a pre-existing user.  However, my application creates a user in AD, creates the folders and then tries to share them and set the permissions.  Fairly often, this fails because AD replication hasn't taken place yet and I get the error thrown by this bit of code
> 
> 
> ...


I know this doesn't answer the question (I don't know the answer to that off the top of my head) but I'm assuming from your description that you are creating and sharing the user's home drive? If that's the case, generally people just set the share permissions to Everyone - Full Control and then use the NTFS permissions to actually restrict access.

----------


## Ginolard

Ah...well, I may have to use that WMI version because it's designed to use SIDs and not domain accounts.

----------


## chris128

Well the WMI stuff only calls the Windows APIs anyway... so its definitely possible using the Windows APIs directly. Also that example you posted doesn't only use the SID, it looks like it requires the user's username and the SID.
*EDIT:* In fact it actually says at the bottom of the article:



> With Windows Vista, you do not need to supply Sid. You can supply just the domain name and the user name, it will work. Using Server 2003, and most likely XP, you have to supply all three, user name, domain, and Sid.


So in fact it is the opposite of what you want - with that example you _always_ need the username.

Anyway, I just took a very quick look at the source code for my Windows API library that contains a function similar to the one I posted here and it looks pretty easy to change it to use a SID (though I haven't tested it). 

Here's where the TRUSTEE structure is created:

vb Code:
'Create a TRUSTEE structure and populate it with the user account details
            Dim Account As New ApiDefinitions.TRUSTEE
            With Account
                .MultipleTrusteeOperation = ApiDefinitions.MULTIPLE_TRUSTEE_OPERATION.NO_MULTIPLE_TRUSTEE
                .pMultipleTrustee = 0
                .TrusteeForm = ApiDefinitions.TRUSTEE_FORM.TRUSTEE_IS_NAME
                .ptstrName = FullAccountName
                .TrusteeType = ApiDefinitions.TRUSTEE_TYPE.TRUSTEE_IS_UNKNOWN
            End With
I imagine you could just change it to this:

vb Code:
'Create a TRUSTEE structure and populate it with the user account details
            Dim Account As New ApiDefinitions.TRUSTEE
            With Account
                .MultipleTrusteeOperation = ApiDefinitions.MULTIPLE_TRUSTEE_OPERATION.NO_MULTIPLE_TRUSTEE
                .pMultipleTrustee = 0
                .TrusteeForm = ApiDefinitions.TRUSTEE_FORM.TRUSTEE_IS_SID
                .ptstrName = FullAccountName
                .TrusteeType = ApiDefinitions.TRUSTEE_TYPE.TRUSTEE_IS_UNKNOWN
            End With

and then you just need to set the ptstrName property to the SID instead of the account name as I'm doing in the example above

----------


## meshrat

Hi
I've used this project to the desired folder on the network and could share it. But I want to access the folder after It was created, I change the permissions (edit or delete the permission) How can I access the permission of  that folder elsewhere in the program  or  change the permission of other users to that folder?
Many thanks to your replies

----------


## Mogge

> _Could not post the contents here as it is too long for the post size limit, so I've attached the 2 vb files to this post._
> 
> See "Attached Files" section at the bottom of this post for my classes that make use of the NetShareAdd Windows API (and a couple of others) - just add them both to your project and then you can use my simple .NET wrapper as shown in the previous post  Of course you can also just use them to see how the APIs are defined and used etc and make your own .NET versions.
> 
> *EDIT:* New version of SharedFolder class uploaded that now allows you to create a share on a remote machine. There is now an optional argument for the _SharedFolder.ShareExistingFolder_ method where you can specify the remote machine name - do not use "\\ServerName", just "ServerName" will do it.
> If you want to create the share locally then just either miss this argument off or specify Nothing for it.
> 
> Here is an example of sharing the folder D:\Shared as "Shared Folder" on a remote server called TestServer:
> 
> ...



Hi Chris

I have enjoyed to use your functions and can use them in VS 2013 without any problems - great!

I have one question - is there any way that I can check if the folder is already shared before trying to share it? I get the NERR_DuplicateShare as result and it actually mess up the share so... not good.

Thx for sharing your work - great job.

/Mogge

----------


## jeffdb27

Chris,
I really love these functions.  Great work!  I realize it has been a few years since this was developed, but I was wondering if it should accept Security Groups like Administrators as the user in SharePermissionEntry?  It throws an error for me when I try to add an entry for Domain\Administrators.  Would this be an easy mod to get it working?  Also, do you have similar routines for removing an existing share or changing the permissions on an existing share?

Thanks,
Jeff

----------

