Tuesday, November 24, 2009

What Is PKEY_ThumbnailCacheId

In Vista and newer Windows operating systems you can implement a IPropertyStore interface for your Shell Namespace Extensions.  One of the things that is asked of your items is what is their PKEY_ThumbnailCacheId.  The PKEY_ThumbnailCacheId is used to determine if the Thumbnail image can be used from the thumbnail cache or if it has to be regenerated by the Shell.  There is no documentation about: PKEY_ThumbnailCacheId.  However in the propkey.h file in the Windows SDK it states:


// Unique value that can be used as a key to cache thumbnails.
// The value changes when the name, volume, or data modified
// of an item changes.


However, the return value of IPropertyStore::GetValue is a PROPVARIANT, which is much like a VARIANT, it can be almost anything.  So what does the shell expect you to return from the GetValue method when it asks for PKEY_ThumbnailCacheId?  A hint can be found in the definition of IThumbnailCache::GetThumbnailByID method.  The unique identifier comes in as a type of WTS_THUMBNAILID – equal to BYTE rgbKey[ 16 ].


So a good key would be an array of bytes with a length of 16.  Where do we get that from?  Well it just so happens that in propvarutil.h there is a function called: InitPropVariantFromGUIDAsBuffer which takes a GUID and creates a byte array with the length of 16.  Since sizeof(GUID) is equal to 16.

So if you use InitPropVariantFromGUIDAsBuffer() method to set the PROPVARIANT in the IPropertyStore::GetValue call with a unique GUID for your shell item everything will work as expected.   


Make sure you change the GUID every time the image changes, otherwise you might be showing a thumbnail with old data.

By the way, 16 bytes is also what is returned from an MD5 hash of a byte array.


Thursday, November 19, 2009

IShellFolderViewCB Is Not Optional

When writing a Shell Namespace Extension with DefView it is important to realize that IShellFolderViewCB is not optional for proper updates of the DefView.

If you construct your DefView like this:

::SHCreateShellFolderView(pcsfv, (IShellView **)ppvReturn);

One of the parameters of SFV_CREATE is psfvcb which points to an instance of IShellFolderViewCB.  IShellFolderViewCB is a callback interface that you can use to get notified of what is happening in the DefView.

If you don’t care what DefView is doing it is tempting to leave it NULL.  However, if you do this the DefView will not update correctly on calls like this:


So always implement a IShellFolderViewCB interface with the minimum functionality when using the DefView.