Commit eebf8df6 authored by Rob Shearman's avatar Rob Shearman Committed by Alexandre Julliard

ole32: Fix some races in the global interface table implementation.

Fix a race between RevokeInterfaceFromGlobal and GetInterfaceFromGlobal by only using the entry inside the critical section. Fix a race between two GetInterfaceFromGlobal by cloning the stream, instead of using it and setting the current position back to zero.
parent 71a5b2d9
...@@ -96,7 +96,7 @@ static void StdGlobalInterfaceTable_Destroy(void* self) ...@@ -96,7 +96,7 @@ static void StdGlobalInterfaceTable_Destroy(void* self)
/*** /***
* A helper function to traverse the list and find the entry that matches the cookie. * A helper function to traverse the list and find the entry that matches the cookie.
* Returns NULL if not found * Returns NULL if not found. Must be called inside git_section critical section.
*/ */
static StdGITEntry* static StdGITEntry*
StdGlobalInterfaceTable_FindEntry(IGlobalInterfaceTable* iface, DWORD cookie) StdGlobalInterfaceTable_FindEntry(IGlobalInterfaceTable* iface, DWORD cookie)
...@@ -106,14 +106,10 @@ StdGlobalInterfaceTable_FindEntry(IGlobalInterfaceTable* iface, DWORD cookie) ...@@ -106,14 +106,10 @@ StdGlobalInterfaceTable_FindEntry(IGlobalInterfaceTable* iface, DWORD cookie)
TRACE("iface=%p, cookie=0x%x\n", iface, (UINT)cookie); TRACE("iface=%p, cookie=0x%x\n", iface, (UINT)cookie);
EnterCriticalSection(&git_section);
LIST_FOR_EACH_ENTRY(e, &self->list, StdGITEntry, entry) { LIST_FOR_EACH_ENTRY(e, &self->list, StdGITEntry, entry) {
if (e->cookie == cookie) { if (e->cookie == cookie)
LeaveCriticalSection(&git_section);
return e; return e;
} }
}
LeaveCriticalSection(&git_section);
TRACE("Entry not found\n"); TRACE("Entry not found\n");
return NULL; return NULL;
...@@ -233,12 +229,19 @@ StdGlobalInterfaceTable_RevokeInterfaceFromGlobal( ...@@ -233,12 +229,19 @@ StdGlobalInterfaceTable_RevokeInterfaceFromGlobal(
TRACE("iface=%p, dwCookie=0x%x\n", iface, (UINT)dwCookie); TRACE("iface=%p, dwCookie=0x%x\n", iface, (UINT)dwCookie);
EnterCriticalSection(&git_section);
entry = StdGlobalInterfaceTable_FindEntry(iface, dwCookie); entry = StdGlobalInterfaceTable_FindEntry(iface, dwCookie);
if (entry == NULL) { if (entry == NULL) {
TRACE("Entry not found\n"); TRACE("Entry not found\n");
LeaveCriticalSection(&git_section);
return E_INVALIDARG; /* not found */ return E_INVALIDARG; /* not found */
} }
list_remove(&entry->entry);
LeaveCriticalSection(&git_section);
/* Free the stream */ /* Free the stream */
hr = CoReleaseMarshalData(entry->stream); hr = CoReleaseMarshalData(entry->stream);
if (hr != S_OK) if (hr != S_OK)
...@@ -248,11 +251,6 @@ StdGlobalInterfaceTable_RevokeInterfaceFromGlobal( ...@@ -248,11 +251,6 @@ StdGlobalInterfaceTable_RevokeInterfaceFromGlobal(
} }
IStream_Release(entry->stream); IStream_Release(entry->stream);
/* chop entry out of the list, and free the memory */
EnterCriticalSection(&git_section);
list_remove(&entry->entry);
LeaveCriticalSection(&git_section);
HeapFree(GetProcessHeap(), 0, entry); HeapFree(GetProcessHeap(), 0, entry);
return S_OK; return S_OK;
} }
...@@ -264,27 +262,38 @@ StdGlobalInterfaceTable_GetInterfaceFromGlobal( ...@@ -264,27 +262,38 @@ StdGlobalInterfaceTable_GetInterfaceFromGlobal(
{ {
StdGITEntry* entry; StdGITEntry* entry;
HRESULT hres; HRESULT hres;
LARGE_INTEGER move;
LPUNKNOWN lpUnk; LPUNKNOWN lpUnk;
IStream *stream;
TRACE("dwCookie=0x%x, riid=%s, ppv=%p\n", dwCookie, debugstr_guid(riid), ppv); TRACE("dwCookie=0x%x, riid=%s, ppv=%p\n", dwCookie, debugstr_guid(riid), ppv);
EnterCriticalSection(&git_section);
entry = StdGlobalInterfaceTable_FindEntry(iface, dwCookie); entry = StdGlobalInterfaceTable_FindEntry(iface, dwCookie);
if (entry == NULL) return E_INVALIDARG; if (entry == NULL) {
LeaveCriticalSection(&git_section);
return E_INVALIDARG;
}
if (!IsEqualIID(&entry->iid, riid)) { if (!IsEqualIID(&entry->iid, riid)) {
LeaveCriticalSection(&git_section);
WARN("entry->iid (%s) != riid\n", debugstr_guid(&entry->iid)); WARN("entry->iid (%s) != riid\n", debugstr_guid(&entry->iid));
return E_INVALIDARG; return E_INVALIDARG;
} }
TRACE("entry=%p\n", entry); TRACE("entry=%p\n", entry);
/* unmarshal the interface */ hres = IStream_Clone(entry->stream, &stream);
hres = CoUnmarshalInterface(entry->stream, riid, ppv);
/* rewind stream, in case it's used again */ LeaveCriticalSection(&git_section);
move.u.LowPart = 0;
move.u.HighPart = 0; if (hres) {
IStream_Seek(entry->stream, move, STREAM_SEEK_SET, NULL); WARN("Failed to clone stream with error 0x%08x\n", hres);
return hres;
}
/* unmarshal the interface */
hres = CoUnmarshalInterface(stream, riid, ppv);
IStream_Release(stream);
if (hres) { if (hres) {
WARN("Failed to unmarshal stream\n"); WARN("Failed to unmarshal stream\n");
......
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