| Platform SDK: Active Directory, ADSI, and Directory Services |
The following code fragment contains a function that enumerates all objects of a specified class (such as group) and displays the members contained in each object on a member server or a computer running Windows NT Workstation/Windows 2000 Professional:
////////////////////////////////////////////////////////////////////////////////////////////////////
/* ListMembersWithWinNtProvider() - Uses the WinNT provider to list children based on a filter
Returns S_OK on success
Parameters
LPWSTR pwszComputer - Computer to list
LPWSTR pwszClass - Filter for listing
LPWSTR pwszUSER = NULL - User Name for ADsOpenObject() binding- If NOT passed - Bind Though ADsGetObject()
LPWSTR pwszPASS = NULL - Password for ADsOpenObject() binding- If NOT passed - Bind Though ADsGetObject()
*/
HRESULT ListMembersWithWinNtProvider(LPWSTR pwszComputer,LPWSTR pwszClass, LPWSTR pwszUSER = NULL, LPWSTR pwszPASS = NULL)
{
HRESULT hr;
LPWSTR pwszBindingString = NULL;
IADsContainer * pIADsCont = NULL;
// Allocate a String for Binding.. This should definitely be big enough..
pwszBindingString = new WCHAR[(wcslen(gbsComputer) *2) + 20];
swprintf(pwszBindingString,L"WinNT://%s,computer",pwszComputer);
// Make sure either NO user is passed - or BOTH user and password are passed
assert(!pwszUSER || (pwszUSER && pwszPASS));
// Bind to the container passed
// If USER and PASS passed in, use ADsOpenObject()
if (pwszUSER)
hr = ADsOpenObject( pwszBindingString,
pwszUSER,
pwszPASS,
ADS_SECURE_AUTHENTICATION,
IID_IADsContainer,
(void**) &pIADsCont);
else
hr = ADsGetObject( pwszBindingString, IID_IADsContainer,(void **)&pIADsCont);
if (SUCCEEDED(hr))
{
VARIANT vFilter;
VariantInit(&vFilter);
LPWSTR pwszFilter = pwszClass;
// Build a Variant of array type, using the filter passed
hr = ADsBuildVarArrayStr(&pwszFilter, 1, &vFilter);
if (SUCCEEDED(hr))
{
// Set the filter for the results of the Enum
hr = pIADsCont->put_Filter(vFilter);
if (SUCCEEDED(hr))
{
IEnumVARIANT * pEnumVariant = NULL; // Ptr to the IEnumVariant Interface
VARIANT Variant; // Variant for retrieving data
ULONG ulElementsFetched; // Number of elements fetched
// Builds an enumerator interface- this will be used
// to enumerate the objects contained in the IADsContainer
hr = ADsBuildEnumerator(pIADsCont,&pEnumVariant);
// While no errors- Loop through and print the data
while (SUCCEEDED(hr) && hr != S_FALSE)
{
// Object comes back as a VARIANT holding an IDispatch *
hr = ADsEnumerateNext(pEnumVariant,1,&Variant,&ulElementsFetched);
if (hr != S_FALSE)
{
assert(HAS_BIT_STYLE(Variant.vt,VT_DISPATCH));
IDispatch *pDispatch = NULL;
IADs *pIADs= NULL;
pDispatch = Variant.pdispVal;
// QI the Variant's IDispatch * for the IADs interface
hr = pDispatch->QueryInterface(IID_IADs,(VOID **) &pIADs) ;
if (SUCCEEDED(hr))
{
// Print some information about the object
BSTR bsResult;
pIADs->get_Name(&bsResult);
wprintf(L" NAME: %s\n",(LPOLESTR) bsResult);
SysFreeString(bsResult);
pIADs->get_ADsPath(&bsResult);
wprintf(L" ADSPATH: %s\n",(LPOLESTR) bsResult);
SysFreeString(bsResult);
puts("------------------------------------------------------");
pIADs->Release();
pIADs = NULL;
}
}
}
// Since the hr from iteration was lost, free
// the interface if the ptr is != NULL
if (pEnumVariant)
{
pEnumVariant->Release();
pEnumVariant = NULL;
}
VariantClear(&Variant);
}
}
VariantClear(&vFilter);
}
delete [] pwszBindingString;
pwszBindingString = NULL;
return hr;
}
The following code enumerates all groups and displays the members contained in each group on a member server or a computer running Windows NT Workstation/Windows 2000 Professional:
'Example: Enumerating all local groups on member server or Windows NT Workstation/Windows 2000 Professional
Dim IADsCont As IADsContainer
Dim Group As IADsGroup
sComputer = InputBox("This script lists the groups on a member server or workstation." & vbCrLf & vbCrLf & "Specify the computer name:")
If sComputer = "" Then
MsgBox "No computer name was specified. You must specify a computer name."
Exit Sub
End If
'''''''''''''''''''''''''''''''''''''''
'Bind to the computer
'''''''''''''''''''''''''''''''''''''''
'Note that this sample uses the caller's security context.
'To specify a user account other than the user account under which
'which your application is running, use IADsOpenDSObject.
Set IADsCont = GetObject("WinNT://" & sComputer & ",computer")
If (Err.Number <> 0) Then
BailOnFailure Err.Number, "on GetObject method"
End If
'''''''''''''''''''''''''''''''''''''''
'Filter to view only group objects
'''''''''''''''''''''''''''''''''''''''
IADsCont.Filter = Array("group")
If (Err.Number <> 0) Then
BailOnFailure Err.Number, "on IADsContainer::Filter method"
End If
strText = ""
intIndex = 0
intNumDisplay = 0
cmember = 0
'Maximum number of groups to list on a msgbox.
MAX_DISPLAY = 10
'''''''''''''''''''''''''''''''''''''''
'Get each group and display its name and its members
'''''''''''''''''''''''''''''''''''''''
For Each Group In IADsCont
intIndex = intIndex + 1
'Get the name
strText = strText & vbCrLf & Right(" " & intIndex, 4) & " " & Group.Name
intNumDisplay = intNumDisplay + 1
'Get the members object
Set memberList = Group.members
If (Err.Number <> 0) Then
BailOnFailure Err.Number, "on IADsGroup::members method"
End If
'Get the enumerate the members of the group from the members object
For Each member In memberList
If cmember = 0 Then
strText = strText & vbCrLf & " " & "Members:"
End If
strText = strText & vbCrLf & " " & member.Name & " (" & member.Class & ")"
cmember = cmember + 1
Next
If cmember = 0 Then
strText = strText & vbCrLf & " " & "No members"
End If
'Display in msgbox if there are MAX_DISPLAY groups to display
If intNumDisplay >= MAX_DISPLAY Then
Call show_groups(strText, sComputer)
strText = ""
intNumDisplay = 0
End If
'Reset the count of members within the current group
cmember = 0
Next
Call show_groups(strText, sComputer)
'''''''''''''''''''''''''''''''''''''''
'Display subroutines
'''''''''''''''''''''''''''''''''''''''
Sub show_groups(strText, strName)
MsgBox strText, vbInformation, "Groups on " & strName
End Sub
Sub BailOnFailure(ErrNum, ErrText) strText = "Error 0x" & Hex(ErrNum) & " " & ErrText
MsgBox strText, vbInformation, "ADSI Error"
WScript.Quit
End Sub