2005-07-31 12:11:56 +00:00
|
|
|
/*
|
|
|
|
* Implementation of the StdGlobalInterfaceTable object
|
|
|
|
*
|
|
|
|
* The GlobalInterfaceTable (GIT) object is used to marshal interfaces between
|
|
|
|
* threading apartments (contexts). When you want to pass an interface but not
|
|
|
|
* as a parameter, it wouldn't get marshalled automatically, so you can use this
|
|
|
|
* object to insert the interface into a table, and you get back a cookie.
|
|
|
|
* Then when it's retrieved, it'll be unmarshalled into the right apartment.
|
|
|
|
*
|
|
|
|
* Copyright 2003 Mike Hearn <mike@theoretic.com>
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
2007-04-20 12:23:52 +00:00
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
2005-07-31 12:11:56 +00:00
|
|
|
*/
|
|
|
|
|
2018-03-20 11:38:17 +00:00
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
|
|
#define COBJMACROS
|
|
|
|
|
|
|
|
#include "windef.h"
|
|
|
|
#include "winbase.h"
|
|
|
|
#include "winuser.h"
|
|
|
|
#include "objbase.h"
|
|
|
|
#include "ole2.h"
|
|
|
|
#include "winerror.h"
|
|
|
|
|
|
|
|
#include "compobj_private.h"
|
|
|
|
|
|
|
|
#include "wine/list.h"
|
|
|
|
#include "wine/debug.h"
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(ole);
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* StdGlobalInterfaceTable definition
|
|
|
|
*
|
|
|
|
* 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 */
|
|
|
|
|
2007-04-20 12:23:52 +00:00
|
|
|
struct list entry;
|
2005-07-31 12:11:56 +00:00
|
|
|
} StdGITEntry;
|
|
|
|
|
|
|
|
/* Class data */
|
|
|
|
typedef struct StdGlobalInterfaceTableImpl
|
|
|
|
{
|
2012-05-17 15:16:51 +00:00
|
|
|
IGlobalInterfaceTable IGlobalInterfaceTable_iface;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2007-04-20 12:23:52 +00:00
|
|
|
struct list list;
|
2005-07-31 12:11:56 +00:00
|
|
|
ULONG nextCookie;
|
2008-01-14 15:45:45 +00:00
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
} StdGlobalInterfaceTableImpl;
|
|
|
|
|
2013-09-26 13:58:03 +00:00
|
|
|
static IGlobalInterfaceTable *std_git;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
static CRITICAL_SECTION git_section;
|
|
|
|
static CRITICAL_SECTION_DEBUG critsect_debug =
|
|
|
|
{
|
|
|
|
0, 0, &git_section,
|
|
|
|
{ &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
|
2005-11-20 15:01:10 +00:00
|
|
|
0, 0, { (DWORD_PTR)(__FILE__ ": global interface table") }
|
2005-07-31 12:11:56 +00:00
|
|
|
};
|
|
|
|
static CRITICAL_SECTION git_section = { &critsect_debug, -1, 0, 0, 0, 0 };
|
|
|
|
|
|
|
|
|
2012-05-17 15:16:51 +00:00
|
|
|
static inline StdGlobalInterfaceTableImpl *impl_from_IGlobalInterfaceTable(IGlobalInterfaceTable *iface)
|
|
|
|
{
|
|
|
|
return CONTAINING_RECORD(iface, StdGlobalInterfaceTableImpl, IGlobalInterfaceTable_iface);
|
|
|
|
}
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
/***
|
|
|
|
* A helper function to traverse the list and find the entry that matches the cookie.
|
2007-07-27 09:49:52 +00:00
|
|
|
* Returns NULL if not found. Must be called inside git_section critical section.
|
2005-07-31 12:11:56 +00:00
|
|
|
*/
|
2012-05-17 15:16:51 +00:00
|
|
|
static StdGITEntry* StdGlobalInterfaceTable_FindEntry(StdGlobalInterfaceTableImpl* This,
|
|
|
|
DWORD cookie)
|
2005-07-31 12:11:56 +00:00
|
|
|
{
|
|
|
|
StdGITEntry* e;
|
|
|
|
|
2012-05-17 15:16:51 +00:00
|
|
|
TRACE("This=%p, cookie=0x%x\n", This, cookie);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2012-05-17 15:16:51 +00:00
|
|
|
LIST_FOR_EACH_ENTRY(e, &This->list, StdGITEntry, entry) {
|
2007-07-27 09:49:52 +00:00
|
|
|
if (e->cookie == cookie)
|
2005-07-31 12:11:56 +00:00
|
|
|
return e;
|
|
|
|
}
|
2012-05-17 15:16:51 +00:00
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
TRACE("Entry not found\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***
|
|
|
|
* Here's the boring boilerplate stuff for IUnknown
|
|
|
|
*/
|
|
|
|
|
|
|
|
static HRESULT WINAPI
|
|
|
|
StdGlobalInterfaceTable_QueryInterface(IGlobalInterfaceTable* iface,
|
|
|
|
REFIID riid, void** ppvObject)
|
|
|
|
{
|
|
|
|
/* Make sure silly coders can't crash us */
|
|
|
|
if (ppvObject == 0) return E_INVALIDARG;
|
|
|
|
|
|
|
|
*ppvObject = 0; /* assume we don't have the interface */
|
|
|
|
|
|
|
|
/* Do we implement that interface? */
|
|
|
|
if (IsEqualIID(&IID_IUnknown, riid) ||
|
|
|
|
IsEqualIID(&IID_IGlobalInterfaceTable, riid))
|
2019-01-29 12:15:33 +00:00
|
|
|
{
|
2005-07-31 12:11:56 +00:00
|
|
|
*ppvObject = iface;
|
2019-01-29 12:15:33 +00:00
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
else
|
2019-01-29 12:15:33 +00:00
|
|
|
{
|
|
|
|
FIXME("(%s), not supported.\n", debugstr_guid(riid));
|
2005-07-31 12:11:56 +00:00
|
|
|
return E_NOINTERFACE;
|
2019-01-29 12:15:33 +00:00
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
/* Now inc the refcount */
|
|
|
|
IGlobalInterfaceTable_AddRef(iface);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI
|
|
|
|
StdGlobalInterfaceTable_AddRef(IGlobalInterfaceTable* iface)
|
|
|
|
{
|
2013-09-26 13:58:03 +00:00
|
|
|
return 1;
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI
|
|
|
|
StdGlobalInterfaceTable_Release(IGlobalInterfaceTable* iface)
|
|
|
|
{
|
2013-09-26 13:58:03 +00:00
|
|
|
return 1;
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***
|
|
|
|
* Now implement the actual IGlobalInterfaceTable interface
|
|
|
|
*/
|
|
|
|
|
|
|
|
static HRESULT WINAPI
|
|
|
|
StdGlobalInterfaceTable_RegisterInterfaceInGlobal(
|
|
|
|
IGlobalInterfaceTable* iface, IUnknown* pUnk,
|
|
|
|
REFIID riid, DWORD* pdwCookie)
|
|
|
|
{
|
2012-05-17 15:16:51 +00:00
|
|
|
StdGlobalInterfaceTableImpl* const This = impl_from_IGlobalInterfaceTable(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
IStream* stream = NULL;
|
|
|
|
HRESULT hres;
|
|
|
|
StdGITEntry* entry;
|
|
|
|
LARGE_INTEGER zero;
|
|
|
|
|
|
|
|
TRACE("iface=%p, pUnk=%p, riid=%s, pdwCookie=0x%p\n", iface, pUnk, debugstr_guid(riid), pdwCookie);
|
|
|
|
|
|
|
|
if (pUnk == NULL) return E_INVALIDARG;
|
2008-01-14 15:45:45 +00:00
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
/* marshal the interface */
|
|
|
|
TRACE("About to marshal the interface\n");
|
|
|
|
|
|
|
|
hres = CreateStreamOnHGlobal(0, TRUE, &stream);
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
if (hres != S_OK) return hres;
|
2005-07-31 12:11:56 +00:00
|
|
|
hres = CoMarshalInterface(stream, riid, pUnk, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLESTRONG);
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
if (hres != S_OK)
|
2005-07-31 12:11:56 +00:00
|
|
|
{
|
|
|
|
IStream_Release(stream);
|
|
|
|
return hres;
|
|
|
|
}
|
|
|
|
|
|
|
|
zero.QuadPart = 0;
|
2007-04-20 12:23:52 +00:00
|
|
|
IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
entry = HeapAlloc(GetProcessHeap(), 0, sizeof(StdGITEntry));
|
2013-09-26 13:58:03 +00:00
|
|
|
if (!entry)
|
|
|
|
{
|
|
|
|
CoReleaseMarshalData(stream);
|
|
|
|
IStream_Release(stream);
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
EnterCriticalSection(&git_section);
|
2008-01-14 15:45:45 +00:00
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
entry->iid = *riid;
|
|
|
|
entry->stream = stream;
|
2012-05-17 15:16:51 +00:00
|
|
|
entry->cookie = This->nextCookie;
|
|
|
|
This->nextCookie++; /* inc the cookie count */
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
/* insert the new entry at the end of the list */
|
2012-05-17 15:16:51 +00:00
|
|
|
list_add_tail(&This->list, &entry->entry);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
/* and return the cookie */
|
|
|
|
*pdwCookie = entry->cookie;
|
2008-01-14 15:45:45 +00:00
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
LeaveCriticalSection(&git_section);
|
2008-01-14 15:45:45 +00:00
|
|
|
|
2007-04-20 12:23:52 +00:00
|
|
|
TRACE("Cookie is 0x%x\n", entry->cookie);
|
2005-07-31 12:11:56 +00:00
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI
|
|
|
|
StdGlobalInterfaceTable_RevokeInterfaceFromGlobal(
|
|
|
|
IGlobalInterfaceTable* iface, DWORD dwCookie)
|
|
|
|
{
|
2012-05-17 15:16:51 +00:00
|
|
|
StdGlobalInterfaceTableImpl* This = impl_from_IGlobalInterfaceTable(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
StdGITEntry* entry;
|
|
|
|
HRESULT hr;
|
|
|
|
|
2008-01-18 17:39:35 +00:00
|
|
|
TRACE("iface=%p, dwCookie=0x%x\n", iface, dwCookie);
|
2007-07-27 09:49:52 +00:00
|
|
|
|
|
|
|
EnterCriticalSection(&git_section);
|
|
|
|
|
2012-05-17 15:16:51 +00:00
|
|
|
entry = StdGlobalInterfaceTable_FindEntry(This, dwCookie);
|
2005-07-31 12:11:56 +00:00
|
|
|
if (entry == NULL) {
|
|
|
|
TRACE("Entry not found\n");
|
2007-07-27 09:49:52 +00:00
|
|
|
LeaveCriticalSection(&git_section);
|
2005-07-31 12:11:56 +00:00
|
|
|
return E_INVALIDARG; /* not found */
|
|
|
|
}
|
2007-07-27 09:49:52 +00:00
|
|
|
|
|
|
|
list_remove(&entry->entry);
|
|
|
|
|
|
|
|
LeaveCriticalSection(&git_section);
|
2008-01-14 15:45:45 +00:00
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
/* Free the stream */
|
|
|
|
hr = CoReleaseMarshalData(entry->stream);
|
|
|
|
if (hr != S_OK)
|
|
|
|
{
|
2007-04-20 12:23:52 +00:00
|
|
|
WARN("Failed to release marshal data, hr = 0x%08x\n", hr);
|
2005-07-31 12:11:56 +00:00
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
IStream_Release(entry->stream);
|
2008-01-14 15:45:45 +00:00
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
HeapFree(GetProcessHeap(), 0, entry);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI
|
|
|
|
StdGlobalInterfaceTable_GetInterfaceFromGlobal(
|
|
|
|
IGlobalInterfaceTable* iface, DWORD dwCookie,
|
|
|
|
REFIID riid, void **ppv)
|
|
|
|
{
|
2012-05-17 15:16:51 +00:00
|
|
|
StdGlobalInterfaceTableImpl* This = impl_from_IGlobalInterfaceTable(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
StdGITEntry* entry;
|
|
|
|
HRESULT hres;
|
2007-07-27 09:49:52 +00:00
|
|
|
IStream *stream;
|
|
|
|
|
2007-04-20 12:23:52 +00:00
|
|
|
TRACE("dwCookie=0x%x, riid=%s, ppv=%p\n", dwCookie, debugstr_guid(riid), ppv);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2007-07-27 09:49:52 +00:00
|
|
|
EnterCriticalSection(&git_section);
|
|
|
|
|
2012-05-17 15:16:51 +00:00
|
|
|
entry = StdGlobalInterfaceTable_FindEntry(This, dwCookie);
|
2007-07-27 09:49:52 +00:00
|
|
|
if (entry == NULL) {
|
|
|
|
WARN("Entry for cookie 0x%x not found\n", dwCookie);
|
|
|
|
LeaveCriticalSection(&git_section);
|
2005-07-31 12:11:56 +00:00
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
2007-07-27 09:49:52 +00:00
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
TRACE("entry=%p\n", entry);
|
2007-07-27 09:49:52 +00:00
|
|
|
|
|
|
|
hres = IStream_Clone(entry->stream, &stream);
|
|
|
|
|
|
|
|
LeaveCriticalSection(&git_section);
|
|
|
|
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
if (hres != S_OK) {
|
2007-07-27 09:49:52 +00:00
|
|
|
WARN("Failed to clone stream with error 0x%08x\n", hres);
|
|
|
|
return hres;
|
|
|
|
}
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
/* unmarshal the interface */
|
2007-07-27 09:49:52 +00:00
|
|
|
hres = CoUnmarshalInterface(stream, riid, ppv);
|
|
|
|
IStream_Release(stream);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2013-09-26 13:58:03 +00:00
|
|
|
if (hres != S_OK) {
|
2007-04-20 12:23:52 +00:00
|
|
|
WARN("Failed to unmarshal stream\n");
|
|
|
|
return hres;
|
|
|
|
}
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
TRACE("ppv=%p\n", *ppv);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Classfactory definition - despite what MSDN says, some programs need this */
|
|
|
|
|
|
|
|
static HRESULT WINAPI
|
|
|
|
GITCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid, LPVOID *ppv)
|
|
|
|
{
|
|
|
|
*ppv = NULL;
|
2013-09-26 13:58:03 +00:00
|
|
|
if (IsEqualIID(riid, &IID_IUnknown) ||
|
|
|
|
IsEqualIID(riid, &IID_IClassFactory))
|
2005-07-31 12:11:56 +00:00
|
|
|
{
|
2009-03-03 09:12:43 +00:00
|
|
|
*ppv = iface;
|
2005-07-31 12:11:56 +00:00
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
return E_NOINTERFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI GITCF_AddRef(LPCLASSFACTORY iface)
|
|
|
|
{
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI GITCF_Release(LPCLASSFACTORY iface)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI
|
|
|
|
GITCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pUnk,
|
|
|
|
REFIID riid, LPVOID *ppv)
|
|
|
|
{
|
2019-01-29 12:15:33 +00:00
|
|
|
IGlobalInterfaceTable *git = get_std_git();
|
|
|
|
HRESULT hr = IGlobalInterfaceTable_QueryInterface(git, riid, ppv);
|
|
|
|
IGlobalInterfaceTable_Release(git);
|
|
|
|
return hr;
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI GITCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
|
|
|
|
{
|
|
|
|
FIXME("(%d), stub!\n",fLock);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2005-08-03 22:31:39 +00:00
|
|
|
static const IClassFactoryVtbl GITClassFactoryVtbl = {
|
2005-07-31 12:11:56 +00:00
|
|
|
GITCF_QueryInterface,
|
|
|
|
GITCF_AddRef,
|
|
|
|
GITCF_Release,
|
|
|
|
GITCF_CreateInstance,
|
|
|
|
GITCF_LockServer
|
|
|
|
};
|
|
|
|
|
2013-09-26 13:58:03 +00:00
|
|
|
static IClassFactory git_classfactory = { &GITClassFactoryVtbl };
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
HRESULT StdGlobalInterfaceTable_GetFactory(LPVOID *ppv)
|
|
|
|
{
|
2013-09-26 13:58:03 +00:00
|
|
|
*ppv = &git_classfactory;
|
2005-07-31 12:11:56 +00:00
|
|
|
TRACE("Returning GIT classfactory\n");
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Virtual function table */
|
2005-08-03 22:31:39 +00:00
|
|
|
static const IGlobalInterfaceTableVtbl StdGlobalInterfaceTableImpl_Vtbl =
|
2005-07-31 12:11:56 +00:00
|
|
|
{
|
|
|
|
StdGlobalInterfaceTable_QueryInterface,
|
|
|
|
StdGlobalInterfaceTable_AddRef,
|
|
|
|
StdGlobalInterfaceTable_Release,
|
|
|
|
StdGlobalInterfaceTable_RegisterInterfaceInGlobal,
|
|
|
|
StdGlobalInterfaceTable_RevokeInterfaceFromGlobal,
|
|
|
|
StdGlobalInterfaceTable_GetInterfaceFromGlobal
|
|
|
|
};
|
|
|
|
|
2013-09-26 13:58:03 +00:00
|
|
|
IGlobalInterfaceTable* get_std_git(void)
|
2005-07-31 12:11:56 +00:00
|
|
|
{
|
2013-09-26 13:58:03 +00:00
|
|
|
if (!std_git)
|
|
|
|
{
|
|
|
|
StdGlobalInterfaceTableImpl* newGIT;
|
|
|
|
|
|
|
|
newGIT = HeapAlloc(GetProcessHeap(), 0, sizeof(StdGlobalInterfaceTableImpl));
|
|
|
|
if (!newGIT) return NULL;
|
|
|
|
|
|
|
|
newGIT->IGlobalInterfaceTable_iface.lpVtbl = &StdGlobalInterfaceTableImpl_Vtbl;
|
|
|
|
list_init(&newGIT->list);
|
|
|
|
newGIT->nextCookie = 0xf100; /* that's where windows starts, so that's where we start */
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2013-09-26 13:58:03 +00:00
|
|
|
if (InterlockedCompareExchangePointer((void**)&std_git, &newGIT->IGlobalInterfaceTable_iface, NULL))
|
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(), 0, newGIT);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
TRACE("Created the GIT at %p\n", newGIT);
|
|
|
|
}
|
|
|
|
|
|
|
|
return std_git;
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2013-09-26 13:58:03 +00:00
|
|
|
void release_std_git(void)
|
|
|
|
{
|
|
|
|
StdGlobalInterfaceTableImpl *git;
|
|
|
|
StdGITEntry *entry, *entry2;
|
|
|
|
|
|
|
|
if (!std_git) return;
|
|
|
|
|
|
|
|
git = impl_from_IGlobalInterfaceTable(std_git);
|
|
|
|
LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &git->list, StdGITEntry, entry)
|
|
|
|
{
|
|
|
|
list_remove(&entry->entry);
|
|
|
|
|
|
|
|
CoReleaseMarshalData(entry->stream);
|
|
|
|
IStream_Release(entry->stream);
|
|
|
|
HeapFree(GetProcessHeap(), 0, entry);
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2013-09-26 13:58:03 +00:00
|
|
|
HeapFree(GetProcessHeap(), 0, git);
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|