Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
The following code example verifies absolute membership of an object by recursively verifying that an object is a member of a group or any groups nested in that group.
/////////////////////////////////////////////////////////////////////
/* RecursiveIsMember()
- Recursively scans the members of passed IADsGroup pointer
and any groups that belong to the passed pointer - for
membership of Passed group.
Returns TRUE if the member is found in the passed group,
or if the passed member is a member of any group which is
a member of the passed group.
Parameters
IADsGroup * pADsGroup - Group from which to
verify members.
LPWSTR pwszMember - LDAP path for object
to verify membership.
BOOL bVerbose - IF TRUE, will output verbose
data for the scan.
OPTIONAL Parameters
LPOLESTR pwszUser - User Name and Password, if the
parameters are not passed,
LPOLESTER pwszPassword - binding will use ADsGetObject;
if the parameters are specified,
ADsOpenObject is used, passing
user name and password.
*/
BOOL RecursiveIsMember(IADsGroup * pADsGroup,
LPWSTR pwszMemberGUID,
LPWSTR pwszMemberPath,
BOOL bVerbose,
LPOLESTR pwszUser,
LPOLESTR pwszPassword)
{
HRESULT hr = S_OK; // COM Result Code
IADsMembers * pADsMembers = NULL; // Pointer to Members
// of the IADsGroup
BOOL fContinue = TRUE; // Looping Variable
IEnumVARIANT * pEnumVariant = NULL; // Pointer to the Enum
// variant
IUnknown * pUnknown = NULL; // IUnknown for getting
// the ENUM initially
VARIANT VariantArray[FETCH_NUM]; // Variant array for temp
// holding returned data
ULONG ulElementsFetched = NULL; // Number of elements
// retrieved
BSTR bsGroupPath = NULL;
BOOL bRet = FALSE;
if(!IADsGroup || !pwszMemberGUID || !pwszMemberPath)
{
return FALSE;
}
// Get the path of the object passed in
hr = pADsGroup->get_ADsPath(&bsGroupPath);
if (!SUCCEEDED(hr))
return hr;
if (bVerbose)
{
WCHAR pwszOutput[2048];
swprintf_s(pwszOutput,
L"Checking the Group: %s\n\n for the member: %s\n\n",
bsGroupPath,
pwszMemberPath);
PrintBanner(pwszOutput);
}
// Get an interface pointer to the IADsCollection of members
hr = pADsGroup->Members(&pADsMembers);
if (SUCCEEDED(hr))
{
// Query the IADsCollection of members for a new ENUM
// Interface. Be aware that the enum comes back as an
// IUnknown *
hr = pADsMembers->get__NewEnum(&pUnknown);
if (SUCCEEDED(hr))
{
// Call the QueryInterface method for the
// IUnknown * for an IEnumVARIANT interface.
hr = pUnknown->QueryInterface(IID_IEnumVARIANT,
(void **)&pEnumVariant);
if (SUCCEEDED(hr))
{
// While no hit errors or end of data...
while (fContinue)
{
ulElementsFetched = 0;
// Get a "batch" number of group members-number
// of rows specified by FETCH_NUM
hr = ADsEnumerateNext(pEnumVariant,
FETCH_NUM,
VariantArray,
&ulElementsFetched);
if (ulElementsFetched )
{
// Loop through the current batch,
// printing the path for each member.
for (ULONG i = 0; i < ulElementsFetched; i++ )
{
// Pointer for holding dispatch of element:
IDispatch * pDispatch = NULL;
// Holds path of object:
BSTR bstrCurrentPath = NULL;
// Holds the GUID of object:
BSTR bstrGuidCurrent = NULL;
// Holds the current object:
IDirectoryObject * pIDOCurrent = NULL;
// Get the dispatch pointer for the variant
pDispatch = VariantArray[i].pdispVal;
assert(HAS_BIT_STYLE(VariantArray[i].vt,
VT_DISPATCH));
// Get the IADs interface for the
// "member" of this group
hr = pDispatch->QueryInterface(IID_IDirectoryObject,
(VOID **) &pIDOCurrent);
if (SUCCEEDED(hr))
{
// Get the GUID for the current object
hr = GetObjectGuid(pIDOCurrent,bstrGuidCurrent);
if (FAILED(hr))
return hr;
IADs * pIADsCurrent = NULL;
// Get the IADs Interface for
// the current object
hr = pIDOCurrent->QueryInterface(IID_IADs,
(void**)&pIADsCurrent);
if (FAILED(hr))
return hr;
// Get the ADsPath property for this member
hr = pIADsCurrent->get_ADsPath(&bstrCurrentPath);
if (SUCCEEDED(hr))
{
if (bVerbose)
wprintf(L"Comparing:\n%s\nWITH:\n%s\n\n",
bstrGuidCurrent,
pwszMemberGUID);
// Verify that the member of this group is
// Equal to passed.
if (_wcsicmp(bstrGuidCurrent,
pwszMemberGUID)==0)
{
if (bVerbose)
wprintf(L"Object: %s is a member of %s\n\n",
pwszMemberPath,
bstrGuidCurrent);
bRet = TRUE;
break;
}
else // Otherwise, bind to this and
// verify that it is a group.
{ // If is it a group then the call to
// the QueryInterface method to
// IADsGroup succeeds.
IADsGroup * pIADsGroupAsMember = NULL;
if (pwszUser)
hr = ADsOpenObject(bstrCurrentPath,
pwszUser,
pwszPassword,
ADS_SECURE_AUTHENTICATION,
IID_IADsGroup,
(void**) &pIADsGroupAsMember);
else
hr = ADsGetObject(bstrCurrentPath,
IID_IADsGroup,
(void **)&pIADsGroupAsMember);
// If bind was completed, then this is a group.
if (SUCCEEDED(hr))
{
// Recursively call this group to
// verify this group.
BOOL bRetRecurse;
bRetRecurse =
RecursiveIsMember(pIADsGroupAsMember,
pwszMemberGUID,
pwszMemberPath,
bVerbose,
pwszUser,
pwszPassword );
if (bRetRecurse)
{
bRet = TRUE;
break;
}
pIADsGroupAsMember->Release();
pIADsGroupAsMember = NULL;
}
}
SysFreeString(bstrCurrentPath);
bstrCurrentPath = NULL;
SysFreeString(bstrGuidCurrent);
bstrGuidCurrent = NULL;
}
// Release.
pIDOCurrent->Release();
pIDOCurrent = NULL;
if (pIADsCurrent)
{
pIADsCurrent->Release();
pIADsCurrent = NULL;
}
}
}
// Clear the variant array.
memset(VariantArray, 0, sizeof(VARIANT)*FETCH_NUM);
}
else
fContinue = FALSE;
}
pEnumVariant->Release();
pEnumVariant = NULL;
}
pUnknown->Release();
pUnknown = NULL;
}
pADsMembers ->Release();
pADsMembers = NULL;
}
// Free the group path if retrieved.
if (bsGroupPath)
{
SysFreeString(bsGroupPath);
bsGroupPath = NULL;
}
return bRet;
}
//////////////////////////////////////////////////////////////////////
/* GetObjectGuid() - Gets the GUID, in string form, from
the passed Directory Object.
Returns S_OK on success.
Parameters
IDirectoryObject * pDO - Directory Object from where
GUID is retrieved.
BSTR & bsGuid - Returned GUID
*/
HRESULT GetObjectGuid(IDirectoryObject * pDO,BSTR &bsGuid)
{
GUID *pObjectGUID = NULL;
PADS_ATTR_INFO pAttributeEntries;
// Get the GUID for the object:
LPWSTR pAttributeName = L"objectGUID";
DWORD dwAttributesReturned = 0;
HRESULT hr;
if(!pDO)
{
return E_FAIL;
}
hr = pDO->GetObjectAttributes(&pAttributeName, // objectGUID
1, // Only objectGUID
&pAttributeEntries, // Returned
// attributes
&dwAttributesReturned // Number of
// attributes
// returned
);
if (SUCCEEDED(hr) && dwAttributesReturned>0)
{
// Verify that the right type was retrieved--
// objectGUID is ADSTYPE_OCTET_STRING
if (pAttributeEntries->dwADsType == ADSTYPE_OCTET_STRING)
{
// Get COM converted string version of the GUID
// lpvalue should be LPBYTE. Should be able to
// cast it to pointer to the GUID.
pObjectGUID =
(GUID*)(pAttributeEntries->pADsValues[0].OctetString.lpValue);
// OLE str to fit a GUID
LPOLESTR szGUID = new WCHAR [64];
szGUID[0]=NULL;
// Convert GUID to string.
::StringFromGUID2(*pObjectGUID, szGUID, 39);
bsGuid = SysAllocString(szGUID);
delete [] szGUID;
}
}
return hr;
}
//////////////////////////////////////////////////////////////////
/* PrintBanner() - Prints a banner to the screen.
Parameters
LPOLESTR pwszBanner - String to print
*/
void PrintBanner(LPOLESTR pwszBanner)
{
_putws(L"");
_putws(L"////////////////////////////////////////////////////");
wprintf(L"\t");
_putws(pwszBanner);
_putws(L"////////////////////////////////////////////////////\n");
}