Leaked source code of windows server 2003
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

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