Atlanta Custom Software Development 

 
   Search        Code/Page
 

User Login
Email

Password

 

Forgot the Password?
Services
» Web Development
» Maintenance
» Data Integration/BI
» Information Management
Programming
  Database
Automation
OS/Networking
Graphics
Links
Tools
» Regular Expr Tester
» Free Tools


In this article you will learn couple of LAN Manager APIs to list groups and users. This demo uses the following APIs
NetAPIBufferFree:FreesmemoryallocatedbytheNetApiBufferAllocatefunctionandothernetworkmanagementfunctions.NetGroupEnum:Listsallglobalgroupsonaserver.NetGroupGetUsers:Listsallmembersofaparticularglobalgroup.NetLocalGroupEnum:Returnsinformationabouteachlocalgroupaccountonaserver.NetLocalGroupGetMembers:Listsallmembersofaspecifiedlocalgroup.NetUserEnum:Listsalluseraccountsonaserver.NetUserGetGroups:Returnsalistofglobalgroupnamestowhichauserbelongs.NetUserGetLocalGroups:Returnsalistoflocalgroupnamestowhichauserbelongs
Step-By-Step Example

- Create a standard exe project
- Add three listbox controls on the form1
- Add the following code in form1

Click here to copy the following block
Private Const LG_INCLUDE_INDIRECT As Long = &H1&

'Level 2
Private Type LOCALGROUP_MEMBERS_INFO_2
  lgrmi2_sid As Long
  lgrmi2_sidusage As Long
  lgrmi2_domainandname As Long
End Type

'Level 0
Private Type LOCALGROUP_USERS_INFO_0
  lgrui0_name As Long
End Type

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
    (Destination As Any, Source As Any, ByVal length As Long)

Private Declare Function NetAPIBufferFree Lib "NETAPI32.dll" Alias _
    "NetApiBufferFree" (ByVal Ptr As Long) As Long
Private Declare Function NetAPIBufferAllocate Lib "NETAPI32.dll" Alias _
    "NetApiBufferAllocate" (ByVal ByteCount As Long, Ptr As Long) As Long
Private Declare Function PtrToStr Lib "kernel32" Alias "lstrcpyW" _
    (RetVal As Byte, ByVal Ptr As Long) As Long

'//To get all users on a specified server
Private Declare Function NetUserEnum Lib "NETAPI32.dll" _
    (servername As Byte, ByVal level As Long, ByVal lFilter As Long, _
    Buffer As Long, ByVal prefmaxlen As Long, entriesread As Long, _
    totalentries As Long, ResumeHandle As Long) As Long

'//To get user membership in all local or global groups
Private Declare Function NetUserGetGroups Lib "NETAPI32.dll" _
    (servername As Byte, UserName As Byte, ByVal level As Long, _
    Buffer As Long, ByVal prefmaxlen As Long, _
    entriesread As Long, totalentries As Long) As Long
Private Declare Function NetUserGetLocalGroups Lib "NETAPI32.dll" _
    (servername As Byte, UserName As Byte, ByVal level As Long, _
    ByVal Flags As Long, Buffer As Long, ByVal prefmaxlen As Long, _
    entriesread As Long, totalentries As Long) As Long

'//To get local/global groups
Private Declare Function NetGroupEnum Lib "NETAPI32.dll" _
    (servername As Byte, ByVal level As Long, Buffer As Long, ByVal _
    prefmaxlen As Long, entriesread As Long, totalentries As Long, _
    ResumeHandle As Long) As Long
Private Declare Function NetLocalGroupEnum Lib "NETAPI32.dll" _
    (servername As Byte, ByVal level As Long, Buffer As Long, ByVal _
    prefmaxlen As Long, entriesread As Long, totalentries As Long, _
    ResumeHandle As Long) As Long

'//To get users of local/global groups

'Note : Dont use this function its obsolute, use NetGroupGetUsers instead of NetGroupEnumUsers
'Private Declare Function NetGroupEnumUsers Lib "NETAPI32.dll" _
'    (servername As Byte, GroupName As Byte, _
'    ByVal level As Long, Buffer As Long, ByVal prefmaxlen As Long, _
'    entriesread As Long, totalentries As Long, ResumeHandle As Long) As Long
    
Private Declare Function NetGroupGetUsers Lib "NETAPI32.dll" _
    (servername As Byte, GroupName As Byte, _
    ByVal level As Long, Buffer As Long, ByVal prefmaxlen As Long, _
    entriesread As Long, totalentries As Long, ResumeHandle As Long) As Long
Private Declare Function NetLocalGroupGetMembers Lib "NETAPI32.dll" _
    (servername As Byte, localgroupname As Byte, _
    ByVal level As Long, Buffer As Long, ByVal prefmaxlen As Long, _
    entriesread As Long, totalentries As Long, ResumeHandle As Long) As Long

Const MACHINE_NAME = "."  '// (.) indicates local machine
Const DOMAIN_NAME = ""  '// blank means local domain

'===========================================================================================
'Description : This function will retrive all local or global groups from a specified server

'SName : Server name
'UName : User name , Pass UserName to get all groups in which user has membership
'    Leave username blank to get all groups
'retCollection : Return collection of groups
'IsLocalGroup : Only valid if user name is supplied, Pass "true" to enum local groups only
'===========================================================================================
Function EnumerateGroups(ByVal SName As String, ByVal UName As String, _
  retGroupCol As Collection, Optional IsLocalGroup As Boolean = True) As Long

  Dim result As Long, bufptr As Long, entriesread As Long, _
      totalentries As Long, ResumeHandle As Long, BufLen As Long, _
      SNArray() As Byte, GNArray(99) As Byte, UNArray() As Byte, _
      GName As String, i As Integer, UNPtr As Long
      
  SNArray = SName & vbNullChar  ' Move to byte array
  UNArray = UName & vbNullChar  ' Move to Byte array
  BufLen = 255  ' Buffer size
  ResumeHandle = 0  ' Start with the first entry

  If UName = "" Then
    If IsLocalGroup = True Then
      result = NetLocalGroupEnum(SNArray(0), 0, bufptr, BufLen, _
          entriesread, totalentries, ResumeHandle)
    Else
      result = NetGroupEnum(SNArray(0), 0, bufptr, BufLen, _
          entriesread, totalentries, ResumeHandle)
    End If
  Else
    If IsLocalGroup = True Then
      'Note: use LG_INCLUDE_INDIRECT flag to get domain groups as well
      result = NetUserGetLocalGroups(SNArray(0), UNArray(0), 0, 0, bufptr, _
          BufLen, entriesread, totalentries)
    Else
      result = NetUserGetGroups(SNArray(0), UNArray(0), 0, bufptr, _
          BufLen, entriesread, totalentries)
    End If
  End If

  EnumerateGroups = result
  If result <> 0 And result <> 234 Then  ' 234 means multiple reads required
    Debug.Print "Error " & result & " enumerating group "
    Exit Function
  End If

  Dim ptrGroup As Long
  Dim nStructSize As Long

  For i = 1 To entriesread
    Erase GNArray
    '//Level 0 contains name so we will use it
    CopyMemory ptrGroup, ByVal bufptr + (4 * (i - 1)), 4
    result = PtrToStr(GNArray(0), ptrGroup)
    GName = GNArray
    retGroupCol.Add GName
  Next i

  result = NetAPIBufferFree(bufptr)  ' Don't leak memory
  
End Function

'===========================================================================================
'Description : This function will retrive all users or users
'       from a specified local or global group of a specified server

'SName : Server name
'GName : Group name , Pass GroupName to get all users in that
'    group or leave it blank to get all users
'retCollection : Return collection of users
'IsLocalGroup : Only valid if group name is supplied, Pass "true" to enum global group users
'===========================================================================================
Function EnumerateUsers(ByVal SName As String, ByVal GName As String, _
  retUserCol As Collection, Optional IsLocalGroup As Boolean = True) As Long

  Dim result As Long, bufptr As Long, entriesread As Long, _
      totalentries As Long, ResumeHandle As Long, BufLen As Long, _
      SNArray() As Byte, GNArray() As Byte, UNArray(99) As Byte, _
      UName As String, i As Integer, UNPtr As Long

  SNArray = SName & vbNullChar  ' Move to byte array
  GNArray = GName & vbNullChar  ' Move to Byte array
  BufLen = 255  ' Buffer size
  ResumeHandle = 0  ' Start with the first entry

  If GName = "" Then
    result = NetUserEnum(SNArray(0), 0, FILTER_NORMAL_ACCOUNT, _
        bufptr, BufLen, entriesread, totalentries, ResumeHandle)
  Else
    If IsLocalGroup = True Then
      '//Level 2 contains name so we will use it
      result = NetLocalGroupGetMembers(SNArray(0), GNArray(0), 2, bufptr, _
          BufLen, entriesread, totalentries, ResumeHandle)
    Else
      '//Level 0 contains name so we will use it
      result = NetGroupGetUsers(SNArray(0), GNArray(0), 0, bufptr, _
          BufLen, entriesread, totalentries, ResumeHandle)

    End If
  End If

  EnumerateUsers = result
  If result <> 0 And result <> 234 Then  ' 234 means multiple reads required
    Debug.Print "Error " & result & " enumerating user "
    If result = 2220 Then Debug.Print "There is no **GLOBAL** group '" & GName & "'"
    Exit Function
  End If

  Dim ptrUser As Long
  Dim lgr2 As LOCALGROUP_MEMBERS_INFO_2
  Dim nStructSize As Long
  nStructSize = Len(lgr2)
  For i = 1 To entriesread
    Erase UNArray
    If GName <> "" And IsLocalGroup = True Then
      '//use level 2 for this case
      CopyMemory lgr2, ByVal bufptr + (nStructSize * (i - 1)), nStructSize
      result = PtrToStr(UNArray(0), lgr2.lgrmi2_domainandname)
    Else
      '//use level 0 for this case which only contains pointer to name (4 bytes)
      CopyMemory ptrUser, ByVal bufptr + (4 * (i - 1)), 4
      result = PtrToStr(UNArray(0), ptrUser)
    End If

    UName = UNArray
    retUserCol.Add UName
  Next i

  result = NetAPIBufferFree(bufptr)  ' Don't leak memory
End Function

Private Sub Form_Load()
  Dim ret As Long, i As Integer
  Dim colGroups As New Collection, colUsers As New Collection

  '======================================================
  ' Display all Local/Global Groups
  '======================================================
  'ret = EnumerateGroups("\\remotemachine", "", colGroups, True)
  ret = EnumerateGroups(MACHINE_NAME, "", colGroups, True)
  For i = 1 To colGroups.Count
    List1.AddItem colGroups(i)
  Next

  '======================================================
  ' Display all users
  '======================================================
  'ret = EnumerateGroups("\\remotemachine", "", colGroups, True)
  ret = EnumerateUsers(MACHINE_NAME, "", colUsers, True)
  For i = 1 To colUsers.Count
    List2.AddItem colUsers(i)
  Next
End Sub

Sub RefreshGroupUsersList()
  Dim ret As Long, i As Integer, GroupName As String
  Dim colGroupUsers As New Collection

  If List1.ListIndex < 0 Then Exit Sub

  List2.Clear
  '======================================================
  ' Display Users of a local/remote machine
  '======================================================
  GroupName = DOMAINNAME & "\" & List1.List(List1.ListIndex) & vbNullChar
  'GroupName = List1.List(List1.ListIndex) & vbNullChar
  ret = EnumerateUsers(MACHINE_NAME, GroupName, colGroupUsers, True)

  For i = 1 To colGroupUsers.Count
    List2.AddItem colGroupUsers(i)
  Next
End Sub

Sub RefreshUserGroupsList()
  Dim ret As Long, i As Integer, UserName As String
  Dim colUserGroups As New Collection

  If List2.ListIndex < 0 Then Exit Sub

  List3.Clear
  '======================================================
  ' Display all associated groups with users
  '======================================================
  'UserName = List2.List(List2.ListIndex) & vbNullChar
  UserName = DOMAINNAME & "\" & List2.List(List2.ListIndex) & vbNullChar
  ret = EnumerateGroups(MACHINE_NAME, UserName, colUserGroups, True)

  For i = 1 To colUserGroups.Count
    List3.AddItem colUserGroups(i)
  Next
End Sub

Private Sub List1_Click()
  RefreshGroupUsersList
  If List2.ListCount > 0 Then List2.ListIndex = 0
End Sub

Private Sub List2_Click()
  RefreshUserGroupsList
End Sub


Submitted By : Nayan Patel  (Member Since : 5/26/2004 12:23:06 PM)

Job Description : He is the moderator of this site and currently working as an independent consultant. He works with VB.net/ASP.net, SQL Server and other MS technologies. He is MCSD.net, MCDBA and MCSE. In his free time he likes to watch funny movies and doing oil painting.
View all (893) submissions by this author  (Birth Date : 7/14/1981 )


Home   |  Comment   |  Contact Us   |  Privacy Policy   |  Terms & Conditions   |  BlogsZappySys

© 2008 BinaryWorld LLC. All rights reserved.