| 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;
}