There are several ways in which a program can query security attributes (Owner, Group and ACLs) of one file and copy them to another file.

In a true Microsoft's way, some are well-documented, but they don't work as advertised, and some work as needed, but they are not documented.

First hit on Google is Get/SetFileSecurity. The name checks out, it accepts a HANDLE, so it should be quick and simple way to do what we want.

Nope, it's not.

It's an older API that doesn't correctly handle inheritable ACLs and its use is not recommended. Not by the API documentation, mind you, but by a random blog post from one of many Microsoft development teams, which you still need to find first. What they recommend instead is Get/SetSecurityInfo.

And you'd still naively think it's the one.

Nope, it's not.

The problem is that SetSecurityInfo will fail with "access denied" if you are trying to set DACL and the file is not opened with READ_CONTROL.

You may wonder why the heck it needs read control... excellent question. That's because it wants to look up the name of the file and then *feed that name into SetNamedSecurityInfo function*. The latter will then re-open the file and start spraying kernel with requests, which is the last thing you need when you are already quite busy with copying a million of files from A to B.

Looking at the trace of SetSecurityInfo with Procmon shows that it generates over a dozen of kernel calls... whereas only one is really needed.

The name of that one call that we want is NtSetSecurityObject, but it's a part of so-called Native API and as such it is officially off-limits for any application use.

However, if we are to comb several pagefuls of relevant APIs, we may spot something called SetKernelObjectSecurity, which looks suspiciously like NtSetSecurityObject.

Long story short, you want to copy security attributes - use Get / SetKernelObjectSecurity. So now you know. Congratulations :)
Made by Pipemetrics in Switzerland

Blog / RSS
Miscellanea Press resources
On robocopy

Legal Terms