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.
1029 lines
21 KiB
1029 lines
21 KiB
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
// 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 pTree;
|
|
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);
|
|
}
|