Beispielcode für die Überprüfung auf Mitgliedschaft in einer Gruppe

Im folgenden Codebeispiel wird die absolute Mitgliedschaft eines Objekts überprüft, indem rekursiv überprüft wird, ob ein Objekt Mitglied einer Gruppe oder einer gruppe ist, die in dieser Gruppe geschachtelt ist.

/////////////////////////////////////////////////////////////////////
/*  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");
}