Search code examples
c++cc++11active-directory

Unable to print all property's name of an Active Directory object


I am trying to print the names of all the properties of an Active Directory object using the below code:


HRESULT ActiveDirectoryWrapper::PrintAllProperties(IADs *pADs) {
    IADsPropertyList *pPList = NULL;
    // Getting info of object
    pADs->GetInfo();
    HRESULT hr = pADs->QueryInterface(IID_IADsPropertyList, (void**)&pPList);

    if (SUCCEEDED(hr))
    {
        // Get the number of properties in the object
        LONG lCount = 0;
        hr = pPList->get_PropertyCount(&lCount);

        if (SUCCEEDED(hr))
        {
            // Iterate over the object's properties and print their names and values
            for (LONG i = 0; i < lCount; i++)
            {
                // Retrieve the property name
                VARIANT propertyName;
                VariantInit(&propertyName);
                propertyName.vt = VT_EMPTY;
                hr = pPList->Next(&propertyName);

                printf("\tProperty name: %S\n", propertyName.bstrVal);
            }
        }
    }

    // Clean up
    pPList->Release();
    return hr;
}

Currently, the problem I am facing is it's able to loop through all the properties but it's printing the property name empty.

For e.g.

Let's suppose there are 4 properties for an IADs object, so it will print Property name: Property name: Property name: Property name:

It tried to print the Property name as V_BSTR(&propertyName) but still the results were the same.

Any help would be appreciated.


Solution

  • The documentation for IADsPropertyList::Next describes the out value like this:

    [out] pVariant

    Address of a caller-allocated variable that contains the value of the next item in the property list. The return value of VT_DISPATCH refers to an IDispatch interface pointer to an object implementing the IADsPropertyEntry interface.

    The key words being "return value of VT_DISPATCH". So you need to call V_DISPATCH(&propertyName) to be able to use the object. But then you still need to call QueryInterface() on it to be able to use it as an IADsPropertyEntry object.

    The documentation for IADsPropertyEntry Property Methods has a C++ example of printing a property name. Using that, your code should look something like this:

    HRESULT ActiveDirectoryWrapper::PrintAllProperties(IADs *pADs) {
        IADsPropertyList *pPList = NULL;
        // Getting info of object
        pADs->GetInfo();
        HRESULT hr = pADs->QueryInterface(IID_IADsPropertyList, (void**)&pPList);
    
        if (SUCCEEDED(hr))
        {
            // Get the number of properties in the object
            LONG lCount = 0;
            hr = pPList->get_PropertyCount(&lCount);
    
            if (SUCCEEDED(hr))
            {
                // Iterate over the object's properties and print their names and values
                for (LONG i = 0; i < lCount; i++)
                {
                    // Retrieve the property name
                    VARIANT propertyName;
                    VariantInit(&propertyName);
                    hr = pPList->Next(&propertyName);
                    
                    IADsPropertyEntry *pEntry = NULL;
                    hr = V_DISPATCH(&propertyName)->QueryInterface(IID_IADsPropertyEntry,
                                          (void**)&pEntry);
                                          
                    BSTR nm = NULL;
                    hr = pEntry->get_Name(&nm);
    
                    printf("\tProperty name: %S\n", nm);
                    
                    VariantClear(&propertyName);
                    pEntry->Release();
                }
            }
        }
    
        // Clean up
        pPList->Release();
        return hr;
    }
    

    For simplicity I didn't check the value of hr, but you may want to for the sake of being safe.