| Platform SDK: Active Directory, ADSI, and Directory Services |
The following code fragment contains two functions that perform a query against a specified root object and displays all groups and groups by type:
////////////////////////////////////////////////////////////////////////////////////////////////////
/* QueryAndOutputGroups() - Gets an IDirectorySearch Interface on the passed root
Performs several sample searches using IDirectorySearch
Parameters
IDirectoryObject * pDirObjectRoot - The root from where searches will be performed
*/
void QueryAndOutputGroups(IDirectoryObject * pDirObjectRoot)
{
HRESULT hr;
DisplayConsoleMsgWaitForEnter(L"To look at the new Active Directory structure, use\n"
L"IDirectorySearch, to perform several querys on the directory\n"
L" NOTE: All of the samples object that this program\n creates"
L" begin with the text 'UGExercise'.\n\n"
L"Hit ENTER to perform a subtree search of ALL the groups.\n" );
/////////////////////////////////////////////////
// Search for groups
// Interface Pointers
IDirectorySearch *pDSSearch=NULL;
// The attributes that are needed
LPWSTR pszAttr[] ={ L"Name", L"ADsPath" };
DWORD dwAttrNameSize = sizeof(pszAttr)/sizeof(LPWSTR);
// Preferences on Search
// Do a DEEP SUBTREE search for all accounts
ADS_SEARCHPREF_INFO arSearchPrefs[1];
DWORD dwNumPrefs;
arSearchPrefs [0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE ;
arSearchPrefs [0].vValue.dwType = ADSTYPE_INTEGER;
arSearchPrefs [0].vValue.Integer = ADS_SCOPE_SUBTREE;
dwNumPrefs = 1;
hr = pDirObjectRoot->QueryInterface(IID_IDirectorySearch,(void**)&pDSSearch);
if (SUCCEEDED(hr))
{
////////////////////////////////////////////////
// Search for all the groups
puts("<<<<<<<<<<<<<<<<<<<<<ALL GROUPS>>>>>>>>>>>>>>>>>");
hr = SimpleDirectorySearch(pDSSearch,
L"(objectCategory=group)",
pszAttr,dwAttrNameSize,
arSearchPrefs,
dwNumPrefs);
////////////////////////////////////////////////
// Search for all the GLOBAL groups
DisplayConsoleMsgWaitForEnter(
L"Hit ENTER to perform a subtree search of all the GLOBAL groups\n");
puts("<<<<<<<<<<<<<<<<<<<<<ALL GLOBAL Groups>>>>>>>>>>>>>>>>>");
hr = SimpleDirectorySearch(pDSSearch,
BuildGroupTypeQueryString(lmrOR,ADS_GROUP_TYPE_GLOBAL_GROUP),
pszAttr,dwAttrNameSize,arSearchPrefs,
dwNumPrefs);
////////////////////////////////////////////////
// Search for all the DOMAIN LOCAL groups
DisplayConsoleMsgWaitForEnter(
L"Hit ENTER to perform a subtree search of all the DOMAIN LOCAL groups\n");
puts("<<<<<<<<<<<<<<<<<<<<<ALL Domain Local Groups>>>>>>>>>>>>>>>>>");
hr = SimpleDirectorySearch(pDSSearch,
BuildGroupTypeQueryString(lmrOR,ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP),
pszAttr,dwAttrNameSize,
arSearchPrefs,
dwNumPrefs);
if (bUseUniversalGroups)
{
////////////////////////////////////////////////
// Search for all the UNIVERSAL groups
DisplayConsoleMsgWaitForEnter(
L"Hit ENTER to perform a subtree search of all the UNIVERSAL groups\n");
puts("<<<<<<<<<<<<<<<<<<<<<ALL Universal Groups>>>>>>>>>>>>>>>>>");
hr = SimpleDirectorySearch(pDSSearch,
BuildGroupTypeQueryString(lmrOR,
ADS_GROUP_TYPE_UNIVERSAL_GROUP),
pszAttr,dwAttrNameSize,
arSearchPrefs,
dwNumPrefs);
}
////////////////////////////////////////////////
// Search for all the Security Enabled groups
DisplayConsoleMsgWaitForEnter(
L"Hit ENTER to perform a subtree search of all Security Enabled groups\n");
puts("<<<<<<<<<<<<<<<<<<<<<ALL Security Enabled Groups>>>>>>>>>>>>>>>>>");
hr = SimpleDirectorySearch(pDSSearch,
BuildGroupTypeQueryString(lmrOR,ADS_GROUP_TYPE_SECURITY_ENABLED),
pszAttr,dwAttrNameSize,
arSearchPrefs,
dwNumPrefs);
////////////////////////////////////////////////
// Search for all the Security Enabled LOCAL groups
DisplayConsoleMsgWaitForEnter(
L"Hit ENTER to perform a subtree search of all Security Enabled LOCAL groups\n");
puts("<<<<<<<<<<<<<<<<<<<<<ALL Security Enabled Domain Local Groups>>>>>>>>>>>>>>>>>");
hr = SimpleDirectorySearch(pDSSearch,
BuildGroupTypeQueryString(lmrAND,ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP | ADS_GROUP_TYPE_SECURITY_ENABLED),
pszAttr,dwAttrNameSize,
arSearchPrefs,
dwNumPrefs);
////////////////////////////////////////////////
// Search for all the DOMAIN LOCAL groups whose
// name begins with 'UGExercise'
DisplayConsoleMsgWaitForEnter(
L"Hit ENTER to perform a subtree search of all DOMAIN LOCAL groups that begin with the text \'UGExercise\'\n");
puts("<<<<<<<<<<<<<<<<<<<<<ALL Domain Local Groups Beginnig with \'UGExercise\' >>>>>>>>>>>>>>>>>");
// Build a string for the Query - this helper
// aids in taking the BITMASK passed to it and
// converting it into a string
WCHAR * szwGTQuery = BuildGroupTypeQueryString(lmrOR,ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP );
WCHAR szwQuery[512];
// Add the bit value to the LDAP query string
// Look for all objects which have
// DOMAIN LOCAL and a groupType == the domain local bitmask
// built previously with BuildGroupTypeQueryString()
wsprintf(szwQuery,L"(&(cn=UGExercise*)%s)",szwGTQuery);
OutputDebugString(szwQuery);
OutputDebugString(L"\r\n");
// Perform the search using the query string built previously (szwQuery)
hr = SimpleDirectorySearch(pDSSearch,szwQuery,pszAttr,dwAttrNameSize,arSearchPrefs,dwNumPrefs);
////////////////////////////////////////////////
// Search for ALL the groups whose
// name begins with 'UGExercise'
DisplayConsoleMsgWaitForEnter(
L"Hit ENTER to perform a subtree search of ALL groups that begin with the text \'UGExercise \'\n");
puts("<<<<<<<<<<<<<<<<<<<<<ALL Groups Beginning with \'UGExercise \' >>>>>>>>>>>>>>>>>");
hr = SimpleDirectorySearch(pDSSearch,
L"(&(cn=UGExercise*)(objectCategory=group))",
pszAttr,dwAttrNameSize,
arSearchPrefs,
dwNumPrefs);
// Release the Search interface
pDSSearch->Release();
pDSSearch= NULL;
}
else
puts("ERROR: pDirObjectRoot->QueryInterface(IID_IDirectorySearch,(void**)&pDSSearch); FAILED!");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/* SimpleDirectorySearch() - Uses IDirectorySearch to search the directory
results are printed to the console window
Parameters
IDirectorySearch *pDSSearch - IDirectorySearch interface from the object
which will serve as the root of the search
LPWSTR pszSearchFilter - LDAP Search filter
LPWSTR pszAttr[] - Array of Attribute names to retrieve
DWORD dwAttrNameSize - Number of elements in pszAttr
PADS_SEARCHPREF_INFO pSearchPrefs - ADSI Array of preferences
DWORD dwNumPrefs - Number of elements in pSearchPrefs
*/
HRESULT SimpleDirectorySearch(IDirectorySearch *pDSSearch,LPWSTR pszSearchFilter, LPWSTR pszAttr[],DWORD dwAttrNameSize,
PADS_SEARCHPREF_INFO pSearchPrefs,DWORD dwNumPrefs )
{
wprintf(L"\nSearch Filter =%s\n",pszSearchFilter);
// COL for iterations
ADS_SEARCH_COLUMN col;
HRESULT hr;
// Interface Pointers
IADs *pObj = NULL;
IADs * pIADs = NULL;
// Handle used for searching
ADS_SEARCH_HANDLE hSearch;
// if the preferences were passed in, call IDirectorySearch::SetSearchPreference()
if (dwNumPrefs && pSearchPrefs)
{
hr = pDSSearch->SetSearchPreference( pSearchPrefs, dwNumPrefs);
if (FAILED(hr))
return hr;
}
// Execute the search using the passed search filter, the
// attributes and the address of the search handle
hr = pDSSearch->ExecuteSearch(pszSearchFilter,pszAttr ,dwAttrNameSize, &hSearch );
if ( SUCCEEDED(hr) )
{
// Call IDirectorySearch::GetNextRow() to retrieve the next row
//of data
while( pDSSearch->GetNextRow( hSearch) != S_ADS_NOMORE_ROWS )
{
// loop through the array of passed column names,
// print the data for each column
for (DWORD x = 0; x < dwAttrNameSize; x++)
{
// Get the data for this column
hr = pDSSearch->GetColumn( hSearch, pszAttr[x], &col );
if ( SUCCEEDED(hr) )
{
// Print the data for the column and free the column
wprintf(L"%s: %s\r\n",pszAttr[x],col.pADsValues->CaseIgnoreString);
pDSSearch->FreeColumn( &col );
}
else
wprintf(L"<%s property NOT available>",pszAttr[x]);
}
puts("------------------------------------------------");
}
// Close the search handle to clean up
pDSSearch->CloseSearchHandle(hSearch);
}
return hr;
}
The following subroutine performs a query against a specified root object and display all groups and groups by type:
'************************************
' QueryAndOutputGroups() - Performs several sample searches using ADO
'
'
' Parameters
'
' oDirObjectRoot As IDirectoryObject - The root from where searches will be performed
'
Sub QueryAndOutputGroups(oDirObjectRoot As IDirectoryObject)
'*******************************
' Search for all the groups
DisplayMessage " "
DisplayMessage "<<<<<<<<<<<<<<<<<<<<<ALL GROUPS>>>>>>>>>>>>>>>>>" 'cn = 'UG*' objectCategory
SimpleDirectorySearch oDirObjectRoot, "objectCategory = 'group'", ADS_SCOPE_SUBTREE
'*****************************************
' Search for all the GLOBAL groups
DisplayMessage " "
DisplayMsgWaitForInput "Hit OK to perform a subtree search of all the GLOBAL groups"
DisplayMessage " "
DisplayMessage "<<<<<<<<<<<<<<<<<<<<<ALL GLOBAL Groups>>>>>>>>>>>>>>>>>"
SimpleDirectorySearch oDirObjectRoot, "GroupType=" & Str(ADS_GROUP_TYPE_GLOBAL_GROUP) & " or " & _
"GroupType=" & Str(ADS_GROUP_TYPE_GLOBAL_GROUP Or ADS_GROUP_TYPE_SECURITY_ENABLED), _
ADS_SCOPE_SUBTREE
'*****************************************
' Search for all the DOMAIN LOCAL groups
DisplayMessage " "
DisplayMsgWaitForInput "Hit OK to perform a subtree search of all the DOMAIN LOCAL groups"
DisplayMessage " "
DisplayMessage "<<<<<<<<<<<<<<<<<<<<<ALL Domain Local Groups>>>>>>>>>>>>>>>>>"
SimpleDirectorySearch oDirObjectRoot, "GroupType=" & Str(ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP) & " or " & _
"GroupType=" & Str(ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP Or ADS_GROUP_TYPE_SECURITY_ENABLED), _
ADS_SCOPE_SUBTREE
' #ifdef USE_UNIVERSAL_GROUPS
'*****************************************
' Search for all the UNIVERSAL groups
DisplayMessage " "
DisplayMsgWaitForInput "Hit OK to perform a subtree search of all the UNIVERSAL groups"
DisplayMessage " "
DisplayMessage "<<<<<<<<<<<<<<<<<<<<<ALL Universal Groups>>>>>>>>>>>>>>>>>"
SimpleDirectorySearch oDirObjectRoot, "GroupType=" & Str(ADS_GROUP_TYPE_UNIVERSAL_GROUP) & " or " & _
"GroupType=" & Str(ADS_GROUP_TYPE_UNIVERSAL_GROUP Or ADS_GROUP_TYPE_SECURITY_ENABLED), _
ADS_SCOPE_SUBTREE
' #End If
'*****************************************
' Search for all the Security Enabled groups
DisplayMessage " "
DisplayMsgWaitForInput "Hit OK to perform a subtree search of all Security Enabled groups"
DisplayMessage " "
DisplayMessage "<<<<<<<<<<<<<<<<<<<<<ALL Security Enabled Groups>>>>>>>>>>>>>>>>>"
SimpleDirectorySearch oDirObjectRoot, "GroupType=" & Str(ADS_GROUP_TYPE_SECURITY_ENABLED) & " or " & _
"GroupType=" & Str(ADS_GROUP_TYPE_SECURITY_ENABLED Or ADS_GROUP_TYPE_SECURITY_ENABLED), _
ADS_SCOPE_SUBTREE
'*****************************************
' Search for all the Security Enabled LOCAL groups
DisplayMessage " "
DisplayMsgWaitForInput "Hit OK to perform a subtree search of all Security Enabled LOCAL groups"
DisplayMessage " "
DisplayMessage "<<<<<<<<<<<<<<<<<<<<<ALL Security Enabled Domain Local Groups>>>>>>>>>>>>>>>>>"
SimpleDirectorySearch oDirObjectRoot, "GroupType=" & Str(ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP Or _
ADS_GROUP_TYPE_SECURITY_ENABLED), _
ADS_SCOPE_SUBTREE
'*****************************************
' Search for all the DOMAIN LOCAL groups whose
' name begins with 'UGExercise'
DisplayMessage " "
DisplayMsgWaitForInput "Hit OK to perform a subtree search of all DOMAIN LOCAL groups that begin with the text 'UGExercise'"
DisplayMessage " "
DisplayMessage "<<<<<<<<<<<<<<<<<<<<<ALL Domain Local Groups Beginnig with 'UGExercise' >>>>>>>>>>>>>>>>>"
SimpleDirectorySearch oDirObjectRoot, "cn='UGExercise*' and (GroupType=" & _
Str(ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP) & " or GroupType=" & _
Str(ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP Or ADS_GROUP_TYPE_SECURITY_ENABLED) & _
")", ADS_SCOPE_SUBTREE
'*****************************************
' Search for ALL the groups whose
' name begins with 'UGExercise'
DisplayMessage " "
DisplayMsgWaitForInput "Hit OK to perform a subtree search of ALL groups that begin with the text 'UGExercise '"
DisplayMessage " "
DisplayMessage "<<<<<<<<<<<<<<<<<<<<<ALL Groups Beginning with 'UGExercise' >>>>>>>>>>>>>>>>>"
SimpleDirectorySearch oDirObjectRoot, " cn='UGExercise*' and objectCategory='group'", ADS_SCOPE_SUBTREE
End Sub
'////////////////////////////////////////////////////////////////////////////////////////////////////
' SimpleDirectorySearch() - Uses ADO to search the directory
' Results are displayed in the list box
' Parameters
'
' oDirObjectRoot As IDirectoryObject - Root of the search
' ByVal sSearchFilter As String - LDAP Search filter
' ByVal lScope As Integer - Scope for Searching possible values are:
' ADS_SCOPE_BASE
' ADS_SCOPE_ONELEVEL
' ADS_SCOPE_SUBTREE
'
' (See IDirectorySearch and ADS_SCOPEENUM in the docs for more info)
'
Sub SimpleDirectorySearch(oDirObjectRoot As IDirectoryObject, ByVal sSearchFilter As String, ByVal lScope As Integer)
Dim iIndex As Integer
iIndex = 0
Dim v, j, i
Dim con As New Connection, rs As New Recordset
Dim Com As New Command
Dim oIADs As IADs
Dim sAdsPathRoot As String
' Get the LDAP path to the passed in object
sAdsPathRoot = GetAdsPath(oDirObjectRoot)
'Open a Connection object
con.Provider = "ADsDSOObject"
'-----------------------------------------------------------------
' To be authenticated using alternate credentials
' use connection properties of User ID and Password
'-----------------------------------------------------------------
' con.Properties("User ID") = "Administrator"
' con.Properties("Password") = ""
' Open the connection
con.Open "Active Directory Provider"
' Create a command object on this connection
Set Com.ActiveConnection = con
' set the query string using SQL Dialect
Com.CommandText = "select name,AdsPath from '" & sAdsPathRoot & "' where " & sSearchFilter & " ORDER BY NAME"
' Tell the user what the search filter is
DisplayMessage "Search Filter = " & Com.CommandText
'---------------------------------------------------
' Or you can use LDAP Dialect, for example,
'---------------------------------------------------
' Ex Com.CommandText = "<LDAP://Microsoft1/dc=Microsoft,DC=com>;(objectClass=*);name"
' For LDAP Dialect, the valid search scope are base, oneLevel and subtree
' Com.CommandText = "<" & adDomainPath & ">;(objectClass=*);name;subtree"
' For LDAP Dialect (<LDAP:...>), there is no way to specify sort order in the string,
' However, you can use this SORT ON property to specify sort order.
' for SQL Dialect you can use ORDER BY in the SQL Statement
' Ex. Com.Properties("Sort On") = "Name"
'Set the preferences for Search
Com.Properties("Page Size") = 1000
Com.Properties("Timeout") = 30 'seconds
Com.Properties("searchscope") = lScope
Com.Properties("Chase referrals") = ADS_CHASE_REFERRALS_EXTERNAL
Com.Properties("Cache Results") = False ' do not cache the result, it results in less memory requirements
'Execute the query
Set rs = Com.Execute
' Tell the user how many rows
DisplayMessage "Returned " & Str(rs.RecordCount) & " rows"
' Navigate the record set
If Not rs.EOF Then
rs.MoveFirst
End If
On Error Resume Next
While Not rs.EOF
' Display the LDAP path for the row
DisplayMessage rs.Fields("AdsPath")
rs.MoveNext
Wend
End Sub