Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

Change file or folder ownership on NTFS

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Change file or folder ownership on NTFS

    Change ownership of a file or folder on an NTFS partition,
    Based on code from Microsoft. Programmatically Change Ownership of a File or Folder

    Added a function to do a folder with all subfolders and files.

    Microsoft article...
    SUMMARY
    This article explains how to call the low-level access control functions
    from Microsoft Visual Basic to change ownership of a file or folder.

    MORE INFORMATION
    If a user has been granted the SE_RESTORE_NAME privilege
    ("Restore files and directories"), that user can change the owner
    of a file or folder on a secure file system. By default,
    Administrators and Backup Operators hold the SE_RESTORE_NAME privilege.

    In addition to being present in the process access token,
    the SE_RESTORE_NAME privilege must also be granted (enabled).
    You can grant this privilege by using the AdjustTokenPrivileges() function.
    After the privilege has been granted, the process can set any valid user
    or group SID as the owner of a file or folder.

    Sample Code
    The following sample Visual Basic code demonstrates how to grant the
    SE_RESTORE_NAME privilege and then set the owner of a file or directory.
    The FileOwnerChange() function takes a file or folder name and a user name.
    It then makes the specified user the owner of the specified file or folder.

    NOTE: This code is useful only when targeting files or folders that reside
    on a secure file system, such as NTFS. The FAT and FAT32 file systems are not secure,
    and therefore, files on these file systems do not have owners.
    Last edited by Pierre Bellisle; 25 Nov 2019, 09:15 PM.

  • #2
    Click image for larger version

Name:	SetFileSecurity01.png
Views:	12
Size:	18.6 KB
ID:	786842

    Code:
    'Change ownership of a file or folder on an NTFS partition from MS.
    
    'Based on MicroSoft...
    
    ' This article explains how to call the low-level access control functions
    ' from Microsoft Visual Basic to change ownership of a file or folder.
    '
    ' If a user has been granted the SE_RESTORE_NAME privilege
    ' ("Restore files and directories"), that user can change the owner
    ' of a file or folder on a secure file system. By default,
    ' Administrators and Backup Operators hold the SE_RESTORE_NAME privilege.
    '
    ' In addition to being present in the process access token,
    ' the SE_RESTORE_NAME privilege must also be granted (enabled).
    ' You can grant this privilege by using the AdjustTokenPrivileges() function.
    ' After the privilege has been granted, the process can set any valid user
    ' or group SID as the owner of a file or folder.
    '
    ' Sample Code
    ' The following sample Visual Basic code demonstrates how to grant the
    ' SE_RESTORE_NAME privilege and then set the owner of a file or directory.
    ' The FileOwnerChange() function takes a file or folder name and a user name.
    ' It then makes the specified user the owner of the specified file or folder.
    '
    ' NOTE: This code is useful only when targeting files or folders that reside
    ' on a secure file system, such as NTFS. The FAT and FAT32 file systems are not secure,
    ' and therefore, files on these file systems do not have owners.
    
    #COMPILE EXE '#Win#
    #REGISTER NONE
    '#RESOURCE "PbrAdmin00.pbr"
    #DIM ALL
    #INCLUDE "Win32Api.inc"
    #INCLUDE "WinNT.inc"
    
    %UNLEN                  = 256
    $SE_TAKE_OWNERSHIP_NAME = "SeTakeOwnershipPrivilege"
    $SE_RESTORE_NAME        = "SeRestorePrivilege"
    
    $AppName  = "File or folder ownership change"
    %EditLog  = 101
    %EditPath = 102
    %ButtonGo = 201
    
    GLOBAL hDlg  AS DWORD
    GLOBAL hEdit AS DWORD
    '_____________________________________________________________________________
    
    SUB TextDel()
    
     SendMessage(hEdit, %WM_SETTEXT, 0, BYVAL 0) 'Erase all, Microsoft recommended way
    
    END SUB
    '_____________________________________________________________________________
    
    SUB TextAdd(BYVAL sText AS STRING)
    
     SendMessage(hEdit, %EM_SETSEL, -1, -1) 'Move the caret to the end of text.
     sText = sText & $CRLF 'Add a CRLF
     SendMessage(hEdit, %EM_REPLACESEL, %TRUE, BYVAL STRPTR(sText)) 'Insert the string at caret position.
    
    END SUB
    '______________________________________________________________________________
    
    FUNCTION FileExist(sFileNameTry AS STRING, Attr AS LONG) AS LONG
    
     SELECT CASE Attr                                '%INVALID_HANDLE_VALUE = &hFFFFFFFF???
       CASE 1 : FUNCTION = (GetFileAttributes(BYVAL STRPTR(sFileNameTry)) AND &HFF000010???) = %FILE_ATTRIBUTE_DIRECTORY 'Folder excluding file
       CASE 2 : FUNCTION = (GetFileAttributes(BYVAL STRPTR(sFileNameTry)) AND &HFF000010???) = %FALSE 'File excluding folder
       CASE 3 : FUNCTION = (GetFileAttributes(BYVAL STRPTR(sFileNameTry)) < %INVALID_HANDLE_VALUE) 'File and folder
     END SELECT
    
    END FUNCTION
    '______________________________________________________________________________
    
    FUNCTION FileSystemGet(BYVAL sDrive AS STRING, zFileSystem AS ASCIIZ * 10) AS LONG
    
     GetVolumeInformation(LEFT$(sDrive, 2), BYVAL 0, 0, BYVAL 0, 0, BYVAL 0, zFileSystem, SIZEOF(zFileSystem))
     TextAdd("FileSystem: " & zFileSystem)
     IF zFileSystem = "NTFS" THEN
       FUNCTION = %TRUE
     END IF
    
    END FUNCTION
    '______________________________________________________________________________
    
    FUNCTION IsUserAdmin() AS LONG
     LOCAL NtAuthority         AS SID_IDENTIFIER_AUTHORITY
     LOCAL AdministratorsGroup AS LONG
     LOCAL IsMember            AS LONG
    
     NtAuthority.value(5) = 5 'SECURITY_NT_AUTHORITY = 5
     IF AllocateAndInitializeSid(NtAuthority, 2, %SECURITY_BUILTIN_DOMAIN_RID, _
                                 %DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, _
                                 AdministratorsGroup) THEN
        IF CheckTokenMembership(%NULL, BYVAL AdministratorsGroup, IsMember) THEN
          IF IsMember THEN
            FUNCTION = 1 'Yep, administrator
          END IF
        END IF
        FreeSid(BYVAL AdministratorsGroup)
     END IF
    
    END FUNCTION
    '_____________________________________________________________________________
    
    FUNCTION TokenPrivilegesAdjust(sPrivilege AS STRING, DoEnable AS LONG) AS LONG
     LOCAL TokenPrivilege AS TOKEN_PRIVILEGES
     LOCAL UniqueId       AS QUAD 'LUID
     LOCAL hToken         AS DWORD
    
     IF OpenProcessToken(GetCurrentProcess(), %TOKEN_ADJUST_PRIVILEGES, hToken) THEN
       IF LookupPrivilegeValue($NUL, BYVAL STRPTR(sPrivilege), UniqueId) THEN
         TokenPrivilege.Privileges(0).Luid = UniqueId
         TokenPrivilege.PrivilegeCount     = 1
         IF DoEnable THEN
           TokenPrivilege.Privileges(0).Attributes = %SE_PRIVILEGE_ENABLED
         ELSE
           TokenPrivilege.Privileges(0).Attributes = 0
         END IF
         IF AdjustTokenPrivileges(hToken, %FALSE, BYVAL VARPTR(TokenPrivilege), 0, BYVAL 0, 0) THEN
           IF GetLastError() THEN
             TextAdd("AdjustTokenPrivileges failed with error.")
           ELSE
             IF DoEnable THEN
               TextAdd("AdjustTokenPrivileges success.")
             ELSE
               TextAdd("AdjustTokenPrivileges closed.")
             END IF
             CloseHandle(hToken)
             FUNCTION = %TRUE
           END IF
         ELSE
           TextAdd("AdjustTokenPrivileges failed.")
         END IF
       ELSE
         TextAdd("LookupPrivilegeValue failed.")
       END IF
     ELSE
        TextAdd("OpenProcessToken failed.")
     END IF
    
    END FUNCTION
    '______________________________________________________________________________
    
    SUB FileOwnerChange(sFileName AS STRING, OwnerAccountName AS STRING)
     LOCAL SecurityDescriptor AS SECURITY_DESCRIPTOR
     LOCAL SecurityId         AS STRING 'SID
     LOCAL sDomainName        AS STRING '%MAX_DOMAIN_NAME_LEN
     LOCAL pSidNameUse        AS DWORD  'SID type
     LOCAL SecurityIdSize     AS LONG
     LOCAL DomainNameSize     AS LONG
    
       LookupAccountName(BYVAL %NULL, (OwnerAccountName), BYVAL %NULL, SecurityIdSize, _
                         BYVAL %NULL, DomainNameSize, pSidNameUse)
       IF SecurityIdSize THEN
         SecurityId  = NUL$(SecurityIdSize)
         sDomainName = NUL$(DomainNameSize)
         IF LookupAccountName(BYVAL %NULL, (OwnerAccountName), BYVAL STRPTR(SecurityId), SecurityIdSize, _
                              (sDomainName), DomainNameSize, pSidNameUse) THEN
           IF InitializeSecurityDescriptor(SecurityDescriptor, %SECURITY_DESCRIPTOR_REVISION) THEN
             IF SetSecurityDescriptorOwner(SecurityDescriptor, BYVAL STRPTR(SecurityId), %FALSE) <> %FALSE THEN
               IF SetFileSecurity((sFileName), %OWNER_SECURITY_INFORMATION, SecurityDescriptor) <> %FALSE THEN
                 TextAdd("Owner of " & sFileName & " changed to " & OwnerAccountName)
                 SetFileAttributes((sFileName), %FILE_ATTRIBUTE_NORMAL)
                 TextAdd("Attribute of " & sFileName & " changed to FILE_ATTRIBUTE_NORMAL")
               ELSE
                 TextAdd("SetFileSecurity failed.")
               END IF
             ELSE
               TextAdd("SetSecurityDescriptorOwner failed")
             END IF
           ELSE
             TextAdd("InitializeSecurityDescriptor failed")
           END IF
         ELSE
           TextAdd("LookupAccountName failed")
         END IF
       END IF
    
    END SUB
    '______________________________________________________________________________
    
    FUNCTION FolderOwnerChange(BYVAL StartIn AS STRING, OwnerAccountName AS STRING) AS LONG
     LOCAL FileFound   AS WIN32_FIND_DATA
     LOCAL hDir        AS DWORD
     LOCAL FolderCount AS LONG
     LOCAL Looper      AS LONG
    
     IF ASC(StartIn , - 1) <> 92 THEN StartIn = StartIn & "\"
     FileOwnerChange((StartIn), OwnerAccountName)
    
     DIM SearchFor(0 TO 0) AS STRING
     SearchFor(0) = StartIn
    
     hDir = FindFirstFile(BYCOPY SearchFor(0) & "*.*", FileFound)
     IF hDir <> %INVALID_HANDLE_VALUE THEN
       DO
         IF (FileFound.dwFileAttributes AND %FILE_ATTRIBUTE_DIRECTORY) THEN
           IF ASC(FileFound.cFilename, -1) <> 46 THEN
             INCR FolderCount
             REDIM PRESERVE SearchFor(0 TO FolderCount)
             SearchFor(FolderCount) = SearchFor(0) & FileFound.cFilename & "\"
             FileOwnerChange(SearchFor(0) & FileFound.cFilename, OwnerAccountName)
           END IF
         ELSE
           FileOwnerChange(SearchFor(0) & FileFound.cFilename, OwnerAccountName)
         END IF
       LOOP WHILE FindNextFile(hDir, FileFound)
    
       FOR Looper = 1 TO FolderCount
         SearchFor(0) = SearchFor(Looper)
         FolderOwnerChange SearchFor(0), OwnerAccountName
       NEXT
       FindClose(hDir)
     END IF
    
    END FUNCTION
    '______________________________________________________________________________
    
    CALLBACK FUNCTION DlgProc
     STATIC zFileName   AS ASCIIZ * %MAX_PATH
     STATIC zUserName   AS ASCIIZ * %UNLEN
     STATIC zFileSystem AS ASCIIZ * 10
    
     SELECT CASE CBMSG
    
       CASE %WM_INITDIALOG
         hEdit = GetDlgItem(CBHNDL, %EditLog)
         PostMessage(hEdit, %EM_SETSEL, -1, -1) 'Deselect text
    
         TextAdd($AppName)
         GetUserName(zUserName, %UNLEN)
         TextAdd("UserName: " & zUserName)
    
       CASE %WM_COMMAND
         SELECT CASE LOWRD(CBWPARAM)
    
           CASE %ButtonGo
             IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
               IF IsUserAdmin() THEN
                 IF TokenPrivilegesAdjust($SE_RESTORE_NAME, %TRUE) THEN
                   TextAdd(zUserName & " is an administrator")
                   CONTROL GET TEXT hDlg, %EditPath TO zFileName
                   IF FileExist((zFileName), 3) THEN
                     IF FileSystemGet(zFileName, zFileSystem) THEN 'Its NTFS
                       IF FileExist((zFileName), 1) THEN 'Folder
                         'Use this to change ownership of a Folder and all subfolders and files.
                         TextAdd("Folder name: " & zFileName)
                         FolderOwnerChange((zFileName), (zUserName))
                       ELSE 'File
                         'Use this to change ownership of one files only.
                         TextAdd("File name: " & zFileName)
                         FileOwnerChange((zFileName), (zUserName))
                       END IF
                     ELSE
                       TextAdd("Unsupporetd filesystem: " & zFileSystem & ", must be NTFS")
                     END IF
                   ELSE
                     IF LEN(zFileName) THEN
                       TextAdd("Invalid folder or filename " & zFileName)
                     ELSE
                       TextAdd("Please give a folder or filename")
                       IF 01 THEN
                         TextDel()
                         TextAdd($AppName)
                         TextAdd("UserName: " & zUserName)
                         CONTROL SET TEXT hDlg, %EditPath, "C:\Tmp3\zzz-Delme.txt"
                       END IF
                     END IF
                   END IF
                    TokenPrivilegesAdjust($SE_RESTORE_NAME, %FALSE)
                 END IF
               END IF
             ELSE
               TextAdd("Please restart program as an administrator")
             END IF
    
         END SELECT
    
       CASE %WM_SIZE
         IF CBWPARAM <> %SIZE_MINIMIZED THEN
           MoveWindow(GetDlgItem(hDlg, %EditPath), 3, 3, LO(WORD, CBLPARAM) - 50, 20, %TRUE)
           MoveWindow(GetDlgItem(hDlg, %ButtonGo), LO(WORD, CBLPARAM) - 43, 3, 40, 21, %TRUE)
           MoveWindow(hEdit, 3, 30, LO(WORD, CBLPARAM) - 6, HI(WORD, CBLPARAM) - 36, %TRUE)
         END IF
    
     END SELECT
    
    END FUNCTION
    '_____________________________________________________________________________
    
    FUNCTION PBMAIN() AS LONG
     LOCAL sCueBannerUnicode1 AS STRING
     LOCAL hIcon              AS DWORD
    
     MessageBox(hDlg, SPACE$(40) & "Be carefull !", $AppName, %MB_OK OR %MB_TOPMOST)
    
     DIALOG NEW %HWND_DESKTOP, $AppName, , , 300, 200, _
     %WS_CAPTION OR %WS_MINIMIZEBOX OR %WS_MAXIMIZEBOX OR %WS_SYSMENU OR %WS_THICKFRAME, 0 TO hDlg
    
     hIcon = ExtractIcon(GetModuleHandle(""), "Shell32.dll", 294)
     SetClassLong(hDlg, %GCL_HICON,hIcon)
    
     CONTROL ADD TEXTBOX, hDlg, %EditPath, "", 2, 2, 296, 12, %WS_CHILD OR %WS_VISIBLE OR _
     %WS_TABSTOP OR %ES_LEFT OR %ES_NOHIDESEL, %WS_EX_CLIENTEDGE OR %WS_EX_LEFT
     sCueBannerUnicode1 = UCODE$("Target file or folder ")
     SendMessage(GetDlgItem(hDlg, %EditPath), %EM_SETCUEBANNER, 1, BYVAL STRPTR(sCueBannerUnicode1))
    
     CONTROL ADD BUTTON, hDlg, %ButtonGo, "&Go", 268, 2, 30, 12, _
     %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %BS_TEXT OR %BS_PUSHBUTTON OR _
     %BS_CENTER OR %BS_VCENTER, %WS_EX_LEFT OR %WS_EX_LTRREADING
    
     CONTROL ADD TEXTBOX, hDlg, %EditLog, "", 2, 2, 296, 66, %WS_CHILD OR %WS_VISIBLE OR _
     %WS_TABSTOP OR %ES_LEFT OR %ES_MULTILINE OR %ES_AUTOVSCROLL OR %WS_VSCROLL OR _
     %ES_NOHIDESEL OR %ES_WANTRETURN, %WS_EX_CLIENTEDGE OR %WS_EX_LEFT
    
     DIALOG SHOW MODAL hDlg CALL DlgProc
     DestroyIcon(hIcon)
    
    END FUNCTION
    '______________________________________________________________________________
    '
    Last edited by Pierre Bellisle; 25 Nov 2019, 09:16 PM.

    Comment

    Working...
    X