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.


I am Managing Director of SalamanderSoft Limited a company devoted to improving IT in education. I am also the project co-ordinator for the open source projects SharePoint Learning Kit and Microsoft Learning Gateway.

12 thoughts on “Setting the Owner of Files and Directories in C#

  1. Hy!
    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. 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.

  3. 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)?

  4. 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. :-)

  5. 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).

Leave a Reply

Your email address will not be published. Required fields are marked *