We help IT Professionals succeed at work.

xp permissions

Ignatz asked
we have an install program that needs to run as Administrator.  Some of the directories and files need to allow User group to edit/create/delete files/folders under our main folder.  This is no problem under 95/95/ME/2000, but XP locks everything down.
How can I change a directory's, and all sub-directories/files permissions to allow User group full access?
I've checked out SetSecurityInfo() but can't make heads or tails of it.
Thank You
Watch Question

Your question is not clear.  Do you want to change the permissions from:

1) The desktop via user interaction?
2) Via your program (and the SetSecurityInfo())?
3) Via your installer?


programatically using C++/win API non-MFC...As part of our installation program.
Thank You!

OK, thanks.  So your question is possibly "how do I use the WIN32 API function SetSecurityInfo() in my application to set the security of a folder or file?"

But your original question still seems to be oriented toward installation, not run-time.

Please elaborate.


we have our own installation .exe that installs some fonts, programs, dll's, and creates some .ini and other files/directories.  As part of this installation program I want to set the permissions on a directory such that any User logged in can modify/create/delete any file/folder under/in this directory.
Thank You

OK, I think I understand.

So now back to your problem.  What is it about SetSecurityInfo() that you are having trouble with?

I can suggest a good resource on this.

Julian Templeman's book, Beginning Windows NT Programming by WROX has an entire chapter (chapter 8) on this topic.  I'd suggest you grab a copy.


I have been unable to find an example of using SetSecurityInfo() that explains how to get, and what to set. How to get SID so that all users will have access,
What to set DACL and SACL to, etc.  A little cryptic without have a good example.  I'll try to grab a copy of the book sometime soon.
Thank You


maybe use SetFileSecurity() instead?

Once you understand [S|D]ACL the use of SetSecurityInfo() will be quite straightforward.  But I don't think I can explain the ACL concept and usage here.  It's a basic NT/2000/XP concept but needs some background before it can be understood especially if you are not used to programming security.

It is covered in many books on NT/2000 programming but I found Templeman's explanation to be among the best.  It tells you what you need to know without the extra junk you'll never use.

I think you can download the programming samples from the WROX web site free of charge.  That might get you started inthe right direction but I'd really suggest the book so that you fully understand what you are doing and that you don't inadvertently open up security holes in the users system.


Should something like this work?

     SID sid;
     DWORD dwsid;
     char szTmp[300];
     DWORD dwtmp=300;
     SID_NAME_USE snu;

     dwsid = sizeof(SID);

here is some snippets from working code..
if i remember, it scans a network share looking for
files that are not owned by the current user and
resetting the ownership to the current user.
Not quite what you want, but it does show basic SID
operations. (in VB cause it had a GUI, but API calls
are API calls are API calls)
Option Explicit


' typedef enum _SE_OBJECT_TYPE (ACCCTRL.H)
Private Const SE_FILE_OBJECT = 1
Private Const SE_SERVICE = 2
Private Const SE_PRINTER = 3
Private Const SE_REGISTRY_KEY = 4
Private Const SE_LMSHARE = 5
Private Const SE_KERNEL_OBJECT = 6
Private Const SE_WINDOW_OBJECT = 7
Private Const SE_DS_OBJECT = 8
Private Const SE_DS_OBJECT_ALL = 9

' drive types for GetDriveType call (winbase.h)
Private Const DRIVE_UNKNOWN = 0
Private Const DRIVE_NO_ROOT_DIR = 1
Private Const DRIVE_REMOVABLE = 2
Private Const DRIVE_FIXED = 3
Private Const DRIVE_REMOTE = 4
Private Const DRIVE_CDROM = 5
Private Const DRIVE_RAMDISK = 6
Private Type tSID_IDENTIFIER_AUTHORITY  'winnt.h
     V0 As Byte
     V1 As Byte
     V2 As Byte
     V3 As Byte
     V4 As Byte
     V5 As Byte
End Type

' definition of  a SID from winnt.h
Private Type tSID       'winnt.h
     Revision As Byte
     SubAuthorityCount As Byte
     IdentifierAuthority As tSID_IDENTIFIER_AUTHORITY
     SubAuthority As Long
End Type

'Our sid contains a flag for whether we have to deallocate at destruction
Private Type OurSid
    FreeMe As Boolean
    System As String    'System we got a SID from for object.. (ie, file-server for a file,localsys for a user)
    Domain As String    ' filled in by GetSIDAccount
    Account As String   '    "
    SIDType As Byte     '    "
    AccountType As Byte '   Only valid for SID for a Account.
    pSID As Long
End Type

' SID related API calls
Private Declare Function GetNamedSecurityInfoA Lib "advapi32.dll" (ByVal pObjName As Long, ByVal ObjType As Long, ByVal SecInfo As Long, ByRef pSIDOwner As Long, ByRef pSIDGroup As Long, ByRef pDACL As Long, ByRef pSACL As Long, ByRef pSD As Long) As Long
Private Declare Function LookupAccountNameA Lib "advapi32.dll" (ByVal SystemName As Long, ByVal AccountName As Long, ByVal pSID As Long, ByRef cbSID As Long, ByVal DomainName As Long, ByRef cbDomainName As Long, ByRef SID_Name_use As Long) As Integer
Private Declare Function LookupAccountSidA Lib "advapi32.dll" (ByVal SystemName As Long, ByVal pSID As Long, ByVal Name As Long, ByRef cbName As Long, ByVal DomainName As Long, ByRef cbDomainName As Long, ByRef SID_Name_use) As Boolean
Private Declare Function CopySid Lib "advapi32.dll" (ByVal nDestLength As Long, ByVal pDestSID As Long, ByVal pSrcSID As Long) As Boolean
Private Declare Function GetLengthSid Lib "advapi32.dll" (ByVal pSID As Long) As Long
Private Declare Function IsValidSid Lib "advapi32.dll" (ByVal pSID As Long) As Boolean
Private Declare Function EqualSid Lib "advapi32.dll" (ByVal pSID1 As Long, ByVal pSID1 As Long) As Boolean
Private Declare Function GetSidIdentifierAuthority Lib "advapi32.dll" (ByVal pSID As Long) As Long
Private Declare Function AllocateAndInitializeSid Lib "advapi32.dll" (ByVal pSIDAuth As Long, ByVal nSubAuth As Byte, A0 As Long, A1 As Long, A2 As Long, A3 As Long, a4 As Long, a5 As Long, a6 As Long, a7 As Long, ByRef newSID As Long) As Boolean
Private Declare Sub FreeSid Lib "advapi32.dll" (ByVal pSID As Long)

'Utility API calls needed
Private Declare Function LocalFree Lib "kernel32.dll" (ByRef pBuf As Long) As Long
Private Declare Function GetDriveTypeA Lib "kernel32.dll" (ByVal RootPath As Long) As Integer
Private Declare Function GetComputerNameA Lib "kernel32.dll" (ByVal NameBuf As Long, ByRef buflen As Long) As Boolean
Private Declare Function GetProcessHeap Lib "kernel32.dll" () As Long
Private Declare Function HeapAlloc Lib "kernel32.dll" (ByVal hHeap As Long, ByVal dwFlags As Long, ByVal dwBytes As Long) As Long
Private Declare Function HeapFree Lib "kernel32.dll" (ByVal hHeap As Long, ByVal dwFlags As Long, ByVal lpMem As Long) As Boolean

'Networking APIs to get path server names
Private Declare Function WNetGetResourceInformationA Lib "mpr.dll" (ByVal NR As Long, ByVal NRout As Long, buflen As Long, dirname As Long) As Long
Private Declare Function WNetGetConnectionA Lib "mpr.dll" (ByVal LocalName As Long, ByVal RemoteName As Long, buflen As Long) As Long
Private Declare Function WNetGetUserA Lib "mpr.dll" (ByVal DevName As Long, ByVal username As Long, buflen As Long) As Long
' Private Storage for this instance
Private memberSID As OurSid

Public Property Get Domain() As String
   Domain = memberSID.Domain
End Property
Public Property Get Account() As String
   Account = memberSID.Account
End Property
Public Property Get SIDType() As Integer
   SIDType = memberSID.SIDType
End Property
Public Property Get SIDpointer() As Long
   SIDpointer = memberSID.pSID
End Property
Public Property Get AccountType() As Long
   AccountType = memberSID.AccountType
End Property

Private Sub Class_Initialize()
    memberSID.Domain = ""
    memberSID.Account = ""
    memberSID.FreeMe = False
    memberSID.SIDType = 0
    memberSID.AccountType = 0
    memberSID.System = ""
End Sub
Private Sub Class_Terminate()
    ' Free any SIDs we have allocated
End Sub

Private Sub FreeSidStorage()
    If memberSID.FreeMe Then
        FreeSid (memberSID.pSID)
    End If
End Sub

Private Function SetOurSid(SrcSid As Long) As Boolean
    Dim LD As Long  'Long dummy
    Dim pSrcAuth As Long, newSID As Long
    Dim SIDLength As Long
    Dim brc As Boolean
    LD = 0
    SetOurSid = False
    If IsValidSid(SrcSid) Then
        pSrcAuth = GetSidIdentifierAuthority(SrcSid)
        brc = AllocateAndInitializeSid(pSrcAuth, 8, LD, LD, LD, LD, LD, LD, LD, LD, newSID)
        If brc Then
            SIDLength = GetLengthSid(SrcSid)
            memberSID.pSID = newSID
            memberSID.FreeMe = True
            brc = CopySid(SIDLength, newSID, SrcSid)        ' copy the SID value
            If brc Then SetOurSid = True
        End If
    End If
End Function

Function GetFileSID(strPath As String) As Boolean
    Dim pSIDOwner As Long, pSD As Long, rc As Long
    Dim ANSIPath As String, Drivetype As Integer
    'Dims for finding servername:
    Dim ServerName As String, NullSpot As Integer, TempPath As String, SlashSpot As Integer, pathbuflen As Long
    Dim ANSIDrive As String, ANSIDriveWithSlash As String, brc As Boolean
    FreeSidStorage      'Free sid storage if someone reuses us...
    GetFileSID = False
    memberSID.System = ""
    ANSIPath = StrConv(strPath, vbFromUnicode)
    ANSIDrive = StrConv(Left$(strPath, 2), vbFromUnicode)
    ANSIDriveWithSlash = StrConv(Left$(strPath, 2) & "\", vbFromUnicode)
    TempPath = String(255, vbNullChar)
    ' Lets determine if we were passed a UNC or driveletter name
    If Left$(strPath, 2) = "\\" Then                        'it's a UNC
        SlashSpot = InStr(3, strPath, "\")
        ServerName = Mid$(strPath, 3, SlashSpot - 3)
        If Mid$(strPath, 2, 1) <> ":" Then Exit Function    ' Not a UNC, Not a drive letter ???
        pathbuflen = 255
        Drivetype = GetDriveTypeA(StrPtr(ANSIDriveWithSlash))
        If Drivetype = DRIVE_REMOTE Then
            rc = WNetGetConnectionA(StrPtr(ANSIDrive), StrPtr(TempPath), pathbuflen) ' we have a drive letter-try to get a share name
            If rc = 0 Then
                TempPath = StrConv(TempPath, vbUnicode)                             ' now parse to get servername
                NullSpot = InStr(TempPath, vbNullChar)
                If NullSpot <> 0 Then TempPath = Left$(TempPath, NullSpot - 1)
                SlashSpot = InStr(3, strPath, "\")
                ServerName = Mid$(strPath, 3, SlashSpot - 3)
                ' failure on getting share name !
                MsgBox "bad share:" & strPath
                Exit Function
            End If
            TempPath = String(255, vbNullChar)
            brc = GetComputerNameA(StrPtr(TempPath), pathbuflen)
            If brc Then
                TempPath = StrConv(TempPath, vbUnicode)
                NullSpot = InStr(TempPath, vbNullChar)
                If NullSpot <> 0 Then TempPath = Left$(TempPath, NullSpot - 1)
                ServerName = "\\" & TempPath
                MsgBox "Bad local computer name for path:" & strPath
                Exit Function
            End If
        End If
     End If
     rc = GetNamedSecurityInfoA(StrPtr(ANSIPath), SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, pSIDOwner, 0, 0, 0, pSD)
    If rc = 0 Then
        If SetOurSid(pSIDOwner) Then
            memberSID.System = ServerName
            GetFileSID = True
            MsgBox "Setoursid failed"
        End If
    End If
End Function

Function GetSIDAccount() As Boolean
    Dim ANSIName As String, ANSIDomain As String, ANSIServer As String
    Dim Name As String, DomainName As String
    Dim NameSize As Long, DomainSize As Long
    Dim brc As Boolean, SIDType As Long
     NameSize = 128
    DomainSize = 128
    ANSIName = String(NameSize, "x")
    ANSIDomain = String(DomainSize, "x")
    ANSIServer = StrConv(memberSID.System, vbFromUnicode)
    memberSID.Account = ""
    memberSID.Domain = ""
    memberSID.SIDType = 0
    GetSIDAccount = False
    brc = LookupAccountSidA(StrPtr(ANSIServer), memberSID.pSID, StrPtr(ANSIName), NameSize, StrPtr(ANSIDomain), DomainSize, SIDType)
    If brc Then
        memberSID.Account = Left$(StrConv(ANSIName, vbUnicode), NameSize)
        memberSID.Domain = Left$(StrConv(ANSIDomain, vbUnicode), DomainSize)
        memberSID.SIDType = SIDType
        GetSIDAccount = True
        MsgBox " (error)= " & Err.LastDllError
    End If
End Function

Function SidIsEqual(AnotherSIDClass As SIDclass) As Boolean
    SidIsEqual = False
    If EqualSid(memberSID.pSID, AnotherSIDClass.SIDpointer) Then SidIsEqual = True
End Function

Function GetUserSID(strUser As String) As Boolean
   Dim pSID As Long, pSD As Long, rc As Long, irc As Integer, AccountType As Long, cbDomainName As Long, cbSID As Long
   Dim ANSIDomain As String, ANSIAccountName As String, ANSIsysname As String
   Dim Domain As String, NullSpot As Integer
   Dim pHeap As Long, pBuf As Long, brc As Boolean
    FreeSidStorage      'Free sid storage if someone reuses us...
    GetUserSID = False
    memberSID.System = ""
    memberSID.Domain = ""
    memberSID.Account = ""

    ANSIDomain = String(128, vbNullChar)
    ANSIAccountName = StrConv(strUser, vbFromUnicode)
    ANSIsysname = StrConv("", vbFromUnicode)
    ' first get required buffer size
    cbDomainName = 128
    cbSID = 1000
    pHeap = GetProcessHeap()
    pBuf = HeapAlloc(pHeap, 0, cbSID)
    irc = LookupAccountNameA(StrPtr(ANSIsysname), StrPtr(ANSIAccountName), pBuf, cbSID, StrPtr(ANSIDomain), cbDomainName, AccountType)
        If irc = 0 Then
            brc = HeapFree(pHeap, 0, pBuf)
            Exit Function
        End If
    Domain = StrConv(ANSIDomain, vbUnicode)
    NullSpot = InStr(Domain, vbNullChar)
    Domain = Left$(Domain, NullSpot - 1)
    If SetOurSid(pBuf) Then
        memberSID.Domain = Domain
        memberSID.Account = strUser
        memberSID.System = ""
        memberSID.AccountType = AccountType
        GetUserSID = True
    End If
    brc = HeapFree(pHeap, 0, pBuf)
End Function

Function GetLoggedOnUser() As String
    Dim szrc As String
    Dim ANSIdev As String, ANSIuser As String, buflen As Long, User As String
    ANSIdev = StrConv("", vbFromUnicode)
    ANSIuser = String(128, vbNullChar)
    buflen = 128
    szrc = WNetGetUserA(StrPtr(ANSIdev), StrPtr(ANSIuser), buflen)
    If szrc <> 0 Then
        GetLoggedOnUser = ""
        Exit Function
    End If
    User = Left$(StrConv(ANSIuser, vbUnicode), buflen - 2)
    GetLoggedOnUser = Left$(User, InStr(User, vbNullChar) - 1)
End Function

Explore More ContentExplore courses, solutions, and other research materials related to this topic.