KnowledgeBase Archive

An Archive of Early Microsoft KnowledgeBase Articles

View on GitHub

Q218965: HOWTO: Obtain the Owner of a File on Windows NT

Article: Q218965
Product(s): Microsoft Visual Basic for Windows
Version(s): WINDOWS:4.0,5.0,6.0; winnt:3.5,3.51,4.0
Operating System(s): 
Keyword(s): kbAPI kbKernBase kbOSWinNT kbVBp kbVBp400 kbVBp500 kbVBp600 kbGrpDSVB kbCodeSnippet
Last Modified: 05-JUN-2001

-------------------------------------------------------------------------------
The information in this article applies to:

- Microsoft Visual Basic Learning Edition for Windows, versions 5.0, 6.0 
- Microsoft Visual Basic Professional Edition for Windows, versions 5.0, 6.0 
- Microsoft Visual Basic Enterprise Edition for Windows, versions 5.0, 6.0 
- Microsoft Visual Basic Standard Edition, 32-bit, for Windows, version 4.0 
- Microsoft Visual Basic Professional Edition, 32-bit, for Windows, version 4.0 
- Microsoft Visual Basic Enterprise Edition, 32-bit, for Windows, version 4.0 
- the operating system: Microsoft Windows NT, versions 3.5, 3.51, 4.0 
- the operating system: Microsoft Windows 2000 
-------------------------------------------------------------------------------

SUMMARY
=======

Retrieving the owner of a file requires obtaining the security descriptor for
the file, then using the security descriptor to get a pointer to the owner's
Security Identifier (SID). Finally, you use the owner's SID to obtain the owner
and domain name of the file.

This article provides a Visual Basic sample code that obtains the owner of a file
on Microsoft Windows NT.

MORE INFORMATION
================

The following sample code retrieves the owner of the file notepad.exe, which is
located in the default Windows folder.

NOTE: If the file is on an NTFS partition, this code returns the assigned owner
of the file, but if it is on a FAT partition, the owner will be "Everyone".

1. Start a new Visual Basic Standard EXE project. Form1 is created by default.

2. Place a command button (Command1) on Form1.

3. Paste the following code into the General Declarations section of Form1:

     Option Explicit

     Private Declare Function GetFileSecurity Lib "advapi32.dll" _
        Alias "GetFileSecurityA" ( _
        ByVal lpFileName As String, _
        ByVal RequestedInformation As Long, _
        pSecurityDescriptor As Byte, _
        ByVal nLength As Long, _
        lpnLengthNeeded As Long _
        ) As Long

     Private Declare Function GetSecurityDescriptorOwner Lib "advapi32.dll" _
        (pSecurityDescriptor As Any, _
        pOwner As Long, _
        lpbOwnerDefaulted As Long) As Long

     Private Declare Function LookupAccountSid Lib "advapi32.dll" _
        Alias "LookupAccountSidA" ( _
        ByVal lpSystemName As String, _
        ByVal Sid As Long, _
        ByVal name As String, _
        cbName As Long, _
        ByVal ReferencedDomainName As String, _
        cbReferencedDomainName As Long, _
        peUse As Long) As Long

     Private Declare Function GetWindowsDirectory Lib "kernel32" _
        Alias "GetWindowsDirectoryA" ( _
        ByVal lpBuffer As String, _
        ByVal nSize As Long) As Long

     Private Const OWNER_SECURITY_INFORMATION = &H1
     Private Const ERROR_INSUFFICIENT_BUFFER = 122&
     Private Const MAX_PATH = 255

     Sub Command1_Click()

        Dim szfilename As String   ' File name to retrieve the owner for
        Dim bSuccess As Long       ' Status variable
        Dim sizeSD As Long         ' Buffer size to store Owner's SID
        Dim pOwner As Long         ' Pointer to the Owner's SID
        Dim name As String         ' Name of the file owner
        Dim domain_name As String  ' Name of the first domain for the owner
        Dim name_len As Long       ' Required length for the owner name
        Dim domain_len As Long     ' Required length for the domain name
        Dim sdBuf() As Byte        ' Buffer for Security Descriptor
        Dim nLength As Long        ' Length of the Windows Directory
        Dim deUse As Long          ' Pointer to a SID_NAME_USE enumerated 
                                   ' type indicating the type of the account

      ' Initialize some required variables.

        bSuccess = 0
        name = ""
        domain_name = ""
        name_len = 0
        domain_len = 0
        pOwner = 0
        szfilename = Space(MAX_PATH)

     ' Obtain the path to the Windows Directory and use the notepad.exe file
     ' as it should be on the system.

     nLength = GetWindowsDirectory(szfilename, Len(szfilename))
     If nLength = 0 Then
       MsgBox "Unable to Obtain the Windows Directory"
     End If
     szfilename = Left$(szfilename, nLength) & "\notepad.exe"

     ' Call GetFileSecurity the first time to obtain the size of the
     ' buffer required for the Security Descriptor.

     bSuccess = GetFileSecurity( _
             szfilename, _
             OWNER_SECURITY_INFORMATION, _
             0, _
             0&, _
             sizeSD)

     If (bSuccess = 0) And _
        (Err.LastDllError <> ERROR_INSUFFICIENT_BUFFER) Then
           MsgBox "GetLastError returned  : " & Err.LastDllError
     End If

     ' Create a buffer of the required size and call GetFileSecurity again.

        ReDim sdBuf(0 To sizeSD - 1) As Byte

     ' Fill the buffer with the security descriptor of the object specified
     ' by the szfilename parameter. The calling process must have the right
     ' to view the specified aspects of the object's security status.

     bSuccess = GetFileSecurity( _
             szfilename, _
             OWNER_SECURITY_INFORMATION, _
             sdBuf(0), _
             sizeSD, _
             sizeSD)

     If (bSuccess <> 0) Then

     ' Obtain the owner's SID from the Security Descriptor.
     '
        bSuccess = GetSecurityDescriptorOwner(sdBuf(0), pOwner, 0&)
        If (bSuccess = 0) Then
            MsgBox "GetLastError returned : " & Err.LastDllError
        End If

     ' Retrieve the name of the account and the name of the first
     ' domain on which this SID is found.  Passes in the Owner's SID
     ' obtained previously.  Call LookupAccountSid twice, the first time
     ' to obtain the required size of the owner and domain names.

        bSuccess = LookupAccountSid(vbNullString, pOwner, name, name_len, _
                                    domain_name, domain_len, deUse)
        If (bSuccess = 0) And _
           (Err.LastDllError <> ERROR_INSUFFICIENT_BUFFER) Then
           MsgBox "GetLastError returned : " & Err.LastDllError
        End If

     '  Allocate the required space in the name and domain_name string
     '  variables. Allocate 1 byte less to avoid the appended NULL character.
     '
        name = Space(name_len - 1)
        domain_name = Space(domain_len - 1)

     '  Call LookupAccountSid again to actually fill in the name of the owner
     '  and the first domain.
     '
        bSuccess = LookupAccountSid(vbNullString, pOwner, name, name_len, _
                                    domain_name, domain_len, deUse)
        If bSuccess = 0 Then
            MsgBox "GetLastError returned : " & Err.LastDllError
        End If

        MsgBox "The Owner of " & szfilename & " is " & name

        End If

     End Sub

4. Press F5 to run the application and then click Command1 to display the owner
  of the file.

Additional query words:

======================================================================
Keywords          : kbAPI kbKernBase kbOSWinNT kbVBp kbVBp400 kbVBp500 kbVBp600 kbGrpDSVB kbCodeSnippet 
Technology        : kbOSWin2000 kbVBSearch kbAudDeveloper kbOSWinSearch kbOSWinNT350 kbOSWinNT400 kbOSWinNT351 kbZNotKeyword6 kbZNotKeyword2 kbVB500Search kbVB600Search kbVBA500 kbVBA600 kbVB500 kbVB600 kbVB400Search kbVB400 kbOSWinNTSearch
Version           : WINDOWS:4.0,5.0,6.0; winnt:3.5,3.51,4.0
Issue type        : kbhowto

=============================================================================

THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Copyright Microsoft Corporation 1986-2002.