From: mayayana on 9 Sep 2009 10:47 Eduardo (or others who may be interested), You posted code to list ACEs for an object and I've begun looking at those options with the idea in mind of writing a full-featured class to encapsulate the horrendous permissions API. But there seem to be gaps and it's hard to figure out how the advapi functions might fill them. * It's fairly easy to set permissions. * It's feasible to figure out whether the current user is an Admin. * You sample code shows how to return ACEs for a specific object. But what I don't find in the API is a basic method to ask: What are the current user's rights with this particular folder, Reg. key, etc.? In other words, rather than listing ACEs and returning a partial list of groups to match up with those ACEs, it would be nice to just "cut to the chase" and do it the other way around: "What's "my" ACE for this object?" If the CU is an Admin that could be a real Admin or a limited Admin. (Having permission to elevate is not the same as having permission.) And I haven't found the method to return the group status of the CU, other than whether or not they're Admin. Also, from my readings I get the impression that Vista virtualization prevents the accurate use of testing permissions by trying to create a file in a folder or by trying to write to HKLM. Virtualization will allow a fake version of the operation without raising an error. So one might write an all-users value to HKLM only to find out later that it ended up in CU keys.
From: Eduardo on 9 Sep 2009 18:39 mayayana escribi�: > Eduardo (or others who may be interested), So, you want to know the permissions of the CU for a particular object. We'll have to investigate. In the code posted we have: 1) Set permissions for "Users" and "Everyone". 2) Remove permissions for "Users" and "Everyone". But we lack of a function to Get permissions for "Users" and "Everyone". If we add that feature, I think we could also add Get/Set/Remove permissions for CU. If we want something even more complete, we could also add functions for ACEs for denying access, because the functions that we have at this time are for ACEs for allowing access.
From: mayayana on 9 Sep 2009 19:16 I've been looking further and found GetEffectiveRightsFromAcl. I'll play around with that and see what I come up with. > > Eduardo (or others who may be interested), > > So, you want to know the permissions of the CU for a particular object. > We'll have to investigate. > > In the code posted we have: > 1) Set permissions for "Users" and "Everyone". > 2) Remove permissions for "Users" and "Everyone". > > But we lack of a function to Get permissions for "Users" and "Everyone". > > If we add that feature, I think we could also add Get/Set/Remove > permissions for CU. > > If we want something even more complete, we could also add functions for > ACEs for denying access, because the functions that we have at this > time are for ACEs for allowing access.
From: Eduardo on 10 Sep 2009 18:10 mayayana escribi�: > I've been looking further and found > GetEffectiveRightsFromAcl. I'll play around > with that and see what I come up with. OK, I could make this API work. For running the sample, add a command button to the form and copy this code: ' ******** begin form's code ************ Option Explicit Private Sub Command1_Click() Dim iP As Long Dim iPW As Boolean Dim iFolder As String Dim iMessage As String iFolder = InputBox("Enter folder path", , _ "C:\Program Files\Internet Explorer") If GetCurrentUserNTPermission(iFolder, 1, iPW, "Read") = 0 Then iMessage = "Read permission: " & iPW & vbCrLf End If If GetCurrentUserNTPermission(iFolder, 1, iPW, "Write") = 0 Then iMessage = iMessage & "Write permission: " & iPW & vbCrLf End If If GetCurrentUserNTPermission(iFolder, 1, iPW, "Execute") = 0 Then iMessage = iMessage & "Execute permission: " & iPW & vbCrLf End If If GetCurrentUserNTPermission(iFolder, 1, iPW) = 0 Then iMessage = iMessage & "All permissions: " & iPW End If If iMessage <> "" Then MsgBox iMessage Else MsgBox "Error", vbExclamation End If End Sub ' ******** end form's code ************ ' and in a module: ' ******** begin module's code ************ Option Explicit Private Enum MULTIPLE_TRUSTEE_OPERATION NO_MULTIPLE_TRUSTEE TRUSTEE_IS_IMPERSONATE End Enum Private Enum TRUSTEE_FORM TRUSTEE_IS_SID TRUSTEE_IS_NAME End Enum Private Enum TRUSTEE_TYPE TRUSTEE_IS_UNKNOWN TRUSTEE_IS_USER TRUSTEE_IS_GROUP End Enum Private Type TRUSTEE pMultipleTrustee As Long MultipleTrusteeOperation As MULTIPLE_TRUSTEE_OPERATION TrusteeForm As TRUSTEE_FORM TrusteeType As TRUSTEE_TYPE ptstrName As String End Type Private Const SE_FILE_OBJECT = 1& Private Const SE_REG_KEY = 4& Private Const DACL_SECURITY_INFORMATION = 4& Private Declare Function GetNamedSecurityInfo Lib "advapi32.dll" _ Alias "GetNamedSecurityInfoA" (ByVal ObjName As String, _ ByVal SE_OBJECT_TYPE As Long, ByVal SecInfo As Long, ByVal _ pSid As Long, ByVal pSidGroup As Long, pDacl As Long, ByVal _ pSacl As Long, pSecurityDescriptor As Long) As Long Private Declare Function GetEffectiveRightsFromAcl Lib _ "advapi32.dll" Alias "GetEffectiveRightsFromAclA" (ByVal pacl _ As Long, pTrustee As TRUSTEE, ByRef pAccessRights As Long) As Long Private Declare Function LocalFree Lib "KERNEL32" (ByVal hMem _ As Long) As Long Private Type GENERIC_MAPPING GenericRead As Long GenericWrite As Long GenericExecute As Long GenericAll As Long End Type Private Declare Function MapGenericMask Lib "advapi32.dll" _ (ByRef grantedAccess As Long, ByRef pgenericmapping As _ GENERIC_MAPPING) As Long Private Const GENERIC_READ As Long = &H80000000 Private Const GENERIC_WRITE As Long = &H40000000 Private Const GENERIC_EXECUTE As Long = &H20000000 Private Const GENERIC_ALL As Long = &H10000000 'standard Private Const DELETE = &H10000 Private Const READ_CONTROL = &H20000 Private Const WRITE_DAC = &H40000 Private Const WRITE_OWNER = &H80000 Private Const SYNCHRONIZE = &H100000 Private Const STANDARD_RIGHTS_REQUIRED = &HF0000 Private Const STANDARD_RIGHTS_READ = READ_CONTROL Private Const STANDARD_RIGHTS_WRITE = READ_CONTROL Private Const STANDARD_RIGHTS_EXECUTE = READ_CONTROL Private Const STANDARD_RIGHTS_ALL = &H1F0000 Private Const SPECIFIC_RIGHTS_ALL = &HFFFF& Private Const ACCESS_SYSTEM_SECURITY = &H1000000 Private Const MAXIMUM_ALLOWED = &H2000000 'specific Private Const FILE_READ_DATA = &H1& ' file & pipe Private Const FILE_LIST_DIRECTORY = &H1& ' directory Private Const FILE_WRITE_DATA = &H2& ' file & pipe Private Const FILE_ADD_FILE = &H2& ' directory Private Const FILE_APPEND_DATA = &H4& ' file Private Const FILE_ADD_SUBDIRECTORY = &H4& ' directory Private Const FILE_CREATE_PIPE_INSTANCE = &H4& ' named pipe Private Const FILE_READ_EA = &H8& ' file & directory Private Const FILE_WRITE_EA = &H10& ' file & directory Private Const FILE_EXECUTE = &H20& ' file Private Const FILE_TRAVERSE = &H20& ' directory Private Const FILE_DELETE_CHILD = &H40& ' directory Private Const FILE_READ_ATTRIBUTES = &H80& ' all Private Const FILE_WRITE_ATTRIBUTES = &H100& ' all 'generic rights masks for files and directories Private Const FILE_ALL_ACCESS As Long = STANDARD_RIGHTS_REQUIRED _ Or SYNCHRONIZE Or 511 Private Const FILE_GENERIC_READ As Long = STANDARD_RIGHTS_READ _ Or FILE_READ_DATA Or FILE_READ_ATTRIBUTES Or _ FILE_READ_EA Or SYNCHRONIZE Private Const FILE_GENERIC_WRITE As Long = STANDARD_RIGHTS_WRITE _ Or FILE_WRITE_DATA Or FILE_WRITE_ATTRIBUTES Or _ FILE_WRITE_EA Or FILE_APPEND_DATA Or SYNCHRONIZE Private Const FILE_GENERIC_EXECUTE As Long = STANDARD_RIGHTS_EXECUTE _ Or FILE_READ_ATTRIBUTES Or FILE_EXECUTE Or SYNCHRONIZE Private Function GetCUPermissions(ByVal nItem As String, nType _ As Long, nPermissions As Long) As Long Dim iTrustee As TRUSTEE Dim iObjType As Long Dim iDACL As Long Dim iDesc As Long Dim iRet As Long GetCUPermissions = -1 On Error GoTo woops If (nType = 1) Then iObjType = SE_FILE_OBJECT 'type 1 Else iObjType = SE_REG_KEY 'type 4 End If iRet = GetNamedSecurityInfo(nItem, iObjType, _ DACL_SECURITY_INFORMATION, 0&, 0&, iDACL, 0&, iDesc) If iRet <> 0 Then GetCUPermissions = iRet: _ nType = 5: GoTo woops iTrustee.pMultipleTrustee = 0 iTrustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE iTrustee.TrusteeForm = TRUSTEE_IS_NAME iTrustee.TrusteeType = TRUSTEE_IS_USER iTrustee.ptstrName = "CURRENT_USER" & vbNullChar iRet = GetEffectiveRightsFromAcl(iDACL, iTrustee, nPermissions) If iRet <> 0 Then GetCUPermissions = iRet: _ nType = 6: GoTo woops GetCUPermissions = 0 woops: On Error Resume Next If iDesc <> 0 Then LocalFree iDesc End Function Public Function GetCurrentUserNTPermission(ByVal nItem As String, _ nType As Long, nPermission As Boolean, Optional nDesiredAccess _ As String = "All") As Long Dim iRet As Long Dim iPermissions As Long Dim iMap As GENERIC_MAPPING Dim iGenericAccess As Long Select Case UCase(nDesiredAccess) Case "READ" iGenericAccess = GENERIC_READ Case "WRITE" iGenericAccess = GENERIC_WRITE Case "EXECUTE" iGenericAccess = GENERIC_EXECUTE Case "ALL" iGenericAccess = GENERIC_ALL Case Else GetCurrentUserNTPermission = 7 End Select If GetCurrentUserNTPermission = 0 Then iRet = GetCUPermissions(nItem, nType, iPermissions) If iRet <> 0 Then GetCurrentUserNTPermission = 8 Else GetCurrentUserNTPermission = 0 iMap.GenericRead = FILE_GENERIC_READ iMap.GenericWrite = FILE_GENERIC_WRITE iMap.GenericExecute = FILE_GENERIC_EXECUTE iMap.GenericAll = FILE_ALL_ACCESS MapGenericMask iGenericAccess, iMap nPermission = (iPermissions And iGenericAccess) _ = iGenericAccess End If End If End Function ' ******** end module's code ************
From: Eduardo on 10 Sep 2009 18:16
Eduardo escribi�: > mayayana escribi�: >> I've been looking further and found >> GetEffectiveRightsFromAcl. I'll play around >> with that and see what I come up with. > > OK, I could make this API work. But I'm not sure what it's returning when I check a virtualized folder, because for "C:\Program Files\Internet Explorer" it tells me that I have write rights, when in fact it's virtualized. But unlike a "normal" folder, when I ask for all access rights, it tells me that I don't have. And it returns the same if I run it as admin or not. |