How should I check that [out] params in COM can be used?
-
03-07-2019 - |
Question
Officially one should not use [out]
parameters from COM functions unless the function succeeded this means that there are (at least) three ways to see if an [out]
parameter can be used.
Consider the following interface
interface IFoo : IUnknown {
HRESULT GetOtherFoo([out] IFoo** ppFoo);
HRESULT Bar();
};
Which of the following ways would you recommend on using it?
1. Check return value
CComPtr<IFoo> other;
HRESULT hr = foo->GetOtherFoo(&other);
if (SUCCEEDED(hr))
other->Bar();
This makes me a bit nervous since a bug in IFoo
could cause a NULL
pointer dereferencing.
2. Check the output parameter
This depends on the fact that if a method fails it mustn't change any of the [out]
parameters (if the parameter changed <==> it's safe to use it).
CComPtr<IFoo> other;
foo->GetOtherFoo(&other);
if (other)
other->Bar();
Note that this sort of happens anyway, CComPtr
's destructor will call Release
if the pointer isn't NULL
so it can't be garbage.
3. The paranoid way, check both
CComPtr<IFoo> other;
HRESULT hr = foo->GetOtherFoo(&other);
if (SUCCEEDED(hr) && other)
other->Bar();
This is a bit verbose in my opinion.
P.S. See related question.
Solution
If you are willing to write more checks and make code a bit slower for making it more reliable option 3 is for you. Since you expect that there are bugs in the COM server it is quite reasonable to check against them.
OTHER TIPS
COM server methods that return a success HRESULT, yet set some of their output parameters to NULL are not very common. There are a few cases (IClientSecurity::QueryBlanket comes to mind) where this is used, but usually the client may expect all output parameters to be non-NULL if the method returned successfully.
It is, after all, a matter of how the method is documented. In the default case, however, I would consider 1. to be a safe way to go.