Geoff Chappell - Software Analyst
This function decrements a global counter.
LONG SHGlobalCounterDecrement (HANDLE hCounter);
The hCounter argument provides a handle to the global counter, as obtained through some earlier call to either SHGlobalCounterCreate or SHGlobalCounterCreateNamed.
The function returns the value that the counter got decremented to.
The global counter is implemented as the release count in a semaphore. The SHGlobalCounterDecrement function is in essence a call to WaitForSingleObject with no timeout, so that the release count is decremented without putting the current thread into a wait state.
For most practical purposes, this function is just like the standard API function InterlockedDecrement except that the 32-bit variable to act on is specified indirectly through a handle instead of directly through an address.
That said, there are two significant differences in behaviour from InterlockedDecrement. The first, and much the more likely to matter in practice, arises because the release count of a semaphore cannot be negative. If the counter is zero, then this function cannot decrement it. The function returns minus one, as if having decremented from zero, but the counter remains at zero.
Another significant difference arises because the function must return the decremented counter yet WaitForSingleObject does not reveal what value the release count had before or after the decrement. To get round this, the function actually implements the decrement as three operations on the release count:
and then returns one less than the pre-incremented value. One problem with this algorithm is that if the counter is already at MAXLONG (which, admittedly, is very unlikely in practice), then the function cannot increment the release count at step 1. As coded, the function proceeds with steps 2 and 3, and ends up decrementing the counter by two. Then, it returns minus one.
The SHGlobalCounterDecrement function is exported from SHLWAPI as ordinal 424 in version 5.00 and higher.
Though this function dates from as long ago as 1999, it was still not documented by Microsoft in the MSDN Library at least as late as the CD edition dated January 2004.