| Platform SDK: Active Directory, ADSI, and Directory Services |
The following code fragment is a function that adds an ACE for an extended right to the ACL of the specified object:
HRESULT SetExtendedRight(
IADs *pObject,
LPOLESTR pszRightsGUID,
LONG lAccessType,
LONG fInheritanceFlags,
LONG fAppliesToObjectType,
LPOLESTR szTrustee
)
{
BOOL bExists = FALSE;
VARIANT var,varACE;
HRESULT hr = E_FAIL;
IADsSecurityDescriptor *pSD = NULL;
IADsAccessControlList *pACL = NULL;
IDispatch *pDisp = NULL;
LPUNKNOWN pUnk = NULL;
ULONG lFetch;
IEnumVARIANT *pEnum = NULL;
IADsAccessControlEntry *pACE = NULL;
IDispatch *pDispatch = NULL;
IDispatch *pDispACE = NULL;
//Check params
//This sample takes the rightsGUID in StringFromGUID2 format and assumes it is the GUID for the correct extended right.
//For extended rights in a DACL, lAccessType must be ADS_ACETYPE_ACCESS_ALLOWED_OBJECT or ADS_ACETYPE_ACCESS_DENIED_OBJECT.
if ((lAccessType!=ADS_ACETYPE_ACCESS_ALLOWED_OBJECT)&&(lAccessType!=ADS_ACETYPE_ACCESS_DENIED_OBJECT))
return E_INVALIDARG;
//This sample takes the szTrustee in an expected naming format and assumes it is the name for the correct trustee.
if (!szTrustee)
return E_INVALIDARG;
if (!pszRightsGUID)
return E_INVALIDARG;
if (pObject)
{
VariantClear(&var);
//Get the nTSecurityDescriptor
LPOLESTR szAttribute = L"nTSecurityDescriptor";
hr = pObject->Get(szAttribute,&var);
if (SUCCEEDED(hr))
{
//Type should be VT_DISPATCH--an IDispatch ptr to the security descriptor object.
if (var.vt==VT_DISPATCH)
{
//Use V_DISPATCH macro to get the IDispatch pointer from the VARIANT structure
//and QI for IADsSecurityDescriptor ptr.
hr = V_DISPATCH( &var )->QueryInterface(IID_IADsSecurityDescriptor,(void**)&pSD);
if (SUCCEEDED(hr))
{
//Get the DACL
hr = pSD->get_DiscretionaryAcl(&pDisp);
if (SUCCEEDED(hr))
{
//QI for IADsAccessControlList interface
hr = pDisp->QueryInterface(IID_IADsAccessControlList,(void**)&pACL);
if (SUCCEEDED(hr))
{
//Create the COM object for the new ACE.
hr = CoCreateInstance(
CLSID_AccessControlEntry,
NULL,
CLSCTX_INPROC_SERVER,
IID_IADsAccessControlEntry,
(void **)&pACE
);
if (SUCCEEDED(hr))
{
//Set the properties of the new ACE.
//For extended right, set the mask to ADS_RIGHT_DS_CONTROL_ACCESS.
hr = pACE->put_AccessMask(ADS_RIGHT_DS_CONTROL_ACCESS);
//Set the trustee.
hr = pACE->put_Trustee( szTrustee );
//For extended rights, set AceType to ADS_ACETYPE_ACCESS_ALLOWED_OBJECT or ADS_ACETYPE_ACCESS_DENIED_OBJECT.
hr = pACE->put_AceType( lAccessType );
//For this sample, set AceFlags so that ACE is not inherited by child objects.
hr = pACE->put_AceFlags(fInheritanceFlags);
//Flags specifies whether the ACE applies to the current object, child objects, or both.
//For this sample, fAppliesToInheritedObject is set to ADS_FLAG_OBJECT_TYPE_PRESENT so that the right applies only to the current object.
hr = pACE->put_Flags( fAppliesToObjectType );
//For extended rights, set ObjectType to the rightsGUID of the extended right.
if (fAppliesToObjectType & ADS_FLAG_OBJECT_TYPE_PRESENT)
{
hr = pACE->put_ObjectType( pszRightsGUID );
}
//Set the inherited object type if right applies to child objects.
if (fAppliesToObjectType & ADS_FLAG_INHERITED_OBJECT_TYPE_PRESENT)
{
hr = pACE->put_InheritedObjectType( pszRightsGUID );
}
//Add the ACE to the ACL.
//Need to QI for IDispatch pointer to pass to the AddAce method.
hr = pACE->QueryInterface(IID_IDispatch,(void**)&pDispACE);
if (SUCCEEDED(hr))
{
hr = pACL->AddAce(pDispACE);
if (SUCCEEDED(hr))
{
//Write the DACL
hr = pSD->put_DiscretionaryAcl(pDisp);
if (SUCCEEDED(hr))
{
//Write the ntSecurityDescriptor property to the property cache.
hr = pObject->Put(szAttribute, var);
if (SUCCEEDED(hr))
{
//Call SetInfo to update the property on the object in the directory.
hr = pObject->SetInfo();
}
}
}
}
if (pDispACE)
pDispACE->Release();
}
if (pACE)
pACE->Release();
}
if (pACL)
pACL->Release();
}
if (pDisp)
pDisp->Release();
}
if (pSD)
pSD->Release();
}
}
VariantClear(&var);
}
return hr;
}