Solved

change file ownership in windows XP

Posted on 2004-08-13
9
412 Views
Last Modified: 2012-06-22
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
0
Comment
Question by:c_hubbard
  • 4
  • 3
  • 2
9 Comments
 
LVL 96

Expert Comment

by:Bob Learned
ID: 11795698
Do you want to do this in your program, or would the Windows Explorer be okay?

Bob
0
 

Author Comment

by:c_hubbard
ID: 11807759
Hi Bob,

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

Uli
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 11811082
0
 
LVL 41

Expert Comment

by:graye
ID: 11817436
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
0
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 

Author Comment

by:c_hubbard
ID: 11818769
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)







0
 
LVL 41

Expert Comment

by:graye
ID: 11826685
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
0
 

Author Comment

by:c_hubbard
ID: 11828359
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



0
 
LVL 41

Accepted Solution

by:
graye earned 125 total points
ID: 11837092
Yep, you're right.... the two issues are complete different.  

But look on the bright side... you now know how to take ownership of a file ?!?!?

Now... on to answering the original question!   Oddly enough, Windows handles file locking in two completely different ways.... one way for files that are opened locally, and an different way for files that are opened via a network share.  I kinda gathered from your situation, that the files are opened over the network via a network share.

Here is a chunk of code that demonstrates the APIs invovled.  It is not a complete solution... it's merely lists the opened files.  To make it close a connection forcably, you'd use the example below to find the "file ID", then follow it with this API

'NET_API_STATUS NetFileClose(
'  LMSTR servername,
'  DWORD fileid
');
Declare Auto Function NetFileClose Lib "Netapi32" ( _
ByVal servername As String, _
ByVal fileid AsInteger) As Integer

I'm gonna post the code now, rather than have you find my own code example yourself (How strange!)

Imports System.Runtime.InteropServices

    'typedef struct _FILE_INFO_3 {
    '  DWORD fi3_id;
    '  DWORD fi3_permissions;
    '  DWORD fi3_num_locks;
    '  LPWSTR fi3_pathname;
    '  LPWSTR fi3_username;
    '} FILE_INFO_3, *PFILE_INFO_3, *LPFILE_INFO_3;
    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto, Pack:=4)> _
    Structure FILE_INFO_3
        Dim fi3_id As Integer
        Dim fi3_permission As Integer
        Dim fi3_num_locks As Integer
        Dim fi3_pathname As String
        Dim fi3_username As String
    End Structure

    'NET_API_STATUS NetFileEnum(
    '  LPWSTR servername,
    '  LPWSTR basepath,
    '  LPWSTR username,
    '  DWORD level,
    '  LPBYTE* bufptr,
    '  DWORD prefmaxlen,
    '  LPDWORD entriesread,
    '  LPDWORD totalentries,
    '  PDWORD_PTR resume_handle
    ');
    Declare Auto Function NetFileEnum Lib "Netapi32" ( _
    ByVal servername As String, _
    ByVal basepath As String, _
    ByVal username As String, _
    ByVal level As Integer, _
    ByRef bufptr As IntPtr, _
    ByVal prefmaxlen As Integer, _
    ByRef entriesread As Integer, _
    ByRef totalentries As Integer, _
    ByVal resume_handle As IntPtr) As Integer

    Const MAX_PREFERRED_LENGTH As Integer = -1

    Const PERM_FILE_READ As Integer = &H1
    Const PERM_FILE_WRITE As Integer = &H2
    Const PERM_FILE_CREATE As Integer = &H4
    Const ACCESS_EXEC As Integer = &H8
    Const ACCESS_DELETE As Integer = &H10
    Const ACCESS_ATRIB As Integer = &H20
    Const ACCESS_PERM As Integer = &H40

    Private Sub DoIt(ByVal Server_Name As String)
        Dim dwIndex, dwStatus, dwReadEntries, dwTotalEntries As Integer
        Dim pCurrent As FILE_INFO_3
        Dim iPtr, pBuffer As IntPtr

        dwStatus = NetFileEnum(Server_Name , Nothing, Nothing, 3, pBuffer, MAX_PREFERRED_LENGTH, dwReadEntries, dwTotalEntries, Nothing)
        Debug.WriteLine(dwStatus & ", " & dwReadEntries & ", " & dwTotalEntries)

        For dwIndex = 0 To dwReadEntries - 1

            iPtr = New IntPtr(pBuffer.ToInt32 + (dwIndex * Len(pCurrent)))
            pCurrent = CType(Marshal.PtrToStructure(iPtr, GetType(FILE_INFO_3)), FILE_INFO_3)

            Debug.WriteLine("dwIndex=" & dwIndex)
            Debug.WriteLine("   id: " & pCurrent.fi3_id)
            Debug.WriteLine("   num_locks: " & pCurrent.fi3_num_locks)
            Debug.WriteLine("   pathname: " & pCurrent.fi3_pathname)
            Debug.WriteLine("   permission: " & pCurrent.fi3_permission)
            Debug.WriteLine("   username: " & pCurrent.fi3_username)
        Next

        MsgBox("Done")
    End Sub
0
 

Author Comment

by:c_hubbard
ID: 11839512
Works perfect...

Thanks alot
ulrich
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Deserialize JSON array VB.Net problem 3 36
Total in textboxes 9 35
.net VBA word safemode 1 24
Round a string to two digits 12 24
1.0 - Introduction Converting Visual Basic 6.0 (VB6) to Visual Basic 2008+ (VB.NET). If ever there was a subject full of murkiness and bad decisions, it is this one!   The first problem seems to be that people considering this task of converting…
It’s quite interesting for me as I worked with Excel using vb.net for some time. Here are some topics which I know want to share with others whom this might help. First of all if you are working with Excel then you need to Download the Following …
This video discusses moving either the default database or any database to a new volume.
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now