351 lines
12 KiB
C++
351 lines
12 KiB
C++
#include <tchar.h>
|
|
#include <windows.h>
|
|
#include <activeds.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
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; i<iArgc; i++)
|
|
{
|
|
|
|
_tprintf(__TEXT("Getting the adsi class: %s\n"), lppszArgv[i]);
|
|
if(SUCCEEDED(result = GetLDAPClass(pDirectorySearchSchemaContainer, lppszArgv[i])))
|
|
{
|
|
_tprintf(__TEXT("Got the class successfully\n"));
|
|
}
|
|
else
|
|
{
|
|
_tprintf(__TEXT("Could not get the LDAP class :%x\n"), result);
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
_tprintf(__TEXT("Could not Get Schema COntainer\n"));
|
|
|
|
}
|
|
else
|
|
_tprintf(__TEXT("Could not CoIntialize\n"));
|
|
|
|
if(SUCCEEDED(result))
|
|
return 0;
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
|
|
HRESULT GetLDAPClass(IDirectorySearch *pDirectorySearchSchemaContainer, LPCTSTR lpszClassName)
|
|
{
|
|
|
|
IDirectoryObject *pDirectoryObject;
|
|
|
|
HRESULT result;
|
|
if(SUCCEEDED(result = GetLDAPSchemaObject(pDirectorySearchSchemaContainer, lpszClassName, &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 call an appropriate function
|
|
for(DWORD i=0; i<lCount; i++)
|
|
{
|
|
nextAttribute = pAdsAttributes + i;
|
|
|
|
// Map each of the LDAP class attributes to WBEM class qualifiers/properties
|
|
if(_tcsicmp(nextAttribute->pszAttrName, 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; i<dwMayContainsCount; i++)
|
|
{
|
|
if(!SUCCEEDED(result = GetLDAPProperty(pDirectorySearchSchemaContainer,nextValue->CaseIgnoreString)))
|
|
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; i<lCount; i++)
|
|
{
|
|
nextAttribute = pAdsAttributes + i;
|
|
}
|
|
|
|
|
|
FreeADsMem((LPVOID *)pAdsAttributes);
|
|
}
|
|
}
|
|
return result;
|
|
|
|
}
|
|
|
|
HRESULT GetLDAPSchemaObject(IDirectorySearch *pDirectorySearchSchemaContainer, LPCTSTR lpszObjectName, IDirectoryObject **ppDirectoryObject)
|
|
{
|
|
// We map the object from the LDAP Display name
|
|
// Hence we cannot directly do an ADsGetObject().
|
|
// We have to send an LDAP query for the instance of ClassSchema/AttributeSchema where the
|
|
// ldapdisplayname attribute is the lpszObjectName parameter.
|
|
HRESULT result = E_FAIL;
|
|
|
|
// Now perform one-level search for a class with the lDAPdisplayName property of that value
|
|
if(SUCCEEDED(result = pDirectorySearchSchemaContainer->SetSearchPreference(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; j<i; j++)
|
|
{
|
|
delete [] (*lpppszLDAPNames)[j];
|
|
delete [] (*lpppszCommonNames)[j];
|
|
}
|
|
|
|
// Delete the arrays themselves
|
|
delete [] (*lpppszLDAPNames);
|
|
delete [] (*lpppszCommonNames);
|
|
|
|
// Set return values to empty
|
|
*lpppszLDAPNames = NULL;
|
|
*lpppszCommonNames = NULL;
|
|
*pdwCount = 0;
|
|
|
|
result = E_FAIL;
|
|
}
|
|
|
|
// Close the search
|
|
pDirectorySearchSchemaContainer->CloseSearchHandle(hADSSearchInner);
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|