Today, find_proxy_manager() may return a proxy manager that is about to
be freed. This happens when the proxy manager's reference count reaches
zero, but proxy_manager_destroy() has not removed the proxy manager from
the apartment proxy list.
Fix this by only incrementing the reference count if it was nonzero. If
the reference count is zero, proxy_manager_destroy() will proceed to
destroy the proxy manager after the current thread releases the
apartment lock (apt->cs).
Granted, this is fragile and far from elegant, but it seems like a safe approach for the time being. Also, the critical section and "safe" refcount increment will prevent the following race condition scenario:
> 1. Thread X: A proxy manager's refcount reaches 0 and is about to be released.
> 2. Thread Y tries to grab it, calls AddRef, notices it returns 1, and drops it.
> 3. Thread Z tries to grab it, calls AddRef, notices it returns 2, and returns it.
> 4. Thread X then proceeds to remove it from the list and free the object.
--
v4: combase: Prevent use-after-free due to a race with proxy_manager_destroy.
https://gitlab.winehq.org/wine/wine/-/merge_requests/2752