• 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 365 Word gets SharePoint eSignature, now you can ditch third-party signing tools by Paul Hill Microsoft has just announced that it will be rolling out an extremely convenient feature for Microsoft 365 customers who use Word throughout this year. The Redmond giant said that you’ll now be able to use SharePoint’s native eSignature service directly in Microsoft Word. The new feature allows customers to request electronic signatures without converting the documents to a PDF or leaving the Word interface, significantly speeding up workflows. Microsoft’s integration of eSignatures also allows you to create eSignature templates which will speed up document approvals, eliminate physical signing steps, and help with compliance and security in the Microsoft 365 environment. This change has the potential to significantly improve the quality-of-life for those in work finding themselves adding lots of signatures to documents as they will no longer have to export PDFs from Word and apply the signature outside of Word. It’s also key to point out that this feature is integrated natively and is not an extension. The move is quite clever from Microsoft, if businesses were using third-party tools to sign their documents, they would no longer need to use these as it’s easier to do it in Word. Not only does it reduce reliance on other tools, it also makes Microsoft’s products more competitive against other office suites such as Google Workspace. Streamlined, secure, and compliant The new eSignature feature is tightly integrated into Word. It lets you insert signature fields seamlessly into documents and request other people’s signatures, all while remaining in Word. The eSignature feature can be accessed in Word by going to the Insert ribbon. When you send a signature request to someone from Word, the recipient will get an automatically generated PDF copy of the Word document to sign. The signed PDF will then be kept in the same SharePoint location as the original Word file. To ensure end-to-end security and compliance, the document never leaves the Microsoft 365 trust boundary. For anyone with a repetitive signing process, this integration allows you to turn Word documents into eSignature templates so they can be reused. Another feature that Microsoft has built in is audit trail and notifications. Both the senders and signers will get email notifications throughout the entire signing process. Additionally, you can view the activity history (audit trail) in the signed PDF to check who signed it and when. Finally, Microsoft said that administrators will be able to control how the feature is used in Word throughout the organization. They can decide to enable it for specific users via an Office group policy or limit it to particular SharePoint sites. The company said that SharePoint eSignature also lets admins log activities in the Purview Audit log. A key security measure included by Microsoft, which was mentioned above, was the Microsoft 365 trust boundary. By keeping documents in this boundary, Microsoft ensures that all organizations can use this feature without worry. The inclusion of automatic PDF creation is all a huge benefit to users as it will cut out the step of manual PDF creation. While creating a PDF isn’t complicated, it can be time consuming. The eSignature feature looks like a win-win-win for organizations that rely on digital signatures. Not only does it speed things along and remain secure, but it’s also packed with features like tracking, making it really useful and comprehensive. When and how your organization gets it SharePoint eSignature has started rolling out to Word on the M365 Beta and Current Channels in the United States, Canada, the United Kingdom, Europe, and Australia-Pacific. This phase of the rollout is expected to be completed by early July. People in the rest of the world will also be gaining this time-saving feature but it will not reach everyone right away, though Microsoft promises to reach everybody by the end of the year. To use the feature, it will need to be enabled by administrators. If you’re an admin who needs to enable this, just go to the M365 Admin Center and enable SharePoint eSignature, ensuring the Word checkbox is selected. Once the service is enabled, apply the “Allow the use of SharePoint eSignature for Microsoft Word” policy. The policy can be enabled via Intune, Group Policy manager, or the Cloud Policy service for Microsoft 365 Assuming the admins have given permission to use the feature, users will be able to access SharePoint eSignatures on Word Desktop using the Microsoft 365 Current Channel or Beta Channel. The main caveats include that the rollout is phased, so you might not get it right away, and it requires IT admins to enable the feature - in which case, it may never get enabled at all. Overall, this feature stands to benefit users who sign documents a lot as it can save huge amounts of time cumulatively. It’s also good for Microsoft who increase organizations’ dependence on Word.
    • It's always good to have an option to secure your stuff to another medium. I did that with DVD/CD collection, and run my own media server now. It's more convenient that way and no need for separate players anymore.
    • Google Search AI Mode gets support for data visualization and custom charts by Aditya Tiwari Google announced it is rolling out support for data visualizations and graphs for finance-related queries in Google Search's AI Mode. Introduced last month at the Google I/O 2025 keynote, the feature lets you analyze complex datasets and create custom charts simply using natural language prompts. The updated AI Mode lets you compare and analyze information over a specific period, Google explained. It generates interactive graphs and provides a comprehensive explanation for your questions. AI Mode utilizes Gemini's multimodal capabilities and multi-step reasoning approach to comprehend the question's intent while accessing historical and real-time information relevant to the question. For instance, instead of manually researching individual companies and their stock prices, you can use AI Mode to compare the stock performance of different companies for a specific year. Once the graph is generated, you can choose the desired time period using the mouse cursor and ask follow-up questions based on the data presented. These new data visualizations for finance queries are available to users who have enabled the AI Mode experiment in Labs. AI Mode was introduced earlier this year as an experimental feature in the US. The feature is an upgraded version of AI Overviews, and Google closely worked with AI power users through the initial development process. It uses the “query fan-out” technique to perform multiple related searches across subtopics and different data sources, then combines them to come up with a comprehensive response. Google updated AI Mode last month to use a custom version of the latest Gemini 2.5 model. It added several new features, including Deep Search, live capabilities, agentic capabilities of Project Mariner, a new shopping experience, and the ability to add personal context by linking Google apps. The search giant is planning to turn AI Mode into its bread and butter. It has begun testing ads for the feature, which will appear below and be integrated into AI Mode responses where relevant.
    • Guys, you should find another way to promote your deals... It's the third article in the last months that promote this deal for an upgrade from 10. Considering that upgrade from 10 to 11 is free it's a total non-sense.
    • Store should be a shrine of useful applications, vetted and verified. Easily sorted by publisher. Windows should start with not much installed and have things as options in the store. Not the wild west mess that it is. You could delete 95%+ of the crap on there and no one would notice. They need to add a better UI to the updates, it's awful right now.
  • Recent Achievements

    • Week One Done
      luxoxfurniture earned a badge
      Week One Done
    • First Post
      Uranus_enjoyer earned a badge
      First Post
    • Week One Done
      Uranus_enjoyer earned a badge
      Week One Done
    • Week One Done
      jfam earned a badge
      Week One Done
    • First Post
      survivor303 earned a badge
      First Post
  • Popular Contributors

    1. 1
      +primortal
      431
    2. 2
      +FloatingFatMan
      239
    3. 3
      snowy owl
      212
    4. 4
      ATLien_0
      211
    5. 5
      Xenon
      157
  • Tell a friend

    Love Neowin? Tell a friend!