You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
262 lines
7.0 KiB
262 lines
7.0 KiB
// Class to enumerate Naming contexts
|
|
// Copyright (c) 2001 Microsoft Corporation
|
|
// Nov 2001 lucios
|
|
// This class is an informal gathering of all
|
|
// that is necessary to enummerate naming contexts
|
|
// in order to fix the bug 472876
|
|
// NTRAID#NTBUG9-472876-2001/11/30-lucios
|
|
#include "pch.h"
|
|
#include <ntdsadef.h>
|
|
#include "enumncs.hpp"
|
|
|
|
#define BREAK_ON_FAILED_HRESULT(hr) if(FAILED(hr)) break;
|
|
|
|
// connects to "LDAP://RootDSE"
|
|
HRESULT enumNCsAux::connectToRootDse(IADs** pDSO)
|
|
{
|
|
HRESULT hr= AdminToolsOpenObject
|
|
(
|
|
L"LDAP://RootDSE",
|
|
0,
|
|
0,
|
|
ADS_SECURE_AUTHENTICATION,
|
|
IID_IADs,
|
|
reinterpret_cast<void**>(pDSO)
|
|
);
|
|
return hr;
|
|
}
|
|
|
|
// gets any property as a variant
|
|
HRESULT enumNCsAux::getProperty
|
|
(
|
|
const wstring &name,
|
|
CComVariant &property,
|
|
IADs *pADObj
|
|
)
|
|
{
|
|
return
|
|
(
|
|
pADObj->Get
|
|
(
|
|
CComBSTR(name.c_str()),
|
|
&property
|
|
)
|
|
);
|
|
}
|
|
|
|
// Gets a string property
|
|
HRESULT enumNCsAux::getStringProperty
|
|
(
|
|
const wstring &name,
|
|
wstring &property,
|
|
IADs *pADObj
|
|
)
|
|
{
|
|
CComVariant propertyVar;
|
|
HRESULT hr = getProperty(name,propertyVar,pADObj);
|
|
if(FAILED(hr)) return(hr);
|
|
if(propertyVar.vt!=VT_BSTR) return E_FAIL;
|
|
property= V_BSTR(&propertyVar);
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
// Gets a long property
|
|
HRESULT enumNCsAux::getLongProperty
|
|
(
|
|
const wstring &name,
|
|
long &property,
|
|
IADs *pADObj
|
|
)
|
|
{
|
|
CComVariant propertyVar;
|
|
HRESULT hr = getProperty(name,propertyVar,pADObj);
|
|
if(FAILED(hr)) return(hr);
|
|
if(propertyVar.vt!=VT_I4) return E_FAIL;
|
|
property= V_I4(&propertyVar);
|
|
return S_OK;
|
|
}
|
|
|
|
// Gets CN=Configuration from a connected rootDse IADs
|
|
HRESULT enumNCsAux::getConfigurationDn(wstring &confDn,IADs *pDSO)
|
|
{
|
|
return
|
|
(
|
|
getStringProperty
|
|
(
|
|
LDAP_OPATT_CONFIG_NAMING_CONTEXT_W,
|
|
confDn,
|
|
pDSO
|
|
)
|
|
);
|
|
}
|
|
|
|
|
|
// gets the IADsContainer from a distinguished name path
|
|
HRESULT enumNCsAux::getContainer(const wstring &path,IADsContainer **pCont)
|
|
{
|
|
return
|
|
(
|
|
ADsGetObject
|
|
(
|
|
path.c_str(),
|
|
IID_IADsContainer,
|
|
reinterpret_cast<void**>(pCont)
|
|
)
|
|
);
|
|
}
|
|
|
|
// Gets the IEnumVARIANT from a container
|
|
HRESULT enumNCsAux::getContainerEnumerator
|
|
(
|
|
IADsContainer* pPart,
|
|
IEnumVARIANT** ppiEnum
|
|
)
|
|
{
|
|
HRESULT hr=S_OK;
|
|
CComPtr<IUnknown> spUnkEnum;
|
|
|
|
do
|
|
{
|
|
hr=pPart->get__NewEnum(&spUnkEnum);
|
|
BREAK_ON_FAILED_HRESULT(hr);
|
|
|
|
CComQIPtr<IEnumVARIANT,&IID_IEnumVARIANT> spRet(spUnkEnum);
|
|
if(!spRet) return E_FAIL;
|
|
*ppiEnum = spRet.Detach();
|
|
} while(0);
|
|
|
|
return hr;
|
|
}
|
|
|
|
// calls IADsObj->get_Class and returns a wstring from it
|
|
HRESULT enumNCsAux::getObjectClass
|
|
(
|
|
wstring &className,
|
|
IADs *IADsObj
|
|
)
|
|
{
|
|
BSTR classBstr;
|
|
HRESULT hr=IADsObj->get_Class(&classBstr);
|
|
if(FAILED(hr)) return hr;
|
|
className=(const wchar_t*)classBstr;
|
|
return S_OK;
|
|
}
|
|
|
|
// Gets the IDispatch from the variant and queries
|
|
// for a IADs(returned in IADsObj)
|
|
HRESULT enumNCsAux::getIADsFromDispatch
|
|
(
|
|
const CComVariant &dispatchVar,
|
|
IADs **ppiIADsObj
|
|
)
|
|
{
|
|
if(dispatchVar.vt!=VT_DISPATCH) return E_INVALIDARG;
|
|
IDispatch *pDisp=V_DISPATCH(&dispatchVar);
|
|
if(pDisp==NULL) return E_FAIL;
|
|
|
|
CComQIPtr<IADs,&IID_IADs> spRet(pDisp);
|
|
if(!spRet) return E_FAIL;
|
|
*ppiIADsObj=spRet.Detach();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// Enumerate the names of the naming contexts.
|
|
// The names are from the crossRef objects in CN=configuration,CN=Partitions
|
|
// that have FLAG_CR_NTDS_DOMAIN set. The property used to extract the names
|
|
// is NCName.
|
|
HRESULT enumNCsAux::enumerateNCs(set<wstring> &ncs)
|
|
{
|
|
HRESULT hr=S_OK;
|
|
try
|
|
{
|
|
ncs.clear();
|
|
|
|
do
|
|
{
|
|
// first of all: connect.
|
|
CComPtr <IADs> spDSO; //for rootDse
|
|
hr=connectToRootDse(&spDSO);
|
|
BREAK_ON_FAILED_HRESULT(hr);
|
|
|
|
wstring partPath;
|
|
|
|
// then get the path to CN=Configuration,...
|
|
hr=getConfigurationDn(partPath,spDSO);
|
|
BREAK_ON_FAILED_HRESULT(hr);
|
|
|
|
// .. and complete it with CN=Partitions
|
|
partPath=L"LDAP://CN=Partitions,"+partPath;
|
|
|
|
// then get the container for the partition..
|
|
CComPtr <IADsContainer> spPart; // or the partitions container
|
|
hr=getContainer(partPath,&spPart);
|
|
BREAK_ON_FAILED_HRESULT(hr);
|
|
|
|
// and enumerate the partition container
|
|
CComPtr <IEnumVARIANT> spPartEnum;//for the enumeration of partition objects
|
|
hr=getContainerEnumerator(spPart,&spPartEnum);
|
|
BREAK_ON_FAILED_HRESULT(hr);
|
|
|
|
CComVariant partitionVar;
|
|
ULONG lFetch=0;
|
|
|
|
while ( S_OK == (hr=spPartEnum->Next(1,&partitionVar,&lFetch)) )
|
|
{
|
|
if (lFetch != 1) continue;
|
|
|
|
CComPtr<IADs> spPartitionObj;
|
|
hr=getIADsFromDispatch(partitionVar,&spPartitionObj);
|
|
BREAK_ON_FAILED_HRESULT(hr);
|
|
do
|
|
{
|
|
wstring className;
|
|
HRESULT hrAux;
|
|
|
|
// Not getting a property/class is not a fatal error
|
|
// so we use an auxilliary HRESULT hrAux
|
|
hrAux=getObjectClass(className,spPartitionObj);
|
|
BREAK_ON_FAILED_HRESULT(hrAux);
|
|
|
|
if(_wcsicmp(className.c_str(),L"crossref")==0)
|
|
{
|
|
long systemFlags;
|
|
hrAux=getLongProperty
|
|
(
|
|
L"systemFlags",
|
|
systemFlags,
|
|
spPartitionObj
|
|
);
|
|
BREAK_ON_FAILED_HRESULT(hrAux);
|
|
if
|
|
(
|
|
(systemFlags & FLAG_CR_NTDS_DOMAIN) ==
|
|
FLAG_CR_NTDS_DOMAIN
|
|
)
|
|
{
|
|
wstring NCName;
|
|
hrAux=getStringProperty
|
|
(
|
|
L"NCName",
|
|
NCName,
|
|
spPartitionObj
|
|
);
|
|
BREAK_ON_FAILED_HRESULT(hrAux);
|
|
ncs.insert(NCName);
|
|
}
|
|
}
|
|
} while(0);
|
|
BREAK_ON_FAILED_HRESULT(hr);
|
|
}
|
|
if(SUCCEEDED(hr)) hr=S_OK;
|
|
BREAK_ON_FAILED_HRESULT(hr);
|
|
} while(0);
|
|
}
|
|
catch( const std::bad_alloc& )
|
|
{
|
|
hr=E_FAIL;
|
|
}
|
|
return hr;
|
|
}
|