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