In a multi-threaded c++ project (working on Windows 11 and Visual Studio 2019), I open an IStream COM object in a dedicated thread, let's naming it Thread A, with the following code:
...
::CComPtr<IStream> pStreamThreadA;
HRESULT hr = pShellItem->BindToHandler(nullptr, BHID_Stream, IID_IStream, (void**)&pStreamThreadA);
...
Once opened, I want to read its content in a second thread, let's naming it Thread B. As it's a COM object, I'm aware that it's hazardous to try to use it in the Thread B while it was created in the Thread A. For that reason I Marshall it with the following code:
In Thread A:
...
const HRESULT hr = ::CoMarshalInterThreadInterfaceInStream(IID_IStream, pStreamThreadA, &m_pMarshall);
...
In Thread B:
...
::CComPtr<IStream> pStreamThreadB;
const HRESULT hr = ::CoGetInterfaceAndReleaseStream(m_pMarshall, IID_IStream, (void**)&pStreamThreadB);
m_pMarshall.Release();
...
But this doesn't work. When I try to seek in my stream in the Thread B, e.g. with the following code:
...
const LARGE_INTEGER zero = {0};
ULARGE_INTEGER pos;
const HRESULT hr = pStreamThreadB->Seek(zero, ::STREAM_SEEK_CUR, &pos);
...
the code execution get stuck in the Seek() function and never returns. For that reason I assume that the stream pointer became invalid (i.e dangling).
On the other hand, and paradoxically, if I bypass the Marshaling code above and I use the stream pointer directly between the threads, barely respecting the usual lock mechanisms, all work fine. But I'm aware that this is very unsafe and not recommended.
So can someone explain me what I'm doing wrong in the above code, and why my Marshaled stream lead to an invalid pointer?