Commit 327100fe authored by Huw Davies's avatar Huw Davies Committed by Alexandre Julliard

ole32: Don't block inside CoDisconnectObject.

This may be called inside a COM call to the object. Signed-off-by: 's avatarHuw Davies <huw@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent 35571a72
......@@ -2042,6 +2042,7 @@ HRESULT WINAPI CoDisconnectObject( LPUNKNOWN lpUnk, DWORD reserved )
manager = get_stub_manager_from_object(apt, lpUnk, FALSE);
if (manager) {
stub_manager_disconnect(manager);
/* Release stub manager twice, to remove the apartment reference. */
stub_manager_int_release(manager);
stub_manager_int_release(manager);
......
......@@ -107,6 +107,7 @@ struct stub_manager
*/
ULONG norm_refs; /* refcount of normal marshals (CS lock) */
BOOL disconnected; /* CoDisconnectObject has been called (CS lock) */
};
/* imported interface proxy */
......@@ -195,6 +196,7 @@ struct stub_manager *get_stub_manager_from_object(APARTMENT *apt, IUnknown *obje
BOOL stub_manager_notify_unmarshal(struct stub_manager *m, const IPID *ipid) DECLSPEC_HIDDEN;
BOOL stub_manager_is_table_marshaled(struct stub_manager *m, const IPID *ipid) DECLSPEC_HIDDEN;
void stub_manager_release_marshal_data(struct stub_manager *m, ULONG refs, const IPID *ipid, BOOL tableweak) DECLSPEC_HIDDEN;
void stub_manager_disconnect(struct stub_manager *m) DECLSPEC_HIDDEN;
HRESULT ipid_get_dispatch_params(const IPID *ipid, APARTMENT **stub_apt, struct stub_manager **manager, IRpcStubBuffer **stub,
IRpcChannelBuffer **chan, IID *iid, IUnknown **iface) DECLSPEC_HIDDEN;
HRESULT start_apartment_remote_unknown(void) DECLSPEC_HIDDEN;
......@@ -213,7 +215,7 @@ HRESULT RPC_CreateClientChannel(const OXID *oxid, const IPID *ipid,
HRESULT RPC_CreateServerChannel(DWORD dest_context, void *dest_context_data, IRpcChannelBuffer **chan) DECLSPEC_HIDDEN;
void RPC_ExecuteCall(struct dispatch_params *params) DECLSPEC_HIDDEN;
HRESULT RPC_RegisterInterface(REFIID riid) DECLSPEC_HIDDEN;
void RPC_UnregisterInterface(REFIID riid) DECLSPEC_HIDDEN;
void RPC_UnregisterInterface(REFIID riid, BOOL wait) DECLSPEC_HIDDEN;
HRESULT RPC_StartLocalServer(REFCLSID clsid, IStream *stream, BOOL multi_use, void **registration) DECLSPEC_HIDDEN;
void RPC_StopLocalServer(void *registration) DECLSPEC_HIDDEN;
HRESULT RPC_GetLocalClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv) DECLSPEC_HIDDEN;
......
......@@ -1581,7 +1581,7 @@ HRESULT RPC_RegisterInterface(REFIID riid)
}
/* stub unregistration */
void RPC_UnregisterInterface(REFIID riid)
void RPC_UnregisterInterface(REFIID riid, BOOL wait)
{
struct registered_if *rif;
EnterCriticalSection(&csRegIf);
......@@ -1591,7 +1591,7 @@ void RPC_UnregisterInterface(REFIID riid)
{
if (!--rif->refs)
{
RpcServerUnregisterIf((RPC_IF_HANDLE)&rif->If, NULL, TRUE);
RpcServerUnregisterIf((RPC_IF_HANDLE)&rif->If, NULL, wait);
list_remove(&rif->entry);
HeapFree(GetProcessHeap(), 0, rif);
}
......
......@@ -123,7 +123,8 @@ static void stub_manager_delete_ifstub(struct stub_manager *m, struct ifstub *if
list_remove(&ifstub->entry);
RPC_UnregisterInterface(&ifstub->iid);
if (!m->disconnected)
RPC_UnregisterInterface(&ifstub->iid, TRUE);
if (ifstub->stubbuffer) IRpcStubBuffer_Release(ifstub->stubbuffer);
IUnknown_Release(ifstub->iface);
......@@ -223,6 +224,7 @@ static struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object)
* the marshalled ifptr.
*/
sm->extrefs = 0;
sm->disconnected = FALSE;
hres = IUnknown_QueryInterface(object, &IID_IExternalConnection, (void**)&sm->extern_conn);
if(FAILED(hres))
......@@ -238,6 +240,21 @@ static struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object)
return sm;
}
void stub_manager_disconnect(struct stub_manager *m)
{
struct ifstub *ifstub;
EnterCriticalSection(&m->lock);
if (!m->disconnected)
{
LIST_FOR_EACH_ENTRY(ifstub, &m->ifstubs, struct ifstub, entry)
RPC_UnregisterInterface(&ifstub->iid, FALSE);
m->disconnected = TRUE;
}
LeaveCriticalSection(&m->lock);
}
/* caller must remove stub manager from apartment prior to calling this function */
static void stub_manager_delete(struct stub_manager *m)
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment