• 0

Change file and folder owner from .NET


Question

Hello, can anyone help me change a folder or file's owner from .NET on windows 2003? I have found a program called subinacl.exe that does this but if is too slow to shell out and execute this. Also if it can be done to subfolders automatically without me going through all the folders it would be great.

Thanks in advance :D

9 answers to this question

Recommended Posts

  • 0

private static void GiveControl(string path, string user, ACCESS_MASK access)
{
	IntPtr sd = IntPtr.Zero;
	IntPtr daclNew = IntPtr.Zero;
	IntPtr eaNew = IntPtr.Zero;

	try
	{
  int err;

  IntPtr daclOld;
  IntPtr unused1, unused2, unused3;
  if ((err = GetNamedSecurityInfo(path, SE_OBJECT_TYPE.FILE, SECURITY_INFORMATION.DACL, out unused1, out unused2, out daclOld, out unused3, out sd)) != 0)
 	 throw new Win32Exception(err);


  if ((eaNew = LocalAlloc(0, 64)) == IntPtr.Zero)
 	 throw new Win32Exception(Marshal.GetLastWin32Error());

  BuildExplicitAccessWithName(eaNew, user, access, ACCESS_MODE.GRANT, INHERITANCE.CONTAINER | INHERITANCE.OBJECT);

  if ((err = SetEntriesInAcl(1, eaNew, daclOld, out daclNew)) != 0) throw new Win32Exception(err);

  if ((err = SetNamedSecurityInfo(path, SE_OBJECT_TYPE.FILE, SECURITY_INFORMATION.DACL, IntPtr.Zero, IntPtr.Zero, daclNew, IntPtr.Zero)) != 0)
 	 throw new Win32Exception(err);

	}
	finally
	{
  LocalFree(sd);
  LocalFree(eaNew);
  LocalFree(daclNew);
	}
}
  
  
private enum ACCESS_MODE : uint
{
	NOT_USED = 0,
	GRANT,
	SET,
	DENY,
	REVOKE,
	SET_AUDIT_SUCCESS,
	SET_AUDIT_FAILURE
}

[Flags]
private enum ACCESS_MASK : uint
{
	EXCLUSIVE = 0x200,
	READDESIGN = 0x400,
	WRITEDESIGN = 0x800,
	WITHGRANT = 0x1000,
	REFERENCE = 0x2000,
	CREATE = 0x4000,
	INSERT = 0x8000,
	DELETE = 0x10000,
	READCONTROL = 0x20000,
	WRITEPERMISSIONS = 0x40000,
	WRITEOWNER = 0x80000,
	MAXIMUM_ALLOWED = 0x2000000,
	ALL = 0x10000000,
	EXECUTE = 0x20000000,
	READ = 0x80000000,
	UPDATE = 0x40000000,
	DROP = 0x100
}

[Flags]
private enum INHERITANCE : uint
{
	OBJECT = 0x1,
	CONTAINER = 0x2,
	NO_PROPAGATE = 0x4,
	INHERIT_ONLY = 0x8,
	INHERITED = 0x10,
	VALID_FLAGS = 0x1F
}

private enum SE_OBJECT_TYPE : uint
{
	UNKNOWN = 0,
	FILE,
	SERVICE,
	PRINTER,
	REGISTRY_KEY,
	LMSHARE,
	KERNEL,
	WINDOW,
	DS,
	DS_ALL,
	PROVIDER_DEFINED,
	WMIGUID,
	REGISTRY_WOW64_32KEY
}

public enum SECURITY_INFORMATION : uint
{
	OWNER = 0x00000001,
	GROUP = 0x00000002,
	DACL = 0x00000004,
	SACL = 0x00000008,

	PROTECTED_DACL = 0x80000000,
	PROTECTED_SACL = 0x40000000,
	UNPROTECTED_DACL = 0x20000000,
	UNPROTECTED_SACL = 0x10000000
}

[DllImport("advapi32.dll", CallingConvention=CallingConvention.Winapi, CharSet=CharSet.Auto)]
private static extern int GetNamedSecurityInfo([In] string pObjectName, [In] SE_OBJECT_TYPE ObjectType, [In] SECURITY_INFORMATION SecurityInfo, [Out] out IntPtr ppsidOwner, [Out] out IntPtr ppsidGroup, [Out] out IntPtr ppDacl, [Out] out IntPtr ppSacl, [Out] out IntPtr ppSecurityDescriptor);  

[DllImport("kernel32.dll", CallingConvention=CallingConvention.Winapi, SetLastError=true, CharSet=CharSet.Auto)]
private static extern IntPtr LocalAlloc([In] uint uFlags, [In] uint uBytes);  


[DllImport("advapi32.dll", CallingConvention=CallingConvention.Winapi,	CharSet=CharSet.Auto)]
private static extern void BuildExplicitAccessWithName([In] IntPtr pExplicitAccess, [In] string pTrusteeName, [In] ACCESS_MASK AccessPermissions, [In] ACCESS_MODE AccessMode, [In] INHERITANCE Inheritance);  


[DllImport("advapi32.dll", CallingConvention=CallingConvention.Winapi, CharSet=CharSet.Auto)]
private static extern int SetEntriesInAcl([In] uint cCountOfExplicitEntries, [In] IntPtr pListOfExplicitEntries, [In] IntPtr OldAcl, [Out] out IntPtr NewAcl);

[DllImport("advapi32.dll", CallingConvention=CallingConvention.Winapi, CharSet=CharSet.Auto)]
private static extern int SetNamedSecurityInfo([In] string pObjectName, [In] SE_OBJECT_TYPE ObjectType, [In] SECURITY_INFORMATION SecurityInfo, [In] IntPtr psidOwner, [In] IntPtr psidGroup, [In] IntPtr pDacl, [In] IntPtr pSacl);

[DllImport("kernel32.dll", CallingConvention=CallingConvention.Winapi, SetLastError=true, CharSet=CharSet.Auto)]
private static extern IntPtr LocalFree([In] IntPtr hMem);

You can assign rights by calling something like

GiveControl(@"C:\Windows", Environment.GetEnvironmentVariable("COMPUTERNAME") + "\Administrator", ACCESS_MASK.ALL);

  • 0

This is what I want to do: On Windows 2003 I have a MySQL Server, and Quota mangement on that drive. I have a windows account named 'demo' with 10mb quota. I create a database named demo and give access to that user. He can create, drop tables, write data. The problem is that when he creates a table, the owner of this file is not 'demo' it is 'Administrators' because it is created by the local service account, so his quota is not updated. What I want to do is create a windows service that changes the owner of these files to 'demo' so his quota is updated. I could create a batch file but I would have to be updating it for every user that I create. Also, it's not just the mySQL database folder, The user also has a folder where anyone can create files and folders, but the owner must still be 'demo' The folder structure is something like this:

d:\mysql\data\<user>

d:\userFiles\<user>\shared

d:\userFiles\<user>\private

EDIT: But your first code will help me on some other stuff I want to do, so thanks :D

  • 0

I found this vbscript example that changes the owner but I get the error:

  Quote
"This security ID may not be assigned as the owner of this object"

set oADsSecurity = CreateObject("ADsSecurityUtility")
Set sd = oADsSecurity.GetSecurityDescriptor("c:\test.txt", 1, 1)
wscript.echo sd.Owner
oADsSecurity.SecurityMask = 1
sd.Owner = "Domain\User"
oADsSecurity.SetSecurityDescriptor "c:\test.txt", 1, sd, 1

It only seems to work when I want to take ownership of a file, not when I want tp asign ownership to another user. :o

  • 0

I found a way to do it. It was on msdn .net documentation all along :blush: ms-help://MS.VSCC.2003/MS.MSDNQTR.2003APR.1033/enu_kbwin32sdk/win32sdk/318744.htm

It's on visual basic 6 but I made an com dll out of it and it's working great.

Thanks for your help and patience :p

Option Explicit

' Global constants we must use with security descriptor
Private Const SECURITY_DESCRIPTOR_REVISION = 1
Private Const OWNER_SECURITY_INFORMATION = 1&amp;

' Access Token constants
Private Const TOKEN_ASSIGN_PRIMARY = &amp;H1
Private Const TOKEN_DUPLICATE = &amp;H2
Private Const TOKEN_IMPERSONATE = &amp;H4
Private Const TOKEN_QUERY = &amp;H8
Private Const TOKEN_QUERY_SOURCE = &amp;H10
Private Const TOKEN_ADJUST_PRIVILEGES = &amp;H20
Private Const TOKEN_ADJUST_GROUPS = &amp;H40
Private Const TOKEN_ADJUST_DEFAULT = &amp;H80
Private Const TOKEN_ALL_ACCESS = TOKEN_ASSIGN_PRIMARY _
      + TOKEN_DUPLICATE + TOKEN_IMPERSONATE + TOKEN_QUERY _
      + TOKEN_QUERY_SOURCE + TOKEN_ADJUST_PRIVILEGES _
      + TOKEN_ADJUST_GROUPS + TOKEN_ADJUST_DEFAULT
Private Const ANYSIZE_ARRAY = 1

' Token Privileges constants
Private Const SE_RESTORE_NAME = "SeRestorePrivilege"
Private Const SE_PRIVILEGE_ENABLED = 2&amp;

' ACL structure
Private Type ACL
   AclRevision As Byte
   Sbz1 As Byte
   AclSize As Integer
   AceCount As Integer
   Sbz2 As Integer
End Type

Private Type SECURITY_DESCRIPTOR
   Revision As Byte
   Sbz1 As Byte
   Control As Long
   Owner As Long
   Group As Long
   Sacl As ACL
   Dacl As ACL
End Type

' Token structures
Private Type LARGE_INTEGER
   lowpart As Long
   highpart As Long
End Type

Private Type LUID
   lowpart As Long
   highpart As Long
End Type

Private Type LUID_AND_ATTRIBUTES
   pLuid As LUID
   Attributes As Long
End Type

Private Type TOKEN_PRIVILEGES
   PrivilegeCount As Long
   Privileges(ANYSIZE_ARRAY) As LUID_AND_ATTRIBUTES
End Type

' Win32 API calls
Private Declare Function LookupAccountName Lib "advapi32.dll" _
      Alias "LookupAccountNameA" (ByVal lpSystemName As String, _
      ByVal lpAccountName As String, Sid As Byte, cbSid As Long, _
      ByVal ReferencedDomainName As String, _
      cbReferencedDomainName As Long, peUse As Integer) As Long
      
Private Declare Function InitializeSecurityDescriptor _
      Lib "advapi32.dll" (pSecurityDescriptor As SECURITY_DESCRIPTOR, _
      ByVal dwRevision As Long) As Long
      
Private Declare Function SetSecurityDescriptorOwner _
      Lib "advapi32.dll" (pSecurityDescriptor As SECURITY_DESCRIPTOR, _
      pOwner As Any, ByVal bOwnerDefaulted As Long) As Long
      
Private Declare Function SetFileSecurity Lib "advapi32.dll" _
      Alias "SetFileSecurityA" (ByVal lpFileName As String, _
      ByVal SecurityInformation As Long, _
      pSecurityDescriptor As SECURITY_DESCRIPTOR) As Long
      
Private Declare Function OpenProcessToken Lib "advapi32.dll" _
      (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, _
      TokenHandle As Long) As Long
      
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long

Private Declare Function LookupPrivilegeValue Lib "advapi32.dll" _
      Alias "LookupPrivilegeValueA" (ByVal lpSystemName As String, _
      ByVal lpName As String, lpLuid As LUID) As Long
      
Private Declare Function AdjustTokenPrivileges Lib "advapi32.dll" _
      (ByVal TokenHandle As Long, ByVal DisableAllPrivileges As Long, _
      NewState As TOKEN_PRIVILEGES, ByVal BufferLength As Long, _
      ByVal PreviousState As Long, ByVal ReturnLength As Long) As Long
      
Private Declare Function CloseHandle Lib "kernel32" _
      (ByVal hObject As Long) As Long

Public Sub ChangeOwnerOfFile(FileName As String, _
      OwnerAccountName As String)

   ' variables for the LookupAccountName API Call
   Dim Sid(255) As Byte             ' Buffer for the SID
   Dim nBufferSize As Long          ' Length of SID Buffer
   Dim szDomainName As String * 255 ' Domain Name Buffer
   Dim nDomain As Long              ' Length of Domain Name buffer
   Dim peUse As Integer             ' SID type
   Dim Result As Long               ' Return value of Win32 API call
   
   ' variables for the InitializeSecurityDescriptor API Call
   Dim SecDesc As SECURITY_DESCRIPTOR
   Dim Revision As Long
   
   Enable_Privilege (SE_RESTORE_NAME)
   
   nBufferSize = 255
   nDomain = 255
   
   Result = LookupAccountName(vbNullString, OwnerAccountName, _
         Sid(0), nBufferSize, szDomainName, nDomain, peUse)
   If (Result = 0) Then
      MsgBox "LookupAccountName failed with error code " _
            &amp; Err.LastDllError
      Exit Sub
   End If
   
   Result = InitializeSecurityDescriptor(SecDesc, _
         SECURITY_DESCRIPTOR_REVISION)
   If (Result = 0) Then
      MsgBox "InitializeSecurityDescriptor failed with error code " _
            &amp; Err.LastDllError
      Exit Sub
   End If
   
   Result = SetSecurityDescriptorOwner(SecDesc, Sid(0), 0)
   If (Result = 0) Then
      MsgBox "SetSecurityDescriptorOwner failed with error code " _
            &amp; Err.LastDllError
      Exit Sub
   End If
   
   Result = SetFileSecurity(FileName, OWNER_SECURITY_INFORMATION, _
         SecDesc)
   If (Result = 0) Then
      MsgBox "SetFileSecurity failed with error code " _
            &amp; Err.LastDllError
      Exit Sub
   Else
      MsgBox "Owner of " &amp; FileName &amp; " changed to " _
            &amp; OwnerAccountName
   End If
   
   Disable_Privilege (SE_RESTORE_NAME)
   
End Sub

Public Function Enable_Privilege(Privilege As String) As Boolean
   Enable_Privilege = ModifyState(Privilege, True)
End Function

Public Function Disable_Privilege(Privilege As String) As Boolean
   Disable_Privilege = ModifyState(Privilege, False)
End Function

Public Function ModifyState(Privilege As String, _
      Enable As Boolean) As Boolean
    
   Dim MyPrives As TOKEN_PRIVILEGES
   Dim PrivilegeId As LUID
   Dim ptrPriv As Long    ' Pointer to Privileges Structure
   Dim hToken As Long     ' Token Handle
   Dim Result As Long     ' Return Value
   
   Result = OpenProcessToken(GetCurrentProcess(), _
         TOKEN_ADJUST_PRIVILEGES, hToken)
   If (Result = 0) Then
      ModifyState = False
      MsgBox "OpenProcessToken failed with error code " _
            &amp; Err.LastDllError
      Exit Function
   End If
   
   Result = LookupPrivilegeValue(vbNullString, Privilege, PrivilegeId)
   If (Result = 0) Then
      ModifyState = False
      MsgBox "LookupPrivilegeValue failed with error code " _
            &amp; Err.LastDllError
      Exit Function
   End If
   
   MyPrives.Privileges(0).pLuid = PrivilegeId
   MyPrives.PrivilegeCount = 1
   If (Enable) Then
      MyPrives.Privileges(0).Attributes = SE_PRIVILEGE_ENABLED
   Else
      MyPrives.Privileges(0).Attributes = 0
   End If
    
   Result = AdjustTokenPrivileges(hToken, False, MyPrives, 0, 0, 0)
   If (Result = 0 Or Err.LastDllError &lt;&gt; 0) Then
      ModifyState = False
      MsgBox "AdjustTokenPrivileges failed with error code " _
            &amp; Err.LastDllError
      Exit Function
   End If
   
   CloseHandle hToken
   
   ModifyState = True

End Function

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Posts

    • How can all of these Neowin deals be "an all time low price". I find that pretty hard to believe.
    • Oh wow, a patch for an Unreal game to improve performance? We'll see...
    • Get this massive 4TB WD_BLACK SN7100 SSD at a new all-time low price by Taras Buria Xbox owners recently received a new storage upgrade option, which allows them to equip the Xbox Series X|S with 4TB of extra space. That card, however, has an eye-watering price tag—nearly as much as the 1TB Xbox Series S. On the PC side, though, things are much better. Right now, if you need a 4TB SSD without selling a kidney, you can get the WD_BLACK SN7100 PCIe Gen4 SSD. It is now available on Amazon at a new all-time low price after a 16% discount (nearly half the cost of the new 4TB Xbox Storage Expansion Card). The SN7100 is a fast, reliable, and, more importantly, affordable Gen4 solid-state drive. Its speeds are rated up to 7,000MB/s sequential read and 6,700MB/s sequential write, while random input-output speeds are rated at 900K IOPS read and 1,350K IOPS write. These specs are not record-breaking, but they are fast enough for modern gaming (DirectStorage is supported), fast loading times in games and apps, and quick file transfer. The WD_BLACK SN7100 has a limited five-year warranty and endurance rating up to 2,400 TBW. You can monitor the health of your drive in the WD_Black Dashboard app on Windows. As for compatibility, you can use the SN7100 in any PC that accommodates M.2 2280 PCIe Gen4 drives, including PlayStation 5. It is compatible with PCIe Gen3 systems, but the maximum speeds will be limited. 4TB WD_BLACK SN7100 PCIe Gen4 Solid-State Drive - $249.99 | 16% off on Amazon US This Amazon deal is US-specific and not available in other regions unless specified. If you don't like it or want to look at more options, check out the Amazon US deals page here. Get Prime (SNAP), Prime Video, Audible Plus or Kindle / Music Unlimited. Free for 30 days. As an Amazon Associate, we earn from qualifying purchases.
    • Snagit 2025.2.0 by Razvan Serea Snagit is the most complete screen capture utility available. Showing someone exactly what you see on your screen is sometimes the quickest and clearest way to communicate. With Snagit, you can select anything on your screen – an area, image, article, Web page, or error message – and capture it. Then, save the screen capture to a file, send it to Snagit​'s editor to add professional effects, share it by e-mail, or drop it into PowerPoint®, Word®, or another favorite application. Capture and share images, text or video from your PC. Create beautiful presentations, flawless documentation and quickly save online content. The latest version of Snagit offers a totally new interface and workflow - making SnagIt easier for beginners to use, while still providing maximum convenience and flexibility for the screen capture experts. Snagit 2025.2.0 changelog: Edit Images from Camtasia Snagit can now be used to seamlessly edit images from Camtasia. Requires Camtasia version 2025.2.0 or later. In the Camtasia Media Bin, right-click an image and select the Edit in Snagit option. In Snagit, make your edits. When finished, click Send in the "Send changes to Camtasia" notification to replace the image on your Camtasia timeline. Step Capture Improved the Step Capture template to accommodate longer auto-populated step text. Annotations such as Callout or Arrow tool objects now anchor to and move with sections as sections are added to, reordered, or deleted from templates. Subscription Software Updated the Account dropdown to open automatically when new subscription related messages are present. Performance Improvements Improved the startup time for Snagit Capture application. Updates for IT Administrators Updated BouncyCastle.Cryptography package to address CVE-2024-29857 and CVE-2024-30172. Removed dependency on Xceed Zip. Updated LeadTools DLLs. Fixed an issue where Snagit might not recognize offline subscription activation. Fixed an issue where the video recording toolbar could be hidden from users when using Snagit in virtual environments or with remote desktop applications. Bug Fixes Fixed an issue where using Step Capture with the Share destination set to File in the Capture Window could result in data loss. Fixed a crash that could occur when capturing on some HDR monitors. Fixed an issue where the cursor object in a capture might include some of the background image in certain situations. Fixed an issue with the Box share destination to use the default browser for authentication. Fixed an issue where the Blur tool Color property could show when the blur or pixelate Type was selected. Fixed an issue where the privacy policy link in Snagit's installer might not open in the expected language. (PONRPD) Download: Snagit 64-bit | 419.0 MB (Shareware) Links: SnagIt Home Page | Release Notes Get alerted to all of our Software updates on Twitter at @NeowinSoftware
  • Recent Achievements

    • Week One Done
      jfam earned a badge
      Week One Done
    • First Post
      survivor303 earned a badge
      First Post
    • Week One Done
      CHUNWEI earned a badge
      Week One Done
    • One Year In
      survivor303 earned a badge
      One Year In
    • Week One Done
      jbatch earned a badge
      Week One Done
  • Popular Contributors

    1. 1
      +primortal
      420
    2. 2
      +FloatingFatMan
      185
    3. 3
      snowy owl
      183
    4. 4
      ATLien_0
      179
    5. 5
      Xenon
      140
  • Tell a friend

    Love Neowin? Tell a friend!