Last time we saw how to bind to a shell item and get its property store.  Today, we loop through the store printing out known properties.

HRESULT _PrintPropertyStore(IPropertyStore *pps)
{
    DWORD cProps;
    HRESULT hr = pps->GetCount(&cProps);
    for (DWORD i = 0; SUCCEEDED(hr) && i < cProps; i++)
    {
        PROPERTYKEY key;
        hr = pps->GetAt(i, &key);
        if (SUCCEEDED(hr))
        {
            PROPVARIANT propvar = {0};
            hr = pps->GetValue(key, &propvar);
            if (SUCCEEDED(hr))
            {
                hr = _PrintPropertyValue(key, propvar);
                PropVariantClear(&propvar);
            }
        }
    }
    return hr;
}

This loop is fairly simple.  I wrote this to break out of the loop if it sees an error.  Ideally I shoud print a warning in this case, but I'm lazy and I have a debugger.  Also notice that I clean up my PROPVARIANT.

In general, property stores provide access to properties in two ways:

  1. You can ask the store for the list of property keys it supports.  This is what I've done above.
  2. You can ask the store for the value of a particular property key. 

Note that #2 doesn't have to be a key returned in #1.  The enumeration of keys from a property store usually includes all the properties the store knows about.  But sometimes there are keys the store doesn't realize it supports.  Other times there are keys you want to let callers ask for directly, but there isn't any benefit to enumerating.  This isn't usually an important distinction, but it's something to keep in mind if you ever implement a property store.