Platform SDK: Active Directory, ADSI, and Directory Services |
The following C/C++ program queries for four types of properties that are 1) non-replicated, 2) indexed, 3) global catalog, and 4) constructed:
// Displays attributes of different types. // #include "stdafx.h" #include <wchar.h> #include <activeds.h> HRESULT FindAttributesByType(IDirectorySearch *pSchemaNC, //IDirectorySearch pointer to schema naming context. DWORD dwAttributeType, //Bit flags to search for in systemFlags LPOLESTR pszAttributerNameType, //ldapDisplayName of the naming attribute you want to display for each returned attribute. //NULL returns common name. BOOL bIsExactMatch //TRUE to find attributes that have systemFlags exactly matching dwAttributeType //FALSE to find attributes that have the dwAttributeType bit set (and possibly others). ); HRESULT FindIndexedAttributes(IDirectorySearch *pSchemaNC, //IDirectorySearch pointer to schema naming context. LPOLESTR pszAttributeNameType, //ldapDisplayName of the naming attribute you want to display for each returned attribute. //NULL returns common name. BOOL bIsIndexed //TRUE to find indexed attributes. //FALSE to find non-indexed attributes. ); HRESULT FindGCAttributes(IDirectorySearch *pSchemaNC, //IDirectorySearch pointer to schema naming context. LPOLESTR pszAttributeNameType, //ldapDisplayName of the naming attribute you want to display for each returned attribute. //NULL returns common name. BOOL bInGC //TRUE to find indexed attributes. //FALSE to find non-indexed attributes. ); int main(int argc, char* argv[]) { HRESULT hr = E_FAIL; LPOLESTR szPath = new OLECHAR[MAX_PATH]; IDirectorySearch *pSchemaNC = NULL; IADs *pObject = NULL; VARIANT var; //Intialize COM CoInitialize(NULL); //Get rootDSE and the schema container's distinguished name. //Bind to current user's domain using current user's security context. hr = ADsOpenObject(L"LDAP://rootDSE", NULL, NULL, ADS_SECURE_AUTHENTICATION, //Use Secure Authentication IID_IADs, (void**)&pObject); if (SUCCEEDED(hr)) { hr = pObject->Get(L"schemaNamingContext",&var); if (SUCCEEDED(hr)) { wcscpy(szPath,L"LDAP://"); wcscat(szPath,var.bstrVal); hr = ADsOpenObject(szPath, NULL, NULL, ADS_SECURE_AUTHENTICATION, //Use Secure Authentication IID_IDirectorySearch, (void**)&pSchemaNC); if (SUCCEEDED(hr)) { //Find non-replicated attributes wprintf(L"Find non-replicated attributes\n"); hr = FindAttributesByType(pSchemaNC, //IDirectorySearch pointer to schema naming context. ADS_SYSTEMFLAG_ATTR_NOT_REPLICATED, //Bit flags to search for in systemFlags NULL, TRUE ); //Find attributes included in the global catalog wprintf(L"Find attributes included in the global catalog\n"); hr = FindGCAttributes(pSchemaNC, NULL, TRUE ); //Find constructed attributes wprintf(L"Find constructed attributes\n"); hr = FindAttributesByType(pSchemaNC, //IDirectorySearch pointer to schema naming context. ADS_SYSTEMFLAG_ATTR_IS_CONSTRUCTED, //Bit flags to search for in systemFlags NULL, FALSE ); //Find indexed attributes wprintf(L"Find indexed attributes\n"); hr = FindIndexedAttributes(pSchemaNC, //IDirectorySearch pointer to schema naming context. NULL, TRUE ); } if (pSchemaNC) pSchemaNC->Release(); } } if (pObject) pObject->Release(); VariantClear(&var); // Uninitialize COM CoUninitialize(); return 0; } HRESULT FindAttributesByType(IDirectorySearch *pSchemaNC, //IDirectorySearch pointer to schema naming context. DWORD dwAttributeType, //Bit flags to search for in systemFlags LPOLESTR pszAttributeNameType, //ldapDisplayName of the naming attribute you want to display for each returned attribute. //NULL returns common name. BOOL bIsExactMatch //TRUE to find attributes that have systemFlags exactly matching dwAttributeType //FALSE to find attributes that have the dwAttributeType bit set (and possibly others). ) { //Create search filter LPOLESTR pszSearchFilter = new OLECHAR[MAX_PATH*2]; if (bIsExactMatch) //Find attributes with systemFlags that exactly match dwAttributeType wsprintf(pszSearchFilter, L"(&(objectCategory=attributeSchema)(systemFlags=%d))",dwAttributeType); else //Find attributes with systemFlags that contain dwAttributeType wsprintf(pszSearchFilter, L"(&(objectCategory=attributeSchema)(systemFlags:1.2.840.113556.1.4.804:=%d))",dwAttributeType); //Attributes are one-level deep in the Schema container so only need to search one level. ADS_SEARCHPREF_INFO SearchPrefs; SearchPrefs.dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE; SearchPrefs.vValue.dwType = ADSTYPE_INTEGER; SearchPrefs.vValue.Integer = ADS_SCOPE_ONELEVEL; DWORD dwNumPrefs = 1; // 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; // Set the search preference hr = pSchemaNC->SetSearchPreference( &SearchPrefs, dwNumPrefs); if (FAILED(hr)) return hr; CONST DWORD dwAttrNameSize = 1; LPOLESTR pszAttribute[dwAttrNameSize]; if (!pszAttributeNameType) pszAttribute[0] = L"cn"; else pszAttribute[0] = pszAttributeNameType; // Execute the search hr = pSchemaNC->ExecuteSearch(pszSearchFilter, pszAttribute, dwAttrNameSize, &hSearch ); if ( SUCCEEDED(hr) ) { // Call IDirectorySearch::GetNextRow() to retrieve the next row //of data while( pSchemaNC->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 = pSchemaNC->GetColumn( hSearch, pszAttribute[x], &col ); if ( SUCCEEDED(hr) ) { // Print the data for the column and free the column wprintf(L"%s: %s\r\n",pszAttribute[x],col.pADsValues->CaseIgnoreString); pSchemaNC->FreeColumn( &col ); } else wprintf(L"<%s property is not a string>",pszAttribute[x]); } } // Close the search handle to clean up pSchemaNC->CloseSearchHandle(hSearch); } return hr; } HRESULT FindIndexedAttributes(IDirectorySearch *pSchemaNC, //IDirectorySearch pointer to schema naming context. LPOLESTR pszAttributeNameType, //ldapDisplayName of the naming attribute you want to display for each returned attribute. //NULL returns common name. BOOL bIsIndexed //TRUE to find indexed attributes. //FALSE to find non-indexed attributes. ) { //Create search filter LPOLESTR pszSearchFilter = new OLECHAR[MAX_PATH*2]; DWORD dwIndexed; if (bIsIndexed) dwIndexed = 1; else dwIndexed = 0; wsprintf(pszSearchFilter, L"(&(objectCategory=attributeSchema)(searchFlags=%d))",dwIndexed); //Attributes are one-level deep in the Schema container so only need to search one level. ADS_SEARCHPREF_INFO SearchPrefs; SearchPrefs.dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE; SearchPrefs.vValue.dwType = ADSTYPE_INTEGER; SearchPrefs.vValue.Integer = ADS_SCOPE_ONELEVEL; DWORD dwNumPrefs = 1; // 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; // Set the search preference hr = pSchemaNC->SetSearchPreference( &SearchPrefs, dwNumPrefs); if (FAILED(hr)) return hr; CONST DWORD dwAttrNameSize = 1; LPOLESTR pszAttribute[dwAttrNameSize]; if (!pszAttributeNameType) pszAttribute[0] = L"cn"; else pszAttribute[0] = pszAttributeNameType; // Execute the search hr = pSchemaNC->ExecuteSearch(pszSearchFilter, pszAttribute, dwAttrNameSize, &hSearch ); if ( SUCCEEDED(hr) ) { // Call IDirectorySearch::GetNextRow() to retrieve the next row //of data while( pSchemaNC->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 = pSchemaNC->GetColumn( hSearch, pszAttribute[x], &col ); if ( SUCCEEDED(hr) ) { // Print the data for the column and free the column wprintf(L"%s: %s\r\n",pszAttribute[x],col.pADsValues->CaseIgnoreString); pSchemaNC->FreeColumn( &col ); } else wprintf(L"<%s property is not a string>",pszAttribute[x]); } } // Close the search handle to clean up pSchemaNC->CloseSearchHandle(hSearch); } return hr; } HRESULT FindGCAttributes(IDirectorySearch *pSchemaNC, //IDirectorySearch pointer to schema naming context. LPOLESTR pszAttributeNameType, //ldapDisplayName of the naming attribute you want to display for each returned attribute. //NULL returns common name. BOOL bInGC //TRUE to find GC attributes. //FALSE to find non-GC attributes. ) { //Create search filter LPOLESTR pszSearchFilter = new OLECHAR[MAX_PATH*2]; LPOLESTR szBool = NULL; if (bInGC) szBool = L"TRUE"; else szBool = L"FALSE"; wsprintf(pszSearchFilter, L"(&(objectCategory=attributeSchema)(isMemberOfPartialAttributeSet=%s))",szBool); //Attributes are one-level deep in the Schema container so only need to search one level. ADS_SEARCHPREF_INFO SearchPrefs; SearchPrefs.dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE; SearchPrefs.vValue.dwType = ADSTYPE_INTEGER; SearchPrefs.vValue.Integer = ADS_SCOPE_ONELEVEL; DWORD dwNumPrefs = 1; // 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; // Set the search preference hr = pSchemaNC->SetSearchPreference( &SearchPrefs, dwNumPrefs); if (FAILED(hr)) return hr; CONST DWORD dwAttrNameSize = 1; LPOLESTR pszAttribute[dwAttrNameSize]; if (!pszAttributeNameType) pszAttribute[0] = L"cn"; else pszAttribute[0] = pszAttributeNameType; // Execute the search hr = pSchemaNC->ExecuteSearch(pszSearchFilter, pszAttribute, dwAttrNameSize, &hSearch ); if ( SUCCEEDED(hr) ) { // Call IDirectorySearch::GetNextRow() to retrieve the next row //of data while( pSchemaNC->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 = pSchemaNC->GetColumn( hSearch, pszAttribute[x], &col ); if ( SUCCEEDED(hr) ) { // Print the data for the column and free the column wprintf(L"%s: %s\r\n",pszAttribute[x],col.pADsValues->CaseIgnoreString); pSchemaNC->FreeColumn( &col ); } else wprintf(L"<%s property is not a string>",pszAttribute[x]); } } // Close the search handle to clean up pSchemaNC->CloseSearchHandle(hSearch); } return hr; }