+1  A: 

You already got a proxy on thread A since you asked for an out-of-process server. What happens next depends on the kind of apartment that thread A lives in, the argument to CoInitializeEx(). If it is MTA you will definitely get the same proxy in thread B, assuming it is MTA as well. The added reference count should keep it alive if Thread A exits. If it is STA then I'm not 100% sure but think you ought to get a new one. Easy to test btw, just use the one from thread A and you'll get RPC_E_WRONGTHREAD if a new one would have to be created.

I don't have a great explanation for why the thread A exit kills the proxy for thread B. Unless you call IGlobalInterfaceTable::RevokeInterfaceFromGlobal(). Which you'd normally do.

Hans Passant
Both threads are STA. Also, I don't call RevokeInterfaceFromGlobal. GetInterfaceFromGlobal just returns E_INVALIDARG when I call it after thread A ended.
Fozi
Very unusual. Where are you calling RevokeInterfaceFromGlobal?
Hans Passant
I have a reference counted object that handles the cookie. When all references are gone, it gets revoked. The cookies are kept in a pool and released at exit.
Fozi
Sounds okayish but dangerous. What references are you actually counting? Do you count up for each GetInterfaceFromGlobal and down when that returned pointer gets counted down to zero by Release() calls? Sounds very hard to do, you can't override the Release method easily. I smell a problem, set a break on the Revoke call.
Hans Passant
No, the cookie holder object itself is guarded by a smart pointer. When it gets deleted the cookie is revoked. The cookie holder is also the class that requests the interface.
Fozi