The microsoft site has all the API's well documented.<br>
The calls you are looking for are:<br>
<br>
For getting the group names given a user ID:<br>
1)NetUserGetGroups (for global groups - specify a userid)<br>
2)NetUserGetLocalGroups (for Local groups - specify a userid)<br>
3)NetGroupEnum (for global groups - gives all group names, no user name req'd)<br>
4)NetLocalGroupEnum (for Local groups - gives all group names, no user name req'd)<br>
<br>
For getting the users within a group: <br>
1)NetGroupGetUsers (for global groups - specify a group)<br>
2)NetLocalGroupGetMembers (for local groups - specify a group)<br>
3)NetUserEnum (for all the users in a domain - no group name req'd)<br>
<br>
There is a snipit of code supplied by microsoft at their site. You should check out the site directly yourself. The code sample is as follows......<br>
__________________________________________________________<br>
Option Explicit<br>
Option Base 0 ' Important assumption for this code<br>
<br>
Type MungeLong<br>
X As Long<br>
Dummy As Integer<br>
End Type<br>
<br>
Type MungeInt<br>
XLo As Integer<br>
XHi As Integer<br>
Dummy As Integer<br>
End Type<br>
<br>
Type TUser0 ' Level 0<br>
ptrName As Long<br>
End Type<br>
<br>
Type TUser1 ' Level 1<br>
ptrName As Long<br>
ptrPassword As Long<br>
dwPasswordAge As Long<br>
dwPriv As Long<br>
ptrHomeDir As Long<br>
ptrComment As Long<br>
dwFlags As Long<br>
ptrScriptPath As Long<br>
End Type<br>
<br>
'<br>
' for dwPriv<br>
'<br>
Const USER_PRIV_MASK = &H3<br>
Const USER_PRIV_GUEST = &H0<br>
Const USER_PRIV_USER = &H1<br>
Const USER_PRIV_ADMIN = &H2<br>
<br>
'<br>
' for dwFlags<br>
'<br>
Const UF_SCRIPT = &H1<br>
Const UF_ACCOUNTDISABLE = &H2<br>
Const UF_HOMEDIR_REQUIRED = &H8<br>
Const UF_LOCKOUT = &H10<br>
Const UF_PASSWD_NOTREQD = &H20<br>
Const UF_PASSWD_CANT_CHANGE = &H40<br>
Const UF_NORMAL_ACCOUNT = &H200 ' Needs to be ORed with the<br>
' other flags<br>
<br>
'<br>
' for lFilter<br>
'<br>
Const FILTER_NORMAL_ACCOUNT = &H2<br>
<br>
Declare Function NetGetDCName Lib "NETAPI32.DLL" (ServerName As Byte, _<br>
DomainName As Byte, DCNPtr As Long) As Long<br>
<br>
Declare Function NetUserDel Lib "NETAPI32.DLL" (ServerName As Byte, _<br>
UserName As Byte) As Long<br>
<br>
Declare Function NetGroupAddUser Lib "NETAPI32.DLL" (ServerName As _<br>
Byte, GroupName As Byte, UserName As Byte) As Long<br>
<br>
Declare Function NetGroupDelUser Lib "NETAPI32.DLL" (ServerName As _<br>
Byte, GroupName As Byte, UserName As Byte) As Long<br>
<br>
' Add using Level 1 user structure<br>
Declare Function NetUserAdd1 Lib "NETAPI32.DLL" Alias "NetUserAdd" _<br>
(ServerName As Byte, ByVal Level As Long, Buffer As TUser1, ParmError _<br>
As Long) As Long<br>
<br>
' Enumerate using Level 0 user structure<br>
Declare Function NetUserEnum0 Lib "NETAPI32.DLL" Alias "NetUserEnum" _<br>
(ServerName As Byte, ByVal Level As Long, ByVal lFilter As Long, _<br>
Buffer As Long, ByVal PrefMaxLen As Long, EntriesRead As Long, _<br>
TotalEntries As Long, ResumeHandle As Long) As Long<br>
<br>
Declare Function NetGroupEnumUsers0 Lib "NETAPI32.DLL" Alias _<br>
"NetGroupGetUsers" (ServerName As Byte, GroupName As Byte, _<br>
ByVal Level As Long, Buffer As Long, ByVal PrefMaxLen As Long, _<br>
EntriesRead As Long, TotalEntries As Long, ResumeHandle As Long) As Long<br>
<br>
Declare Function NetGroupEnum0 Lib "NETAPI32.DLL" Alias "NetGroupEnum" _<br>
(ServerName As Byte, ByVal Level As Long, Buffer As Long, ByVal _<br>
PrefMaxLen As Long, EntriesRead As Long, TotalEntries As Long, _<br>
ResumeHandle As Long) As Long<br>
<br>
Declare Function NetUserGetGroups0 Lib "NETAPI32.DLL" Alias _<br>
"NetUserGetGroups" (ServerName As Byte, UserName As Byte, _<br>
ByVal Level As Long, Buffer As Long, ByVal PrefMaxLen As Long, _<br>
EntriesRead As Long, TotalEntries As Long) As Long<br>
<br>
Declare Function NetAPIBufferFree Lib "NETAPI32.DLL" Alias _<br>
"NetApiBufferFree" (ByVal Ptr As Long) As Long<br>
<br>
Declare Function NetAPIBufferAllocate Lib "NETAPI32.DLL" Alias _<br>
"NetApiBufferAllocate" (ByVal ByteCount As Long, Ptr As Long) As Long<br>
<br>
Declare Function PtrToStr Lib "Kernel32" Alias "lstrcpyW" _<br>
(RetVal As Byte, ByVal Ptr As Long) As Long<br>
<br>
Declare Function StrToPtr Lib "Kernel32" Alias "lstrcpyW" _<br>
(ByVal Ptr As Long, Source As Byte) As Long<br>
<br>
Declare Function PtrToInt Lib "Kernel32" Alias "lstrcpynW" _<br>
(RetVal As Any, ByVal Ptr As Long, ByVal nCharCount As Long) As Long<br>
<br>
Declare Function StrLen Lib "Kernel32" Alias "lstrlenW" _<br>
(ByVal Ptr As Long) As Long<br>
<br>
Function AddUserToGroup(ByVal SName As String, _<br>
ByVal GName As String, ByVal UName As String) As Long<br>
'<br>
' This only adds users to global groups - not to local groups<br>
'<br>
Dim SNArray() As Byte, GNArray() As Byte, UNArray() As Byte, _<br>
Result As Long<br>
SNArray = SName & vbNullChar<br>
GNArray = GName & vbNullChar<br>
UNArray = UName & vbNullChar<br>
Result = NetGroupAddUser(SNArray(0), GNArray(0), UNArray(0))<br>
If Result = 2220 Then Debug.Print _<br>
"There is no **GLOBAL** group '" & GName & "'"<br>
AddUserToGroup = Result<br>
End Function<br>
<br>
Function DelUser(ByVal SName As String, ByVal UName As String) As Long<br>
Dim UNArray() As Byte, SNArray() As Byte<br>
UNArray = UName & vbNullChar<br>
SNArray = SName & vbNullChar<br>
DelUser = NetUserDel(SNArray(0), UNArray(0))<br>
End Function<br>
<br>
Function DelUserFromGroup(ByVal SName As String, _<br>
ByVal GName As String, ByVal UName As String) As Long<br>
'<br>
' This only deletes users from global groups - not local groups<br>
'<br>
Dim SNArray() As Byte, GNArray() As Byte, UNArray() As Byte, _<br>
Result As Long<br>
SNArray = SName & vbNullChar<br>
GNArray = GName & vbNullChar<br>
UNArray = UName & vbNullChar<br>
Result = NetGroupDelUser(SNArray(0), GNArray(0), UNArray(0))<br>
If Result = 2220 Then Debug.Print _<br>
"There is no **GLOBAL** group '" & GName & "'"<br>
DelUserFromGroup = Result<br>
End Function<br>
<br>
Function EnumerateGroups(ByVal SName As String, _<br>
ByVal UName As String) As Long<br>
'<br>
' Enumerates global groups only - not local groups<br>
'<br>
' The buffer is filled from the left with pointers to user names that<br>
' are filled from the right side. For example:<br>
'<br>
' ptr1¦ptr2¦...¦ptrn¦<garbage>¦strn¦...¦str2¦str1<br>
' ^-------------- BufPtr buffer ----------------^<br>
'<br>
' On NT, TotalEntries is the number of entries left to be read including<br>
' the currently read entries.<br>
'<br>
' On LanMan and OS/2, it is the total number of entries, period. Code<br>
' would have to be changed to reflect this if the Domain controller<br>
' wasn't an NT machine.<br>
'<br>
' BufPtr gets the address of the buffer (or ptr1 - add 4 to BufPtr for<br>
' each additional pointer)<br>
'<br>
Dim Result As Long, BufPtr As Long, EntriesRead As Long, _<br>
TotalEntries As Long, ResumeHandle As Long, BufLen As Long, _<br>
SNArray() As Byte, GNArray(99) As Byte, UNArray() As Byte, _<br>
GName As String, I As Integer, UNPtr As Long, _<br>
TempPtr As MungeLong, TempStr As MungeInt<br>
<br>
SNArray = SName & vbNullChar ' Move to byte array<br>
UNArray = UName & vbNullChar ' Move to Byte array<br>
BufLen = 255 ' Buffer size<br>
ResumeHandle = 0 ' Start with the first entry<br>
<br>
Do<br>
If UName = "" Then<br>
Result = NetGroupEnum0(SNArray(0), 0, BufPtr, BufLen, _<br>
EntriesRead, TotalEntries, ResumeHandle)<br>
Else<br>
Result = NetUserGetGroups0(SNArray(0), UNArray(0), 0, BufPtr, _<br>
BufLen, EntriesRead, TotalEntries)<br>
End If<br>
EnumerateGroups = Result<br>
If Result <> 0 And Result <> 234 Then ' 234 means multiple reads<br>
' required<br>
Debug.Print "Error " & Result & " enumerating group " & _<br>
EntriesRead & " of " & TotalEntries<br>
Exit Function<br>
End If<br>
For I = 1 To EntriesRead<br>
' Get pointer to string from beginning of buffer<br>
' Copy 4 byte block of memory in 2 steps<br>
Result = PtrToInt(TempStr.XLo, BufPtr + (I - 1) * 4, 2)<br>
Result = PtrToInt(TempStr.XHi, BufPtr + (I - 1) * 4 + 2, 2)<br>
LSet TempPtr = TempStr ' munge 2 Integers to a Long<br>
' Copy string to array and convert to a string<br>
Result = PtrToStr(GNArray(0), TempPtr.X)<br>
GName = Left(GNArray, StrLen(TempPtr.X))<br>
Debug.Print "Group: " & GName<br>
Next I<br>
Loop Until EntriesRead = TotalEntries<br>
' The above condition only valid for reading accounts on NT<br>
' but not OK for OS/2 or LanMan<br>
<br>
Result = NetAPIBufferFree(BufPtr) ' Don't leak memory<br>
<br>
End Function<br>
<br>
Function EnumerateUsers(ByVal SName As String, ByVal GName As String) _<br>
As Long<br>
'<br>
' If a group name is specified, it must be a global group<br>
' and not a local group.<br>
'<br>
' The buffer is filled from the left with pointers to user names that<br>
' are filled from the right side. For example:<br>
'<br>
' ptr1¦ptr2¦...¦ptrn¦<garbage>¦strn¦...¦str2¦str1<br>
' ^-------------- BufPtr buffer ----------------^<br>
'<br>
' On Windows NT, TotalEntries is the number of entries left to be read,<br>
' including the currently read entries.<br>
' On LanMan and OS/2, it is the total number of entries, period. Code<br>
' would have to be changed to reflect this if the Domain controller<br>
' wasn't an NT machine.<br>
'<br>
' BufPtr gets the address of the buffer (or ptr1 - add 4 to BufPtr for<br>
' each additional pointer)<br>
'<br>
' SName should be "\\servername"<br>
'<br>
Dim Result As Long, BufPtr As Long, EntriesRead As Long, _<br>
TotalEntries As Long, ResumeHandle As Long, BufLen As Long, _<br>
SNArray() As Byte, GNArray() As Byte, UNArray(99) As Byte, _<br>
UName As String, I As Integer, UNPtr As Long, TempPtr As MungeLong, _<br>
TempStr As MungeInt<br>
<br>
SNArray = SName & vbNullChar ' Move to byte array<br>
GNArray = GName & vbNullChar ' Move to Byte array<br>
BufLen = 255 ' Buffer size<br>
ResumeHandle = 0 ' Start with the first entry<br>
<br>
Do<br>
If GName = "" Then<br>
Result = NetUserEnum0(SNArray(0), 0, FILTER_NORMAL_ACCOUNT, _<br>
BufPtr, BufLen, EntriesRead, TotalEntries, ResumeHandle)<br>
Else<br>
Result = NetGroupEnumUsers0(SNArray(0), GNArray(0), 0, BufPtr, _<br>
BufLen, EntriesRead, TotalEntries, ResumeHandle)<br>
End If<br>
EnumerateUsers = Result<br>
If Result <> 0 And Result <> 234 Then ' 234 means multiple reads<br>
' required<br>
Debug.Print "Error " & Result & " enumerating user " _<br>
& EntriesRead & " of " & TotalEntries<br>
If Result = 2220 Then Debug.Print _<br>
"There is no **GLOBAL** group '" & GName & "'"<br>
Exit Function<br>
End If<br>
For I = 1 To EntriesRead<br>
' Get pointer to string from beginning of buffer<br>
' Copy 4-byte block of memory in 2 steps<br>
Result = PtrToInt(TempStr.XLo, BufPtr + (I - 1) * 4, 2)<br>
Result = PtrToInt(TempStr.XHi, BufPtr + (I - 1) * 4 + 2, 2)<br>
LSet TempPtr = TempStr ' munge 2 integers into a Long<br>
' Copy string to array<br>
Result = PtrToStr(UNArray(0), TempPtr.X)<br>
UName = Left(UNArray, StrLen(TempPtr.X))<br>
Debug.Print "User: " & UName<br>
Next I<br>
Loop Until EntriesRead = TotalEntries<br>
' The above condition is only valid for reading accounts on Windows NT,<br>
' but is not OK for OS/2 or LanMan<br>
<br>
Result = NetAPIBufferFree(BufPtr) ' Don't leak memory<br>
<br>
End Function<br>
<br>
Function GetPrimaryDCName(ByVal MName As String, _<br>
ByVal DName As String) As String<br>
Dim Result As Long, DCName As String, DCNPtr As Long<br>
Dim DNArray() As Byte, MNArray() As Byte, DCNArray(100) As Byte<br>
MNArray = MName & vbNullChar<br>
DNArray = DName & vbNullChar<br>
Result = NetGetDCName(MNArray(0), DNArray(0), DCNPtr)<br>
If Result <> 0 Then<br>
Debug.Print "Error: " & Result<br>
Exit Function<br>
End If<br>
Result = PtrToStr(DCNArray(0), DCNPtr)<br>
Result = NetAPIBufferFree(DCNPtr)<br>
DCName = DCNArray()<br>
GetPrimaryDCName = DCName<br>
End Function<br>
<br>
Function AddUser(ByVal SName As String, ByVal UName As String, _<br>
ByVal PWD As String) As Long<br>
Dim Result As Long, UNPtr As Long, PWDPtr As Long, ParmError As Long<br>
Dim SNArray() As Byte, UNArray() As Byte, PWDArray() As Byte<br>
Dim UserStruct As TUser1<br>
'<br>
' Move to byte arrays<br>
'<br>
SNArray = SName & vbNullChar<br>
UNArray = UName & vbNullChar<br>
PWDArray = PWD & vbNullChar<br>
'<br>
' Allocate buffer space<br>
'<br>
Result = NetAPIBufferAllocate(UBound(UNArray) + 1, UNPtr)<br>
Result = NetAPIBufferAllocate(UBound(PWDArray) + 1, PWDPtr)<br>
'<br>
' Copy arrays to the buffer<br>
'<br>
Result = StrToPtr(UNPtr, UNArray(0))<br>
Result = StrToPtr(PWDPtr, PWDArray(0))<br>
'<br>
' Fill the structure<br>
'<br>
With UserStruct<br>
.ptrName = UNPtr<br>
.ptrPassword = PWDPtr<br>
.dwPasswordAge = 3<br>
.dwPriv = USER_PRIV_USER<br>
.ptrHomeDir = 0<br>
.ptrComment = 0<br>
.dwFlags = UF_NORMAL_ACCOUNT Or UF_SCRIPT<br>
.ptrScriptPath = 0<br>
End With<br>
'<br>
' Add the user<br>
'<br>
Result = NetUserAdd1(SNArray(0), 1, UserStruct, ParmError)<br>
AddUser = Result<br>
If Result <> 0 Then<br>
Debug.Print "Error " & Result & " in parameter " & ParmError _<br>
& " when adding user " & UName<br>
End If<br>
'<br>
' Release buffers from memory<br>
'<br>
Result = NetAPIBufferFree(UNPtr)<br>
Result = NetAPIBufferFree(PWDPtr)<br>
<br>
End Function<br>
<br>