Login | Register   
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


Tip of the Day
Language: NT
Expertise: Beginner
Jun 22, 1998

NT Server Local Groups

Question:
I would like to be able to gain access to NT server local groups for enum, member enum, add member, delete member.

We have a lot of servers as well as NT and OS/2 domains. Because of this, there is a need to synchronize users and group memberships across multiple servers.

I have not found anything that will allow me to access a local group on a server from a VB program running on a client. Can you point me in the right direction?

Answer:
None of the NT Unicode network functions are particularly easy to use. In fact, they are a real pain. However, the following code will do what you want:

' ************************************************
' In a form
' ************************************************
Option Explicit

Private Sub Command1_Click()
On Error Resume Next
   Dim p_vntRtn   As Variant
   Dim p_lngNum   As Long
   Dim p_lngLoop  As Long
   Dim p_strGroup As String
   
   p_strGroup = Trim$(Me.List1.List(Me.List1.ListIndex))
   If Len(p_strGroup) <= 0 Then
      MsgBox "You must select a group first!"
      Exit Sub
   End If
   
   Me.List2.Clear
   p_vntRtn = GetLocalGroupMembers("", p_strGroup)
   
   p_lngNum = UBound(p_vntRtn)
   If p_lngNum > 0 Then
      For p_lngLoop = 1 To p_lngNum
         Me.List2.AddItem p_vntRtn(p_lngLoop)
      Next p_lngLoop
   End If
   
End Sub

Private Sub Command2_Click()
On Error Resume Next
   Dim p_vntRtn   As Variant
   Dim p_lngNum   As Long
   Dim p_lngLoop  As Long
   
   Me.List1.Clear
   p_vntRtn = GetLocalGroups("")
   
   p_lngNum = UBound(p_vntRtn)
   If p_lngNum > 0 Then
      For p_lngLoop = 1 To p_lngNum
         Me.List1.AddItem p_vntRtn(p_lngLoop)
      Next p_lngLoop
   End If
   
End Sub

Private Sub Command3_Click()
   Dim p_blnRtn   As Boolean
   Dim p_strGroup As String
   Dim p_strUser  As String
   
   p_strGroup = Trim$(Me.List1.List(Me.List1.ListIndex))
   If Len(p_strGroup) <= 0 Then
      MsgBox "You must select a group first!"
      Exit Sub
   End If
  
   p_strUser = Trim$(Me.Text1.Text)
   If Len(p_strUser) <= 0 Then
      MsgBox "You must add a user name first!"
      Exit Sub
   End If
   
   p_blnRtn = AddDelUserToLocal(p_strGroup, _
                             p_strUser, _
                             "", True)
End Sub

Private Sub Command4_Click()
   Dim p_blnRtn   As Boolean
   Dim p_strGroup As String
   Dim p_strUser  As String
   
   p_strGroup = Trim$(Me.List1.List(Me.List1.ListIndex))
   If Len(p_strGroup) <= 0 Then
      MsgBox "You must select a group first!"
      Exit Sub
   End If
  
   p_strUser = Trim$(Me.Text2.Text)
   If Len(p_strUser) <= 0 Then
      MsgBox "You must add a user name first!"
      Exit Sub
   End If
   
   p_blnRtn = AddDelUserToLocal(p_strGroup, _
                             p_strUser, _
                             "", False)
End Sub


' ************************************************
' In a BAS file
' ************************************************

Option Explicit

Private Const NERR_Success             As Long = 0&

Private Const LocalGroupInfo0          As Long = 0&
Private Const LocalGroupInfo1          As Long = 1&

Private Const LocalGroupMembersInfo0   As Long = 0&
Private Const LocalGroupMembersInfo1   As Long = 1&
Private Const LocalGroupMembersInfo2   As Long = 2&
Private Const LocalGroupMembersInfo3   As Long = 3&

Private Const SidTypeUser              As Long = 1&
Private Const SidTypeGroup             As Long = 2&
Private Const SidTypeDomain            As Long = 3&
Private Const SidTypeAlias             As Long = 4&
Private Const SidTypeWellKnownGroup    As Long = 5&
Private Const SidTypeDeletedAccount    As Long = 6&
Private Const SidTypeInvalid           As Long = 7&
Private Const SidTypeUnknown           As Long = 8&
    
Public Declare Sub CopyMem _
   Lib "kernel32" Alias "RtlMoveMemory" _
   (pTo As Any, _
    pFrom As Any, _
    ByVal lCount As Long)
Private Declare Function lstrlenW _
   Lib "kernel32" _
   (ByVal psString As Long) As Long
Private Declare Function NetApiBufferFree _
   Lib "netapi32.dll" _
   (ByVal p_lngPtrBuffer As Long) As Long

Private Type LOCALGROUP_INFO_0
   PtrGroupName                        As Long
End Type

Private Type LOCALGROUP_MEMBERS_INFO_0
   PtrSidID                            As Long
End Type

Private Type LOCALGROUP_MEMBERS_INFO_1
   PtrSidID                            As Long
   SidUsage                            As Long
   PtrName                             As Long
End Type

Private Type LOCALGROUP_MEMBERS_INFO_3
   DomainAndName                       As Long
End Type

Private Declare Function NetLocalGroupEnum _
   Lib "netapi32" _
   (ByVal psServer As Long, _
    ByVal level As Long, _
    pPtrBuffer As Long, _
    ByVal prefmaxlen As Long, _
    EntriesRead As Long, _
    TotalEntries As Long, _
    ResumeHandle As Long) As Long
 
Private Declare Function NetLocalGroupGetMembers _
   Lib "netapi32" _
   (ByVal psServer As Long, _
    ByVal psLocalGroupName As Long, _
    ByVal level As Long, _
    pPtrBuffer As Long, _
    ByVal prefmaxlen As Long, _
    EntriesRead As Long, _
    TotalEntries As Long, _
    ResumeHandle As Long) As Long
 
Private Declare Function NetLocalGroupAddMembers _
   Lib "netapi32" _
   (ByVal psServer As Long, _
    ByVal psLocalGroupName As Long, _
    ByVal level As Long, _
    pPtrBuffer As Long, _
    ByVal membercount As Long) As Long
    
Private Declare Function NetLocalGroupDelMembers _
   Lib "netapi32" _
   (ByVal psServer As Long, _
    ByVal psLocalGroupName As Long, _
    ByVal level As Long, _
    pPtrBuffer As Long, _
    ByVal membercount As Long) As Long
    
' ================================================
' Get all the memebers of a selected local group
' ================================================
Public Function GetLocalGroupMembers(ByVal xi_strServerName As String, _
                                     ByVal xi_strLocalGroupName As String) As Variant
   Dim p_lngRtn                     As Long
   Dim p_lngPtrBuffer               As Long
   Dim p_lngPtrServerName           As Long
   Dim p_lngPtrLocalGroupName       As Long
   Dim p_lngPreferredMaxLen         As Long
   Dim p_lngEntriesRead             As Long
   Dim p_lngTotalEntries            As Long
   Dim p_lngResumeHwnd              As Long
   Dim p_lngLoop                    As Long
   Dim p_lngSidType                 As Long
   Dim p_strUserName                As String
   Dim p_strSidType                 As String
   Dim p_strSID                     As String
   Dim p_typLocalGroupMembers1      As LOCALGROUP_MEMBERS_INFO_1
   Dim p_alngMemberInfo()           As Long
   Dim p_astrMemberInfo()           As String
   
   ' Convert the server name to a pointer
   If Len(Trim$(xi_strServerName)) = 0 Then
      p_lngPtrServerName = 0&
   Else
      p_lngPtrServerName = StrPtr(xi_strServerName)
   End If
   
   ' Convert the user name to a pointer
   If Len(Trim$(p_lngPtrLocalGroupName)) = 0 Then
      MsgBox "You must enter a local group name!", vbExclamation, "Input Error"
      Exit Function
   Else
      p_lngPtrLocalGroupName = StrPtr(xi_strLocalGroupName)
   End If
   
   p_lngPreferredMaxLen = 4096&
   p_lngResumeHwnd = 0&
   p_lngRtn = NetLocalGroupGetMembers(p_lngPtrServerName, _
                                      p_lngPtrLocalGroupName, _
                                      LocalGroupMembersInfo1, _
                                      p_lngPtrBuffer, _
                                      p_lngPreferredMaxLen, _
                                      p_lngEntriesRead, _
                                      p_lngTotalEntries, _
                                      p_lngResumeHwnd)
   If p_lngRtn = NERR_Success Then
      ReDim p_alngMemberInfo(0 To (p_lngEntriesRead * 3) - 1) As Long
      ReDim p_astrMemberInfo(1 To p_lngEntriesRead) As String
      
      ' This gets the pointers to the structures
      CopyMem p_alngMemberInfo(0), _
              ByVal p_lngPtrBuffer, _
              p_lngEntriesRead * 4 * 3
      
      If p_lngEntriesRead > 0 Then
         For p_lngLoop = 0 To p_lngEntriesRead - 1
            p_strSidType = TranslateSidUsage(p_alngMemberInfo((p_lngLoop * 3) + 1))
            p_strUserName = PointerToStringW(p_alngMemberInfo((p_lngLoop * 3) + 2))
            p_astrMemberInfo(p_lngLoop + 1) = p_strUserName & " [" & p_strSidType & "]"
         Next p_lngLoop
      End If
      
      If p_lngPtrBuffer Then
         NetApiBufferFree p_lngPtrBuffer
      End If
      
      GetLocalGroupMembers = p_astrMemberInfo
   Else
      GetLocalGroupMembers = ""
   End If
   
End Function

' ================================================
' Get all of the local groups
' ================================================
Public Function GetLocalGroups(ByVal xi_strServerName As String) As Variant
   Dim p_lngRtn                     As Long
   Dim p_lngLoop                    As Long
   Dim p_lngPtrBuffer               As Long
   Dim p_lngPtrServerName           As Long
   Dim p_lngPreferredMaxLen         As Long
   Dim p_lngResumeHwnd              As Long
   Dim p_lngEntriesRead             As Long
   Dim p_lngTotalEntries            As Long
   Dim p_alngGroupInfo()            As Long
   Dim p_astrGroupInfo()            As String
   
   ' Convert the server name to a pointer
   If Len(Trim$(xi_strServerName)) = 0 Then
      p_lngPtrServerName = 0&
   Else
      p_lngPtrServerName = StrPtr(xi_strServerName)
   End If

   p_lngPreferredMaxLen = 4096&
   p_lngResumeHwnd = 0&

   p_lngRtn = NetLocalGroupEnum(p_lngPtrServerName, _
                                LocalGroupInfo0, _
                                p_lngPtrBuffer, _
                                p_lngPreferredMaxLen, _
                                p_lngEntriesRead, _
                                p_lngTotalEntries, _
                                p_lngResumeHwnd)
   If p_lngRtn = NERR_Success Then
      ReDim p_alngGroupInfo(0 To p_lngEntriesRead - 1) As Long
      ReDim p_astrGroupInfo(1 To p_lngEntriesRead) As String
      
      ' This gets the pointers to the structures
      CopyMem p_alngGroupInfo(0), _
              ByVal p_lngPtrBuffer, _
              p_lngEntriesRead * 4
      
      If p_lngEntriesRead > 0 Then
         For p_lngLoop = 0 To p_lngEntriesRead - 1
            p_astrGroupInfo(p_lngLoop + 1) = PointerToStringW(p_alngGroupInfo(p_lngLoop))
         Next p_lngLoop
      End If
      
      If p_lngPtrBuffer Then
         NetApiBufferFree p_lngPtrBuffer
      End If
      
      GetLocalGroups = p_astrGroupInfo
   Else
      GetLocalGroups = ""
   End If
   
End Function

' ================================================
' Either add or delete a user from a selected
' local group (depends upon xi_blnAddUser)
' ================================================
Function AddDelUserToLocal(ByVal xi_strGroupName As String, _
                           ByVal xi_strUserName As String, _
                           ByVal xi_strServerName As String, _
                           ByVal xi_blnAddUser As Boolean) As Boolean
   Dim p_lngPtrGroupName   As Long
   Dim p_lngPtrUserName    As Long
   Dim p_lngPtrServerName  As Long
   Dim p_lngMemberCount    As Long
   Dim p_lngRtn            As Long
   
   ' Convert the server name to a pointer
   If Len(Trim$(xi_strServerName)) = 0 Then
      p_lngPtrServerName = 0&
   Else
      p_lngPtrServerName = StrPtr(xi_strServerName)
   End If

   ' Convert the group name to a pointer
   p_lngPtrGroupName = StrPtr(xi_strGroupName)
   
   ' Convert the user name to a pointer
   p_lngPtrUserName = StrPtr(xi_strUserName)
   
   ' Add the user
   p_lngMemberCount = 1
   
   If xi_blnAddUser = True Then
      p_lngRtn = NetLocalGroupAddMembers(p_lngPtrServerName, _
                                         p_lngPtrGroupName, _
                                         LocalGroupMembersInfo3, _
                                         p_lngPtrUserName, _
                                         p_lngMemberCount)
   Else
      p_lngRtn = NetLocalGroupDelMembers(p_lngPtrServerName, _
                                         p_lngPtrGroupName, _
                                         LocalGroupMembersInfo3, _
                                         p_lngPtrUserName, _
                                         p_lngMemberCount)
   End If
   
   If p_lngRtn = NERR_Success Then
      AddDelUserToLocal = True
   Else
      AddDelUserToLocal = False
   End If
   
End Function

' ================================================
' Convert the SID type to a text string
' ================================================
Private Function TranslateSidUsage(ByVal xi_lngSidType As Long) As String
   Dim p_strTmp                  As String
   
   Select Case xi_lngSidType
      Case SidTypeUser
         p_strTmp = "User Account"
      Case SidTypeGroup
         p_strTmp = "Global Group Account"
      Case SidTypeDomain
         p_strTmp = "Domain Group Account"
      Case SidTypeAlias
         p_strTmp = "Alias Account"
      Case SidTypeWellKnownGroup
         p_strTmp = "Well-known Group Account (ie, Everyone)"
      Case SidTypeDeletedAccount
         p_strTmp = "Deleted Account"
      Case SidTypeInvalid
         p_strTmp = "Invalid Account"
      Case SidTypeUnknown
         p_strTmp = "Account Type Cannot Be Determined"
      Case Else
         p_strTmp = "Bad Parameter for Sid Usage"
   End Select
   
   ' Set the return value
   TranslateSidUsage = p_strTmp
   
End Function

' ================================================
' Convert a pointer to a string into a string
' ================================================
Public Function PointerToStringW(ByVal xi_lngPtrToString As Long) As String
   Dim p_strText           As String
   Dim p_lngLength         As Long

   If xi_lngPtrToString Then
         p_lngLength = lstrlenW(xi_lngPtrToString)
      If p_lngLength > 0 Then
         p_strText = Space$(p_lngLength)
         CopyMem ByVal StrPtr(p_strText), ByVal xi_lngPtrToString, p_lngLength * 2
      End If
   End If
   
   PointerToStringW = p_strText

End Function

' ================================================
' Convert a pointer to a string into a string via 
' a byte array
' ================================================
Private Function PointerToStringWByte(ByVal xi_lngPtrToString As Long) As String
   Dim p_abytBuffer()      As Byte
   Dim p_lngLen            As Long
   
   If xi_lngPtrToString <> 0 Then
      p_lngLen = lstrlenW(xi_lngPtrToString) * 2
      If p_lngLen Then
         ReDim p_abytBuffer(0 To (p_lngLen - 1)) As Byte
         CopyMem p_abytBuffer(0), ByVal xi_lngPtrToString, p_lngLen
         PointerToStringWByte = p_abytBuffer
      End If
   End If
   
End Function
DevX Pro
 
Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap