In the global interface table:
- Print warnings when things go wrong. - Alter the way we do refcounting. - Don't release the stream on retrieval, just rewind it instead. - Implement thread safety.
This commit is contained in:
parent
af62e83d1c
commit
266e19ebc0
|
@ -26,6 +26,8 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#define NONAMELESSUNION
|
||||||
|
#define NONAMELESSSTRUCT
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -98,6 +100,16 @@ static ICOM_VTABLE(IGlobalInterfaceTable) StdGlobalInterfaceTableImpl_Vtbl =
|
||||||
StdGlobalInterfaceTable_GetInterfaceFromGlobal
|
StdGlobalInterfaceTable_GetInterfaceFromGlobal
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static CRITICAL_SECTION git_section;
|
||||||
|
static CRITICAL_SECTION_DEBUG critsect_debug =
|
||||||
|
{
|
||||||
|
0, 0, &git_section,
|
||||||
|
{ &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
|
||||||
|
0, 0, { 0, (DWORD)(__FILE__ ": global interface table") }
|
||||||
|
};
|
||||||
|
static CRITICAL_SECTION git_section = { &critsect_debug, -1, 0, 0, 0, 0 };
|
||||||
|
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Let's go! Here is the constructor and destructor for the class.
|
* Let's go! Here is the constructor and destructor for the class.
|
||||||
*
|
*
|
||||||
|
@ -139,11 +151,17 @@ StdGITEntry* StdGlobalInterfaceTable_FindEntry(IGlobalInterfaceTable* iface, DWO
|
||||||
|
|
||||||
TRACE("iface=%p, cookie=0x%x\n", iface, (UINT)cookie);
|
TRACE("iface=%p, cookie=0x%x\n", iface, (UINT)cookie);
|
||||||
|
|
||||||
|
EnterCriticalSection(&git_section);
|
||||||
e = self->firstEntry;
|
e = self->firstEntry;
|
||||||
while (e != NULL) {
|
while (e != NULL) {
|
||||||
if (e->cookie == cookie) return e;
|
if (e->cookie == cookie) {
|
||||||
|
LeaveCriticalSection(&git_section);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
e = e->next;
|
e = e->next;
|
||||||
}
|
}
|
||||||
|
LeaveCriticalSection(&git_section);
|
||||||
|
|
||||||
TRACE("Entry not found\n");
|
TRACE("Entry not found\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -175,14 +193,14 @@ HRESULT WINAPI StdGlobalInterfaceTable_QueryInterface(IGlobalInterfaceTable* ifa
|
||||||
ULONG WINAPI StdGlobalInterfaceTable_AddRef(IGlobalInterfaceTable* iface) {
|
ULONG WINAPI StdGlobalInterfaceTable_AddRef(IGlobalInterfaceTable* iface) {
|
||||||
StdGlobalInterfaceTableImpl* const self = (StdGlobalInterfaceTableImpl*) iface;
|
StdGlobalInterfaceTableImpl* const self = (StdGlobalInterfaceTableImpl*) iface;
|
||||||
|
|
||||||
/* self->ref++; */
|
/* InterlockedIncrement(&self->ref); */
|
||||||
return self->ref;
|
return self->ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG WINAPI StdGlobalInterfaceTable_Release(IGlobalInterfaceTable* iface) {
|
ULONG WINAPI StdGlobalInterfaceTable_Release(IGlobalInterfaceTable* iface) {
|
||||||
StdGlobalInterfaceTableImpl* const self = (StdGlobalInterfaceTableImpl*) iface;
|
StdGlobalInterfaceTableImpl* const self = (StdGlobalInterfaceTableImpl*) iface;
|
||||||
|
|
||||||
/* self->ref--; */
|
/* InterlockedDecrement(&self->ref); */
|
||||||
if (self->ref == 0) {
|
if (self->ref == 0) {
|
||||||
/* Hey ho, it's time to go, so long again 'till next weeks show! */
|
/* Hey ho, it's time to go, so long again 'till next weeks show! */
|
||||||
StdGlobalInterfaceTable_Destroy(self);
|
StdGlobalInterfaceTable_Destroy(self);
|
||||||
|
@ -213,6 +231,8 @@ HRESULT WINAPI StdGlobalInterfaceTable_RegisterInterfaceInGlobal(IGlobalInterfac
|
||||||
entry = HeapAlloc(GetProcessHeap(), 0, sizeof(StdGITEntry));
|
entry = HeapAlloc(GetProcessHeap(), 0, sizeof(StdGITEntry));
|
||||||
if (entry == NULL) return E_OUTOFMEMORY;
|
if (entry == NULL) return E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
EnterCriticalSection(&git_section);
|
||||||
|
|
||||||
entry->iid = *riid;
|
entry->iid = *riid;
|
||||||
entry->stream = stream;
|
entry->stream = stream;
|
||||||
entry->cookie = self->nextCookie;
|
entry->cookie = self->nextCookie;
|
||||||
|
@ -227,7 +247,10 @@ HRESULT WINAPI StdGlobalInterfaceTable_RegisterInterfaceInGlobal(IGlobalInterfac
|
||||||
|
|
||||||
/* and return the cookie */
|
/* and return the cookie */
|
||||||
*pdwCookie = entry->cookie;
|
*pdwCookie = entry->cookie;
|
||||||
TRACE("Cookie is 0x%ld\n", entry->cookie);
|
|
||||||
|
LeaveCriticalSection(&git_section);
|
||||||
|
|
||||||
|
TRACE("Cookie is 0x%lx\n", entry->cookie);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,11 +266,17 @@ HRESULT WINAPI StdGlobalInterfaceTable_RevokeInterfaceFromGlobal(IGlobalInterfac
|
||||||
return E_INVALIDARG; /* not found */
|
return E_INVALIDARG; /* not found */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Free the stream */
|
||||||
|
IStream_Release(entry->stream);
|
||||||
|
|
||||||
/* chop entry out of the list, and free the memory */
|
/* chop entry out of the list, and free the memory */
|
||||||
|
EnterCriticalSection(&git_section);
|
||||||
if (entry->prev) entry->prev->next = entry->next;
|
if (entry->prev) entry->prev->next = entry->next;
|
||||||
else self->firstEntry = entry->next;
|
else self->firstEntry = entry->next;
|
||||||
if (entry->next) entry->next->prev = entry->prev;
|
if (entry->next) entry->next->prev = entry->prev;
|
||||||
else self->lastEntry = entry->prev;
|
else self->lastEntry = entry->prev;
|
||||||
|
LeaveCriticalSection(&git_section);
|
||||||
|
|
||||||
HeapFree(GetProcessHeap(), 0, entry);
|
HeapFree(GetProcessHeap(), 0, entry);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -255,11 +284,14 @@ HRESULT WINAPI StdGlobalInterfaceTable_RevokeInterfaceFromGlobal(IGlobalInterfac
|
||||||
HRESULT WINAPI StdGlobalInterfaceTable_GetInterfaceFromGlobal(IGlobalInterfaceTable* iface, DWORD dwCookie, REFIID riid, void **ppv) {
|
HRESULT WINAPI StdGlobalInterfaceTable_GetInterfaceFromGlobal(IGlobalInterfaceTable* iface, DWORD dwCookie, REFIID riid, void **ppv) {
|
||||||
StdGITEntry* entry;
|
StdGITEntry* entry;
|
||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
|
LARGE_INTEGER move;
|
||||||
|
LPUNKNOWN lpUnk;
|
||||||
|
|
||||||
TRACE("dwCookie=0x%lx, riid=%s\n", dwCookie, debugstr_guid(riid));
|
TRACE("dwCookie=0x%lx, riid=%s, ppv=%p\n", dwCookie, debugstr_guid(riid), ppv);
|
||||||
|
|
||||||
entry = StdGlobalInterfaceTable_FindEntry(iface, dwCookie);
|
entry = StdGlobalInterfaceTable_FindEntry(iface, dwCookie);
|
||||||
if (entry == NULL) return E_INVALIDARG;
|
if (entry == NULL) return E_INVALIDARG;
|
||||||
|
|
||||||
if (!IsEqualIID(&entry->iid, riid)) {
|
if (!IsEqualIID(&entry->iid, riid)) {
|
||||||
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;
|
||||||
|
@ -267,9 +299,21 @@ HRESULT WINAPI StdGlobalInterfaceTable_GetInterfaceFromGlobal(IGlobalInterfaceTa
|
||||||
TRACE("entry=%p\n", entry);
|
TRACE("entry=%p\n", entry);
|
||||||
|
|
||||||
/* unmarshal the interface */
|
/* unmarshal the interface */
|
||||||
hres = CoGetInterfaceAndReleaseStream(entry->stream, riid, ppv);
|
hres = CoUnmarshalInterface(entry->stream, riid, ppv);
|
||||||
if (hres) return hres;
|
if (hres) {
|
||||||
|
WARN("Failed to unmarshal stream\n");
|
||||||
|
return hres;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* rewind stream, in case it's used again */
|
||||||
|
move.s.LowPart = 0;
|
||||||
|
move.s.HighPart = 0;
|
||||||
|
IStream_Seek(entry->stream, move, STREAM_SEEK_SET, NULL);
|
||||||
|
|
||||||
|
/* addref it */
|
||||||
|
lpUnk = *ppv;
|
||||||
|
IUnknown_AddRef(lpUnk);
|
||||||
|
TRACE("ppv=%p\n", *ppv);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue