Rob Shearman : ole32:
Fix some races in the global interface table implementation.
Alexandre Julliard
julliard at wine.codeweavers.com
Wed May 23 08:10:55 CDT 2007
Module: wine
Branch: master
Commit: eebf8df6015472de393c049c4daea6f7be06b905
URL: http://source.winehq.org/git/wine.git/?a=commit;h=eebf8df6015472de393c049c4daea6f7be06b905
Author: Rob Shearman <rob at codeweavers.com>
Date: Tue May 22 10:31:11 2007 +0100
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.
---
dlls/ole32/git.c | 55 +++++++++++++++++++++++++++++++----------------------
1 files changed, 32 insertions(+), 23 deletions(-)
diff --git a/dlls/ole32/git.c b/dlls/ole32/git.c
index 222eb6f..b51990d 100644
--- a/dlls/ole32/git.c
+++ b/dlls/ole32/git.c
@@ -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.
- * Returns NULL if not found
+ * Returns NULL if not found. Must be called inside git_section critical section.
*/
static StdGITEntry*
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);
- EnterCriticalSection(&git_section);
LIST_FOR_EACH_ENTRY(e, &self->list, StdGITEntry, entry) {
- if (e->cookie == cookie) {
- LeaveCriticalSection(&git_section);
+ if (e->cookie == cookie)
return e;
- }
}
- LeaveCriticalSection(&git_section);
TRACE("Entry not found\n");
return NULL;
@@ -232,12 +228,19 @@ StdGlobalInterfaceTable_RevokeInterfaceFromGlobal(
HRESULT hr;
TRACE("iface=%p, dwCookie=0x%x\n", iface, (UINT)dwCookie);
-
+
+ EnterCriticalSection(&git_section);
+
entry = StdGlobalInterfaceTable_FindEntry(iface, dwCookie);
if (entry == NULL) {
TRACE("Entry not found\n");
+ LeaveCriticalSection(&git_section);
return E_INVALIDARG; /* not found */
}
+
+ list_remove(&entry->entry);
+
+ LeaveCriticalSection(&git_section);
/* Free the stream */
hr = CoReleaseMarshalData(entry->stream);
@@ -248,11 +251,6 @@ StdGlobalInterfaceTable_RevokeInterfaceFromGlobal(
}
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);
return S_OK;
}
@@ -264,27 +262,38 @@ StdGlobalInterfaceTable_GetInterfaceFromGlobal(
{
StdGITEntry* entry;
HRESULT hres;
- LARGE_INTEGER move;
LPUNKNOWN lpUnk;
-
+ IStream *stream;
+
TRACE("dwCookie=0x%x, riid=%s, ppv=%p\n", dwCookie, debugstr_guid(riid), ppv);
-
+
+ EnterCriticalSection(&git_section);
+
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)) {
+ LeaveCriticalSection(&git_section);
WARN("entry->iid (%s) != riid\n", debugstr_guid(&entry->iid));
return E_INVALIDARG;
}
TRACE("entry=%p\n", entry);
-
+
+ hres = IStream_Clone(entry->stream, &stream);
+
+ LeaveCriticalSection(&git_section);
+
+ if (hres) {
+ WARN("Failed to clone stream with error 0x%08x\n", hres);
+ return hres;
+ }
+
/* unmarshal the interface */
- hres = CoUnmarshalInterface(entry->stream, riid, ppv);
-
- /* rewind stream, in case it's used again */
- move.u.LowPart = 0;
- move.u.HighPart = 0;
- IStream_Seek(entry->stream, move, STREAM_SEEK_SET, NULL);
+ hres = CoUnmarshalInterface(stream, riid, ppv);
+ IStream_Release(stream);
if (hres) {
WARN("Failed to unmarshal stream\n");
More information about the wine-cvs
mailing list