| Platform SDK: Active Directory, ADSI, and Directory Services |
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;
}