Here are the rules that we follow for using BSTRs:

1) It is the callee's responsibility to SysAlloc() a new copy if they want to store it internally
2) It is the callee's responsibility to SysAlloc() to return a copy of an internally stored BSTR
3) It is the caller's responsibility to SysFree() a BSTR that was returned from a call
4) Don't have BSTR parameters be [in, out] (This really gets confusing) only declare them [in] or [out, retval]

To make this easier, we use the _bstr_t smart BSTR class - It will automatically SysFree() when it goes out of scope, and SysAlloc()'s and SysFree()'s during assignment if necessary. Here is some samples.

Assume the following in the ATL server class:
private:
bstr_t mbstrtInternal1;
bstr_t mbstrtInternal2;

Also assume 2 methods
PassIn - takes a BSTR and stores it
PassOut - Returns an internal BSTR

// Server code
PassIn(BSTR bstrVal)
{
// Make sure something passed in (Optional)
if (bstrVal == NULL || SysStringLen(bstrVal) == 0) {
return E_INVALIDARG;
}

// Make copy of passed in BSTR (bstr_t autmatically does this)
mbstrtInternal1 = bstrVal;

return S_OK;
}

PassOut(BSTR *pbstrVal)
{
// Validate that a pointer was passed in
if (pbstrVal == NULL) {
return E_POINTER;
}

*pbstrVal = mbstrtInternal2.copy();
}

// Client Code

...
bstr_t bstrtString;
BSTR bstrOut;
IObj *pObj;
HRESULT hr;

CoCreateInstance(..., &pObj);

bstrtString = L"Chad Yost";

hr = pObj->PassIn(bstrtString);
hr = pObj->PassOut(&bstrOut);
bstrtString = bstr_t(bstrOut, false);

...