Re: Is this the Right way TO release COM interface ?
What function prototype(s) would you use for an API that can be used to
retrieve a registry value that controls debug logging where non-existance
of
the value is a normal condition? Non-existance of the value must be
distinguished from every possible value. The function will be called
quite
frequently so that a user can control debug output without restarting the
program, so using exceptions is contra-indicated.
RegOpenKeyEx will serve just fine. Note that my version of
RegOpenKeyEx as a COM method would look like this:
enum RegOpenKeyExErrorCode
{
SUCCESSFUL,
KEY_DOES_NOT_EXIST
};
HRESULT RegOpenKeyEx
(
[in] HKEY hKey,
[in] BSTR SubKey,
[in]DWORD ulOptions,
[in] REGSAM samDesired,
[out] PHKEY phkResult,
[out, retval] RegOpenKeyExErrorCode** ErrorCode
);
The error code would then contain any error codes that may be of
interest to the user (IOW the programmer), everything else
(communication failure, insufficient rights, etc.) should be set
inside the HRESULT of the function, indicating some kind of
exceptional execution.
Well this is rather absurd. Of course a COM version of RegOpenKeyEx should
yield a COM interface, not an HKEY. Other parameters would need to have
types adjusted as well, to be Automation-friendly.
But look, you're right back to checking an error code. We need to also add
InsufficientPermission to your enum to meet the requirement of not throwing
exceptions to handle non-exceptional conditions. By this time the HRESULT
is getting nearly useless, so why bother with it at all? Then let's just
rename your RegOpenKeyExErrorCode to HRESULT and...
You also failed to solve the problem. You've broken the request into two
separate steps (open the key, checking for non-existance) and (read the
value within the key). But success in the first is no guarantee of success
in the second, even under a single tasking system, and with Windows there's
a race condition as well.
That is probably where we have different views: In my eyes the HRESULT
should only ever return the following values: S_OK, E_UNEXPECTED (an
exception has occured), or one of those error codes that have to do
with COM as a remoting architecture (for example server has died).
Oh, so you have no use for E_OUTOFMEMORY, E_ACCESSDENIED, or any of the
hundreds of other non-remoting errors that Microsoft had defined? I pity
the user that has to debug a failure with absolutely no information on what
went wrong. Also E_UNEXPECTED isn't the catch all, that's E_FAIL.
E_UNEXPECTED is a run-time assertion failure, the caller messed up by
calling functions out of order or something like that.
Probably you'll say that returning two different error codes (one for
exceptional errors and one for non-exceptional errors) is a waste of
resources. However, I consider this approach as easier to wrap in
other languages (BTW, how does a VB programmer finds out that an
operation returned S_FALSE?).
How does a VB programmer use a RegOpenKeyExErrorCode*?
Regards,
Stuart