• 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

    • Microsoft is removing legacy drivers from Windows Update by Usama Jawad Last month, we learned that Microsoft is making major changes to the development of hardware drivers in Windows. This included the retirement of Windows Metadata and Internet Services (WMIS), along with the process for pre-production driver signing. Now, the Redmond tech firm has informed partners that it will be getting rid of old drivers in Windows Update. In what is being described as a "strategic" move to improve the security posture and compatibility of Windows, Microsoft has announced that it will be performing a cleanup of legacy drivers that are still being delivered through Windows Update. Right now, the first phase only targets drivers that already have modern replacements present in Windows Update. As a part of its cleanup process, Microsoft will expire legacy drivers so that it is not offered to any system. This expiration involves removing audience segments in the Hardware Development Center. Partners can still republish a driver that was deemed as legacy by Microsoft, but the firm may require a justification. Once the Redmond tech giant completes its first phase of this cleanup, it will give partners a six-month grace period to share any concerns. However, if no concerns are brought forward, the drivers will be permanently eradicated from Windows Update. Microsoft has emphasized that this will be a regular activity moving forward and while the current phase only targets legacy drivers with newer replacements, the next phases may expand the scope of this cleanup and remove other drivers too. That said, each time the company takes a step in this direction, it will inform partners so that there is transparency between both parties. Microsoft believes that this move will help improve the security posture of Windows and ensure that an optimized set of drivers is offered to end-users. The firm has asked partners to review their drivers in Hardware Program so that there are no unexpected surprises during this cleanup process.
    • No idea, but I had a client the other week that lost the entire drive to it. I suggested relying on the Samsung T7's instead. The Sandisk Extreme's had reliability issues too.
    • I use it every day so personally yes I need it, or rather I want it. I use OpenShell though, not the garbage modern Start Menu. I just counted and at the moment I have a total of 92 program shortcuts organized into six folders almost exactly the way I did back in Windows 95. I can get to any program I want to run very quickly. I never use Search to find or run programs.
    • I do miss the Apps view from Windows 8.1 Update.
    • I use the search function and little else since Windows 11 (but there are times where Saved Searches take precedence since the search feature on the Start menu is worse than before). I use other features in previous releases.
  • Recent Achievements

    • Collaborator
      lethalman went up a rank
      Collaborator
    • Week One Done
      Wayne Robinson earned a badge
      Week One Done
    • One Month Later
      Karan Khanna earned a badge
      One Month Later
    • Week One Done
      Karan Khanna earned a badge
      Week One Done
    • First Post
      MikeK13 earned a badge
      First Post
  • Popular Contributors

    1. 1
      +primortal
      664
    2. 2
      ATLien_0
      262
    3. 3
      Michael Scrip
      212
    4. 4
      +FloatingFatMan
      168
    5. 5
      Steven P.
      156
  • Tell a friend

    Love Neowin? Tell a friend!