SHARE_INFO_502 Structure and using shi502_security_descriptor
-
sexta-feira, 2 de março de 2012 22:06
This is for VB.Net using Visual Studio 2010. To keep things simple, I'm just targeting .Net v2 for now. I'm posting here because I believe it's strictly an issue of managed platform invoke marshalling. I'm trying to use NetShareEnum to report and manipulate share permissions. I can get NetShareEnum() to work fine. I can extract the individual shares into structures. However, I've been unable to use the shi502_security_descriptor pointer member of a SHARE_INFO_502 structure.
For example, I'd like to use GetSecurityDescriptorDacl() to get the share's Dacl. I've even managed to do this fine in C++ but I can't seem to make the leap to managed code. I can find examples for creating new Security Descriptors but none for taking a pointer member of a structure and using it with other api's.
Can anyone give me a working example to take the shi502_security_descriptor pointer (of type System.IntPtr) and actually use it with the advapi32.dll security functions, such as GetSecurityDescriptorDacl() or GetExplicitEntriesFromAcl()? Please include your DllImportAttribute declarations. Thanks!
Todas as Respostas
-
sábado, 3 de março de 2012 17:32
Hi,
in the following excerpt, 'Item' is the starting point of type SHARE_INFO_502. Maybe you don't have all functions (residing in my own libraries), but the relevant declarations are below:
Dim pSecdesc = item.security_descriptor If pSecdesc <> IntPtr.Zero Then Dim DaclPresent, DaclDefaulted As Boolean Dim dacl As IntPtr If Functions.GetSecurityDescriptorDacl(pSecdesc, DaclPresent, dacl, DaclDefaulted) Then Dim count As UInteger Dim ListStartPtr, CurrentPtr As IntPtr Dim Type = GetType(EXPLICIT_ACCESS) Dim structSize = Marshal.SizeOf(Type) If Functions.GetExplicitEntriesFromAcl(dacl, count, ListStartPtr) = Errors.Success Then Try CurrentPtr = ListStartPtr Debug.Print("Acl:") Debug.Indent() For i = 1UI To count Dim record As EXPLICIT_ACCESS Debug.Print("#" & i & ":") Debug.Indent() record = DirectCast(Marshal.PtrToStructure(CurrentPtr, Type), EXPLICIT_ACCESS) Debug.Print("Accessmode = " & record.AccessMode.ToString) Debug.Print("AccessPermissions = " & record.AccessPermissions.ToString) Debug.Print("Inheritance = " & record.Inheritance.ToString) Debug.Print("Trustee:") Debug.Indent() If record.Trustee.TrusteeForm = TrusteeForm.IsSid Then Dim sidString = Helper.ConvertSidToStringSid(record.Trustee.Name) Debug.Print("Name (SID) = " & sidString) Else Debug.Print("Name = " & record.Trustee.Name.ToString) End If Debug.Print("MultipleTrusteeOperation = " & record.Trustee.MultipleTrusteeOperation.ToString) Debug.Print("TrusteeForm = " & record.Trustee.TrusteeForm.ToString) Debug.Print("TrusteeType = " & record.Trustee.TrusteeType.ToString) Debug.Unindent() Debug.Unindent() CurrentPtr = AddPointer(CurrentPtr, structSize) Next Debug.Unindent() Finally Helper.LocalFree(ListStartPtr) End Try Else Helper.ThrowWin32Exception("GetExplicitEntriesFromAcl") End If Else Helper.ThrowWin32Exception("GetSecurityDescriptorDacl") End If End If
Declarations:
Public Declare Function GetSecurityDescriptorDacl Lib "Advapi32.dll" ( _ ByVal SecurityDescriptor As IntPtr, _ ByRef DaclPresent As Boolean, _ ByRef Dacl As IntPtr, _ ByRef DaclDefaulted As Boolean) As BooleanPublic Declare Auto Function GetExplicitEntriesFromAcl Lib "Advapi32.dll" ( _ ByVal ACL As IntPtr, _ ByRef CountOfExplicitEntries As UInt32, _ ByRef ListOfExplicitEntries As IntPtr) As UInt32<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _ Public Structure EXPLICIT_ACCESS Public AccessPermissions As AccessMask Public AccessMode As AccessMode Public Inheritance As UInt32 Public Trustee As TRUSTEE End Structure
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _ Public Structure TRUSTEE Public MultipleTrustee As IntPtr Public MultipleTrusteeOperation As MultipleTrusteeOperation Public TrusteeForm As TrusteeForm Public TrusteeType As TrusteeType Public Name As IntPtr End Structure
Public Enum MultipleTrusteeOperation NoMultipleTrustee TrusteeIsImpersonate End Enum Public Enum TrusteeForm IsSid IsName BadForm IsObjectsAndSid IsObjectsAndName End Enum Public Enum TrusteeType IsUnknown IsUser IsGroup IsDomain IsAlias IsWellKnownGroup IsDeleted IsInvalid IsComputer End Enum
Let me know if declarations are missing.
Armin
- Sugerido como Resposta Mike FengMicrosoft Contingent Staff, Moderator quinta-feira, 8 de março de 2012 16:27
- Marcado como Resposta Mike FengMicrosoft Contingent Staff, Moderator terça-feira, 20 de março de 2012 06:45
-
quinta-feira, 8 de março de 2012 16:28Moderador
Hi Bcmem,
Welcome to the MSDN Forum.
How about Armin's suggestion? Does it work for you?
@Armin,
Thank you for contrubuting on this forum.
Have a nice day.
Best regards,
Mike Feng
MSDN Community Support | Feedback to us
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
-
quinta-feira, 8 de março de 2012 16:44
Armin,
Thanks for the thorough help. My basic problem was incorrect ByRef and ByVal choices. I can now get the ACL's using GetExplicitEntriesFromAcl(). The actual object is a Windows share and the returned trustees are SID's, not names. So I declared the Trustee structure with Name as IntPtr. I can't get past ConvertSidToString. Debugging looks good up to that step. bResult is returning 2 (the number of ACL's) so there is no error. However, the conversion does not give me a valid string. Since the string is LPTSTR *StringSid, I declared it as ByRef IntPtr so I can free it later using LocalFree(). Can you share your Helper code for calling Convert or is there something wrong? Thanks again! Here are my relevant code snippits:
<StructLayoutAttribute(LayoutKind.Sequential)> _
Private Structure EXPLICIT_ACCESS
Public grfAccessPermissions As UInteger
Public grfAccessMode As ACCESS_MODE
Public grfInheritance As UInteger
Public Trustee As TRUSTEE
End Structure<StructLayoutAttribute(LayoutKind.Sequential)> _
Private Structure TRUSTEE
Public pMultipleTrustee As UInteger
Public MultipleTrusteeOperation As MULTIPLE_TRUSTEE_OPERATION
Public TrusteeForm As TRUSTEE_FORM
Public TrusteeType As TRUSTEE_TYPE
Public Name As System.IntPtr
End Structure<DllImportAttribute("advapi32.dll", entrypoint:="GetExplicitEntriesFromAcl")> _
Private Shared Function GetExplicitEntriesFromAcl(<InAttribute()> ByVal pacl As IntPtr, <OutAttribute()> ByRef pCountOfExplicitEntries As UInteger, <OutAttribute()> ByRef pListOfExplicitEntries As System.IntPtr) As UInteger
End Function<DllImportAttribute("advapi32.dll", EntryPoint:="ConvertSidToStringSid")> _
Private Shared Function ConvertSidToStringSid(<InAttribute()> ByVal Sid As System.IntPtr, <OutAttribute()> ByRef StringSid As System.IntPtr) As System.Int32
End FunctionDim pDacl As System.IntPtr
bResult = GetSecurityDescriptorDacl(PsecDesc, bDaclPresent, pDacl, bDaclDefaulted)
Dim pcCountOfExplicitEntries As UInteger
Dim pListOfExplicitEntries As System.IntPtr
Result = GetExplicitEntriesFromAcl(pDacl, pcCountOfExplicitEntries, pListOfExplicitEntries)
Dim ExplicitEntries(pcCountOfExplicitEntries - 1) As EXPLICIT_ACCESS
For j = 0 To pcCountOfExplicitEntries - 1
ExplicitEntries(j) = Marshal.PtrToStructure( _
CType(pListOfExplicitEntries.ToInt32 + Marshal.SizeOf(GetType(EXPLICIT_ACCESS)) * j, IntPtr) _
, GetType(EXPLICIT_ACCESS) _)If ExplicitEntries(j).Trustee.TrusteeForm = TRUSTEE_FORM.TRUSTEE_IS_SID Then
Dim PstrSid As System.IntPtr
bResult = ConvertSidToStringSid(ExplicitEntries(j).Trustee.Name, PstrSid)
Dim strSid As String
strSid = Marshal.PtrToStringAuto(PstrSid)
Debug.Print(Shares(i).shi502_netname + ": " + strSid)
LocalFree(PstrSid)
End If
Next
-
quinta-feira, 15 de março de 2012 04:55
Hi Bcmem,
Your code isnot debuggerable, This is may be the reason Armin doesn't follow this thread anymore, so would you like to post a debuggerable code snippet here?
Have a nice day.
Ghost,
Call me ghost for short, Thanks
To get the better anwser, it should be a better question. -
quinta-feira, 15 de março de 2012 08:25
Oh, I'm sorry, somehow I've overlooked this thread. It was not because the code is not compilable, though you're right, Ghost, it's not compilable even if I add missing declarations. Inappropriate data type handling is not good for a programmer. :)
bcmem, please add Option Strict On at the top of the file and do the necessary corrections. If you post again, the thread will become "unread" and I will (try to) respond.
Armin
-
quinta-feira, 15 de março de 2012 09:07
Again sorry for not replying. Helper.ConvertSidToStringSid is nothing special, but here it is:
Public Shared Function ConvertSidToStringSid(ByVal sid As IntPtr) As String Dim bufferPtr As IntPtr If Functions.ConvertSidToStringSid(sid, bufferPtr) Then Try Return Marshal.PtrToStringAuto(bufferPtr) Finally LocalFree(bufferPtr) End Try Else ThrowWin32Exception("ConvertSidToStringSid") End If End FunctionOur declarations of ConvertSidToStringSid match, so I don't post mine. EDIT: This statement turned to be out wrong, later.
The only noticable thing I see - but I don't think it's the problem - is that you're using pListOfExplicitEntries.ToInt32. This would fail on a 64 bit machine, or at least it's not safe. You may change that later. I wanted to post my AddPointer function at this point, but it again references own libraries.
I guess 'i' in "Shares(i).shi502_netname" is the loop variable for the enclosing loop.
You shouldn't ignore the return value or GetExplicitEntriesFromAcl.
ExplicitEntries(j) = Marshal.PtrToStructure( _
Ok, I've pieced together working code keeping yours and added mine. Current state: There's a problem in the line
CType(pListOfExplicitEntries.ToInt32 + Marshal.SizeOf(GetType(EXPLICIT_ACCESS)) * j, IntPtr) _
, GetType(EXPLICIT_ACCESS) _)because I get a different result than in my original posted coded. I'm looking at it now and will report again.....
Armin
- Editado Armin Zingler quinta-feira, 15 de março de 2012 09:32
-
quinta-feira, 15 de março de 2012 09:31
Solution:
Your declaration of
Public pMultipleTrustee As UInteger
in structure Trustee is wrong. Must be IntPtr, not UInteger. Not what I posted. ;)
In addition, the Auto charset is missing in your declaration of ConvertSidToStringSid. That's why the ANSI version is used instead of Unicode, so the correct version is:
Public Declare Auto Function ConvertSidToStringSid Lib "Advapi32.dll" ( _ ByVal SID As IntPtr, _ ByRef StringSid As IntPtr) As BooleanGetting back an ANSI String called with Marshal.PtrToStringAuto doesn't match because the latter expects Unicode.
Should work now.
Armin
- Marcado como Resposta bcmem quinta-feira, 15 de março de 2012 13:25
- Não Marcado como Resposta Mike FengMicrosoft Contingent Staff, Moderator terça-feira, 20 de março de 2012 08:29
- Marcado como Resposta Mike FengMicrosoft Contingent Staff, Moderator terça-feira, 20 de março de 2012 08:29
-
quinta-feira, 15 de março de 2012 13:24
Armin,
Thanks so much for your time and help. It was indeed the string charset; I can't believe how much time I wasted on this issue. I didn't include "Charset:=" because it appeared my program default was Unicode so I thought the Unicode version would be automatically chosen. I guess that's the case in C++ when you include the real SDK headers but not for VB.Net. I may be back to the forums as I progress but I've learned a lot troubleshooting this issue. Thanks again.
-
quinta-feira, 15 de março de 2012 13:25Thanks for the tip.
-
quinta-feira, 15 de março de 2012 13:28Thanks for the code post and I'll keep the 64-bit in mind. I was aware that my code might not work on 64-bit but is less of a priority right now. I only use 32-bit workstations for development at the moment. Also, I assume (but could be wrong) that since I'm targeting 32-bit on compilation, 64-bit Windows would run it as 32-bit. Thanks.

