There's one last topic I want to touch on before I close this series: Canonical values. So far I've talked about how to determine when the property itself is writable. But once you decide to write a property, how do you figure out what type the value should be? What if you get it wrong?
The first edition of the property system didn't enforce the type of values. As a result, some people used VT_UI4, others VT_I2, and some just used strings for the same property. This led to complicated error-prone code. So we decided to add an enforcement layer that makes sure the value complies with the type specified by the property description and performs some minor cleanup when possible. We dubbed this the "coercion" layer.
To cut to the chase, this layer uses IPropertyDescription::IsCanonicalValue and IPropertyDescription::CoerceToCanonicalValue to enforce the type requirements. So if you are creating a program that writes properties, you might want to add some debug code to see if your values pass the test and to see how they get interpreted by the coercion layer.
Here's a quick summary of what happens in IPropertyDescription::CoerceToCanonicalValue:
- Convert "empty" values to VT_EMPTY. This includes VT_NULL, null pointers, and strings with just spaces.
- Convert the value to the type given by IPropertyDescription::GetPropertyType
- Convert the result to a canonical form (remove leading/trailing spaces, removing duplicates from vectors, etc)
MSDN will eventually get expanded documentation on this function, but you should be able to figure out what's happening through experimentation too.
As a final note, a property handler can decide it doesn't like a value and either reject or truncate it. Unfortunately, it won't tell you why -- it just returns and error or INPLACE_S_TRUNCATED to indicate when this happened.