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