Using IDirectorySearch

By far the easiest and most common way of searching Active Directory is to use ADO and the ADSI OLE DB provider. Of course, C and C++ developers can use ADO or OLE DB from their applications, but they might prefer the ADSI IDirectorySearch interface, which is a low-level interface for searching Active Directory.

As I mentioned at the beginning of this chapter, the ADSI OLE DB provider uses IDirectorySearch to perform its work. IDirectorySearch and IDirectoryObject (explained in Chapter 7) are the only two interfaces in ADSI that don't support Automation—that is, they don't support IDispatch, cannot be used by the scripting languages, and are difficult to use from Visual Basic. Since this book is targeted to readers using a variety of development environments, I wanted to give an example of how you can use this interface directly using C and C++. The source code is simple enough and is similar to the VBScript version of the Phone sample. Listing 5-2 shows the code, which is also included on the companion CD.

 #define _WIN32_WINNT 0x0500
#define _UNICODE
#include <stdio.h>
#include <tchar.h> #include <objbase.h>
#include <activeds.h>
// Attributes to return
_TCHAR *rgpszAttributeList[] = { _TEXT("cn"), _TEXT("telephoneNumber") };
// LDAP search filter
_TCHAR *pszSearchFormat = _TEXT("(&(objectCategory=person)(sn=%s*))");
//—————————————————————————————————-
// wmain ( int argc, wchar_t *argv[] )
// Entry point for UNICODE console mode apps
//—————————————————————————————————-
void wmain( int argc, wchar_t *argv[] )
{
// Create buffer for the query string
_TCHAR *pszQuery = new _TCHAR[_MAX_PATH];
// Initialize the buffer
_tcscpy(pszQuery, _TEXT(""));
// Loop through all the command line arguments
if (argc > 1)
    {
    // Copy the name to search from the command line argument array
    _tcscpy(pszQuery, argv[1]);
    // Initialize variables
    HRESULT hResult;
    IADs *pobjIADs;
    VARIANT varDomain;
    // Initialize COM
    CoInitialize(NULL);
    // Get a base IADs object
    hResult = ADsGetObject(_TEXT("GC://rootDSE"), IID_IADs, 
        (void**)&pobjIADs);
    // Use the Get method to get the default naming context 
    // (directory partition)
    hResult = pobjIADs->Get(_TEXT("defaultNamingContext"), &varDomain);
    // Build LDAP path to the domain
    _TCHAR *pszLDAPPath = new _TCHAR[_MAX_PATH];
    _tcscpy(pszLDAPPath, _TEXT("GC://"));
    _tcscat(pszLDAPPath, varDomain.bstrVal);
    // Get the directory search interface to the domain
    IDirectorySearch *pContainerToSearch = NULL;
    hResult = ADsGetObject( pszLDAPPath,
        IID_IDirectorySearch, 
        (void **)&pContainerToSearch);
    // Create search filter in LDAP format
    _TCHAR *pszSearchFilter = new _TCHAR[_MAX_PATH];
    // Create LDAP format search string
    _stprintf(pszSearchFilter, pszSearchFormat, pszQuery);
    // Variables for column name and data
    ADS_SEARCH_COLUMN colSearchColumn;
    // Create search preferences structure
    ADS_SEARCHPREF_INFO arSearchPrefs[3];
    // Set a subtree search
    arSearchPrefs[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
    arSearchPrefs[0].vValue.dwType = ADSTYPE_INTEGER;
    arSearchPrefs[0].vValue.Integer = ADS_SCOPE_SUBTREE;
    // Set page size for 20 rows
    arSearchPrefs[1].dwSearchPref = ADS_SEARCHPREF_PAGESIZE;
    arSearchPrefs[1].vValue.dwType = ADSTYPE_INTEGER;
    arSearchPrefs[1].vValue.Integer = 20;
    // Turn sorting on
    // Create a sort key using the cn attribute
    ADS_SORTKEY adsSortKey;
    adsSortKey.pszAttrType = _TEXT("cn");  // Attribute to sort on
    adsSortKey.pszReserved = NULL;         // Reserved, not used
    adsSortKey.fReverseorder = 0;         // Normal sort, not reversed
    // Create the sort search preference
    arSearchPrefs[2].dwSearchPref = ADS_SEARCHPREF_SORT_ON;
    arSearchPrefs[2].vValue.dwType = ADSTYPE_PROV_SPECIFIC;
    arSearchPrefs[2].vValue.ProviderSpecific.dwLength = sizeof(ADS_SORTKEY);
    arSearchPrefs[2].vValue.ProviderSpecific.lpValue = (LPBYTE) &adsSortKey;
    // Set the search preferences
    hResult = pContainerToSearch->SetSearchPreference( &arSearchPrefs[0], 3);
    // Handle to search results that is passed to other methods of 
    // IDirectorySearch.
    ADS_SEARCH_HANDLE hSearch;     // Execute search by providing LDAP filter, attribute list, and size
    // Returns handle to search
    hResult = pContainerToSearch->ExecuteSearch(pszSearchFilter,
        rgpszAttributeList,
        sizeof(rgpszAttributeList) / sizeof(LPOLESTR),
        &hSearch);
    if ( SUCCEEDED(hResult) )
        {
        // Call IDirectorySearch::GetNextRow() to retrieve the next 
        // row of data
        hResult = pContainerToSearch->GetFirstRow(hSearch);
        if (SUCCEEDED(hResult))
            {
            // Loop through each row returned
            while (hResult != S_ADS_NOMORE_ROWS)
                {
                // Get and print the first attribute (common name)
                hResult = pContainerToSearch->GetColumn(hSearch, 
                    rgpszAttributeList[0], &colSearchColumn);
                if (SUCCEEDED(hResult))
                    {
                    // Display the cn attribute
                    _tprintf(_TEXT("%s\t"), 
                        colSearchColumn.pADsValues->CaseIgnoreString);
                    pContainerToSearch->FreeColumn( &colSearchColumn );
                    }
                // Get and print Telephone Number
                hResult = pContainerToSearch->GetColumn(hSearch, 
                      rgpszAttributeList[1], &colSearchColumn);
                    if (SUCCEEDED(hResult))
                        {
                        // Display the phone number attribute
                        _tprintf(_TEXT("%s"), 
                            colSearchColumn.pADsValues->CaseIgnoreString);
                    pContainerToSearch->FreeColumn( &colSearchColumn );
                    }
                else  // Didn't get phone number, display substitute text
                    _tprintf(_TEXT("(number not listed)"));                 // Start a new line
                _tprintf(_TEXT("\n"));
                //Get the next row
                hResult = pContainerToSearch->GetNextRow(hSearch);
                }
            }
        // Close the search handle to clean up
        pContainerToSearch->CloseSearchHandle(hSearch);
        }
    // Clean up objects
    if (pContainerToSearch)
        pContainerToSearch->Release();
    if (pobjIADs)
        pobjIADs->Release();
 
    // Uninitialize COM
    CoUninitialize();
    }
    return;
}

Listing 5-2 Phone.cpp uses IDirectorySearch to search Active Directory.



MicrosoftR WindowsR 2000 Active DirectoryT Programming
MicrosoftR WindowsR 2000 Active DirectoryT Programming
ISBN: N/A
EAN: N/A
Year: 2001
Pages: 108

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net