Daniel Wilson
asked on
Win API in VB6 -- What is a Struct_MembersOf_PACL ?
The richer translations of the SetSecurityInfo declaration into VB include a Struct_MembersOf_PACL as one of the types.
'http://binaryworld.net/Main/ApiDetail.aspx?ApiId=4821
Declare Function SetSecurityInfo Lib "ADVAPI32" (ByVaL handle As Long, ByRef ObjectType As SE_OBJECT_TYPE, ByVaL SecurityInfo As Long, ByRef psidOwner As SID, ByRef psidGroup As SID, ByVaL pDacl As Struct_MembersOf_PACL, ByVaL pSacl As Struct_MembersOf_PACL) As Long
What is the thing?
I have the ACL structure:
'http://msdn.microsoft.com/en-us/library/aa374931(VS.85).aspx
Private Type ACL
AclRevision As Byte
Sbz1 As Byte
AclSize As Integer
AceCount As Integer
Sbz2 As Integer
End Type
Is that what I need? Or is a Struct_MembersOf_PACL something else?
Thanks!
'http://binaryworld.net/Main/ApiDetail.aspx?ApiId=4821
Declare Function SetSecurityInfo Lib "ADVAPI32" (ByVaL handle As Long, ByRef ObjectType As SE_OBJECT_TYPE, ByVaL SecurityInfo As Long, ByRef psidOwner As SID, ByRef psidGroup As SID, ByVaL pDacl As Struct_MembersOf_PACL, ByVaL pSacl As Struct_MembersOf_PACL) As Long
What is the thing?
I have the ACL structure:
'http://msdn.microsoft.com/en-us/library/aa374931(VS.85).aspx
Private Type ACL
AclRevision As Byte
Sbz1 As Byte
AclSize As Integer
AceCount As Integer
Sbz2 As Integer
End Type
Is that what I need? Or is a Struct_MembersOf_PACL something else?
Thanks!
That is a pointer to a DACL, see http://msdn.microsoft.com/en-us/library/aa379588(VS.85).aspx ("SetSecurityInfo Function"). However, a DACL has no "members", it is a more or less "opaque" thing. Check out http://msdn.microsoft.com/en-us/library/ms717798(VS.85).aspx ("Creating a DACL") which shows a less cumbersome way to build one using 'ConvertStringSecurityDesc riptorToSe curityDesc riptor()' (http://msdn.microsoft.com/en-us/library/aa376401.aspx)
ASKER
Right, it's a pointer. And VB6 obfuscates pointers severely.
Would you use the translation that sees pDacl and pSacl as Long then?
Thanks!
Would you use the translation that sees pDacl and pSacl as Long then?
Thanks!
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Looks like you're right. I hit upon something more complex (and evidently wrong) as an attempt at solving this one:
https://www.experts-exchange.com/questions/24330006/SetSecurityInfo-returns-error-1336-ERROR-INVALID-ACL.html
Thanks for steering me away from one non-solution!
https://www.experts-exchange.com/questions/24330006/SetSecurityInfo-returns-error-1336-ERROR-INVALID-ACL.html
Thanks for steering me away from one non-solution!
ASKER
I even get error 1336 when passing a NULL DACL ...
lErrorCheck = SetSecurityInfo(MyHandle, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, _
0, 0, 0, 0)
lErrorCheck = SetSecurityInfo(MyHandle, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,
0, 0, 0, 0)
Hmmm, what kind of object are you trying to apply the ACL to?
ASKER
The current process.
Simplified, it is:
MyPID = GetCurrentProcessID()
OpenProcess(ACCESS_RIGHT_R EAD_CONTRO L Or ACCESS_RIGHT_WRITE_DAC, 0, MyPID)
GetSecurityInfo(MyHandle, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, 0, 0, pCurDacl, 0, pSD)
SetEntriesInAcl(1, ea, pCurDacl, pNewDacl)
SetSecurityInfo(MyHandle, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, 0, 0, pNewDacl, 0)
Simplified, it is:
MyPID = GetCurrentProcessID()
OpenProcess(ACCESS_RIGHT_R
GetSecurityInfo(MyHandle, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,
SetEntriesInAcl(1, ea, pCurDacl, pNewDacl)
SetSecurityInfo(MyHandle, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,
First of all, try PROCESS_ALL_ACCESS as the access mask. Also, does 'SetEntriesInAcl()' succed?
ASKER
Yes, SetEntriesInAcl returns 0 ... which I understand to mean Success.
like I have below? Currently I'm using PROCESS_QUERY_INFORMATION
like I have below? Currently I'm using PROCESS_QUERY_INFORMATION
Dim ea As EXPLICIT_ACCESS
1090 With ea
1100 .grfAccessPermissions = PROCESS_ALL_ACCESS
1110 .grfAccessMode = GRANT_ACCESS
1120 .grfInheritance = NO_INHERITANCE
1130 .TRUSTEE.TrusteeForm = TRUSTEE_IS_NAME
1140 .TRUSTEE.TrusteeType = TRUSTEE_IS_GROUP
'1150 .TRUSTEE.ptstrName = "CURRENT_USER" & vbNullChar 'Perhaps this should actually have the current Windows user name ... not sure
1150 .TRUSTEE.ptstrName = "EVERYONE" '& vbNullChar
1160 End With
ASKER
http://msdn.microsoft.com/en-us/library/ms684880.aspx doesn't say what the constant PROCESS_ALL_ACCESS equals. I'm going to assume it equals &HFFFF.
Hm, I've never set en EXPLICITACCESS struct manually (or seen that) - have you tried doing that with 'BuildExplicitAccessWithNa me()' (http://msdn.microsoft.com/en-us/library/aa376378(VS.85).aspx)? See also http://support.microsoft.com/kb/295004 ("How to use high-level access control APIs from Visual Basic")
ASKER
Nice idea ... same error 1336 ERROR_INVALID_ACL
Code now looks like:
(I'm using &HFFFF as PROCESS_ALL_ACCESS.)
further ideas?
Code now looks like:
(I'm using &HFFFF as PROCESS_ALL_ACCESS.)
further ideas?
MyPID = GetCurrentProcessID()
OpenProcess(ACCESS_RIGHT_READ_CONTROL Or ACCESS_RIGHT_WRITE_DAC, 0, MyPID)
Call BuildExplicitAccessWithName(ea, "EVERYONE", ACCESS_RIGHT_PROCESS_ALL_ACCESS, GRANT_ACCESS, 0)
GetSecurityInfo(MyHandle, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, 0, 0, pCurDacl, 0, pSD)
SetEntriesInAcl(1, ea, pCurDacl, pNewDacl)
SetSecurityInfo(MyHandle, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, 0, 0, pNewDacl, 0)
Aaah, just spotted a subtle difference - 'SetEntriesInAcl()' is declared as follows:
DWORD SetEntriesInAcl(
ULONG cCountOfExplicitEntries,
// number of entries in the list
PEXPLICIT_ACCESS pListOfExplicitEntries,
// pointer to list of entries with new access data
PACL OldAcl, // pointer to the original ACL
PACL *NewAcl // receives a pointer to the new ACL
);
with the last argument being 'PACL *NewAcl' - which is a pointer to a pointer (or the address of a pointer). Dunno VB, so let me just ask a stupid question: Are you taking this into account?
DWORD SetEntriesInAcl(
ULONG cCountOfExplicitEntries,
// number of entries in the list
PEXPLICIT_ACCESS pListOfExplicitEntries,
// pointer to list of entries with new access data
PACL OldAcl, // pointer to the original ACL
PACL *NewAcl // receives a pointer to the new ACL
);
with the last argument being 'PACL *NewAcl' - which is a pointer to a pointer (or the address of a pointer). Dunno VB, so let me just ask a stupid question: Are you taking this into account?
ASKER
That's probably the worst thing about VB -- the obfuscation of pointers.
Let me try VarPtr(pNewDacl). I think that would be the right answer there.
The other thing in that declaration that has me worried is the 2nd argument. I have an Explicit_Access, not a list of them.
Let me try VarPtr(pNewDacl). I think that would be the right answer there.
The other thing in that declaration that has me worried is the 2nd argument. I have an Explicit_Access, not a list of them.
The address of one element will do - if the 1st arg is '1'.
ASKER
VarPtr(pNewDacl) is wrong. It results in pNewDacl remaining = 0.
The truth is, just passing a Long (which is a pointer to something) by reference (that is, using a pointer to it) is giving us the double indirection.
Private Declare Function SetEntriesInAcl Lib "Advapi32.dll" Alias "SetEntriesInAclA" (ByVal cCountOfExplicitEntries As Long, pListOfExplicitEntries As EXPLICIT_ACCESS, ByVal OldAcl As Long, ByRef NewAcl As Long) As Long
I'm still not sure about PEXPLICIT_ACCESS.
I'm attaching a watch list from the last run without the VarPtr() ...
SetSecurityInfo-WatchList.gif
The truth is, just passing a Long (which is a pointer to something) by reference (that is, using a pointer to it) is giving us the double indirection.
Private Declare Function SetEntriesInAcl Lib "Advapi32.dll" Alias "SetEntriesInAclA" (ByVal cCountOfExplicitEntries As Long, pListOfExplicitEntries As EXPLICIT_ACCESS, ByVal OldAcl As Long, ByRef NewAcl As Long) As Long
I'm still not sure about PEXPLICIT_ACCESS.
I'm attaching a watch list from the last run without the VarPtr() ...
SetSecurityInfo-WatchList.gif
ASKER
>>The address of one element will do - if the 1st arg is '1'.
OK, that's cool. Then we're fine as that's also a ByRef parameter.
(In VB6 parameters are ByRef unless specified ByVal. MS switched this in .Net.)
OK, that's cool. Then we're fine as that's also a ByRef parameter.
(In VB6 parameters are ByRef unless specified ByVal. MS switched this in .Net.)
Have you checked http://support.microsoft.com/kb/295004 ("How to use high-level access control APIs from Visual Basic") from above - it comes with sample code.
ASKER
Their example works. They are using GetNamedSecurityInfo and SetNamedSecurityInfo.
I'll try tweaking their code until it does what I want.
Thanks for the help so far!
What we're actually working on now is this question that's been out there for a day.
https://www.experts-exchange.com/questions/24330006/SetSecurityInfo-returns-error-1336-ERROR-INVALID-ACL.html
So if we get a solution, please post it there as you will have earned the points!
I'll try tweaking their code until it does what I want.
Thanks for the help so far!
What we're actually working on now is this question that's been out there for a day.
https://www.experts-exchange.com/questions/24330006/SetSecurityInfo-returns-error-1336-ERROR-INVALID-ACL.html
So if we get a solution, please post it there as you will have earned the points!
ASKER
I can't use GetNamedSecurityInfo and SetNamedSecurityInfo.
http://msdn.microsoft.com/en-us/library/aa379593(VS.85).aspx
Again, thanks for the help!
http://msdn.microsoft.com/en-us/library/aa379593(VS.85).aspx
"The GetSecurityInfo and SetSecurityInfo functions support all types of kernel objects. The GetNamedSecurityInfo and SetNamedSecurityInfo functions work only with the following kernel objects: semaphore, event, mutex, waitable timer, and file mapping."
I'll have to pick this up again when my mind is fresher.Again, thanks for the help!