Platform SDK: Active Directory, ADSI, and Directory Services

Example Code for Enumerating Users on a Member Server or Windows 2000 Professional

[Visual Basic]

The following script enumerates all users on a member server or Windows 2000 Professional:

Dim cont As IADsContainer

'Example: Enumerating all local users on member server or workstation
'''''''''''''''''''''''''''''''''''''''
'Parse the arguments
'''''''''''''''''''''''''''''''''''''''
sComputer = InputBox("This script lists the users on a member server or workstation." & vbCrLf & vbCrLf & "Specify the computer name:")
 
If sComputer = "" Then
  Exit Sub
End If
 
'''''''''''''''''''''''''''''''''''''''
'Bind to the computer
'''''''''''''''''''''''''''''''''''''''
'Note that this sample uses the logged-on user's context
'To specify a user account other than the user account under 
'which your application is running, use IADsOpenDSObject.
Set cont = GetObject("WinNT://" & sComputer & ",computer")
If (Err.Number <> 0) Then
   BailOnFailure Err.Number, "on GetObject method"
End If
 
'''''''''''''''''''''''''''''''''''''''
'Filter to view only user objects
'''''''''''''''''''''''''''''''''''''''
cont.Filter = Array("User")
If (Err.Number <> 0) Then
   BailOnFailure Err.Number, "on IADsContainer::Filter method"
End If
 
strText = ""
intIndex = 0
intNumDisplay = 0
cmember = 0
'Maximum number of users to list on a msgbox.
MAX_DISPLAY = 20
 
'''''''''''''''''''''''''''''''''''''''
'Get each user
'''''''''''''''''''''''''''''''''''''''
For Each user In cont
    intIndex = intIndex + 1
    'Get the name
    strText = strText & vbCrLf & Right("  " & intIndex, 4) & " " & user.Name
    intNumDisplay = intNumDisplay + 1
    'Display in msgbox if there are MAX_DISPLAY users to display
    If intNumDisplay >= MAX_DISPLAY Then
        Call show_users(strText, sComputer)
        strText = ""
        intNumDisplay = 0
    End If
    'Reset the count of members within the current group
    cmember = 0
Next
Call show_users(strText, sComputer)
'''''''''''''''''''''''''''''''''''''''
'Display subroutines
'''''''''''''''''''''''''''''''''''''''
Sub show_users(strText, strName)
    MsgBox strText, vbInformation, "Users on " & strName
End Sub
 
Sub BailOnFailure(ErrNum, ErrText)    strText = "Error 0x" & Hex(ErrNum) & " " & ErrText
    MsgBox strText, vbInformation, "ADSI Error"
    WScript.Quit
End Sub
[C++]

The following code fragment contains a function that enumerates all objects of a specified class (such as user) and displays the members contained in each object on a member server or Windows 2000 Professional:

////////////////////////////////////////////////////////////////////////////////////////////////////
/*  ListObjectsWithWinNtProvider()    - 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 ListObjectsWithWinNtProvider(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;
}