If you code in C/C++ without using any wrapper stuff, then both out and retval would have the same effect.
If you generate wrappers or use other langages, then one argument would become the return vale of the function.
HRESULT Test([out, retval] int *rv) { ... }
would become
int Test() { ... }
and throw an exception in case of an error (negative HRESULT).