Home > Development > Setting the Owner of Files and Directories in C#

Setting the Owner of Files and Directories in C#

I recently had a requirement to set the owners of users home directories on a Windows server. The .Net framework has built-in support for this so it simply looked like a case of doing this:

IdentityReference owner = new NTAccount("MYDOMAIN\\MyUser");
DirectoryInfo directory = new DirectoryInfo("c:\\myDirectory");
DirectorySecurity directorySecurity = directory.GetAccessControl();

However, when I tried this I just got an InvalidOperationException with the message "The security identifier is not allowed to be the owner of this object".

It turns out that the reason for this is that normally you are only allowed to take ownership yourself, and not assign it. For a user to take ownership they must either have been given the Take Ownership permission or be an administrator.

There is one exception to this rule, and that is if the user has the Restore files and directories privilege then they can assign ownership to other users. Now administrators have this privilege, but by default it is disabled. More details on this from Microsoft.

So to set the owner of the file, you need to have the Restore Files and Directories privilege and then enable it before setting the owner. Really we should also disable the privilege when we’ve finished using it as well.

Unfortunately .Net doesn’t have built in support for this yet, so we are reduced to PInvoking native methods and here’s the code:

sealed class UnmanagedCode
    [DllImport("kernel32.dll", SetLastError=true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool CloseHandle(IntPtr hObject);

    // Use this signature if you do not want the previous state
    [DllImport("advapi32.dll", SetLastError=true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool AdjustTokenPrivileges(IntPtr tokenHandle,
        [MarshalAs(UnmanagedType.Bool)]bool disableAllPrivileges,
        ref TOKEN_PRIVILEGES newState,
        UInt32 bufferLength,
        IntPtr previousState,
        IntPtr returnLength);

    [DllImport("kernel32.dll", ExactSpelling = true)]
    static extern IntPtr GetCurrentProcess();

    [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
    static extern bool OpenProcessToken
        (IntPtr processHandle, int desiredAccess, ref IntPtr phtok);

    [DllImport("advapi32.dll", SetLastError = true)]
    static extern bool LookupPrivilegeValue
            (string host, string name, ref LUID lpLuid);

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public UInt32 PrivilegeCount;
        public LUID Luid;
        public UInt32 Attributes;

    public struct LUID
       public uint LowPart;
       public int HighPart;

    const int SE_PRIVILEGE_ENABLED = 0x00000002;
    const int TOKEN_QUERY = 0x00000008;
    const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
    const string SE_RESTORE_PRIVILEGE = "SeRestorePrivilege"; 

    public static void GiveRestorePrivilege()
        TOKEN_PRIVILEGES tokenPrivileges;
        tokenPrivileges.PrivilegeCount = 1;
        tokenPrivileges.Luid = new LUID();
        tokenPrivileges.Attributes = SE_PRIVILEGE_ENABLED;

        IntPtr tokenHandle = RetrieveProcessToken();

            bool success = LookupPrivilegeValue
                        (null, SE_RESTORE_PRIVILEGE, ref tokenPrivileges.Luid);
            if (success == false)
                int lastError = Marshal.GetLastWin32Error();
                throw new Exception(
                    string.Format("Could not find privilege {0}. Error {1}",
                                        SE_RESTORE_PRIVILEGE, lastError));

            success = AdjustTokenPrivileges(
                                                tokenHandle, false,
                                                ref tokenPrivileges, 0,
                                                IntPtr.Zero, IntPtr.Zero);
            if (success == false)
                int lastError = Marshal.GetLastWin32Error();
                throw new Exception(
                    string.Format("Could not assign privilege {0}. Error {1}",
                                    SE_RESTORE_PRIVILEGE, lastError));


    static IntPtr RetrieveProcessToken()
        IntPtr processHandle = GetCurrentProcess();
        IntPtr tokenHandle = IntPtr.Zero;
        bool success = OpenProcessToken(processHandle,
                                        TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
                                        ref tokenHandle);
        if (success == false)
            int lastError = Marshal.GetLastWin32Error();
            throw new Exception(
                string.Format("Could not retrieve process token. Error {0}",
        return tokenHandle;

To remove the privilege you will just need to replace SE_PRIVILEGE_ENABLED with the disabled value. In my use I’m just setting the owner and finishing the process so it’s not really required.

Categories: Development Tags:
  1. Oliver
    November 22nd, 2012 at 17:13 | #1

    Don’t work for me.
    Want to set another User as owner to a file of mine.

    IdentityReference account = new NTAccount(“DOMAIN”, “user”);
    FileInfo file = new FileInfo(@”C:\xxx\yyy.dat”);
    FileSecurity directorySecurity = directory.GetAccessControl();


  2. Tommy
    May 26th, 2013 at 18:11 | #2

    Tommy :
    Hi Richard!
    How to use code above?

  3. June 25th, 2013 at 09:14 | #3

    You need to compile it into a C# project.

  4. lahor
    March 17th, 2014 at 18:20 | #4

    Thank you for this post. This code worked for me. My requirement was to grab ownership of a folder, change attributes and then restore ownership to the user.

  5. Azmy Sukkoor
    March 31st, 2014 at 13:13 | #5

    Great, this worked! Thanks for the code.

  6. May 25th, 2014 at 23:58 | #6

    Hi, Does this code work on server 2012R2?

    I have to code as follows:
    IdentityReference owner = new NTAccount(“DOMAIN”, name);
    FileInfo f = new FileInfo(SaveLocation);
    FileSecurity fs = f.GetAccessControl();
    fs = f.GetAccessControl();

    The Service Account is a member of the backup operators group but I still get “Error: The security identifier is not allowed to be the owner of this object.” with or without the line “UnmanagedCode.GiveRestorePrivilege();”.

    Stepping through the code everything seems to succeed, so I’m at at a total loss as I have used this code before and it worked (Server 2008R2)?

  7. May 28th, 2014 at 10:14 | #7

    Does it work when the service account is a domain admin?

  8. Walter Bankovitch
    September 13th, 2014 at 00:21 | #8

    Thank you! Works for me!

  9. October 12th, 2014 at 22:20 | #9

    Be aware that AdjustTokenPrivileges will return TRUE even if the user does not have all (or any) of the privileges in question. If you want to detect this case, you have to call GetLastError even if AdjustTokenPrivileges returned TRUE; usually, you shouldn’t do this, but AdjustTokenPrivileges is one of the few exceptions.

    In this case that means that if you run the program without elevation, it will fail when attempting to change the ownership, rather than when attempting to enable the privilege. There’s nothing necessarily wrong with that, but it sometimes causes confusion. :-)

  10. December 1st, 2014 at 08:02 | #10

    @Harry Johnston
    Thanks interesting to know – thanks for the tip.

  11. Achim
    August 28th, 2015 at 18:05 | #11

    Hi Richard,
    I tried this code. But it doesn’t work for me.
    If you find an error in my code, please notify me.

    IdentityReference owner = new NTAccount(Environment.UserDomainName, Environment.UserName);
    FileInfo file = new FileInfo(Environment.SystemDirectory + @”\sppsvc.exe”);
    FileSecurity fileSecurity = file.GetAccessControl();

    The previos owner is TrustedInstaller.
    If I do the same with cmd with Administrator rights it works: “takeown /F C:\Windows\System32\sppsvc.exe”.

    I’m starting my C#-Project with Admin rights (chose it in the app.manifest).

  12. August 31st, 2015 at 22:31 | #12

    Did you call GiveRestorePrivilege first?

  1. No trackbacks yet.