• 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

    • I actually didn't like the classic Start Menu as much as the XP, Vista, 7 style menu. Mainly didn't like how you either had to click Programs every time, when that is what you would want 95% of the time, or fill up that top section (I forget what it was called back then) which was both harder than it should have been and looked ugly.
    • Beat Saber drops PlayStation VR support, no more content coming to the platform by Pulasthi Ariyasinghe Beat Saber, one of the most popular virtual reality games ever, is dropping support for the entire PlayStation VR platform. Developer Beat Games announced the decision today, saying that while PlayStation 4 and 5 players will be able to keep playing the title, no more content will be released for Beat Saber on the platform going forward. "As we look to the future and plan the next big leap for Beat Saber, we have made the decision to no longer release updates for PS4 and PS5 starting in June 2025," said the Meta-owned studio in a social media post today. "Our passion for VR remains unwavering. We are excited about the possibilities that lie ahead and what we can bring to Beat Saber fans who have been on this journey with us over the past 7 years." Lady Gaga’s Abracadabra, which released onto Beat Saber as a premium song on June 5, will be the final piece of new content that will release on PlayStation VR and PlayStation VR2. No new songs will be offered on the platforms, though customer support will still be available. Moreover, Beat Saber's multiplayer functionality is also being shut off on PlayStation soon. This feature will shut down on January 21, 2026, across both consoles. Beat Games confirmed that current Beat Saber content will remain playable on PlayStation 4 and PlayStation 5 even after dropping support, whether it be from the base game, DLC, or individual purchases. Beat Saber will also remain purchasable on the PlayStation Store, and its in-game store will continue to function for players who want to buy any previously released content. Cross-buy between PlayStation 4 and 5 will remain active as well. "We're grateful for the incredible support you've shown us over the years, and we're excited to share what the future holds for Beat Saber," added the studio. Beat Games assured PC players that alongside Meta Quest headsets, the Steam version of Beat Saber will continue to get support going forward.
    • You're right. I did a quick check before posting, but clearly looked at the wrong number (was looking at the stock price, and brain farted into thinking that was market cap in billions). I was surprised it was lower than I thought, but clearly should have looked closer.
    • Soon: honda puts a turbo'd k24 in a rocket with a big spoiler and some extra body trim.
    • Half a trillion? Do your homework, they're worth more than 3 freaking trillion dollars. As for the correlation between market cap and features, I think you're mistaken. There are some things called priorities. It obviously wasn't a priority for them to implement this, as it's still not a priority to implement moving taskbar to different locations of the screen. The trillions of dollars they're worth, have nothing to do with this.
  • Recent Achievements

    • First Post
      TIGOSS earned a badge
      First Post
    • Week One Done
      slackerzz earned a badge
      Week One Done
    • Week One Done
      vivetool earned a badge
      Week One Done
    • Reacting Well
      pnajbar earned a badge
      Reacting Well
    • Week One Done
      TBithoney earned a badge
      Week One Done
  • Popular Contributors

    1. 1
      +primortal
      680
    2. 2
      ATLien_0
      279
    3. 3
      Michael Scrip
      221
    4. 4
      +FloatingFatMan
      197
    5. 5
      Steven P.
      134
  • Tell a friend

    Love Neowin? Tell a friend!