When using CComPtr or CComQIPtr, one would normally not call Release() at all. That's what smart pointers are for -- they do the reference counting for you. i.e. When the smart pointer object goes out of scope, its destructor would be invoked which would call Release() on the interface pointer for you.

However, if you really do want to invoke Release() yourself, then version 1 would be fine i.e. sp.Release() that calls the Release() member funtion of the smart pointer class, thereby giving it an opportunity to clear up it's internal raw pointer state after invoking Release() on the same.