Thread overview
Registry API: Null values
Sep 14, 2003
Matthew Wilson
Sep 14, 2003
Matthew Wilson
Sep 14, 2003
Patrick Down
Sep 14, 2003
Matthew Wilson
Sep 15, 2003
Matthew Wilson
Sep 14, 2003
Andy Friesen
September 14, 2003
Am interested in everyone's thoughts about how to handle keys without
values, ie. what to return when calling get_Value(NULL) or get_Value("") for
keys that do not have a value.

The options are:

1. Return a null reference for the Value
2. Return a Value whose name is null, and whose type is REG_NONE (0).
3. Return a Value whose name is the empty string, and whose type is REG_NONE
(0).
4. Throw an exception.

I'm not keen on throwing an exception, not really on having nulls around the place, so it's currently option 3. I can't say I'm in love with it, but it seems to me to be the best, since it is definitive (Value.get_Type() returns REG_NONE) and non-null-weilding (so it's harmless to pass the "name" to things expecting a non-null string).

Thoughts appreciated.

Matthew

P.S. Walter, still hanging out for those properties ...


September 14, 2003
Hmm, how about

5. Key.get_Value() returns a Value, which returns REG_NONE for
Value.get_Type(), but throws an exception if any of the get_Value_DWORD(),
get_Value_MULTI_SZ() etc. methods are called.

I think that's probably the best. (Still interested in all your opinions
though, :) )

Matthew


"Matthew Wilson" <matthew@stlsoft.org> wrote in message news:bk0udu$b38$1@digitaldaemon.com...
> Am interested in everyone's thoughts about how to handle keys without
> values, ie. what to return when calling get_Value(NULL) or get_Value("")
for
> keys that do not have a value.
>
> The options are:
>
> 1. Return a null reference for the Value
> 2. Return a Value whose name is null, and whose type is REG_NONE (0).
> 3. Return a Value whose name is the empty string, and whose type is
REG_NONE
> (0).
> 4. Throw an exception.
>
> I'm not keen on throwing an exception, not really on having nulls around
the
> place, so it's currently option 3. I can't say I'm in love with it, but it
> seems to me to be the best, since it is definitive (Value.get_Type()
returns
> REG_NONE) and non-null-weilding (so it's harmless to pass the "name" to
> things expecting a non-null string).
>
> Thoughts appreciated.
>
> Matthew
>
> P.S. Walter, still hanging out for those properties ...
>
>


September 14, 2003
Matthew Wilson wrote:

> Am interested in everyone's thoughts about how to handle keys without
> values, ie. what to return when calling get_Value(NULL) or get_Value("") for
> keys that do not have a value.
> 
> The options are:
> 
> 1. Return a null reference for the Value
> 2. Return a Value whose name is null, and whose type is REG_NONE (0).
> 3. Return a Value whose name is the empty string, and whose type is REG_NONE
> (0).
> 4. Throw an exception.

Python dictionaries offer all of the above.  The [] operator raises a ValueError if the key does not exist, and the get(keyName, default) method will return the default should the key not exist. (such as null)

This does mean more methods that do nearly the same thing, but I find that the extra bit of sugar really does make the interface a lot easier to work with.

 -- andy

September 14, 2003
"Matthew Wilson" <matthew@stlsoft.org> wrote in news:bk0unb$bcj$1@digitaldaemon.com:

> Hmm, how about
> 
> 5. Key.get_Value() returns a Value, which returns REG_NONE for
> Value.get_Type(), but throws an exception if any of the
> get_Value_DWORD(), get_Value_MULTI_SZ() etc. methods are called.
> 
> I think that's probably the best. (Still interested in all your
> opinions though, :) )

I like this one too.  What do you do when some asks for DWORD and the actual type is string?
September 14, 2003
I throw a RegistryException, as in:


private void Key_QueryValue(in HKEY hkey, in char[] name, out uint value,
out REG_VALUE_TYPE type)
{
//printf("Key_QueryValue(uint)\n");

    DWORD   cbData  =   value.size;
    LONG    res     =   RegQueryValueExA(hkey, name, (Reserved)0, type,
&value, cbData);

    if(0 != res)
    {
        throw new RegistryException("Cannot read the requested value", res);
    }
    else
    {
        switch(type)
        {
            default:
                throw new RegistryException("Cannot read the given value as
a 32-bit integer");
                break;
version(LittleEndian)
{
            case    REG_VALUE_TYPE.REG_DWORD_LITTLE_ENDIAN:
                assert(REG_VALUE_TYPE.REG_DWORD ==
REG_VALUE_TYPE.REG_DWORD_LITTLE_ENDIAN);
                break;
            case    REG_VALUE_TYPE.REG_DWORD_BIG_ENDIAN:
} // version(LittleEndian)
version(BigEndian)
{
            case    REG_VALUE_TYPE.REG_DWORD_BIG_ENDIAN:
                assert(REG_VALUE_TYPE.REG_DWORD ==
REG_VALUE_TYPE.REG_DWORD_BIG_ENDIAN);
                break;
            case    REG_VALUE_TYPE.REG_DWORD_LITTLE_ENDIAN:
} // version(BigEndian)
                value = swap(value);
                break;
        }
    }
}

class Value
{
    . . .

    uint get_Value_DWORD()
    {
        REG_VALUE_TYPE  type;
        uint            value;

        Key_QueryValue(m_key.m_hkey, m_name, value, type);

        if(type != m_type)
        {
            throw new RegistryException("Value type has been changed since
the value was acquired");
        }

        return value;
    }

However, the same is not true in the other direction. If the type is convertible to a string form, then that is done (swapping around the endian-ness as necessary). Hence the types that are implicitly converted to string are REG_SZ, REG_EXPAND_SZ, REG_DWORD*, REG_QWORD*. REG_BINARY and REG_MULTI_SZ are not converted, and an exception is thrown.

REG_RESOURCE_LIST, REG_FULL_RESOURCE_DESCRIPTOR and REG_RESOURCE_REQUIREMENTS_LIST are not supported in any form at this time.

Note that "Value" instances contain name, Key reference and type. Hence, when a Value's value is acquired, it is conceivable that another process may have deleted the existing value and created another with a different type. Hence, the get_Value_*() methods throw an exception if that's happened. It's not perfect, of course, but since client code is going to be wanting to dispatch on type - Value.get_Type() - we need to catch the possible external breaking changes. The alternative is to just know nothing about a type, and get its type each time get_Type() is called. If anyone's got any firm opinions either way, this'd be a good time to hear them. :)

Matthew


"Patrick Down" <pat@codemoon.com> wrote in message news:Xns93F662E5C3ACEpatcodemooncom@63.105.9.61...
> "Matthew Wilson" <matthew@stlsoft.org> wrote in news:bk0unb$bcj$1@digitaldaemon.com:
>
> > Hmm, how about
> >
> > 5. Key.get_Value() returns a Value, which returns REG_NONE for
> > Value.get_Type(), but throws an exception if any of the
> > get_Value_DWORD(), get_Value_MULTI_SZ() etc. methods are called.
> >
> > I think that's probably the best. (Still interested in all your
> > opinions though, :) )
>
> I like this one too.  What do you do when some asks for DWORD and the actual type is string?


September 15, 2003
"Matthew Wilson" <matthew@stlsoft.org> ha scritto nel messaggio news:bk0unb$bcj$1@digitaldaemon.com...
> Hmm, how about
>
> 5. Key.get_Value() returns a Value, which returns REG_NONE for
> Value.get_Type(), but throws an exception if any of the get_Value_DWORD(),
> get_Value_MULTI_SZ() etc. methods are called.
>
> I think that's probably the best. (Still interested in all your opinions
> though, :) )

Perfectly consistent, no nulls hanging around, and doesn't throw exceptions unless needed. Go for it!

Ric


September 15, 2003
Am glad you like. The first version - read-only/enumeration - is just about ready. I am hoping to deploy in the next few hours.

:)

"Riccardo De Agostini" <riccardo.de.agostini@email.it> wrote in message news:bk429e$1gi5$12@digitaldaemon.com...
> "Matthew Wilson" <matthew@stlsoft.org> ha scritto nel messaggio news:bk0unb$bcj$1@digitaldaemon.com...
> > Hmm, how about
> >
> > 5. Key.get_Value() returns a Value, which returns REG_NONE for
> > Value.get_Type(), but throws an exception if any of the
get_Value_DWORD(),
> > get_Value_MULTI_SZ() etc. methods are called.
> >
> > I think that's probably the best. (Still interested in all your opinions
> > though, :) )
>
> Perfectly consistent, no nulls hanging around, and doesn't throw
exceptions
> unless needed. Go for it!
>
> Ric
>
>