#include #include #include #include HRESULT GetLDAPClass(IDirectorySearch *pDirectorySearchSchemaContainer, LPCTSTR lpszClassName); HRESULT GetProperties(IDirectorySearch *pDirectorySearchSchemaContainer, PADS_ATTR_INFO pAttribute); HRESULT GetLDAPProperty(IDirectorySearch *pDirectorySearchSchemaContainer, LPCTSTR lpszPropertyName); HRESULT GetLDAPSchemaObject(IDirectorySearch *pDirectorySearchSchemaContainer, LPCTSTR lpszObjectName, IDirectoryObject **ppDIrectoryObject); LPTSTR CreateADSIPath(LPCTSTR lpszLDAPSchemaObjectName, LPCTSTR lpszSchemaContainerSuffix); HRESULT GetAllAttributes(IDirectorySearch *pDirectorySearchSchemaContainer, PADS_SEARCHPREF_INFO pSearchInfo, DWORD dwSearchInfoCount, LPTSTR **lpppszLDAPNames, LPTSTR **lpppszCommonNames, DWORD *pdwCount); LPCTSTR MAY_CONTAIN_ATTR = __TEXT("mayContain"); LPCTSTR SYSTEM_MAY_CONTAIN_ATTR = __TEXT("systemMayContain"); LPCTSTR MUST_CONTAIN_ATTR = __TEXT("mustContain"); LPCTSTR SYSTEM_MUST_CONTAIN_ATTR = __TEXT("systemMustContain"); LPCTSTR POSS_SUPERIORS_ATTR = __TEXT("possSuperiors"); LPCTSTR SYSTEM_POSS_SUPERIORS_ATTR = __TEXT("systemPossSuperiors"); LPCTSTR LDAP_PREFIX = __TEXT("LDAP://CN="); LPCTSTR OBJECT_CLASS_EQUALS_ATTRIBUTE_SCHEMA = __TEXT("(objectClass=attributeSchema)"); LPCTSTR SCHEMA_SUFFIX = __TEXT(",CN=Schema,CN=Configuration,DC=dsprovider,DC=microsoft,DC=com"); LPCTSTR SCHEMA_PATH = __TEXT("LDAP://CN=Schema,CN=Configuration,DC=dsprovider,DC=microsoft,DC=com"); LPCTSTR LDAP_DISP_NAME_EQUALS = __TEXT("(lDAPDisplayName="); LPCTSTR LDAP_DISPLAY_NAME_ATTR = __TEXT("LDAPDisplayName"); LPCTSTR COMMON_NAME_ATTR = __TEXT("cn"); LPCTSTR RIGHT_BRACKET = __TEXT(")"); LPCTSTR COMMA = __TEXT(","); static ADS_SEARCHPREF_INFO pSearchInfo[2]; int main() { LPWSTR lpszCommandLine = GetCommandLine(); INT iArgc; LPCTSTR * lppszArgv = (LPCTSTR *)CommandLineToArgvW(lpszCommandLine, &iArgc); IDirectorySearch *pDirectorySearchSchemaContainer; pSearchInfo[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE; pSearchInfo[0].vValue.Integer = ADS_SCOPE_ONELEVEL; pSearchInfo[1].dwSearchPref = ADS_SEARCHPREF_PAGESIZE; pSearchInfo[1].vValue.Integer = 256; HRESULT result; if(SUCCEEDED(result = CoInitialize(NULL))) { if(SUCCEEDED(result = ADsGetObject((LPTSTR)SCHEMA_PATH, IID_IDirectorySearch, (LPVOID *) &pDirectorySearchSchemaContainer))) { // Attempt to get all the attributes in AD // Get the LDAPDisplayName attributes of all the instances of the // class "AttributeSchema" LPTSTR * lppszLDAPNames, *lppszCommonNames; DWORD dwCount; result = GetAllAttributes(pDirectorySearchSchemaContainer, pSearchInfo, 2, &lppszLDAPNames, &lppszCommonNames, &dwCount); for(INT i=1; iGetObjectAttributes(NULL, -1, &pAdsAttributes, &lCount))) { PADS_ATTR_INFO nextAttribute; // GO thru each of the attributes and call an appropriate function for(DWORD i=0; ipszAttrName, SYSTEM_MAY_CONTAIN_ATTR) == 0) GetProperties(pDirectorySearchSchemaContainer, nextAttribute); else if(_tcsicmp(nextAttribute->pszAttrName, MAY_CONTAIN_ATTR) == 0) GetProperties(pDirectorySearchSchemaContainer, nextAttribute); else if(_tcsicmp(nextAttribute->pszAttrName, SYSTEM_MUST_CONTAIN_ATTR) == 0) GetProperties(pDirectorySearchSchemaContainer, nextAttribute); else if(_tcsicmp(nextAttribute->pszAttrName, MUST_CONTAIN_ATTR) == 0) GetProperties(pDirectorySearchSchemaContainer, nextAttribute); else if(_tcsicmp(nextAttribute->pszAttrName, SYSTEM_POSS_SUPERIORS_ATTR) == 0) GetProperties(pDirectorySearchSchemaContainer, nextAttribute); else if(_tcsicmp(nextAttribute->pszAttrName, POSS_SUPERIORS_ATTR) == 0) GetProperties(pDirectorySearchSchemaContainer, nextAttribute); } FreeADsMem((LPVOID *)pAdsAttributes); } } return result; } HRESULT GetProperties(IDirectorySearch *pDirectorySearchSchemaContainer, PADS_ATTR_INFO pAttribute) { HRESULT result; DWORD dwMayContainsCount = pAttribute->dwNumValues; PADSVALUE nextValue = pAttribute->pADsValues; for(DWORD i=0; iCaseIgnoreString))) break; nextValue ++; } return result; } HRESULT GetLDAPProperty(IDirectorySearch *pDirectorySearchSchemaContainer, LPCTSTR lpszPropertyName) { HRESULT result = E_FAIL; IDirectoryObject *pDirectoryObject; if(SUCCEEDED(result = GetLDAPSchemaObject(pDirectorySearchSchemaContainer, lpszPropertyName, &pDirectoryObject))) { DWORD lCount = 0; PADS_ATTR_INFO pAdsAttributes = NULL; // Get all the attributes of the ADSI class if(SUCCEEDED(result = pDirectoryObject->GetObjectAttributes(NULL, -1, &pAdsAttributes, &lCount))) { PADS_ATTR_INFO nextAttribute; // GO thru each of the attributes and collect the syntax information for(DWORD i=0; iSetSearchPreference(pSearchInfo, 1))) { // For the search filter; LPTSTR lpszSearchFilter = new TCHAR[ _tcslen(LDAP_DISP_NAME_EQUALS) + _tcslen(lpszObjectName) + _tcslen(RIGHT_BRACKET) + 1]; _tcscpy(lpszSearchFilter, LDAP_DISP_NAME_EQUALS); _tcscat(lpszSearchFilter, lpszObjectName); _tcscat(lpszSearchFilter, RIGHT_BRACKET); ADS_SEARCH_HANDLE hADSSearch; if(SUCCEEDED(result = pDirectorySearchSchemaContainer->ExecuteSearch(lpszSearchFilter, (LPTSTR *)&COMMON_NAME_ATTR, 1, &hADSSearch))) { if(SUCCEEDED(result = pDirectorySearchSchemaContainer->GetNextRow(hADSSearch))) { // Get the column for the CN attribute ADS_SEARCH_COLUMN adsColumn; if(SUCCEEDED(result = pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPTSTR)COMMON_NAME_ATTR, &adsColumn))) { // Now get the IDirectoryObject interface on this ADSI object // First form the ADSI path to the class/property instance LPTSTR lpszADSIObjectPath = CreateADSIPath((*adsColumn.pADsValues).DNString, SCHEMA_SUFFIX); // Get the IDirectoryObject interface on the class/property object if(SUCCEEDED(result = ADsGetObject(lpszADSIObjectPath, IID_IDirectoryObject, (LPVOID *)ppDirectoryObject))) { } // Delete the ADSI path) delete [] lpszADSIObjectPath; // Free the column pDirectorySearchSchemaContainer->FreeColumn(&adsColumn); } } // Close the search pDirectorySearchSchemaContainer->CloseSearchHandle(hADSSearch); } // Delete the filter delete [] lpszSearchFilter; } return result; } LPTSTR CreateADSIPath(LPCTSTR lpszLDAPSchemaObjectName, LPCTSTR lpszSchemaContainerSuffix) { LPTSTR lpszADSIObjectPath = new TCHAR[_tcslen(LDAP_PREFIX) + _tcslen(lpszLDAPSchemaObjectName) + _tcslen(COMMA) + _tcslen(lpszSchemaContainerSuffix) + 1]; _tcscpy(lpszADSIObjectPath, LDAP_PREFIX); _tcscat(lpszADSIObjectPath, lpszLDAPSchemaObjectName); _tcscat(lpszADSIObjectPath, lpszSchemaContainerSuffix); return lpszADSIObjectPath; } HRESULT GetAllAttributes(IDirectorySearch *pDirectorySearchSchemaContainer, PADS_SEARCHPREF_INFO pSearchInfo, DWORD dwSearchInfoCount, LPTSTR **lpppszLDAPNames, LPTSTR **lpppszCommonNames, DWORD *pdwCount) { HRESULT result; // Now perform a search for the attributes ldapdisplayname and common names if(SUCCEEDED(result = pDirectorySearchSchemaContainer->SetSearchPreference(pSearchInfo, dwSearchInfoCount))) { ADS_SEARCH_HANDLE hADSSearchOuter; LPCTSTR lppszAttributesRequired[] = { LDAP_DISPLAY_NAME_ATTR, COMMON_NAME_ATTR }; if(SUCCEEDED(result = pDirectorySearchSchemaContainer->ExecuteSearch((LPTSTR)OBJECT_CLASS_EQUALS_ATTRIBUTE_SCHEMA, (LPTSTR *)lppszAttributesRequired, 1, &hADSSearchOuter))) { *pdwCount = 0; // Calculate the number of rows first. You HAVE to iterate :-( // Which means that you have to execute the search again while(SUCCEEDED(result = pDirectorySearchSchemaContainer->GetNextRow(hADSSearchOuter)) && result != S_ADS_NOMORE_ROWS) (*pdwCount) ++; // Close the search pDirectorySearchSchemaContainer->CloseSearchHandle(hADSSearchOuter); ADS_SEARCH_HANDLE hADSSearchInner; if(SUCCEEDED(result = pDirectorySearchSchemaContainer->ExecuteSearch((LPTSTR)OBJECT_CLASS_EQUALS_ATTRIBUTE_SCHEMA, (LPTSTR *)&lppszAttributesRequired, 2, &hADSSearchInner))) { // Allocate enough memory for the classes and names *lpppszLDAPNames = new LPTSTR [*pdwCount]; *lpppszCommonNames = new LPTSTR [*pdwCount]; // The index of the attribute being processed DWORD i = 0; // Get the names of the attributes now while(SUCCEEDED(result = pDirectorySearchSchemaContainer->GetNextRow(hADSSearchInner))&& result != S_ADS_NOMORE_ROWS) { // Get the column for the LDAP Display Name attribute ADS_SEARCH_COLUMN adsLDAPNameColumn, adsCommonNameColumn; if(SUCCEEDED(result = pDirectorySearchSchemaContainer->GetColumn(hADSSearchInner, (LPTSTR)COMMON_NAME_ATTR, &adsCommonNameColumn))) { // Copy the attribute value (*lpppszCommonNames)[i] = new TCHAR[_tcslen((*adsCommonNameColumn.pADsValues).DNString) + 1]; _tcscpy((*lpppszCommonNames)[i], (*adsCommonNameColumn.pADsValues).DNString); pDirectorySearchSchemaContainer->FreeColumn(&adsCommonNameColumn); if(SUCCEEDED(result = pDirectorySearchSchemaContainer->GetColumn(hADSSearchInner, (LPTSTR)LDAP_DISPLAY_NAME_ATTR, &adsLDAPNameColumn))) { // Copy the attribute value (*lpppszLDAPNames)[i] = new TCHAR[_tcslen((*adsLDAPNameColumn.pADsValues).DNString) + 1]; _tcscpy((*lpppszLDAPNames)[i], (*adsLDAPNameColumn.pADsValues).DNString); // Free the column pDirectorySearchSchemaContainer->FreeColumn(&adsLDAPNameColumn); } else break; i++; } else break; } // Something went wrong? Release allocated resources if(i != *pdwCount) { // Delete the contents of the arrays for(DWORD j=0; jCloseSearchHandle(hADSSearchInner); } } } return result; }