Platform SDK: Active Directory, ADSI, and Directory Services

Example Code for Ranging with IDirectorySearch

The following C++ code fragment contains a function that uses ranging to retrieve the members of a group using IDirectorySearch:

////////////////////////////////////////////////////////////////////////////////////////////////////
/*  PrintAttributeWithRanging()    - Uses IDirectorySearch to read an attribute with ADSI ranging
 
    Parameters
 
        IDirectoryObject * pDirObject   - Object from which the attribute will be read
        LPOLESTR pwszAttribute          - Name of the attribute
        int iScope                      - Scope of the search
        int iNumToDisplayAtATime        - Number of Attributes to retrieve at a time
 
*/
HRESULT PrintAttributeWithRanging(IDirectoryObject * pDirObject,LPOLESTR pwszAttribute, int iScope,int iNumToDisplayAtATime)
{
    HRESULT hr;
    ADS_SEARCH_COLUMN col;
 
    // Interface Pointers
    IDirectorySearch *pDSSearch=NULL;
 
    // Get an IDirectorySearch * from the passed IDirectoryObject
    hr = pDirObject->QueryInterface(IID_IDirectorySearch,(void**)&pDSSearch);
    if (FAILED(hr))
        return hr;
 
    // The attribute which will come back from the search
    WCHAR pszAttr[512];
    DWORD dwAttrNameSize = 1;//sizeof(pszAttr)/sizeof(LPWSTR);
 
    // Preferences on Search
    ADS_SEARCHPREF_INFO arSearchPrefs[1];
    DWORD dwNumPrefs;
 
    // Set the scope to the passed value
    arSearchPrefs [0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE ; 
    arSearchPrefs [0].vValue.dwType = ADSTYPE_INTEGER;
    arSearchPrefs [0].vValue.Integer = ADS_SCOPE_BASE;
 
    // Number of elements in arSearchPrefs
    dwNumPrefs = 1;   
 
    ADS_SEARCH_HANDLE hSearch;  // Handle for searching. ADSI uses this 
                              // to keep its place
 
    // Set the preferences for search
    hr = pDSSearch->SetSearchPreference( arSearchPrefs, dwNumPrefs);
    if (FAILED(hr))
        return hr;
 
    // Do a series of Range searches, grabbing 10 at a time.
    int iRange = 0;
    DWORD dAttribsGotten = 0;
    while (SUCCEEDED(hr))
    {
 
        LPWSTR  pSrchFilter = (LPWSTR)&pszAttr;
        int     iAttribsGottenLastSrch =0;
 
        // Build the Range String : ex: L"Member;Range=0-5" 
        swprintf(pSrchFilter ,L"%s;Range=%d-%d",pwszAttribute,iRange,iRange+iNumToDisplayAtATime-1);
 
        // Display info to the user
        wprintf(L"\nPerforming a Range IDirectorySearch for the attribute '%s'\n"
                L"The search filter is %s\n\nEntries %d through %d:\n\n"
                ,pwszAttribute,pSrchFilter,iRange,iRange+iNumToDisplayAtATime-1);
 
        // Executing a BASE level search
        hr = pDSSearch->ExecuteSearch(L"(CN=*)",&pSrchFilter,dwAttrNameSize, &hSearch );                                      // Execute the Search
 
        if ( SUCCEEDED(hr) )
        {    
 
           while( pDSSearch->GetNextRow( hSearch) != S_ADS_NOMORE_ROWS )
           {
                LPWSTR pszColumn;
                while(pDSSearch->GetNextColumnName( hSearch, &pszColumn )!= S_ADS_NOMORE_COLUMNS )
                {        //printf("%S ", pszColumn ); 
 
                    // Get the ADsPath and save it in the list
                    hr = pDSSearch->GetColumn( hSearch, pszColumn, &col );
                    if ( SUCCEEDED(hr) )
                    {
                        for (DWORD x = 0; x< col.dwNumValues; x++)
                        {
                            wprintf(L"%d: %s\n",dAttribsGotten,(col.pADsValues+x)->CaseIgnoreString);
                            dAttribsGotten++; 
                            iAttribsGottenLastSrch++;
                        } 
 
                        // Copy the BSTR
                        // Free the column that GetColumn returns
                        pDSSearch->FreeColumn( &col );
                    }
 
                    FreeADsMem( pszColumn ); 
                } 
             }
 
            // Close the search handle and release the IDirectorySearch interface
            pDSSearch->CloseSearchHandle(hSearch);
        } 
 
        if (FAILED(hr) || hr ==S_ADS_NOMORE_ROWS || iAttribsGottenLastSrch== 0 || iAttribsGottenLastSrch< iNumToDisplayAtATime  )
            break;
        iRange += iNumToDisplayAtATime;
    }
    pDSSearch->Release();
    pDSSearch= NULL;
    return hr;
 
}