1088 lines
21 KiB
C++
1088 lines
21 KiB
C++
//---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1995
|
|
//
|
|
// File: cggi.cxx
|
|
//
|
|
// Contents: This file contains the Group Object's
|
|
IADsGroup and IADsGroupOperation methods
|
|
//
|
|
// History: 11-1-95 krishnag Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
#include "nds.hxx"
|
|
#pragma hdrstop
|
|
|
|
|
|
BOOL
|
|
VerifyIfMember(
|
|
BSTR bstrMember,
|
|
VARIANT * VariantArray,
|
|
ULONG cElementFetched
|
|
);
|
|
|
|
|
|
|
|
|
|
// Class CNDSGroup
|
|
|
|
|
|
STDMETHODIMP CNDSGroup::get_Description(THIS_ BSTR FAR* retval)
|
|
{
|
|
GET_PROPERTY_BSTR((IADsGroup *)this,Description);
|
|
}
|
|
|
|
STDMETHODIMP CNDSGroup::put_Description(THIS_ BSTR bstrDescription)
|
|
{
|
|
PUT_PROPERTY_BSTR((IADsGroup *)this,Description);
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CNDSGroup::Members(
|
|
THIS_ IADsMembers FAR* FAR* ppMembers
|
|
)
|
|
{
|
|
VARIANT varProp;
|
|
HRESULT hr = S_OK;
|
|
BSTR bstrADsPath = NULL;
|
|
|
|
if (!ppMembers) {
|
|
RRETURN(E_ADS_BAD_PARAMETER);
|
|
}
|
|
|
|
VariantInit(&varProp);
|
|
|
|
hr = _pADs->GetEx(L"Member", &varProp);
|
|
|
|
//
|
|
// Do not bail out on failure here if you could not find
|
|
// any data set for the Members property. You need to
|
|
// pass it all the way through and on enumeration
|
|
// return nothing.
|
|
//
|
|
|
|
if (hr == E_ADS_PROPERTY_NOT_FOUND) {
|
|
SAFEARRAY *aList = NULL;
|
|
|
|
VariantInit(&varProp);
|
|
|
|
SAFEARRAYBOUND aBound;
|
|
|
|
aBound.lLbound = 0;
|
|
aBound.cElements = 0;
|
|
|
|
aList = SafeArrayCreate( VT_VARIANT, 1, &aBound );
|
|
|
|
if ( aList == NULL ) {
|
|
hr = E_OUTOFMEMORY;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
V_VT(&varProp) = VT_ARRAY | VT_VARIANT;
|
|
V_ARRAY(&varProp) = aList;
|
|
}
|
|
else {
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
hr = _pADs->get_ADsPath(&bstrADsPath);
|
|
|
|
hr = CNDSGroupCollection::CreateGroupCollection(
|
|
bstrADsPath,
|
|
varProp,
|
|
_Credentials,
|
|
IID_IADsMembers,
|
|
(void **)ppMembers
|
|
);
|
|
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
error:
|
|
|
|
if (bstrADsPath) {
|
|
ADsFreeString(bstrADsPath);
|
|
}
|
|
|
|
VariantClear(&varProp);
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CNDSGroup::IsMember(
|
|
THIS_ BSTR bstrMember,
|
|
VARIANT_BOOL FAR* bMember
|
|
)
|
|
{
|
|
IADsMembers FAR * pMembers = NULL;
|
|
IUnknown FAR * pUnknown = NULL;
|
|
IEnumVARIANT FAR * pEnumVar = NULL;
|
|
DWORD i = 0;
|
|
HRESULT hr = S_OK;
|
|
VARIANT_BOOL fMember = FALSE;
|
|
VARIANT VariantArray[10];
|
|
BOOL fContinue = TRUE;
|
|
ULONG cElementFetched = 0;
|
|
|
|
if (!bstrMember) {
|
|
RRETURN(E_ADS_BAD_PARAMETER);
|
|
}
|
|
|
|
if (!bMember) {
|
|
RRETURN(E_ADS_BAD_PARAMETER);
|
|
}
|
|
|
|
hr = Members(
|
|
&pMembers
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = pMembers->get__NewEnum(
|
|
&pUnknown
|
|
);
|
|
//
|
|
// If it has no members, we will return FALSE
|
|
//
|
|
if (hr == E_FAIL) {
|
|
hr = S_OK;
|
|
goto error;
|
|
}
|
|
|
|
hr = pUnknown->QueryInterface(
|
|
IID_IEnumVARIANT,
|
|
(void **)&pEnumVar
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
while (fContinue) {
|
|
|
|
hr = pEnumVar->Next(
|
|
10,
|
|
VariantArray,
|
|
&cElementFetched
|
|
);
|
|
|
|
if (hr == S_FALSE) {
|
|
fContinue = FALSE;
|
|
|
|
//
|
|
// Reset hr to S_OK, we want to return success
|
|
//
|
|
|
|
hr = S_OK;
|
|
}
|
|
|
|
|
|
fMember = (VARIANT_BOOL)VerifyIfMember(
|
|
bstrMember,
|
|
VariantArray,
|
|
cElementFetched
|
|
);
|
|
if (fMember) {
|
|
|
|
fContinue = FALSE;
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < cElementFetched; i++ ) {
|
|
|
|
IDispatch *pDispatch = NULL;
|
|
|
|
pDispatch = VariantArray[i].pdispVal;
|
|
pDispatch->Release();
|
|
|
|
}
|
|
|
|
memset(VariantArray, 0, sizeof(VARIANT)*10);
|
|
|
|
}
|
|
|
|
error:
|
|
|
|
*bMember = fMember? VARIANT_TRUE: VARIANT_FALSE;
|
|
|
|
if (pEnumVar) {
|
|
pEnumVar->Release();
|
|
}
|
|
|
|
if (pUnknown) {
|
|
pUnknown->Release();
|
|
}
|
|
|
|
if (pMembers) {
|
|
pMembers->Release();
|
|
}
|
|
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
BOOL
|
|
VerifyIfMember(
|
|
BSTR bstrMember,
|
|
VARIANT * VariantArray,
|
|
ULONG cElementFetched
|
|
)
|
|
{
|
|
DWORD i = 0;
|
|
HRESULT hr = S_OK;
|
|
IADs FAR * pObject = NULL;
|
|
IDispatch FAR * pDispatch = NULL;
|
|
|
|
for (i = 0; i < cElementFetched; i++ ) {
|
|
|
|
IDispatch *pDispatch = NULL;
|
|
BSTR bstrName = NULL;
|
|
|
|
pDispatch = VariantArray[i].pdispVal;
|
|
|
|
hr = pDispatch->QueryInterface(
|
|
IID_IADs,
|
|
(VOID **) &pObject
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = pObject->get_ADsPath(&bstrName);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
if (!_wcsicmp(bstrName, bstrMember)) {
|
|
|
|
SysFreeString(bstrName);
|
|
bstrName = NULL;
|
|
|
|
pObject->Release();
|
|
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
SysFreeString(bstrName);
|
|
bstrName = NULL;
|
|
|
|
pObject->Release();
|
|
|
|
}
|
|
|
|
error:
|
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CNDSGroup::Add(THIS_ BSTR bstrNewItem)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
WCHAR szNDSUserPathName[MAX_PATH];
|
|
WCHAR szNDSUserTreeName[MAX_PATH];
|
|
IUnknown * pUnknown = NULL;
|
|
IADs * pUser = NULL;
|
|
|
|
WCHAR szNDSGroupPathName[MAX_PATH];
|
|
WCHAR szNDSGroupTreeName[MAX_PATH];
|
|
BSTR bstrPathName = NULL;
|
|
|
|
hr = ::GetObject(
|
|
bstrNewItem,
|
|
_Credentials,
|
|
(void **)&pUnknown
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = pUnknown->QueryInterface(IID_IADs, (void **)&pUser);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = BuildNDSPathFromADsPath(
|
|
bstrNewItem,
|
|
szNDSUserTreeName,
|
|
szNDSUserPathName
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = _pADs->get_ADsPath(&bstrPathName);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = BuildNDSPathFromADsPath(
|
|
bstrPathName,
|
|
szNDSGroupTreeName,
|
|
szNDSGroupPathName
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
hr = AddEntry(_pADs, L"Member",szNDSUserPathName);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
// hr = AddEntry(_pADs, L"Equivalent To Me", szNDSUserPathName);
|
|
// BAIL_ON_FAILURE(hr);
|
|
|
|
hr = AddEntry(pUser, L"Group Membership", szNDSGroupPathName);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
error:
|
|
|
|
if (bstrPathName) {
|
|
ADsFreeString(bstrPathName);
|
|
}
|
|
|
|
if (pUnknown) {
|
|
pUnknown->Release();
|
|
}
|
|
|
|
if (pUser) {
|
|
pUser->Release();
|
|
}
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CNDSGroup::Remove(THIS_ BSTR bstrNewItem)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
WCHAR szNDSUserPathName[MAX_PATH];
|
|
WCHAR szNDSUserTreeName[MAX_PATH];
|
|
IUnknown * pUnknown = NULL;
|
|
IADs * pUser = NULL;
|
|
|
|
WCHAR szNDSGroupPathName[MAX_PATH];
|
|
WCHAR szNDSGroupTreeName[MAX_PATH];
|
|
BSTR bstrPathName = NULL;
|
|
|
|
hr = ::GetObject(
|
|
bstrNewItem,
|
|
_Credentials,
|
|
(void **)&pUnknown
|
|
);
|
|
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = pUnknown->QueryInterface(IID_IADs, (void **)&pUser);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = BuildNDSPathFromADsPath(
|
|
bstrNewItem,
|
|
szNDSUserTreeName,
|
|
szNDSUserPathName
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = _pADs->get_ADsPath(&bstrPathName);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = BuildNDSPathFromADsPath(
|
|
bstrPathName,
|
|
szNDSGroupTreeName,
|
|
szNDSGroupPathName
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
hr = RemoveEntry(_pADs, L"Member",szNDSUserPathName);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
// hr = RemoveEntry(_pADs, L"Equivalent To Me", szNDSUserPathName);
|
|
// BAIL_ON_FAILURE(hr);
|
|
|
|
hr = RemoveEntry(pUser, L"Group Membership", szNDSGroupPathName);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
error:
|
|
|
|
if (bstrPathName) {
|
|
ADsFreeString(bstrPathName);
|
|
}
|
|
|
|
if (pUnknown) {
|
|
pUnknown->Release();
|
|
}
|
|
|
|
if (pUser) {
|
|
pUser->Release();
|
|
}
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
AddEntry(
|
|
IADs * pADs,
|
|
LPWSTR pszAttribute,
|
|
LPWSTR pszValue
|
|
)
|
|
{
|
|
|
|
HRESULT hr = S_OK;
|
|
VARIANT vOldValue;
|
|
VARIANT vNewValue;
|
|
SAFEARRAY * pArray = NULL;
|
|
|
|
VariantInit(&vOldValue);
|
|
VariantInit(&vNewValue);
|
|
|
|
#if defined(BUILD_FOR_NT40)
|
|
|
|
hr = pADs->Get(pszAttribute, &vOldValue);
|
|
if (hr == E_ADS_PROPERTY_NOT_FOUND) {
|
|
|
|
|
|
VariantInit(&vNewValue);
|
|
V_BSTR(&vNewValue) = SysAllocString(pszValue);
|
|
V_VT(&vNewValue) = VT_BSTR;
|
|
|
|
hr = pADs->Put(pszAttribute, vNewValue);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
}else{
|
|
|
|
hr = VarAddEntry(
|
|
pszValue,
|
|
vOldValue,
|
|
&vNewValue
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = pADs->Put(pszAttribute, vNewValue);
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
#else
|
|
|
|
//
|
|
// NT5 supports appending values. So we don't need to read everything.
|
|
// append ourselves and write everything
|
|
//
|
|
|
|
SAFEARRAYBOUND sabNewArray;
|
|
int i;
|
|
VARIANT v;
|
|
|
|
sabNewArray.cElements = 1;
|
|
sabNewArray.lLbound = 0;
|
|
|
|
pArray = SafeArrayCreate(
|
|
VT_VARIANT,
|
|
1,
|
|
&sabNewArray
|
|
);
|
|
if (!pArray) {
|
|
hr = E_OUTOFMEMORY;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
VariantInit(&v);
|
|
|
|
V_BSTR(&v) = SysAllocString(pszValue);
|
|
V_VT(&v) = VT_BSTR;
|
|
|
|
i = 0;
|
|
hr = SafeArrayPutElement(
|
|
pArray,
|
|
(long *)&i,
|
|
(void *)&v
|
|
);
|
|
|
|
VariantClear(&v);
|
|
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
V_VT(&vNewValue) = VT_ARRAY | VT_VARIANT;
|
|
V_ARRAY(&vNewValue) = pArray;
|
|
|
|
hr = pADs->PutEx(ADS_PROPERTY_APPEND, pszAttribute, vNewValue);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
#endif
|
|
|
|
hr = pADs->SetInfo();
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
error:
|
|
|
|
VariantClear(&vOldValue);
|
|
VariantClear(&vNewValue);
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT
|
|
RemoveEntry(
|
|
IADs * pADs,
|
|
LPWSTR pszAttribute,
|
|
LPWSTR pszValue
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
VARIANT vOldValue;
|
|
VARIANT vNewValue;
|
|
SAFEARRAY * pArray = NULL;
|
|
|
|
VariantInit(&vOldValue);
|
|
VariantInit(&vNewValue);
|
|
|
|
#if defined(BUILD_FOR_NT40)
|
|
|
|
hr = pADs->Get(pszAttribute, &vOldValue);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = VarRemoveEntry(
|
|
pszValue,
|
|
vOldValue,
|
|
&vNewValue
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
if (V_VT(&vNewValue) == VT_EMPTY) {
|
|
hr = pADs->PutEx(ADS_PROPERTY_CLEAR, pszAttribute, vNewValue);
|
|
}else {
|
|
hr = pADs->Put(pszAttribute, vNewValue);
|
|
|
|
}
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
#else
|
|
|
|
SAFEARRAYBOUND sabNewArray;
|
|
VARIANT v;
|
|
int i;
|
|
|
|
//
|
|
// NT5 supports deleting values. So we don't need to read everything.
|
|
// delete ourselves and write everything - Very inefficient!
|
|
//
|
|
|
|
sabNewArray.cElements = 1;
|
|
sabNewArray.lLbound = 0;
|
|
|
|
pArray = SafeArrayCreate(
|
|
VT_VARIANT,
|
|
1,
|
|
&sabNewArray
|
|
);
|
|
if (!pArray) {
|
|
hr = E_OUTOFMEMORY;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
VariantInit(&v);
|
|
|
|
V_BSTR(&v) = SysAllocString(pszValue);
|
|
V_VT(&v) = VT_BSTR;
|
|
|
|
i = 0;
|
|
hr = SafeArrayPutElement(
|
|
pArray,
|
|
(long *)&i,
|
|
(void *)&v
|
|
);
|
|
|
|
VariantClear(&v);
|
|
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
V_VT(&vNewValue) = VT_ARRAY | VT_VARIANT;
|
|
V_ARRAY(&vNewValue) = pArray;
|
|
|
|
hr = pADs->PutEx(ADS_PROPERTY_DELETE, pszAttribute, vNewValue);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
#endif
|
|
|
|
hr = pADs->SetInfo();
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
error:
|
|
|
|
VariantClear(&vOldValue);
|
|
VariantClear(&vNewValue);
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
VarFindEntry(
|
|
LPWSTR pszNDSPathName,
|
|
VARIANT varMembers
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD dwSLBound = 0;
|
|
DWORD dwSUBound = 0;
|
|
DWORD i = 0;
|
|
VARIANT v;
|
|
|
|
if (!(V_VT(&varMembers) == (VT_VARIANT|VT_ARRAY))) {
|
|
return(E_FAIL);
|
|
}
|
|
|
|
//
|
|
// Check that there is only one dimension in this array
|
|
//
|
|
|
|
if ((V_ARRAY(&varMembers))->cDims != 1) {
|
|
hr = E_FAIL;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
//
|
|
// Check that there is atleast one element in this array
|
|
//
|
|
|
|
if ((V_ARRAY(&varMembers))->rgsabound[0].cElements == 0){
|
|
hr = E_FAIL;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
//
|
|
// We know that this is a valid single dimension array
|
|
//
|
|
|
|
hr = SafeArrayGetLBound(V_ARRAY(&varMembers),
|
|
1,
|
|
(long FAR *)&dwSLBound
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = SafeArrayGetUBound(V_ARRAY(&varMembers),
|
|
1,
|
|
(long FAR *)&dwSUBound
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
for (i = dwSLBound; i <= dwSUBound; i++) {
|
|
VariantInit(&v);
|
|
hr = SafeArrayGetElement(V_ARRAY(&varMembers),
|
|
(long FAR *)&i,
|
|
&v
|
|
);
|
|
|
|
if (!_wcsicmp(V_BSTR(&v), pszNDSPathName)) {
|
|
VariantClear(&v);
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
VariantClear(&v);
|
|
}
|
|
|
|
error:
|
|
|
|
RRETURN(E_FAIL);
|
|
}
|
|
|
|
HRESULT
|
|
VarMultipleAddEntry(
|
|
LPWSTR pszNDSPathName,
|
|
VARIANT varMembers,
|
|
VARIANT * pvarNewMembers
|
|
)
|
|
{ SAFEARRAYBOUND sabNewArray;
|
|
SAFEARRAY * pFilter = NULL;
|
|
HRESULT hr = S_OK;
|
|
DWORD dwSLBound = 0;
|
|
DWORD dwSUBound = 0;
|
|
DWORD i = 0;
|
|
VARIANT v;
|
|
|
|
VariantInit(pvarNewMembers);
|
|
|
|
if (!(V_VT(&varMembers) == (VT_VARIANT|VT_ARRAY))) {
|
|
return(E_FAIL);
|
|
}
|
|
|
|
//
|
|
// Check that there is only one dimension in this array
|
|
//
|
|
|
|
if ((V_ARRAY(&varMembers))->cDims != 1) {
|
|
hr = E_FAIL;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
//
|
|
// Check that there is atleast one element in this array
|
|
//
|
|
|
|
if ((V_ARRAY(&varMembers))->rgsabound[0].cElements == 0){
|
|
hr = E_FAIL;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
//
|
|
// We know that this is a valid single dimension array
|
|
//
|
|
|
|
hr = SafeArrayGetLBound(V_ARRAY(&varMembers),
|
|
1,
|
|
(long FAR *)&dwSLBound
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = SafeArrayGetUBound(V_ARRAY(&varMembers),
|
|
1,
|
|
(long FAR *)&dwSUBound
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
sabNewArray.cElements = (dwSUBound - dwSLBound + 1) + 1;
|
|
sabNewArray.lLbound = dwSLBound;
|
|
|
|
pFilter = SafeArrayCreate(
|
|
VT_VARIANT,
|
|
1,
|
|
&sabNewArray
|
|
);
|
|
|
|
|
|
if (!pFilter) {
|
|
hr = E_OUTOFMEMORY;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
for (i = dwSLBound; i <= dwSUBound; i++) {
|
|
|
|
VariantInit(&v);
|
|
|
|
hr = SafeArrayGetElement(
|
|
V_ARRAY(&varMembers),
|
|
(long FAR *)&i,
|
|
&v
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = SafeArrayPutElement(
|
|
pFilter,
|
|
(long*)&i,
|
|
(void *)&v
|
|
);
|
|
|
|
VariantClear(&v);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
}
|
|
|
|
VariantInit(&v);
|
|
V_VT(&v) = VT_BSTR;
|
|
V_BSTR(&v) = SysAllocString(pszNDSPathName);
|
|
|
|
hr = SafeArrayPutElement(
|
|
pFilter,
|
|
(long *)&i,
|
|
(void *)&v
|
|
);
|
|
VariantClear(&v);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
V_VT(pvarNewMembers) = VT_ARRAY | VT_VARIANT;
|
|
V_ARRAY(pvarNewMembers) = pFilter;
|
|
|
|
RRETURN(S_OK);
|
|
|
|
error:
|
|
|
|
if (pFilter) {
|
|
SafeArrayDestroy(pFilter);
|
|
}
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
HRESULT
|
|
VarMultipleRemoveEntry(
|
|
LPWSTR pszNDSPathName,
|
|
VARIANT varMembers,
|
|
VARIANT * pvarNewMembers
|
|
)
|
|
{ SAFEARRAYBOUND sabNewArray;
|
|
SAFEARRAY * pFilter = NULL;
|
|
HRESULT hr = S_OK;
|
|
DWORD dwSLBound = 0;
|
|
DWORD dwSUBound = 0;
|
|
DWORD i = 0;
|
|
DWORD dwNewCount = 0;
|
|
VARIANT v;
|
|
|
|
VariantInit(pvarNewMembers);
|
|
|
|
|
|
if(!(V_VT(&varMembers) == (VT_VARIANT|VT_ARRAY))){
|
|
return(E_FAIL);
|
|
}
|
|
|
|
//
|
|
// Check that there is only one dimension in this array
|
|
//
|
|
|
|
if ((V_ARRAY(&varMembers))->cDims != 1) {
|
|
hr = E_FAIL;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
//
|
|
// Check that there is atleast one element in this array
|
|
//
|
|
|
|
if ((V_ARRAY(&varMembers))->rgsabound[0].cElements == 0){
|
|
hr = E_FAIL;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
//
|
|
// We know that this is a valid single dimension array
|
|
//
|
|
|
|
hr = SafeArrayGetLBound(V_ARRAY(&varMembers),
|
|
1,
|
|
(long FAR *)&dwSLBound
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = SafeArrayGetUBound(V_ARRAY(&varMembers),
|
|
1,
|
|
(long FAR *)&dwSUBound
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
sabNewArray.cElements = (dwSUBound - dwSLBound);
|
|
sabNewArray.lLbound = dwSLBound;
|
|
|
|
pFilter = SafeArrayCreate(
|
|
VT_VARIANT,
|
|
1,
|
|
&sabNewArray
|
|
);
|
|
|
|
|
|
if (!pFilter) {
|
|
hr = E_OUTOFMEMORY;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
for (i = dwSLBound, dwNewCount = dwSLBound; i <= dwSUBound; i++) {
|
|
VariantInit(&v);
|
|
hr = SafeArrayGetElement(
|
|
V_ARRAY(&varMembers),
|
|
(long FAR *)&i,
|
|
&v
|
|
);
|
|
|
|
if (!_wcsicmp(V_BSTR(&v), pszNDSPathName)) {
|
|
|
|
VariantClear(&v);
|
|
//
|
|
// skip this entry
|
|
//
|
|
continue;
|
|
|
|
}
|
|
hr = SafeArrayPutElement(
|
|
pFilter,
|
|
(long*)&dwNewCount,
|
|
(void *)&v
|
|
);
|
|
|
|
VariantClear(&v);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
dwNewCount++;
|
|
|
|
}
|
|
|
|
V_VT(pvarNewMembers) = VT_ARRAY | VT_VARIANT;
|
|
V_ARRAY(pvarNewMembers) = pFilter;
|
|
|
|
RRETURN(S_OK);
|
|
|
|
|
|
error:
|
|
|
|
if (pFilter) {
|
|
SafeArrayDestroy(pFilter);
|
|
}
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
|
|
|
|
HRESULT
|
|
VarSingleAddEntry(
|
|
LPWSTR pszNDSPathName,
|
|
VARIANT varMembers,
|
|
VARIANT * pvarNewMembers
|
|
)
|
|
{ SAFEARRAYBOUND sabNewArray;
|
|
SAFEARRAY * pFilter = NULL;
|
|
HRESULT hr = S_OK;
|
|
DWORD dwSLBound = 0;
|
|
DWORD dwSUBound = 0;
|
|
DWORD i = 0;
|
|
VARIANT v;
|
|
|
|
VariantInit(pvarNewMembers);
|
|
|
|
if(!((V_VT(&varMembers) & VT_TYPEMASK) == VT_BSTR)){
|
|
return(E_FAIL);
|
|
}
|
|
|
|
sabNewArray.cElements = (1) + 1;
|
|
sabNewArray.lLbound = 0;
|
|
|
|
pFilter = SafeArrayCreate(
|
|
VT_VARIANT,
|
|
1,
|
|
&sabNewArray
|
|
);
|
|
if (!pFilter) {
|
|
hr = E_OUTOFMEMORY;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
i = 0;
|
|
hr = SafeArrayPutElement(
|
|
pFilter,
|
|
(long *)&i,
|
|
(void *)&varMembers
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
i++;
|
|
|
|
VariantInit(&v);
|
|
V_VT(&v) = VT_BSTR;
|
|
V_BSTR(&v) = SysAllocString(pszNDSPathName);
|
|
|
|
hr = SafeArrayPutElement(
|
|
pFilter,
|
|
(long *)&i,
|
|
(void *)&v
|
|
);
|
|
VariantClear(&v);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
V_VT(pvarNewMembers) = VT_ARRAY | VT_VARIANT;
|
|
V_ARRAY(pvarNewMembers) = pFilter;
|
|
|
|
RRETURN(S_OK);
|
|
|
|
error:
|
|
|
|
if (pFilter) {
|
|
SafeArrayDestroy(pFilter);
|
|
}
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
VarSingleRemoveEntry(
|
|
LPWSTR pszNDSPathName,
|
|
VARIANT varMembers,
|
|
VARIANT * pvarNewMembers
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
VariantInit(pvarNewMembers);
|
|
|
|
if(!((V_VT(&varMembers) & VT_TYPEMASK) == VT_BSTR)){
|
|
return(E_FAIL);
|
|
}
|
|
|
|
V_VT(pvarNewMembers) = VT_EMPTY;
|
|
V_BSTR(pvarNewMembers) = NULL;
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
VarRemoveEntry(
|
|
LPWSTR pszNDSPathName,
|
|
VARIANT varMembers,
|
|
VARIANT * pvarNewMembers
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (V_VT(&varMembers) == (VT_VARIANT|VT_ARRAY)) {
|
|
|
|
hr = VarMultipleRemoveEntry(
|
|
pszNDSPathName,
|
|
varMembers,
|
|
pvarNewMembers
|
|
);
|
|
RRETURN(hr);
|
|
|
|
}else if (V_VT(&varMembers) == VT_BSTR){
|
|
|
|
hr = VarSingleRemoveEntry(
|
|
pszNDSPathName,
|
|
varMembers,
|
|
pvarNewMembers
|
|
);
|
|
|
|
RRETURN(hr);
|
|
|
|
}else {
|
|
|
|
RRETURN(E_FAIL);
|
|
}
|
|
}
|
|
|
|
|
|
HRESULT
|
|
VarAddEntry(
|
|
LPWSTR pszNDSPathName,
|
|
VARIANT varMembers,
|
|
VARIANT * pvarNewMembers
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (V_VT(&varMembers) == (VT_VARIANT|VT_ARRAY)){
|
|
|
|
hr = VarMultipleAddEntry(
|
|
pszNDSPathName,
|
|
varMembers,
|
|
pvarNewMembers
|
|
);
|
|
RRETURN(hr);
|
|
|
|
}else if ((V_VT(&varMembers) & VT_TYPEMASK) == VT_BSTR){
|
|
|
|
hr = VarSingleAddEntry(
|
|
pszNDSPathName,
|
|
varMembers,
|
|
pvarNewMembers
|
|
);
|
|
|
|
RRETURN(hr);
|
|
|
|
}else {
|
|
|
|
RRETURN(E_FAIL);
|
|
}
|
|
}
|
|
|