How do we change permissions on a share as fast as Explorer does it?


A customer wanted to know what they could do to speed up changing permissions on a share.

We have a large share (over 50,000 files in over 5000 folders). If we have four or five users with access to the share, and we add one more user, it takes around two minutes. If we have a hundred users and add one more, it takes around seven minutes. Here's the code we are using to add a user:

// Get the current ACL on the directory.
var info = new DirectoryInfo(sharePath);
var security = info.GetAccessControl(AccessControlSections.Access);

// Create a new rule that grants the user read access.
var rule = new FileSystemAccessRule(user,
    FileSystemRights.Read | FileSystemRight.Synchronize,
    InheritanceFlags.ContainerInherit |
    InheritanceFlags.ObjectInherit,
    PropagationFlags.None,
    AccesControlType.Allow);

// Add the rule to the existing ACL.
security.AddAccessRule(rule);
security.SetAccessRuleProtection(true, false);

// Set the modified ACL back on the directory.
info.SetAccessControl(security);

What can we do get this code to perform as well as Explorer?

One suggestion was to create a security group that encompasses the people who have access to the share. The job of controlling who has access to the share is now delegated to the security group. When you need to grant Bob access to the share, you merely add Bob to the security group. When you decide that Bob no longer has access, you remove him from the group.

The customer liaison replied, "The customer cannot use this workaround. How can they improve their code so it is as fast as Explorer?"

We were unable to figure out exactly why the customer refused to use security groups. Whenever we asked, the customer merely changed the subject and asked how to get their code to be as fast as Explorer.

I stepped in and pointed out the obvious:

The customer's code is not doing what they claim they are doing. They claim to be changing share permissions, but the code is actually changing directory permissions.

To change share permissions, use Get­Named­Security­Info to read the existing permissions on the share and Set­Named­Security­Info to change the permissions. There doesn't appear to be a BCL class for doing this, so you may need to pinvoke to the underlying Win32 functions, then use Object­Security.Set­Security­Descriptor­Binary­Form to convert it into something you can manipulate more easily.

That was the last we heard from the customer, so it's not clear whether they gave up and decided that we weren't being helpful, or whether the tap on the shoulder was enough to clue them in to why their comparison was a false one. I don't know whether they took any of our advice to put the security information in a security group, but I suspect they didn't.

Comments (37)
  1. Joshua says:

    I have the exact same issue. For some reason the managed code is really slow compared to setting folder permissions in explorer. One of these days I'm gonna disassemble it and find out why.

  2. Wyatt says:

    Theory: They probably didn't want to use security groups because they were doing this to a network share, which they had permissions to do, but they didn't have permissions from their IT overlords to modify group membership in AD (normal), and didn't want to deal with IT every time they needed to add a user.

  3. Well, you mistreated a customer.

    Per my experience, when you tell customers a workaround, if you don't tell them why you don't give them the solution, they think you are up to no good. (At lest say "Not equally fast? Strange!") Worse, if there is a conspiracy theory concerning you abound, the customer suddenly switches from laughing at it to considering it. Suppose your customer had heard that Microsoft and Windows 10 are spying on people...

    You should have at least inquired whether what they do with Explorer is changing the folder permission.

    [I explained to them that what they are doing in Explorer is changing share permissions, not directory permissions. If they want to be as fast as Explorer, then they should do what Explorer does. Instead of changing directory permissions, they should change share permissions. -Raymond]
  4. John says:

    Now I wonder why they didn't think of the obvious solution: Launch Explorer and do some PostMessage(... WM_KEYDOWN/KEYUP/LBUTTONDOWN ...) to automate adding the user to the share via Explorer.

  5. Peter says:

    If I had to guess, I'd say that the customer is deploying their software inside *their* customer's environment, so changing anything in active directory is a complete non-starter.

  6. James Sutherland says:

    Creating groups may indeed be something they lack the access rights to do, as suggested above, and they wouldn't want to admit to MS that they don't have control of their company infrastructure.

    Some years ago I moonlighted doing support for another department (not my official job title, but that department managed to fall out with the actual IT department to the extent they had to get support elsewhere); I put in a request for an external mailing list, so they could add all the students on an international course they were running. A month later, I was given the details for the internal-only mailing list they'd created for me. (I've moved since then; the new place is on Office 365, which also seems to have no user-level shared list facilities; if I get really bored one day, I might write a plugin to remedy that and save us having to cut/paste a list of email addresses from our internal Wiki any time we have a research group announcement.)

  7. wqw says:

    @Wyatt: You create *local* group to the server the share is located, add users/groups from AD to it and grant permissions to this local group. There are no AD overlords involved per se.

  8. > security.SetAccessRuleProtection(true, false);

    I suspect the "false" is the problem... it's probably explicitly touching every subfolder and file rather than just setting the ACL on the parent folder and then letting everything else inherit it from there.

    msdn.microsoft.com/.../system.security.accesscontrol.objectsecurity.setaccessruleprotection%28v=vs.110%29.aspx

    > preserveInheritance

    > Type: System.Boolean

    > true to preserve inherited access rules; false to remove inherited access rules. This parameter is ignored if isProtected is false.

  9. Ian Boyd says:

    Using a group. That's actually a good note. I've dealt with programming ACLs, and I knew that everything cascades every time.

    Just the group. Much better.

  10. q says:

    Another issue with using a group is that the change takes unknown time to propagate and the user needs to log on again in order to get an authentication token with the new group membership.

  11. Adam M. says:

    Does it take Explorer 2 minutes to change parent directory permissions, going from 4 to 5 users, with 50,000 descendant files, when the ACL specifies that the changes are supposed to be inherited from the parent directory? That would surprise me. (Does inheritance work by altering every descendant rather than the permission check testing ancestors?) If Explorer doesn't take 2 minutes, then I think they still have a legitimate question: why doesn't the .NET API perform very well? I realize I could test it myself by creating 50,000 files, but maybe you know off-hand how the inheritance works.

  12. Adam M. says:

    Also, I think it's possible you misinterpreted their question. It's not completely clear that saying that they're adding users to the share implies they were making a false comparison with Explorer. IIRC, users must be given access to both the share and the underlying directory, so changing directory permissions is part of the process of granting access to a share (if you don't use groups). Perhaps the talk of shares was completely irrelevant...

  13. DWalker says:

    Changing DIRECTORY and maybe file permissions through Explorer definitely can take several minutes, depending on what you click.  If you explicitly re-set all child permissions, you can watch the fancy animation while Explorer touches all of the files in all of the subfolders.

  14. dave says:

    re: Adam M.

    (Does inheritance work by altering every descendant rather than the permission check testing ancestors?)

    Yes. The design tradeoff is propagating the changed ACL at the time the ACL changes, or consulting a tree of ACLs at the time you want to open the file.  The decision is in favour of file opening: there is just one ACL to look at.

  15. Tim! says:

    @dave: Are you entirely sure that Windows doesn't consult an ACL tree structure?  A full ACL list is an awful lot of metadata to attach to every single file.

  16. dave says:

    @Tim!  

    Yes, I'm sure.  As corroborating evidence, note that it takes a significant amount of time to flow the addition of an ACE down a large directory tree. If that ACE were only added to the root of the tree, it would take almost no time.

    Actually, 'tree' was the wrong word, given that a file system is a directed graph (hopefully acyclic), not a tree.  A given file can be catalogued in more than one directory.

    Consider also open-by-file-id.  I don't think the file has backlinks to every directory it's catalogued in, so it would be impossible to check inherited permissions in that case.

    [Also: Hard links allow a file to appear in multiple directories at once. -Raymond]
  17. dave says:

    re: hard links:

    Yes, that's what I meant by the para about the file system not being a tree but a DAG.  

  18. @Raymond:

    — "I explained to them that what they are doing [...]"

    You most probably became the straw that broke the camel's back. The customer was probably using the word "share" metonymically, because they have written a fully working code AND seem to be getting their intended result, except with sub-optimal performance.

    But the problem part is this:

    — "Whenever we asked, the customer merely changed the subject and asked how to get their code to be as fast as Explorer"!

    It implies that you (second person plural) had asked more than once; for all he knows, it is you (second person plural) who kept changing the subject and evaded giving the solution for no reason. Have you noticed? Your blog post title reads "How do we change permissions on a share as fast as Explorer does it?" but it is not talking about this subject.

    I envy your job security though. You don't seem to be getting a pay deduction or a pink slip with your pay check for this behavior; you even get to brag about it in the company-hosted blog.

  19. Yukkuri says:

    Did someone urinate in Fleet Command's breakfast cereal today or what? The only inappropriate thing on this blog post is your laughable instance that Raymond needs to be fired.

  20. Voo says:

    @Fleet Command: Yeah totally unanswered question, apart from the whole paragraph detailing which APIs explorer uses. Clearly only a genius could figure out what explorer does from "ususe Get­Named­Security­Info to read the existing permissions on the share and Set­Named­Security­Info to change the permissions".

    But then you seem to be thinking that just answering questions instead of actually solving the customers problem is the right thing to do, which is a much bigger problem than the missing reading comprehension... Much easier though.

  21. Gabe says:

    Adam M.: I believe that at one point they considered making inherited permissions work by walking the tree and testing ACLs, but that doesn't work across network mount points. The server doing the access check would go up to the root of the volume containing the share, while the user would expect the access check would go up to the root of whatever volume contains the mount point.

    Tim!: Since Win2k, each distinct security descriptor (the owner, group, SACL, and DACL) is stored in a single place in a file called $Secure that has an index of every SD on the volume. When multiple files have the same SD, they both have pointers to the same entry in $Secure. Since most files share their SD with other files on the disk, this saves lots of space. See http://www.ntfs.com/ntfs-permissions-security-descriptor.htm for more details.

    dave: Files do know their names. The MFT record for a file contains an attribute entry for each name (a.k.a hard link) that the file has, and each FILE_NAME attribute contains a pointer to the parent directory. So you can open a file by ID and still find out its name in each directory it's hard linked to. See msdn.microsoft.com/.../bb470123(v=vs.85).aspx

  22. cheong00 says:

    I suspect if the access to every subdirectories in there is the same, do the first folder once and then use GetFileSecurity() once and SetFileSecruity() to all other folders will shorten the time required.

    Of course the SetFileSecurity() has some permission condition to satisfy in order to success, but since the customer is using the program themselves and the task is repetitive task, they need set it once only.

  23. @Voo:

    — "But then you seem to be thinking that just answering questions instead of actually solving the customers problem is the right thing to do."

    Well, neither the question is answered nor the problem is solved. The problem was low performance. Microsoft offered a non-feasible workaround and split hair over the definition of "share".

  24. Paul says:

    @Fleet Command

    Oh come on, File Permissions and Share Permissions are entirely different things and any network administrator should know the difference between the two, calling that splitting hairs is being disingenuous to say the least.

    The customer wanted to know how to make changing share permissions happen as fast as explorer did, telling them to change the share permissions rather than file permissions so it is doing the same as explorer is doing *is* answering their questions in regards to performance.

    If they meant file permissions they should have said that, however they also received a valid workaround in the suggestion to use groups (a local group would suffice if it was a network admin thing preventing domain groups being used) and the suggested APIs to use would also have been a valid solution to their question.

    The customer either asked the wrong question or came up with the wrong answer themselves for the question they asked, being told the correct approach to solve their question sounds like an appropriate answer to me. You seem to be under the impression that MS should have answered a different question to the one that was asked and it is their fault for not making the correct assumption despite the customer never properly clarifying if they meant File or Share permissions.

  25. Neil says:

    The problem with the file not knowing the ACL is that you have to go find it. The problem with the file knowing the ACL is that you have to keep it up-to-date. Most of the time, you're not changing the ACL, so you optimise for the former case.

    Novell Netware gave the impression of using the latter strategy, although rather than storing the ACL as a property of the ancestor directory I think it kept a separate list (which conveniently allowed you to query a volume for all of its ACLs).

  26. þ says:

    @Paul: Maybe, maybe not. But here, the old adage "pot calling the kettle black" comes to mind. Microsoft itself is a company that uses many definition wrong:

    * "Boot volume", in Microsoft definition, is not volume on which boot files reside.

    * "System volume" is not the volume on which %systemroot% resides.

    * "Hypervisor" is consistently called "Virtual Machine" by mistake, even though the hypervisor is called "Hyper-V".

    * Something branded as "Windows 2000 SDK" includes a compiler for x64 while Windows 2000 did not have an x64 edition.

    * "Multi-targeting pack" only targets a single version of CLR, not multiple.

    * What Microsoft calls a "Windows Store app" (others call Metro-style app or Modern app) can come from outside Windows Store; and Windows Store sells both traditional desktops and the new Metro apps.

    * Microsoft consistently calls wrong things "x86" instead of "IA-32" or worse, "ARM"! (Not to mention that they don't seem to know that "x64" is actually an extension of "x86".)

    * "CAPCHA" in Microsoft is called "HIPS".

    * Instead if "the Mail app", they write "Mail app", and instead of "Active Directory, the directory service" they write "Active Directory directory service" every time.

    * Things that one usually finds in "My Document" folder is frequently neither "my" (i.e. not made by users) nor "document" (i.e. cryptic app data).

    * Windows 8 and later by mistake say "sign in" when they mean "log in".

    And yet this company permits itself to preach what's share permission?

  27. Grarl says:

    @Fleet Command: If the question asked is "How do we do A as fast as Explorer does it?", it's a perfectly reasonable response to point out "but you're not even doing A, you're doing B, which is a different operation entirely and is slower by its very nature".

    [Exactly. The customer asked "How can we do X as fast as Explorer?" and we said, "Explorer isn't doing X at all. Explorer is doing Y. You should do Y if you want to be as fast as Explorer. But understand that X and Y are different things, so don't expect doing Y to be identical to doing X." -Raymond]
  28. DWalker says:

    @Grarl:  You are spot on with your rephrasing: "you're not even doing A, you're doing B, which is a different operation entirely and is slower by its very nature".  

  29. @Grarl: "Reasonable" is not one of terms of my employment. It is not logic exam or a TV competition. Customers call, say all the wrong things, and ask for the most unreasonable things. We're a team of three; we have the window of opportunity of exactly one reply to either turn that annoyed person into a satisfied person that feels we got him/her covered. So, read between the line, read his mind, or date his wife; just make sure the job is done.

    In this case, you can answer both "how to do A" and "how to do B" in one message.

  30. @Fleet Command: I think it's a little silly to assume that the actual interaction with the customer went exactly how Raymond describes it in his post, though.  This blog is for entertainment purposes, after all (Mr. Chen's entertainment first and foremost), so naturally things are paraphrased, reworded, and exaggerated.  Also it doesn't sound like Raymond (or anyone else in the R&D group for that matter) interacts directly with the customer at all and instead goes through customer liaisons.  The company I work at has a very similar support structure, which allows us to discuss internal implementations and the like in the e-mail thread without worrying that any of that information goes to the customer.  It also prevents an engineer from insulting their customer without realizing it.

  31. Darran Rowe says:

    @MNGoldenEagle:

    There is also the important thing of older blog posts which deal with this kind of topic make it more clear that the customer liaison is where everything happens. Of course, normally it would be silly to assume that they have been a reader for long enough to know, but in this case it is easy. Fleet Command has been attempting to insult Raymond for a long time now, especially with this type of post.

    Because there was less emphasis on the liaison doing anything, it allowed Fleet Command to read things the way that he/she wanted much more easily and thus allowed him/her to jump to the conclusion that Microsoft are evil much easier.

    But well, because of his/her past behaviour I originally didn't bother writing a reply, but it seemed to have escalated. So I will just write the most important thing here.

    DON'T FEED THE TROLL

    Then again, this also gave a corollary to Tuesday's post about error message reading. Due to whatever reason, Fleet Command read the post how he/she expected to see it, or how he/she wanted to see it. This can easily translate to error messages.

  32. ersdfsdf says:

    @FleetCommand: So to summarize: Someone asked how to do A as fast as explorer. The answer was twofold:

    a) Explorer is actually doing B, which you can do by doing this and this and

    b) To further optimize performance of the actual goal you're trying to achieve do this instead.

    And your problem with that seems to be that they did not answer how to do A faster - which you haven't actually shown is possible to do and even if it were, would not help the customer at all but would just lead them down a wrong corridor.

    That is nothing but a lazy "literally answer the question" customer service which is sadly the standard in the industry (admittedly it is much easier to just answer a weird question, than to figure out the real problem and help the customer solve that).

  33. dave says:

    @ þ

    seems like an accurate posting name!

  34. Darran Rowe says:

    @ersdfsdf:

    As an answer to the changing the permissions on the file or directory, the answer is simply Explorer doesn't do it that fast either.

    It is easy to demonstrate that modifying a permission on a directory where there are files or directories below it in the hierarchy results in the permissions having to propagate down when inheritable permissions are enabled.

    The rationale behind this AFAIR is for speed on access, which is an extremely common operation, where changing isn't. I think that it goes though the tree and applies all of the relevant ACEs to the child items that has inheritable permissions enabled, and this is normally on by default.

    To be honest, I would be surprised if Fleet Command him/herself didn't know any of this. But since the whole point of the replies by Fleet Command was purely about trying to rant at Raymond and maybe Microsoft in general, facts don't have to be part of it. So as I wrote in my previous reply, just ignore any replies by Fleet Command if they are like this.

  35. Henri Hein says:

    @Dave,

    Ha, thanks for that.  We needed a humorous conclusion to this thread.

  36. Yolanda says:

    I noticed everyone was commenting on the topic, until this Darran Rowe guy came and started insulting another guy. Does he do this often?

  37. Darran Rowe says:

    @Yolanda:

    To help you decide that for yourself, let's go a bit into my history,

    My account has been active since 5th August 2005. I have been reading and commenting on this blog for a while, but because of the annoying thing of getting old, I decided to rename my account to something more fitting and stuff.

    The original name I used was Crescens2k.

Comments are closed.

Skip to main content