windows-nt/Source/XPSP1/NT/ds/adsi/nds/ctree.cxx
2020-09-26 16:20:57 +08:00

1029 lines
20 KiB
C++

//---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995
//
// File: cdomain.cxx
//
// Contents: Microsoft ADs NDS Provider Tree Object
//
//
// History: 01-30-95 krishnag Created.
//
//----------------------------------------------------------------------------
#include "nds.hxx"
#pragma hdrstop
// Class CNDSTree
DEFINE_IDispatch_Implementation(CNDSTree)
DEFINE_IADs_Implementation(CNDSTree)
CNDSTree::CNDSTree():
_pPropertyCache(NULL)
{
VariantInit(&_vFilter);
ENLIST_TRACKING(CNDSTree);
}
HRESULT
CNDSTree::CreateTreeObject(
BSTR bstrADsPath,
CCredentials& Credentials,
DWORD dwObjectState,
REFIID riid,
void **ppvObj
)
{
HRESULT hr = S_OK;
WCHAR szADsParent[MAX_PATH];
WCHAR szCommonName[MAX_PATH];
memset(szADsParent, 0, sizeof(szADsParent));
memset(szCommonName, 0, sizeof(szCommonName));
//
// Determine the parent and rdn name
//
hr = BuildADsParentPath(
bstrADsPath,
szADsParent,
szCommonName
);
//
// call the helper function
//
hr = CNDSTree::CreateTreeObject(
szADsParent,
szCommonName,
L"user",
Credentials,
dwObjectState,
riid,
ppvObj
);
RRETURN_EXP_IF_ERR(hr);
}
HRESULT
CNDSTree::CreateTreeObject(
BSTR Parent,
BSTR CommonName,
BSTR ClassName,
CCredentials& Credentials,
DWORD dwObjectState,
REFIID riid,
void **ppvObj
)
{
CNDSTree FAR * pTree = NULL;
HRESULT hr = S_OK;
hr = AllocateTree(Credentials, &pTree);
BAIL_ON_FAILURE(hr);
hr = pTree->InitializeCoreObject(
Parent,
CommonName,
ClassName,
L"",
CLSID_NDSTree,
dwObjectState
);
BAIL_ON_FAILURE(hr);
hr = pTree->QueryInterface(riid, ppvObj);
BAIL_ON_FAILURE(hr);
pTree->Release();
RRETURN(hr);
error:
delete pTree;
RRETURN_EXP_IF_ERR(hr);
}
CNDSTree::~CNDSTree( )
{
VariantClear(&_vFilter);
delete _pDispMgr;
delete _pPropertyCache;
}
STDMETHODIMP
CNDSTree::QueryInterface(REFIID iid, LPVOID FAR* ppv)
{
if (ppv == NULL) {
RRETURN(E_POINTER);
}
if (IsEqualIID(iid, IID_IUnknown))
{
*ppv = (IADs FAR *) this;
}
else if (IsEqualIID(iid, IID_IADsContainer))
{
*ppv = (IADsContainer FAR *) this;
}
else if (IsEqualIID(iid, IID_IADs))
{
*ppv = (IADs FAR *) this;
}
else if (IsEqualIID(iid, IID_IDispatch))
{
*ppv = (IADs FAR *) this;
}
else if (IsEqualIID(iid, IID_ISupportErrorInfo))
{
*ppv = (ISupportErrorInfo FAR *) this;
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return NOERROR;
}
HRESULT
CNDSTree::InterfaceSupportsErrorInfo(
THIS_ REFIID riid
)
{
if (IsEqualIID(riid, IID_IADs) ||
IsEqualIID(riid, IID_IADsContainer)) {
RRETURN(S_OK);
} else {
RRETURN(S_FALSE);
}
}
HRESULT
CNDSTree::SetInfo()
{
DWORD dwStatus = 0L;
WCHAR szNDSPathName[MAX_PATH];
HANDLE hOperationData = NULL;
HANDLE hObject = NULL;
HRESULT hr = S_OK;
if (GetObjectState() == ADS_OBJECT_UNBOUND) {
hr = NDSCreateObject();
BAIL_ON_FAILURE(hr);
//
// If the create succeded, set the object type to bound
//
SetObjectState(ADS_OBJECT_BOUND);
}else {
hr = NDSSetObject();
BAIL_ON_FAILURE(hr);
}
error:
RRETURN_EXP_IF_ERR(hr);
}
HRESULT
CNDSTree::NDSSetObject()
{
DWORD dwStatus = 0L;
LPWSTR pszNDSPathName = NULL;
HANDLE hOperationData = NULL;
HANDLE hObject = NULL;
HRESULT hr = S_OK;
hr = BuildNDSPathFromADsPath(
_ADsPath,
&pszNDSPathName
);
BAIL_ON_FAILURE(hr);
dwStatus = ADsNwNdsOpenObject(
pszNDSPathName,
_Credentials,
&hObject,
NULL,
NULL,
NULL,
NULL
);
if (dwStatus) {
hr = HRESULT_FROM_WIN32(GetLastError());
BAIL_ON_FAILURE(hr);
}
dwStatus = NwNdsCreateBuffer(
NDS_OBJECT_MODIFY,
&hOperationData
);
if (dwStatus) {
hr = HRESULT_FROM_WIN32(GetLastError());
BAIL_ON_FAILURE(hr);
}
hr = _pPropertyCache->NDSMarshallProperties(
hOperationData
);
BAIL_ON_FAILURE(hr);
dwStatus = NwNdsModifyObject(
hObject,
hOperationData
);
CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
error:
if (hOperationData) {
dwStatus = NwNdsFreeBuffer(hOperationData);
}
if (hObject) {
dwStatus = NwNdsCloseObject(hObject);
}
if (pszNDSPathName) {
FreeADsStr(pszNDSPathName);
}
RRETURN_EXP_IF_ERR(hr);
}
HRESULT
CNDSTree::NDSCreateObject()
{
DWORD dwStatus = 0L;
LPWSTR pszNDSParentName = NULL;
HANDLE hOperationData = NULL;
HANDLE hObject = NULL;
HRESULT hr = S_OK;
hr = BuildNDSPathFromADsPath(
_Parent,
&pszNDSParentName
);
BAIL_ON_FAILURE(hr);
dwStatus = ADsNwNdsOpenObject(
pszNDSParentName,
_Credentials,
&hObject,
NULL,
NULL,
NULL,
NULL
);
CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
dwStatus = NwNdsCreateBuffer(
NDS_OBJECT_ADD,
&hOperationData
);
CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
hr = _pPropertyCache->NDSMarshallProperties(
hOperationData
);
BAIL_ON_FAILURE(hr);
dwStatus = NwNdsAddObject(
hObject,
_Name,
hOperationData
);
CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
error:
if (hOperationData) {
dwStatus = NwNdsFreeBuffer(hOperationData);
}
if (hObject) {
dwStatus = NwNdsCloseObject(hObject);
}
if (pszNDSParentName) {
FreeADsStr(pszNDSParentName);
}
RRETURN_EXP_IF_ERR(hr);
}
HRESULT
CNDSTree::GetInfo()
{
RRETURN(GetInfo(TRUE));
}
HRESULT
CNDSTree::GetInfo(
BOOL fExplicit
)
{
DWORD dwStatus = 0L;
HANDLE hObject = NULL;
HANDLE hOperationData = NULL;
HRESULT hr = S_OK;
LPWSTR pszNDSPathName = NULL;
if (GetObjectState() == ADS_OBJECT_UNBOUND) {
hr = E_ADS_OBJECT_UNBOUND;
BAIL_ON_FAILURE(hr);
}
hr = BuildNDSPathFromADsPath(
_ADsPath,
&pszNDSPathName
);
BAIL_ON_FAILURE(hr);
dwStatus = ADsNwNdsOpenObject(
pszNDSPathName,
_Credentials,
&hObject,
NULL,
NULL,
NULL,
NULL
);
CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
hOperationData = NULL;
dwStatus = NwNdsReadObject(
hObject,
NDS_INFO_ATTR_NAMES_VALUES,
&hOperationData
);
CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
hr = _pPropertyCache->NDSUnMarshallProperties(
hOperationData,
fExplicit
);
BAIL_ON_FAILURE(hr);
error:
if (hOperationData) {
dwStatus = NwNdsFreeBuffer(hOperationData);
}
if (hObject) {
dwStatus = NwNdsCloseObject(hObject);
}
if (pszNDSPathName) {
FreeADsStr(pszNDSPathName);
}
RRETURN_EXP_IF_ERR(hr);
}
STDMETHODIMP
CNDSTree::GetInfoEx(THIS_ VARIANT vProperties, long lnReserved)
{
RRETURN_EXP_IF_ERR(E_NOTIMPL);
}
/* IADsContainer methods */
STDMETHODIMP
CNDSTree::get_Count(long FAR* retval)
{
RRETURN_EXP_IF_ERR(E_NOTIMPL);
}
STDMETHODIMP
CNDSTree::get_Filter(THIS_ VARIANT FAR* pVar)
{
HRESULT hr;
VariantInit(pVar);
hr = VariantCopy(pVar, &_vFilter);
RRETURN_EXP_IF_ERR(hr);
}
STDMETHODIMP
CNDSTree::put_Filter(THIS_ VARIANT Var)
{
HRESULT hr;
hr = VariantCopy(&_vFilter, &Var);
RRETURN_EXP_IF_ERR(hr);
}
STDMETHODIMP
CNDSTree::put_Hints(THIS_ VARIANT Var)
{
RRETURN_EXP_IF_ERR( E_NOTIMPL);
}
STDMETHODIMP
CNDSTree::get_Hints(THIS_ VARIANT FAR* pVar)
{
RRETURN_EXP_IF_ERR(E_NOTIMPL);
}
STDMETHODIMP
CNDSTree::GetObject(
BSTR ClassName,
BSTR RelativeName,
IDispatch * FAR* ppObject
)
{
HRESULT hr = S_OK;
hr = ::RelativeGetObject(
_ADsPath,
ClassName,
RelativeName,
_Credentials,
ppObject,
FALSE
);
RRETURN_EXP_IF_ERR(hr);
}
STDMETHODIMP
CNDSTree::get__NewEnum(
THIS_ IUnknown * FAR* retval
)
{
HRESULT hr;
IUnknown FAR* punkEnum=NULL;
IEnumVARIANT * penum = NULL;
*retval = NULL;
hr = CNDSTreeEnum::Create(
(CNDSTreeEnum **)&penum,
_ADsPath,
_vFilter,
_Credentials
);
BAIL_ON_FAILURE(hr);
hr = penum->QueryInterface(
IID_IUnknown,
(VOID FAR* FAR*)retval
);
BAIL_ON_FAILURE(hr);
if (penum) {
penum->Release();
}
RRETURN(NOERROR);
error:
if (penum) {
delete penum;
}
RRETURN_EXP_IF_ERR(hr);
}
STDMETHODIMP
CNDSTree::Create(
THIS_ BSTR ClassName,
BSTR RelativeName,
IDispatch * FAR* ppObject
)
{
HRESULT hr = S_OK;
IADs * pADs = NULL;
VARIANT var;
WCHAR szNDSTreeName[MAX_PATH];
DWORD dwSyntaxId = 0;
//
// Get the TreeName for this object
//
hr = BuildNDSTreeNameFromADsPath(
_ADsPath,
szNDSTreeName
);
BAIL_ON_FAILURE(hr);
//
// Validate if this class really exists in the schema
// and validate that this object can be created in this
// container
//
hr = CNDSGenObject::CreateGenericObject(
_ADsPath,
RelativeName,
ClassName,
_Credentials,
ADS_OBJECT_UNBOUND,
IID_IDispatch,
(void **)ppObject
);
BAIL_ON_FAILURE(hr);
error:
RRETURN_EXP_IF_ERR(hr);
}
STDMETHODIMP
CNDSTree::Delete(
THIS_ BSTR bstrClassName,
BSTR bstrRelativeName
)
{
LPWSTR pszNDSPathName = NULL;
HRESULT hr = S_OK;
DWORD dwStatus = 0;
HANDLE hParentObject = NULL;
hr = BuildNDSPathFromADsPath(
_ADsPath,
&pszNDSPathName
);
BAIL_ON_FAILURE(hr);
dwStatus = ADsNwNdsOpenObject(
pszNDSPathName,
_Credentials,
&hParentObject,
NULL,
NULL,
NULL,
NULL
);
if (dwStatus) {
hr = HRESULT_FROM_WIN32(GetLastError());
BAIL_ON_FAILURE(hr);
}
CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
dwStatus = NwNdsRemoveObject(
hParentObject,
bstrRelativeName
);
CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
error:
if (hParentObject) {
NwNdsCloseObject(
hParentObject
);
}
if (pszNDSPathName) {
FreeADsStr(pszNDSPathName);
}
RRETURN_EXP_IF_ERR(hr);
}
STDMETHODIMP
CNDSTree::CopyHere(
THIS_ BSTR SourceName,
BSTR NewName,
IDispatch * FAR* ppObject
)
{
RRETURN_EXP_IF_ERR(E_NOTIMPL);
}
STDMETHODIMP
CNDSTree::MoveHere(
THIS_ BSTR SourceName,
BSTR NewName,
IDispatch * FAR* ppObject
)
{
RRETURN_EXP_IF_ERR(E_NOTIMPL);
}
HRESULT
CNDSTree::AllocateTree(
CCredentials& Credentials,
CNDSTree ** ppTree
)
{
CNDSTree FAR * pTree = NULL;
CDispatchMgr FAR * pDispMgr = NULL;
CPropertyCache FAR * pPropertyCache = NULL;
HRESULT hr = S_OK;
pTree = new CNDSTree();
if (pTree == NULL) {
hr = E_OUTOFMEMORY;
}
BAIL_ON_FAILURE(hr);
pDispMgr = new CDispatchMgr;
if (pDispMgr == NULL) {
hr = E_OUTOFMEMORY;
}
BAIL_ON_FAILURE(hr);
hr = LoadTypeInfoEntry(pDispMgr,
LIBID_ADs,
IID_IADs,
(IADs *)pTree,
DISPID_REGULAR
);
BAIL_ON_FAILURE(hr);
hr = LoadTypeInfoEntry(pDispMgr,
LIBID_ADs,
IID_IADsContainer,
(IADsContainer *)pTree,
DISPID_NEWENUM
);
BAIL_ON_FAILURE(hr);
hr = CPropertyCache::createpropertycache(
(CCoreADsObject FAR *)pTree,
&pPropertyCache
);
BAIL_ON_FAILURE(hr);
pTree->_Credentials = Credentials;
pTree->_pPropertyCache = pPropertyCache;
pTree->_pDispMgr = pDispMgr;
*ppTree = pTree;
RRETURN(hr);
error:
delete pDispMgr;
RRETURN(hr);
}
STDMETHODIMP
CNDSTree::Get(
THIS_ BSTR bstrName,
VARIANT FAR* pvProp
)
{
HRESULT hr = S_OK;
DWORD dwSyntaxId;
DWORD dwNumValues;
LPNDSOBJECT pNdsSrcObjects = NULL;
//
// retrieve data object from cache; if one exists
//
hr = _pPropertyCache->getproperty(
bstrName,
&dwSyntaxId,
&dwNumValues,
&pNdsSrcObjects
);
BAIL_ON_FAILURE(hr);
//
// translate the Nds objects to variants
//
hr = NdsTypeToVarTypeCopyConstruct(
pNdsSrcObjects,
dwNumValues,
pvProp,
FALSE
);
BAIL_ON_FAILURE(hr);
error:
if (pNdsSrcObjects) {
NdsTypeFreeNdsObjects(
pNdsSrcObjects,
dwNumValues
);
}
RRETURN_EXP_IF_ERR(hr);
}
STDMETHODIMP
CNDSTree::GetEx(
THIS_ BSTR bstrName,
VARIANT FAR* pvProp
)
{
HRESULT hr = S_OK;
DWORD dwSyntaxId;
DWORD dwNumValues;
LPNDSOBJECT pNdsSrcObjects = NULL;
//
// retrieve data object from cache; if one exists
//
hr = _pPropertyCache->getproperty(
bstrName,
&dwSyntaxId,
&dwNumValues,
&pNdsSrcObjects
);
BAIL_ON_FAILURE(hr);
//
// translate the Nds objects to variants
//
hr = NdsTypeToVarTypeCopyConstruct(
pNdsSrcObjects,
dwNumValues,
pvProp,
TRUE
);
BAIL_ON_FAILURE(hr);
error:
if (pNdsSrcObjects) {
NdsTypeFreeNdsObjects(
pNdsSrcObjects,
dwNumValues
);
}
RRETURN_EXP_IF_ERR(hr);
}
STDMETHODIMP
CNDSTree::Put(
THIS_ BSTR bstrName,
VARIANT vProp
)
{
HRESULT hr = S_OK;
DWORD dwSyntaxId = 0;
DWORD dwIndex = 0;
LPNDSOBJECT pNdsDestObjects = NULL;
WCHAR szNDSTreeName[MAX_PATH];
//
// Issue: How do we handle multi-valued support
//
DWORD dwNumValues = 1;
//
// Get the TreeName for this object
//
hr = BuildNDSTreeNameFromADsPath(
_ADsPath,
szNDSTreeName
);
BAIL_ON_FAILURE(hr);
//
// check if this is a legal property for this object,
//
hr = ValidatePropertyinCache(
szNDSTreeName,
_ADsClass,
bstrName,
_Credentials,
&dwSyntaxId
);
BAIL_ON_FAILURE(hr);
//
// check if the variant maps to the syntax of this property
//
hr = VarTypeToNdsTypeCopyConstruct(
dwSyntaxId,
&vProp,
&dwNumValues,
&pNdsDestObjects
);
BAIL_ON_FAILURE(hr);
//
// Find this property in the cache
//
hr = _pPropertyCache->findproperty(
bstrName,
&dwIndex
);
//
// If this property does not exist in the
// cache, add this property into the cache.
//
if (FAILED(hr)) {
hr = _pPropertyCache->addproperty(
bstrName,
dwSyntaxId
);
//
// If the operation fails for some reason
// move on to the next property
//
BAIL_ON_FAILURE(hr);
}
//
// Now update the property in the cache
//
hr = _pPropertyCache->putproperty(
bstrName,
CACHE_PROPERTY_MODIFIED,
dwSyntaxId,
dwNumValues,
pNdsDestObjects
);
BAIL_ON_FAILURE(hr);
error:
if (pNdsDestObjects) {
NdsTypeFreeNdsObjects(
pNdsDestObjects,
dwNumValues
);
}
RRETURN_EXP_IF_ERR(hr);
}
STDMETHODIMP
CNDSTree::PutEx(
THIS_ long lnControlCode,
BSTR bstrName,
VARIANT vProp
)
{
HRESULT hr = S_OK;
DWORD dwSyntaxId = 0;
DWORD dwIndex = 0;
LPNDSOBJECT pNdsDestObjects = NULL;
WCHAR szNDSTreeName[MAX_PATH];
//
// Issue: How do we handle multi-valued support
//
DWORD dwNumValues = 1;
//
// Get the TreeName for this object
//
hr = BuildNDSTreeNameFromADsPath(
_ADsPath,
szNDSTreeName
);
BAIL_ON_FAILURE(hr);
//
// check if this is a legal property for this object,
//
hr = ValidatePropertyinCache(
szNDSTreeName,
_ADsClass,
bstrName,
_Credentials,
&dwSyntaxId
);
BAIL_ON_FAILURE(hr);
//
// check if the variant maps to the syntax of this property
//
hr = VarTypeToNdsTypeCopyConstruct(
dwSyntaxId,
&vProp,
&dwNumValues,
&pNdsDestObjects
);
BAIL_ON_FAILURE(hr);
//
// Find this property in the cache
//
hr = _pPropertyCache->findproperty(
bstrName,
&dwIndex
);
//
// If this property does not exist in the
// cache, add this property into the cache.
//
if (FAILED(hr)) {
hr = _pPropertyCache->addproperty(
bstrName,
dwSyntaxId
);
//
// If the operation fails for some reason
// move on to the next property
//
BAIL_ON_FAILURE(hr);
}
//
// Now update the property in the cache
//
hr = _pPropertyCache->putproperty(
bstrName,
CACHE_PROPERTY_MODIFIED,
dwSyntaxId,
dwNumValues,
pNdsDestObjects
);
BAIL_ON_FAILURE(hr);
error:
if (pNdsDestObjects) {
NdsTypeFreeNdsObjects(
pNdsDestObjects,
dwNumValues
);
}
RRETURN_EXP_IF_ERR(hr);
}