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.
757 lines
16 KiB
757 lines
16 KiB
//***************************************************************************
|
|
//
|
|
// adminacl.cpp
|
|
//
|
|
// Module: WBEM Instance provider
|
|
//
|
|
// Purpose: IIS AdminACL class
|
|
//
|
|
// Copyright (c)1998 Microsoft Corporation, All Rights Reserved
|
|
//
|
|
//***************************************************************************
|
|
|
|
|
|
|
|
#include "iisprov.h"
|
|
|
|
|
|
CAdminACL::CAdminACL()
|
|
{
|
|
m_pADs = NULL;
|
|
m_pSD = NULL;
|
|
m_pDACL = NULL;
|
|
}
|
|
|
|
|
|
CAdminACL::~CAdminACL()
|
|
{
|
|
CloseSD();
|
|
}
|
|
|
|
|
|
void CAdminACL::CloseSD()
|
|
{
|
|
if(m_pDACL)
|
|
{
|
|
m_pDACL->Release();
|
|
m_pDACL = NULL;
|
|
}
|
|
|
|
if(m_pSD)
|
|
{
|
|
m_pSD->Release();
|
|
m_pSD = NULL;
|
|
}
|
|
|
|
if(m_pADs)
|
|
{
|
|
m_pADs->Release();
|
|
m_pADs = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
HRESULT CAdminACL::GetObjectAsync(
|
|
IWbemClassObject* pObj,
|
|
ParsedObjectPath* pParsedObject,
|
|
WMI_CLASS* pWMIClass
|
|
)
|
|
{
|
|
if(!m_pSD || !m_pSD || !m_pDACL)
|
|
return E_UNEXPECTED;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if( pWMIClass->eKeyType == TYPE_AdminACL )
|
|
{
|
|
hr = PingAdminACL(pObj);
|
|
}
|
|
else if( pWMIClass->eKeyType == TYPE_AdminACE )
|
|
{
|
|
_bstr_t bstrTrustee;
|
|
GetTrustee(pObj, pParsedObject, bstrTrustee);
|
|
hr = GetACE(pObj, bstrTrustee);
|
|
}
|
|
else
|
|
hr = E_INVALIDARG;
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CAdminACL::DeleteObjectAsync(ParsedObjectPath* pParsedObject)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
_bstr_t bstrTrustee;
|
|
|
|
// get the trustee from key
|
|
GetTrustee(NULL, pParsedObject, bstrTrustee);
|
|
|
|
// remove the ACE
|
|
hr = RemoveACE(bstrTrustee);
|
|
|
|
// set the modified AdminACL back into the metabase
|
|
if(SUCCEEDED(hr))
|
|
hr = SetSD();
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CAdminACL::PutObjectAsync(
|
|
IWbemClassObject* pObj,
|
|
ParsedObjectPath* pParsedObject,
|
|
WMI_CLASS* pWMIClass
|
|
)
|
|
{
|
|
if(!m_pSD || !m_pSD || !m_pDACL)
|
|
return E_UNEXPECTED;
|
|
|
|
HRESULT hr;
|
|
|
|
if( pWMIClass->eKeyType == TYPE_AdminACL )
|
|
{
|
|
hr = SetAdminACL(pObj);
|
|
}
|
|
else if( pWMIClass->eKeyType == TYPE_AdminACE )
|
|
{
|
|
_bstr_t bstrTrustee;
|
|
GetTrustee(NULL, pParsedObject, bstrTrustee);
|
|
|
|
BOOL fAceExisted = FALSE;
|
|
hr = UpdateACE(pObj, bstrTrustee, fAceExisted);
|
|
if(fAceExisted == FALSE)
|
|
hr = AddACE(pObj, bstrTrustee);
|
|
}
|
|
else
|
|
hr = E_INVALIDARG;
|
|
|
|
// set the modified AdminACL back into the metabase
|
|
if(SUCCEEDED(hr))
|
|
hr = SetSD();
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CAdminACL::PingAdminACL(
|
|
IWbemClassObject* pObj
|
|
)
|
|
{
|
|
_variant_t vt;
|
|
BSTR bstr;
|
|
long lVal;
|
|
HRESULT hr;
|
|
|
|
// Owner
|
|
hr = m_pSD->get_Owner(&bstr);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
vt = bstr;
|
|
hr = pObj->Put(L"Owner", 0, &vt, 0);
|
|
SysFreeString(bstr);
|
|
}
|
|
|
|
// Group
|
|
if(SUCCEEDED(hr))
|
|
hr = m_pSD->get_Group(&bstr);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
vt = bstr;
|
|
hr = pObj->Put(L"Group", 0, &vt, 0);
|
|
SysFreeString(bstr);
|
|
}
|
|
|
|
// ControlFlags
|
|
if(SUCCEEDED(hr))
|
|
hr = m_pSD->get_Control(&lVal);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
vt.vt = VT_I4;
|
|
vt.lVal = lVal;
|
|
hr = pObj->Put(L"ControlFlags", 0, &vt, 0);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CAdminACL::SetAdminACL(
|
|
IWbemClassObject* pObj
|
|
)
|
|
{
|
|
_variant_t vt;
|
|
HRESULT hr;
|
|
|
|
// Owner
|
|
hr = pObj->Get(L"Owner", 0, &vt, NULL, NULL);
|
|
if(SUCCEEDED(hr) && vt.vt == VT_BSTR)
|
|
hr = m_pSD->put_Owner(vt.bstrVal);
|
|
|
|
// Owner
|
|
if(SUCCEEDED(hr))
|
|
hr = pObj->Get(L"Group", 0, &vt, NULL, NULL);
|
|
if(SUCCEEDED(hr) && vt.vt == VT_BSTR)
|
|
hr = m_pSD->put_Group(vt.bstrVal);
|
|
|
|
// ControlFlags
|
|
if(SUCCEEDED(hr))
|
|
hr = pObj->Get(L"ControlFlags", 0, &vt, NULL, NULL);
|
|
if(SUCCEEDED(hr) && vt.vt == VT_I4)
|
|
hr = m_pSD->put_Control(vt.lVal);
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CAdminACL::OpenSD(_bstr_t bstrAdsPath)
|
|
{
|
|
_variant_t var;
|
|
HRESULT hr;
|
|
IDispatch* pDisp = NULL;
|
|
|
|
// close SD interface first
|
|
CloseSD();
|
|
|
|
hr = GetAdsPath(bstrAdsPath);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
|
|
// get m_pADs
|
|
hr = ADsGetObject(
|
|
bstrAdsPath,
|
|
IID_IADs,
|
|
(void**)&m_pADs
|
|
);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
|
|
// get m_pSD
|
|
hr = m_pADs->Get(L"AdminACL",&var);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
|
|
hr = V_DISPATCH(&var)->QueryInterface(
|
|
IID_IADsSecurityDescriptor,
|
|
(void**)&m_pSD
|
|
);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
|
|
// get m_pDACL
|
|
hr = m_pSD->get_DiscretionaryAcl(&pDisp);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
|
|
hr = pDisp->QueryInterface(
|
|
IID_IADsAccessControlList,
|
|
(void**)&m_pDACL
|
|
);
|
|
|
|
pDisp->Release();
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CAdminACL::SetSD()
|
|
{
|
|
_variant_t var;
|
|
HRESULT hr;
|
|
IDispatch* pDisp = NULL;
|
|
|
|
// put m_pDACL
|
|
hr = m_pDACL->QueryInterface(
|
|
IID_IDispatch,
|
|
(void**)&pDisp
|
|
);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
|
|
hr = m_pSD->put_DiscretionaryAcl(pDisp);
|
|
pDisp->Release();
|
|
if(FAILED(hr))
|
|
return hr;
|
|
|
|
// put AdminACL
|
|
hr = m_pSD->QueryInterface(
|
|
IID_IDispatch,
|
|
(void**)&pDisp
|
|
);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
|
|
var.vt = VT_DISPATCH;
|
|
var.pdispVal = pDisp;
|
|
hr = m_pADs->Put(L"AdminACL",var); // pDisp will be released by this call Put().
|
|
if(FAILED(hr))
|
|
return hr;
|
|
|
|
// Commit the change to the active directory
|
|
hr = m_pADs->SetInfo();
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CAdminACL::GetAdsPath(_bstr_t& bstrAdsPath)
|
|
{
|
|
WCHAR* p = new WCHAR[bstrAdsPath.length() + 1];
|
|
if(p == NULL)
|
|
return E_OUTOFMEMORY;
|
|
|
|
lstrcpyW(p, bstrAdsPath);
|
|
|
|
bstrAdsPath = L"IIS://LocalHost";
|
|
|
|
// trim first three charaters "/LM"
|
|
bstrAdsPath += (p+3);
|
|
|
|
delete [] p;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CAdminACL::PingACE(
|
|
IWbemClassObject* pObj,
|
|
IADsAccessControlEntry* pACE
|
|
)
|
|
{
|
|
_variant_t vt;
|
|
BSTR bstr;
|
|
long lVal;
|
|
HRESULT hr;
|
|
|
|
// AccessMask
|
|
hr = pACE->get_AccessMask(&lVal);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
vt.vt = VT_I4;
|
|
vt.lVal = lVal;
|
|
hr = pObj->Put(L"AccessMask", 0, &vt, 0);
|
|
}
|
|
|
|
// AceType
|
|
if(SUCCEEDED(hr))
|
|
hr = pACE->get_AceType(&lVal);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
vt.vt = VT_I4;
|
|
vt.lVal = lVal;
|
|
hr = pObj->Put(L"AceType", 0, &vt, 0);
|
|
}
|
|
|
|
// AceFlags
|
|
if(SUCCEEDED(hr))
|
|
hr = pACE->get_AceFlags(&lVal);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
vt.vt = VT_I4;
|
|
vt.lVal = lVal;
|
|
hr = pObj->Put(L"AceFlags", 0, &vt, 0);
|
|
}
|
|
|
|
// Flags
|
|
if(SUCCEEDED(hr))
|
|
hr = pACE->get_Flags(&lVal);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
vt.vt = VT_I4;
|
|
vt.lVal = lVal;
|
|
hr = pObj->Put(L"Flags", 0, &vt, 0);
|
|
}
|
|
|
|
// ObjectType
|
|
if(SUCCEEDED(hr))
|
|
hr = pACE->get_ObjectType(&bstr);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
vt = bstr;
|
|
hr = pObj->Put(L"ObjectType", 0, &vt, 0);
|
|
SysFreeString(bstr);
|
|
}
|
|
|
|
// InheritedObjectType
|
|
if(SUCCEEDED(hr))
|
|
hr = pACE->get_InheritedObjectType(&bstr);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
vt = bstr;
|
|
hr = pObj->Put(L"InheritedObjectType", 0, &vt, 0);
|
|
SysFreeString(bstr);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CAdminACL::GetACE(
|
|
IWbemClassObject* pObj,
|
|
_bstr_t& bstrTrustee
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
_variant_t var;
|
|
IEnumVARIANT* pEnum = NULL;
|
|
ULONG lFetch;
|
|
BSTR bstr;
|
|
IDispatch *pDisp = NULL;
|
|
IADsAccessControlEntry *pACE = NULL;
|
|
|
|
hr = GetACEEnum(&pEnum);
|
|
if ( FAILED(hr) )
|
|
return hr;
|
|
|
|
//////////////////////////////////////////////
|
|
// Enumerate ACEs
|
|
//////////////////////////////////////////////
|
|
hr = pEnum->Next( 1, &var, &lFetch );
|
|
while( hr == S_OK )
|
|
{
|
|
if ( lFetch == 1 )
|
|
{
|
|
if ( VT_DISPATCH != V_VT(&var) )
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
break;
|
|
}
|
|
|
|
pDisp = V_DISPATCH(&var);
|
|
|
|
/////////////////////////////
|
|
// Get the individual ACE
|
|
/////////////////////////////
|
|
hr = pDisp->QueryInterface(
|
|
IID_IADsAccessControlEntry,
|
|
(void**)&pACE
|
|
);
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
hr = pACE->get_Trustee(&bstr);
|
|
|
|
if( SUCCEEDED(hr) && !lstrcmpiW(bstr, bstrTrustee) )
|
|
{
|
|
hr = PingACE(pObj, pACE);
|
|
|
|
SysFreeString(bstr);
|
|
pACE->Release();
|
|
break;
|
|
}
|
|
|
|
SysFreeString(bstr);
|
|
pACE->Release();
|
|
}
|
|
}
|
|
|
|
hr = pEnum->Next( 1, &var, &lFetch );
|
|
}
|
|
|
|
pEnum->Release();
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CAdminACL::RemoveACE(
|
|
_bstr_t& bstrTrustee
|
|
)
|
|
{
|
|
HRESULT hRemoved = WBEM_E_INVALID_PARAMETER;
|
|
HRESULT hr = S_OK;
|
|
_variant_t var;
|
|
IEnumVARIANT* pEnum = NULL;
|
|
ULONG lFetch;
|
|
BSTR bstr;
|
|
IDispatch *pDisp = NULL;
|
|
IADsAccessControlEntry *pACE = NULL;
|
|
|
|
|
|
hr = GetACEEnum(&pEnum);
|
|
if ( FAILED(hr) )
|
|
return hr;
|
|
|
|
//////////////////////////////////////////////
|
|
// Enumerate ACEs
|
|
//////////////////////////////////////////////
|
|
hr = pEnum->Next( 1, &var, &lFetch );
|
|
while( hr == S_OK )
|
|
{
|
|
if ( lFetch == 1 )
|
|
{
|
|
if ( VT_DISPATCH != V_VT(&var) )
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
break;
|
|
}
|
|
|
|
pDisp = V_DISPATCH(&var);
|
|
|
|
/////////////////////////////
|
|
// Get the individual ACE
|
|
/////////////////////////////
|
|
hr = pDisp->QueryInterface(
|
|
IID_IADsAccessControlEntry,
|
|
(void**)&pACE
|
|
);
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
hr = pACE->get_Trustee(&bstr);
|
|
|
|
if( SUCCEEDED(hr) && !lstrcmpiW(bstr, bstrTrustee) )
|
|
{
|
|
// remove ACE
|
|
hr = pACE->QueryInterface(IID_IDispatch,(void**)&pDisp);
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
hRemoved = m_pDACL->RemoveAce(pDisp);
|
|
pDisp->Release();
|
|
}
|
|
|
|
SysFreeString(bstr);
|
|
pACE->Release();
|
|
break;
|
|
}
|
|
|
|
SysFreeString(bstr);
|
|
pACE->Release();
|
|
}
|
|
}
|
|
|
|
hr = pEnum->Next( 1, &var, &lFetch );
|
|
}
|
|
|
|
pEnum->Release();
|
|
|
|
return hRemoved;
|
|
}
|
|
|
|
// parse ParsedObjectPath to get the Trustee key
|
|
void CAdminACL::GetTrustee(
|
|
IWbemClassObject* pObj,
|
|
ParsedObjectPath* pPath,
|
|
_bstr_t& bstrTrustee
|
|
)
|
|
{
|
|
KeyRef* pkr;
|
|
WCHAR* pszKey = L"Trustee";
|
|
|
|
pkr = CUtils::GetKey(pPath, pszKey);
|
|
if(pkr == NULL)
|
|
throw WBEM_E_INVALID_OBJECT;
|
|
|
|
bstrTrustee = pkr->m_vValue;
|
|
if (pObj)
|
|
{
|
|
_bstr_t bstr = pkr->m_pName;
|
|
HRESULT hr = pObj->Put(bstr, 0, &pkr->m_vValue, 0);
|
|
THROW_ON_ERROR(hr);
|
|
}
|
|
}
|
|
|
|
|
|
HRESULT CAdminACL::GetACEEnum(
|
|
IEnumVARIANT** pEnum
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPUNKNOWN pUnk = NULL;
|
|
|
|
if(!pEnum)
|
|
return E_INVALIDARG;
|
|
|
|
if(*pEnum)
|
|
(*pEnum)->Release();
|
|
|
|
hr = m_pDACL->get__NewEnum( &pUnk );
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
hr = pUnk->QueryInterface( IID_IEnumVARIANT, (void**) pEnum );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// addd a ACE
|
|
HRESULT CAdminACL::AddACE(
|
|
IWbemClassObject* pObj,
|
|
_bstr_t& bstrTrustee
|
|
)
|
|
{
|
|
HRESULT hr = m_pDACL->put_AclRevision(ADS_SD_REVISION_DS);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
|
|
// create a ACE
|
|
IADsAccessControlEntry* pACE = NULL;
|
|
hr = NewACE(
|
|
pObj,
|
|
bstrTrustee,
|
|
&pACE
|
|
);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
|
|
// add the ACE
|
|
IDispatch* pDisp = NULL;
|
|
hr = pACE->QueryInterface(IID_IDispatch,(void**)&pDisp);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = m_pDACL->AddAce(pDisp);
|
|
pDisp->Release();
|
|
}
|
|
|
|
pACE->Release();
|
|
|
|
return hr;
|
|
}
|
|
|
|
////////////////////////////////////
|
|
// function to create an ACE
|
|
////////////////////////////////////
|
|
HRESULT CAdminACL::NewACE(
|
|
IWbemClassObject* pObj,
|
|
_bstr_t& bstrTrustee,
|
|
IADsAccessControlEntry** ppACE
|
|
)
|
|
{
|
|
if(!ppACE)
|
|
return E_INVALIDARG;
|
|
|
|
HRESULT hr;
|
|
hr = CoCreateInstance(
|
|
CLSID_AccessControlEntry,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IADsAccessControlEntry,
|
|
(void**)ppACE
|
|
);
|
|
|
|
// Trustee
|
|
_variant_t vt;
|
|
if(SUCCEEDED(hr))
|
|
hr = (*ppACE)->put_Trustee(bstrTrustee);
|
|
|
|
if(SUCCEEDED(hr))
|
|
hr = SetDataOfACE(pObj, *ppACE);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CAdminACL::SetDataOfACE(
|
|
IWbemClassObject* pObj,
|
|
IADsAccessControlEntry* pACE
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
_variant_t vt;
|
|
|
|
// AccessMask
|
|
hr = pObj->Get(L"AccessMask", 0, &vt, NULL, NULL);
|
|
if(SUCCEEDED(hr) && vt.vt == VT_I4)
|
|
hr = pACE->put_AccessMask(vt.lVal);
|
|
|
|
// AceType
|
|
if(SUCCEEDED(hr))
|
|
hr = pObj->Get(L"AceType", 0, &vt, NULL, NULL);
|
|
if(SUCCEEDED(hr) && vt.vt == VT_I4)
|
|
hr = pACE->put_AceType(vt.lVal);
|
|
|
|
// AceFlags
|
|
if(SUCCEEDED(hr))
|
|
hr = pObj->Get(L"AceFlags", 0, &vt, NULL, NULL);
|
|
if(SUCCEEDED(hr) && vt.vt == VT_I4)
|
|
hr = pACE->put_AceFlags(vt.lVal);
|
|
|
|
// Flags
|
|
if(SUCCEEDED(hr))
|
|
hr = pObj->Get(L"Flags", 0, &vt, NULL, NULL);
|
|
if(SUCCEEDED(hr) && vt.vt == VT_I4)
|
|
hr = pACE->put_Flags(vt.lVal);
|
|
|
|
// ObjectType
|
|
if(SUCCEEDED(hr))
|
|
hr = pObj->Get(L"ObjectType", 0, &vt, NULL, NULL);
|
|
if(SUCCEEDED(hr) && vt.vt == VT_BSTR)
|
|
hr = pACE->put_ObjectType(vt.bstrVal);
|
|
|
|
// InheritedObjectType
|
|
if(SUCCEEDED(hr))
|
|
hr = pObj->Get(L"InheritedObjectType", 0, &vt, NULL, NULL);
|
|
if(SUCCEEDED(hr) && vt.vt == VT_BSTR)
|
|
hr = pACE->put_InheritedObjectType(vt.bstrVal);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CAdminACL::UpdateACE(
|
|
IWbemClassObject* pObj,
|
|
_bstr_t& bstrTrustee,
|
|
BOOL& fAceExisted
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
_variant_t var;
|
|
IEnumVARIANT* pEnum = NULL;
|
|
ULONG lFetch;
|
|
BSTR bstr;
|
|
IDispatch *pDisp = NULL;
|
|
IADsAccessControlEntry *pACE = NULL;
|
|
|
|
fAceExisted = FALSE;
|
|
|
|
hr = GetACEEnum(&pEnum);
|
|
if ( FAILED(hr) )
|
|
return hr;
|
|
|
|
//////////////////////////////////////////////
|
|
// Enumerate ACEs
|
|
//////////////////////////////////////////////
|
|
hr = pEnum->Next( 1, &var, &lFetch );
|
|
while( hr == S_OK )
|
|
{
|
|
if ( lFetch == 1 )
|
|
{
|
|
if ( VT_DISPATCH != V_VT(&var) )
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
break;
|
|
}
|
|
|
|
pDisp = V_DISPATCH(&var);
|
|
|
|
/////////////////////////////
|
|
// Get the individual ACE
|
|
/////////////////////////////
|
|
hr = pDisp->QueryInterface(
|
|
IID_IADsAccessControlEntry,
|
|
(void**)&pACE
|
|
);
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
hr = pACE->get_Trustee(&bstr);
|
|
|
|
if( SUCCEEDED(hr) && !lstrcmpiW(bstr, bstrTrustee) )
|
|
{
|
|
fAceExisted = TRUE;
|
|
|
|
// Update the data of the ACE
|
|
hr = SetDataOfACE(pObj, pACE);
|
|
|
|
SysFreeString(bstr);
|
|
pACE->Release();
|
|
break;
|
|
}
|
|
|
|
SysFreeString(bstr);
|
|
pACE->Release();
|
|
}
|
|
}
|
|
|
|
hr = pEnum->Next( 1, &var, &lFetch );
|
|
}
|
|
|
|
pEnum->Release();
|
|
|
|
return hr;
|
|
}
|
|
|