ole32: Lock spies list when iterating it.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2019-09-24 15:56:38 +02:00 committed by Alexandre Julliard
parent e95215d08c
commit d449b617e7
2 changed files with 50 additions and 16 deletions

View File

@ -1744,7 +1744,7 @@ static void COM_TlsDestroy(void)
LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &info->spies, struct init_spy, entry)
{
list_remove(&cursor->entry);
IInitializeSpy_Release(cursor->spy);
if (cursor->spy) IInitializeSpy_Release(cursor->spy);
heap_free(cursor);
}
@ -1777,13 +1777,36 @@ static struct init_spy *get_spy_entry(struct oletls *info, unsigned int id)
LIST_FOR_EACH_ENTRY(spy, &info->spies, struct init_spy, entry)
{
if (id == spy->id)
if (id == spy->id && spy->spy)
return spy;
}
return NULL;
}
/*
* When locked, don't modify list (unless we add a new head), so that it's
* safe to iterate it. Freeing of list entries is delayed and done on unlock.
*/
static inline void lock_init_spies(struct oletls *info)
{
info->spies_lock++;
}
static void unlock_init_spies(struct oletls *info)
{
struct init_spy *spy, *next;
if (--info->spies_lock) return;
LIST_FOR_EACH_ENTRY_SAFE(spy, next, &info->spies, struct init_spy, entry)
{
if (spy->spy) continue;
list_remove(&spy->entry);
heap_free(spy);
}
}
/******************************************************************************
* CoRegisterInitializeSpy [OLE32.@]
*
@ -1869,16 +1892,16 @@ HRESULT WINAPI CoRevokeInitializeSpy(ULARGE_INTEGER cookie)
if (!info || cookie.HighPart != GetCurrentThreadId())
return E_INVALIDARG;
if ((spy = get_spy_entry(info, cookie.LowPart)))
{
if (!(spy = get_spy_entry(info, cookie.LowPart))) return E_INVALIDARG;
IInitializeSpy_Release(spy->spy);
spy->spy = NULL;
if (!info->spies_lock)
{
list_remove(&spy->entry);
heap_free(spy);
return S_OK;
}
return E_INVALIDARG;
return S_OK;
}
HRESULT enter_apartment( struct oletls *info, DWORD model )
@ -2000,17 +2023,21 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoInitializeEx(LPVOID lpReserved, DWORD dwCoIni
RunningObjectTableImpl_Initialize();
}
lock_init_spies(info);
LIST_FOR_EACH_ENTRY(cursor, &info->spies, struct init_spy, entry)
{
IInitializeSpy_PreInitialize(cursor->spy, dwCoInit, info->inits);
if (cursor->spy) IInitializeSpy_PreInitialize(cursor->spy, dwCoInit, info->inits);
}
unlock_init_spies(info);
hr = enter_apartment( info, dwCoInit );
lock_init_spies(info);
LIST_FOR_EACH_ENTRY(cursor, &info->spies, struct init_spy, entry)
{
hr = IInitializeSpy_PostInitialize(cursor->spy, hr, dwCoInit, info->inits);
if (cursor->spy) hr = IInitializeSpy_PostInitialize(cursor->spy, hr, dwCoInit, info->inits);
}
unlock_init_spies(info);
return hr;
}
@ -2034,7 +2061,7 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoInitializeEx(LPVOID lpReserved, DWORD dwCoIni
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
{
struct oletls * info = COM_CurrentInfo();
struct init_spy *cursor;
struct init_spy *cursor, *next;
LONG lCOMRefCnt;
TRACE("()\n");
@ -2042,20 +2069,24 @@ void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
/* will only happen on OOM */
if (!info) return;
LIST_FOR_EACH_ENTRY(cursor, &info->spies, struct init_spy, entry)
lock_init_spies(info);
LIST_FOR_EACH_ENTRY_SAFE(cursor, next, &info->spies, struct init_spy, entry)
{
IInitializeSpy_PreUninitialize(cursor->spy, info->inits);
if (cursor->spy) IInitializeSpy_PreUninitialize(cursor->spy, info->inits);
}
unlock_init_spies(info);
/* sanity check */
if (!info->inits)
{
ERR("Mismatched CoUninitialize\n");
LIST_FOR_EACH_ENTRY(cursor, &info->spies, struct init_spy, entry)
lock_init_spies(info);
LIST_FOR_EACH_ENTRY_SAFE(cursor, next, &info->spies, struct init_spy, entry)
{
IInitializeSpy_PostUninitialize(cursor->spy, info->inits);
if (cursor->spy) IInitializeSpy_PostUninitialize(cursor->spy, info->inits);
}
unlock_init_spies(info);
return;
}
@ -2080,10 +2111,12 @@ void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
InterlockedExchangeAdd(&s_COMLockCount,1); /* restore the lock count. */
}
lock_init_spies(info);
LIST_FOR_EACH_ENTRY(cursor, &info->spies, struct init_spy, entry)
{
IInitializeSpy_PostUninitialize(cursor->spy, info->inits);
if (cursor->spy) IInitializeSpy_PostUninitialize(cursor->spy, info->inits);
}
unlock_init_spies(info);
}
/******************************************************************************

View File

@ -179,6 +179,7 @@ struct oletls
DWORD unknown2[46];
IUnknown *cancel_object; /* cancel object set by CoSetCancelObject (+F8h on x86) */
struct list spies; /* Spies installed with CoRegisterInitializeSpy */
DWORD spies_lock;
};