Link to home
Start Free TrialLog in
Avatar of c_hubbard
c_hubbard

asked on

change file ownership in windows XP

Hi,

I read and process Files dropped by users on our network.
Sometimes the user forgets to close the file.
Is it possible to change/override ownership of that file (i have admin rights) in Window XP.

BRegards
Ulrich
Avatar of Bob Learned
Bob Learned
Flag of United States of America image

Do you want to do this in your program, or would the Windows Explorer be okay?

Bob
Avatar of c_hubbard
c_hubbard

ASKER

Hi Bob,

Thanks for your help.  I need to do this in my program.

Uli
I think the only way to do this is via the API calls GetNamedSecurityInfo and SetNamedSecurityInfo.

I don't have an example handy that uses those APIs to take ownership, but I've got one for setting permissions (so let me know if you'd like me to post it).

    'DWORD GetNamedSecurityInfo(
    '  LPTSTR pObjectName,
    '  SE_OBJECT_TYPE ObjectType,
    '  SECURITY_INFORMATION SecurityInfo,
    '  PSID* ppsidOwner,
    '  PSID* ppsidGroup,
    '  PACL* ppDacl,
    '  PACL* ppSacl,
    '  PSECURITY_DESCRIPTOR* ppSecurityDescriptor
    ');
    Declare Auto Function GetNamedSecurityInfo Lib "AdvAPI32.DLL" ( _
    ByVal pObjectName As String, _
    ByVal ObjectType As Integer, _
    ByVal SecurityInfo As Integer, _
    ByRef ppsidOwner As IntPtr, _
    ByRef ppsidGroup As IntPtr, _
    ByRef ppDacl As IntPtr, _
    ByRef ppSacl As IntPtr, _
    ByRef ppSecurityDescriptor As IntPtr) As Integer

    'DWORD SetNamedSecurityInfo(
    '  LPTSTR pObjectName,
    '  SE_OBJECT_TYPE ObjectType,
    '  SECURITY_INFORMATION SecurityInfo,
    '  PSID psidOwner,
    '  PSID psidGroup,
    '  PACL pDacl,
    '  PACL pSacl
    ');
    Declare Auto Function SetNamedSecurityInfo Lib "AdvAPI32.DLL" ( _
    ByVal pObjectName As String, _
    ByVal ObjectType As Integer, _
    ByVal SecurityInfo As Integer, _
    ByVal psidOwner As IntPtr, _
    ByVal psidGroup As IntPtr, _
    ByVal pDacl As IntPtr, _
    ByVal pSacl As IntPtr) As Integer
Hi,

Thanks for the reply.
It seems these API calls are possibly what i am looking for unfortunately i know little about security on networks especially how file ownerships is handled.

I tested the code using an Excel file that is held open by another user. If i try to open the file i get the usual "File in Use" message.

I can run the code passing the FileLocation, XP username and desired permissions.
The code runs fine without error but the ownership doesn't seem to change, i still can't open the file.. same error when i try to open it.

Do you need administrator permission to successfully run the code?
Whats happens to the "old user" whose ownership is taken away as he will still have the file open?


example:
'strUserName  = firstname.lastname (thats my xp login)
' strPerm  = "Full Control"

SetPermissions(ByRef strPath As String, ByVal strUserName As String, ByVal strPerm As String)
        Dim pSecDesc, pNewDACL, pOldDACL As IntPtr
        Dim ea As EXPLICIT_ACCESS
        Dim Win32Error As Win32Exception
        Dim ret, iPerm As Integer
        Dim bIsFile As Boolean

        ' Do a quick sanity check!
        bIsFile = True
        If File.Exists(strPath) = False Then
            If Directory.Exists(strPath) = False Then
                Throw New Exception("File or Directory not found")
            End If
            bIsFile = False
        End If

        ' Translate the desired permissions
        Select Case strPerm
            Case "Full Control"
                iPerm = ALL_ACCESS
            Case "Modify"
                iPerm = ALL_ACCESS And Not (WRITE_DAC Or WRITE_OWNER Or DELETE_CHILD)
            Case "Read & Execute"
                iPerm = GENERIC_READ Or GENERIC_EXECUTE
            Case "List Folder Contents"
                If bIsFile = False Then
                    Throw New Exception("Permission argument not applicable to files")
                End If
                iPerm = GENERIC_EXECUTE
            Case "Read"
                iPerm = GENERIC_READ
            Case "Write"
                iPerm = GENERIC_WRITE
            Case Else
                Throw New Exception("Invalid permission argument")
        End Select

   ret = GetNamedSecurityInfo(strPath, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, pOldDACL, Nothing, Nothing, Nothing, pSecDesc)
        If ret <> 0 Then
            Win32Error = New Win32Exception(ret)
            Throw New Exception(Win32Error.Message)
        End If

        ' build an explicit access structure
        BuildExplicitAccessWithName(ea, strUserName, iPerm, SET_ACCESS, CONTAINER_INHERIT_ACE Or OBJECT_INHERIT_ACE)

        ' merge this Explict Access with the existing DACL
        ret = SetEntriesInAcl(1, ea, pOldDACL, pNewDACL)
        If ret <> 0 Then
            Win32Error = New Win32Exception(ret)
            Throw New Exception(Win32Error.Message)
        End If

        ' write the new Security Descriptor/DACL back
        ret = SetNamedSecurityInfo(strPath, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, Nothing, Nothing, pNewDACL, Nothing)
        If ret <> 0 Then
            Win32Error = New Win32Exception(ret)
            Throw New Exception(Win32Error.Message)
        End If

        ' clean up and go home
        LocalFree(pNewDACL)
        LocalFree(pSecDesc)







That's kinda funny that you're using my example code for setting permissions.... that's the code example that what I was offering to post!  :)

Here is an example that should be of more help to you.  I just finished banging it out a few minutes ago, so there might be a few rough edges somewhere...

Imports System.Runtime.InteropServices
Imports System.IO
Imports System.ComponentModel
Module ChgOwner

    Private Const SE_FILE_OBJECT = 1&
    Private Const OWNER_SECURITY_INFORMATION = &H1

    Private Const NAME_SIZE = 64
    Private Const SID_SIZE = 32

    'DWORD GetNamedSecurityInfo(
    '  LPTSTR pObjectName,
    '  SE_OBJECT_TYPE ObjectType,
    '  SECURITY_INFORMATION SecurityInfo,
    '  PSID* ppsidOwner,
    '  PSID* ppsidGroup,
    '  PACL* ppDacl,
    '  PACL* ppSacl,
    '  PSECURITY_DESCRIPTOR* ppSecurityDescriptor
    ');
    Declare Auto Function GetNamedSecurityInfo Lib "AdvAPI32.DLL" ( _
    ByVal pObjectName As String, _
    ByVal ObjectType As Integer, _
    ByVal SecurityInfo As Integer, _
    ByRef ppsidOwner As IntPtr, _
    ByRef ppsidGroup As IntPtr, _
    ByRef ppDacl As IntPtr, _
    ByRef ppSacl As IntPtr, _
    ByRef ppSecurityDescriptor As IntPtr) As Integer

    'DWORD SetNamedSecurityInfo(
    '  LPTSTR pObjectName,
    '  SE_OBJECT_TYPE ObjectType,
    '  SECURITY_INFORMATION SecurityInfo,
    '  PSID psidOwner,
    '  PSID psidGroup,
    '  PACL pDacl,
    '  PACL pSacl
    ');
    Declare Auto Function SetNamedSecurityInfo Lib "AdvAPI32.DLL" ( _
    ByVal pObjectName As String, _
    ByVal ObjectType As Integer, _
    ByVal SecurityInfo As Integer, _
    ByVal psidOwner As IntPtr, _
    ByVal psidGroup As IntPtr, _
    ByVal pDacl As IntPtr, _
    ByVal pSacl As IntPtr) As Integer

    'BOOL LookupAccountName(
    '  LPCTSTR lpSystemName,
    '  LPCTSTR lpAccountName,
    '  PSID Sid,
    '  LPDWORD cbSid,
    '  LPTSTR ReferencedDomainName,
    '  LPDWORD cchReferencedDomainName,
    '  PSID_NAME_USE peUse
    ');
    Declare Auto Function LookupAccountName Lib "advapi32.dll" ( _
    ByVal lpSystemName As String, _
    ByVal lpAccountName As String, _
    ByVal Sid As IntPtr, _
    ByRef cbSid As Integer, _
    ByVal lpReferencedDomainName As String, _
    ByRef cchReferencedDomainName As Integer, _
    ByRef peUse As IntPtr) As Boolean

    Public Declare Function LocalFree Lib "kernel32" ( _
    ByVal hMem As IntPtr) As Integer

    Sub ChangeOwner(ByRef strPath As String, ByVal strUserName As String)
        Dim pSecDesc, pNewOwner, pOldOwner, deUse As IntPtr
        Dim Win32Error As Win32Exception
        Dim domain_name As String
        Dim ret, sid_len, domain_len As Integer

        ' Series of quick sanity checks before we proceed...

        ' Do we have the required Privilege?
        'If SetPrivileges() = False Then
        'Throw New Exception("Required privilege not held by the user")
        'End If

        ' Does the file even exist?
        If File.Exists(strPath) = False Then
            If Directory.Exists(strPath) = False Then
                Throw New Exception("File or Directory not found")
            End If
        End If

        ' Can we convert the name to a valid SID?
        sid_len = SID_SIZE
        pNewOwner = Marshal.AllocHGlobal(sid_len)
        domain_len = NAME_SIZE
        domain_name = Space(domain_len)
        If LookupAccountName(Nothing, strUserName, pNewOwner, sid_len, domain_name, domain_len, deUse) = False Then
            ret = Marshal.GetLastWin32Error()
            Win32Error = New Win32Exception(ret)
            Throw New Exception(Win32Error.Message)
        End If

        ' get the Security Descriptor and Owner
        ret = GetNamedSecurityInfo(strPath, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, Nothing, pOldOwner, Nothing, Nothing, pSecDesc)
        If ret <> 0 Then
            Win32Error = New Win32Exception(ret)
            Throw New Exception(Win32Error.Message)
        End If

        ' write the new Security Descriptor and Owner
        ret = SetNamedSecurityInfo(strPath, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, pNewOwner, Nothing, Nothing, Nothing)
        If ret <> 0 Then
            Win32Error = New Win32Exception(ret)
            Throw New Exception(Win32Error.Message)
        End If

        ' clean up and go home
        Marshal.FreeHGlobal(pNewOwner)
        LocalFree(pSecDesc)
    End Sub
End Module
Hi,

Thanks for the reply again.
Graye: i found this code on the web and adapted it for my use... sorry for nicking you code :)
I have the feeling i am chasing the wrong solution, like i said i know little about fileownerships on networks etc.

I believe there is a difference between an application having a lock on a file (having it open) and Fileownership. I treated them as the same :(
My problem is that a different networkuser has this file open with, in this case Excel and therefore this application has a lock on that file.
I want to force the file to be unlocked so that i can use it.

Can the AdvAPI32 libary handle things like this or are there other ways to do this programatically?

Thanks again for your help

ulrich



ASKER CERTIFIED SOLUTION
Avatar of graye
graye
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Works perfect...

Thanks alot
ulrich