Gotcha: You must release property stores quickly

The general rule is that you should minimize the length of time you have a property store open.  It is best to acquire the data you need and then release the store.

Read-only property stores lock files for reading using a filesystem oplock.  An oplock does more than just lock a file -- it blocks writers until the reader releases the lock.  This way a short-lived read operation simply delays a write instead of causing it to fail outright. 

Now the gotcha is that the following code will deadlock:

IShellItem2 *psi = ...
IPropertyStore *ppsReadOnly;
psi->GetPropertyStore(GPS_DEFAULT, IID_PPV_ARGS(&ppsReadOnly));

IPropertyStore *ppsReadWrite;
psi->GetPropertyStore(GPS_READWRITE, IID_PPV_ARGS(&ppsReadWrite));

ppsReadWrite->Release();
ppsReadOnly->Release();

The first call to GetPropertyStore creates the oplock.  Any writers will block until it is released.  Thus the second call to GetPropertyStore blocks.  But the reader won't get released until the call completes. 

You might ask why was this feature added if it has such a big gotcha?  There are several reasons.  First, locking a file for reading is an important feature for the code reading the file.  We have to lock the file to prevent the data from changing while someone is reading it.  Second, since we lock the file anyway, callers should never have the file open long-term anyway.  Third, we discovered in testing that Windows often tried to read from a file just around the same time as it wanted to write to a file.  This led to error dialogs.  Using an oplock eliminates these error dialogs by waiting until the short-lived reader is finished.

-Ben Karas