Question:
Is there a way to pass in a local workstation’s host name and get a return of a list of the local administrators for that workstation? I have seen this in the Hyena program and wanted to do the same from VB5/VB6 code.
Answer:
On a form with a command button and a listbox, paste the following code:
Private Sub Command1_Click() Dim vntRtn As Variant Dim lngNumItems As Long Dim lngLoop As Long Me.List1.Clear vntRtn = Module1.GetAdminUsers("PDCNEW") On Error Resume Next lngNumItems = UBound(vntRtn) On Error GoTo 0 If lngNumItems > 0 Then For lngLoop = 1 To lngNumItems Me.List1.AddItem vntRtn(lngLoop) Next lngLoop End If End Sub
In a BAS file called Module1, paste the following code:
Option ExplicitPrivate Declare Function NetUserEnum _ Lib "netapi32" _ (abytServer As Byte, _ ByVal Level As Long, _ ByVal Flags As Long, _ lngBuffer As Long, _ ByVal MaxLen As Long, _ lpEntriesRead As Long, _ lpTotalEntries As Long, _ lpResume_Handle As Long) As LongPrivate Declare Function NetApiBufferFree _ Lib "netapi32" _ (ByVal pBuffer As Long) As LongPrivate Declare Sub CopyMem _ Lib "kernel32" Alias "RtlMoveMemory" _ (pTo As Any, _ uFrom As Any, _ ByVal lSize As Long)Private Declare Function lstrlenW _ Lib "kernel32" _ (ByVal lpString As Long) As LongPrivate Declare Function lstrlen _ Lib "kernel32" _ (ByVal lpString As Long) As LongPrivate Const USER_PRIV_GUEST As Long = &H0Private Const USER_PRIV_USER As Long = &H1Private Const USER_PRIV_ADMIN As Long = &H2Private Const constUserInfo1 As Long = 1Private Type USER_INFO_1_API usri1_name As Long usri1_password As Long usri1_password_age As Long usri1_priv As Long usri1_home_dir As Long usri1_comment As Long usri1_flags As Long usri1_script_path As LongEnd TypePrivate Type USER_INFO_1 usri1_name As String usri1_password As Long usri1_password_age As Long usri1_priv As Long usri1_home_dir As String usri1_comment As String usri1_flags As Long usri1_script_path As StringEnd TypePrivate Const NERR_Success As Long = 0&Private Const ERROR_MORE_DATA As Long = 234&Public Function GetAdminUsers(Optional ByVal xi_strServer As String) As Variant Dim lngBuffer As Long Dim abytServer() As Byte Dim atypUsers() As USER_INFO_1_API Dim astrAdmins() As String Dim strName As String Dim lngTotalUsers As Long Dim lngTotalUsersRead As Long Dim lngRtn As Long Dim lngResumeHwnd As Long Dim lngNumAdmins As Long Dim lngLevel As Long Dim lngLoop As Long Const Flags& = 0 If Len(xi_strServer) = 0 Then abytServer = "" Else If InStr(1, xi_strServer, "\", vbTextCompare) <= 0 Then xi_strServer = "\" & xi_strServer Else ' Already OK End If abytServer = xi_strServer & vbNullChar End If 'call API to Enumerate users If Len(xi_strServer) <> 0 Then lngRtn = NetUserEnum(abytServer(0), constUserInfo1, _ Flags, lngBuffer, _ &H4000, lngTotalUsersRead, _ lngTotalUsers, lngResumeHwnd) Else lngRtn = NetUserEnum(ByVal 0&, constUserInfo1, _ Flags, lngBuffer, _ &H4000, lngTotalUsersRead, _ lngTotalUsers, lngResumeHwnd) End If If lngTotalUsersRead > 0 Then ReDim atypUsers(0 To lngTotalUsersRead - 1) CopyMem atypUsers(0), _ ByVal lngBuffer, _ Len(atypUsers(0)) * lngTotalUsersRead lngLoop = 0 lngNumAdmins = 0 For lngLoop = 0 To lngTotalUsers - 1 strName = PointerToStringW(atypUsers(lngLoop).usri1_name) lngLevel = atypUsers(lngLoop).usri1_priv If lngLevel = USER_PRIV_ADMIN Then lngNumAdmins = lngNumAdmins + 1 ReDim Preserve astrAdmins(1 To lngNumAdmins) astrAdmins(lngNumAdmins) = strName End If Next lngLoop End If ' Set the return value GetAdminUsers = astrAdmins If lngBuffer Then NetApiBufferFree lngBuffer End If End FunctionPrivate Function PointerToStringW(lpStringW As Long) As String Dim Buffer() As Byte Dim nLen As Long If lpStringW Then nLen = lstrlenW(lpStringW) * 2 If nLen Then ReDim Buffer(0 To (nLen - 1)) As Byte CopyMem Buffer(0), ByVal lpStringW, nLen PointerToStringW = Buffer End If End IfEnd Function