With this patch, RhymBox makes it to the login screen now! :) ChangeLog: - Implement the global interface table object using a simple linked list - Connect it via CoCreateInstance It relies upon my previous patch which stubbed this object out. thanks -mike
diff -u dlls/ole32/compobj.c dlls/ole32-mike/compobj.c --- dlls/ole32/compobj.c Sat Jan 11 20:58:10 2003 +++ dlls/ole32-mike/compobj.c Sun Mar 9 19:49:42 2003 @@ -1317,6 +1318,20 @@ *ppv = 0; /* + * The Standard Global Interface Table (GIT) object is a process-wide singleton. + * Rather than create a class factory, we can just check for it here + */ + if (IsEqualIID(rclsid, &CLSID_StdGlobalInterfaceTable)) { + if (StdGlobalInterfaceTableInstance == NULL) + StdGlobalInterfaceTableInstance = StdGlobalInterfaceTable_Construct(); + hres = IGlobalInterfaceTable_QueryInterface( (IGlobalInterfaceTable*) StdGlobalInterfaceTableInstance, iid, ppv); + if (hres) return hres; + + TRACE("Retrieved GIT (%p)\n", *ppv); + return S_OK; + } + + /* * Get a class factory to construct the object we want. */ hres = CoGetClassObject(rclsid, diff -u dlls/ole32/git.c dlls/ole32-mike/git.c --- dlls/ole32/git.c Sun Mar 9 20:11:24 2003 +++ dlls/ole32-mike/git.c Sun Mar 9 20:05:57 2003 @@ -50,15 +50,31 @@ * This class implements IGlobalInterfaceTable and is a process-wide singleton * used for marshalling interfaces between threading apartments using cookies. */ + +/* Each entry in the linked list of GIT entries */ +typedef struct StdGITEntry +{ + DWORD cookie; + IID iid; /* IID of the interface */ + IStream* stream; /* Holds the marshalled interface */ + + struct StdGITEntry* next; + struct StdGITEntry* prev; +} StdGITEntry; + +/* Class data */ typedef struct StdGlobalInterfaceTableImpl { ICOM_VFIELD(IGlobalInterfaceTable); ULONG ref; + struct StdGITEntry* firstEntry; + struct StdGITEntry* lastEntry; + ULONG nextCookie; - /* FIXME: put the table here */ } StdGlobalInterfaceTableImpl; + /* IUnknown */ static HRESULT WINAPI StdGlobalInterfaceTable_QueryInterface(IGlobalInterfaceTable* iface, REFIID riid, void** ppvObject); static ULONG WINAPI StdGlobalInterfaceTable_AddRef(IGlobalInterfaceTable* iface); @@ -94,7 +110,10 @@ ICOM_VTBL(newGIT) = &StdGlobalInterfaceTableImpl_Vtbl; - newGIT->ref = 0; /* Initialise the reference count */ + newGIT->ref = 0; /* Initialise the reference count */ + newGIT->firstEntry = NULL; /* we start with an empty table */ + newGIT->lastEntry = NULL; + newGIT->nextCookie = 0xf100; /* that's where windows starts, so that's where we start */ TRACE("Created the GIT at %p\n", newGIT); return (void*)newGIT; @@ -104,15 +123,35 @@ void StdGlobalInterfaceTable_Destroy(void* self) { TRACE("(%p)\n", self); FIXME("Revoke held interfaces here\n"); + HeapFree(GetProcessHeap(), 0, self); } /*** + * A helper function to traverse the list and find the entry that matches the cookie. + * Returns NULL if not found + */ +StdGITEntry* StdGlobalInterfaceTable_FindEntry(IGlobalInterfaceTable* iface, DWORD cookie) { + StdGlobalInterfaceTableImpl* const self = (StdGlobalInterfaceTableImpl*) iface; + StdGITEntry* e; + + TRACE("iface=%p, cookie=0x%x\n", iface, (UINT)cookie); + + e = self->firstEntry; + while (e != NULL) { + if (e->cookie == cookie) return e; + e = e->next; + } + return NULL; +} + +/*** * Here's the boring boilerplate stuff for IUnknown */ HRESULT WINAPI StdGlobalInterfaceTable_QueryInterface(IGlobalInterfaceTable* iface, REFIID riid, void** ppvObject) { StdGlobalInterfaceTableImpl* const self = (StdGlobalInterfaceTableImpl*) iface; + /* Make sure silly coders can't crash us */ if (ppvObject == 0) return E_INVALIDARG; @@ -126,7 +165,7 @@ } else return E_NOINTERFACE; /* Now inc the refcount */ - StdGlobalInterfaceTable_AddRef(iface); + /* we don't use refcounts for now: StdGlobalInterfaceTable_AddRef(iface); */ return S_OK; } @@ -155,16 +194,92 @@ */ HRESULT WINAPI StdGlobalInterfaceTable_RegisterInterfaceInGlobal(IGlobalInterfaceTable* iface, IUnknown* pUnk, REFIID riid, DWORD* pdwCookie) { - FIXME("stub\n"); - return E_NOTIMPL; + StdGlobalInterfaceTableImpl* const self = (StdGlobalInterfaceTableImpl*) iface; + IStream* stream = NULL; + HRESULT hres; + StdGITEntry* entry; + + TRACE("iface=%p, pUnk=%p, riid=%s, pdwCookie=%p\n", iface, pUnk, debugstr_guid(riid), pdwCookie); + + if (pUnk == NULL) return E_INVALIDARG; + + /* marshal the interface */ + hres = CoMarshalInterThreadInterfaceInStream(riid, pUnk, &stream); + if (hres) return hres; + entry = HeapAlloc(GetProcessHeap(), 0, sizeof(StdGITEntry)); + if (entry == NULL) return E_OUTOFMEMORY; + + entry->iid = *riid; + entry->stream = stream; + entry->cookie = self->nextCookie; + self->nextCookie++; /* inc the cookie count */ + + if (self->firstEntry == NULL) { + /* create the first entry */ + entry->next = NULL; + entry->prev = NULL; + self->firstEntry = entry; + self->lastEntry = entry; + } else { + /* insert the new entry onto the end of the list */ + entry->prev = self->lastEntry; + entry->prev->next = entry; + /* and move the last entry pointer along one */ + self->lastEntry = self->lastEntry->next; + } + + /* and return the cookie */ + *pdwCookie = entry->cookie; + return S_OK; } HRESULT WINAPI StdGlobalInterfaceTable_RevokeInterfaceFromGlobal(IGlobalInterfaceTable* iface, DWORD dwCookie) { - FIXME("stub\n"); - return E_NOTIMPL; + StdGlobalInterfaceTableImpl* const self = (StdGlobalInterfaceTableImpl*) iface; + StdGITEntry* entry; + + TRACE("iface=%p, dwCookie=0x%x\n", iface, (UINT)dwCookie); + + entry = StdGlobalInterfaceTable_FindEntry(iface, dwCookie); + if (entry == NULL) { + TRACE("Entry not found\n"); + return E_INVALIDARG; /* not found */ + } + + /* chop entry out of the list, and free the memory */ + if (self->firstEntry == self->lastEntry) { + /* we only have one entry */ + self->firstEntry = NULL; + self->lastEntry = NULL; + } else if (entry == self->firstEntry) { + /* we have more than one entry, this is the first */ + self->firstEntry = entry->next; + self->firstEntry->prev = NULL; + } else if (entry == self->lastEntry) { + /* we have more than one entry, this is the last */ + self->lastEntry = entry->prev; + self->lastEntry->next = NULL; + } else { + /* we have more than one entry, and this is in the middle */ + entry->prev->next = entry->next; + entry->next->prev = entry->prev; + } + + + HeapFree(GetProcessHeap(), 0, entry); + return S_OK; } HRESULT WINAPI StdGlobalInterfaceTable_GetInterfaceFromGlobal(IGlobalInterfaceTable* iface, DWORD dwCookie, REFIID riid, void **ppv) { - FIXME("stub\n"); - return E_NOTIMPL; + StdGITEntry* entry; + HRESULT hres; + + entry = StdGlobalInterfaceTable_FindEntry(iface, dwCookie); + if (entry == NULL) return E_INVALIDARG; + if (!IsEqualIID(&entry->iid, &riid)) return E_INVALIDARG; + + /* unmarshal the interface */ + hres = CoGetInterfaceAndReleaseStream(entry->stream, riid, *ppv); + if (hres) return hres; + + return S_OK; } diff -u dlls/ole32/marshal.c dlls/ole32-mike/marshal.c --- dlls/ole32/marshal.c Thu Dec 19 22:16:35 2002 +++ dlls/ole32-mike/marshal.c Sun Mar 9 15:41:21 2003 @@ -555,7 +555,7 @@ LARGE_INTEGER seekto; HRESULT hres; - TRACE("(,%s,)\n",debugstr_guid(riid)); + TRACE("(%s, %p, %p)\n",debugstr_guid(riid), pUnk, ppStm); hres = CreateStreamOnHGlobal(0, TRUE, ppStm); if (hres) return hres; /* CoMarshalInterface(...); */ diff -u dlls/ole32/oleproxy.c dlls/ole32-mike/oleproxy.c --- dlls/ole32/oleproxy.c Sun Mar 9 20:11:24 2003 +++ dlls/ole32-mike/oleproxy.c Sun Mar 9 17:48:02 2003 @@ -516,16 +516,7 @@ ) ) return MARSHAL_GetStandardMarshalCF(ppv); - - if (IsEqualIID(rclsid, &CLSID_StdGlobalInterfaceTable)) { - if (StdGlobalInterfaceTableInstance == NULL) { - StdGlobalInterfaceTableInstance = StdGlobalInterfaceTable_Construct(); - FIXME("Created (%p)\n", StdGlobalInterfaceTableInstance); - } - *ppv = StdGlobalInterfaceTableInstance; - return S_OK; - } - + FIXME("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(iid)); return CLASS_E_CLASSNOTAVAILABLE; }