Monday, March 10, 2008

The Danger of 'Special' Values

When defining the meaning of a data field, it can be tempting to specify certain values that the field may hold as special. Those values would signify a different meaning than all other values.

A great example of this is in the Windows Installer API, where the docs for MsiRecordSetInteger state "To set a record integer field to NULL_INTEGER, set iValue to MSI_NULL_INTEGER".

So the MSI_NULL_INTEGER constant:
#define MSI_NULL_INTEGER 0x80000000
has a different meaning than any other integer.

There can be good reasons for doing this. The Windows Installer team probably made a special value for NULL to obviate the need for every field in the msi database to have a boolean attached to it specifying whether the field is null or not. Obviously there is a large space saving advantage here.

But the dangers of doing this are obvious. What if someone wants to store 0x80000000 and not have it considered as a null value? This is exactly the reason why the docs for the LockPermissions table declares:
"You cannot specify GENERIC_READ in the Permission column. Attempting to do so will fail. Instead, you must specify a value such as KEY_READ or FILE_GENERIC_READ."

It just so happens that the value of the GENERIC_READ constant is, you guessed it, 0x80000000. Ouch.

So, while the docs are technically correct, it is worth noting that you can use GENERIC_READ, as long as it is combined with another bit flag. This is the reason that InstEd has included GenericRead in it's Permissions column bit flag editor.

InstEd Permission bit flag editor

No comments: