ReactOS  0.4.14-dev-315-gbb6fece
git.c
Go to the documentation of this file.
1 /*
2  * Implementation of the StdGlobalInterfaceTable object
3  *
4  * The GlobalInterfaceTable (GIT) object is used to marshal interfaces between
5  * threading apartments (contexts). When you want to pass an interface but not
6  * as a parameter, it wouldn't get marshalled automatically, so you can use this
7  * object to insert the interface into a table, and you get back a cookie.
8  * Then when it's retrieved, it'll be unmarshalled into the right apartment.
9  *
10  * Copyright 2003 Mike Hearn <mike@theoretic.com>
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public
14  * License as published by the Free Software Foundation; either
15  * version 2.1 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with this library; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26 
27 #include <stdarg.h>
28 
29 #define COBJMACROS
30 
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winuser.h"
34 #include "objbase.h"
35 #include "ole2.h"
36 #include "winerror.h"
37 
38 #include "compobj_private.h"
39 
40 #include "wine/list.h"
41 #include "wine/debug.h"
42 
44 
45 /****************************************************************************
46  * StdGlobalInterfaceTable definition
47  *
48  * This class implements IGlobalInterfaceTable and is a process-wide singleton
49  * used for marshalling interfaces between threading apartments using cookies.
50  */
51 
52 /* Each entry in the linked list of GIT entries */
53 typedef struct StdGITEntry
54 {
56  IID iid; /* IID of the interface */
57  IStream* stream; /* Holds the marshalled interface */
58 
59  struct list entry;
60 } StdGITEntry;
61 
62 /* Class data */
64 {
66 
67  struct list list;
69 
71 
73 
76 {
77  0, 0, &git_section,
79  0, 0, { (DWORD_PTR)(__FILE__ ": global interface table") }
80 };
81 static CRITICAL_SECTION git_section = { &critsect_debug, -1, 0, 0, 0, 0 };
82 
83 
85 {
86  return CONTAINING_RECORD(iface, StdGlobalInterfaceTableImpl, IGlobalInterfaceTable_iface);
87 }
88 
89 /***
90  * A helper function to traverse the list and find the entry that matches the cookie.
91  * Returns NULL if not found. Must be called inside git_section critical section.
92  */
94  DWORD cookie)
95 {
96  StdGITEntry* e;
97 
98  TRACE("This=%p, cookie=0x%x\n", This, cookie);
99 
101  if (e->cookie == cookie)
102  return e;
103  }
104 
105  TRACE("Entry not found\n");
106  return NULL;
107 }
108 
109 /***
110  * Here's the boring boilerplate stuff for IUnknown
111  */
112 
113 static HRESULT WINAPI
115  REFIID riid, void** ppvObject)
116 {
117  /* Make sure silly coders can't crash us */
118  if (ppvObject == 0) return E_INVALIDARG;
119 
120  *ppvObject = 0; /* assume we don't have the interface */
121 
122  /* Do we implement that interface? */
123  if (IsEqualIID(&IID_IUnknown, riid) ||
124  IsEqualIID(&IID_IGlobalInterfaceTable, riid))
125  {
126  *ppvObject = iface;
127  }
128  else
129  {
130  FIXME("(%s), not supported.\n", debugstr_guid(riid));
131  return E_NOINTERFACE;
132  }
133 
134  /* Now inc the refcount */
135  IGlobalInterfaceTable_AddRef(iface);
136  return S_OK;
137 }
138 
139 static ULONG WINAPI
141 {
142  return 1;
143 }
144 
145 static ULONG WINAPI
147 {
148  return 1;
149 }
150 
151 /***
152  * Now implement the actual IGlobalInterfaceTable interface
153  */
154 
155 static HRESULT WINAPI
158  REFIID riid, DWORD* pdwCookie)
159 {
161  IStream* stream = NULL;
162  HRESULT hres;
165 
166  TRACE("iface=%p, pUnk=%p, riid=%s, pdwCookie=0x%p\n", iface, pUnk, debugstr_guid(riid), pdwCookie);
167 
168  if (pUnk == NULL) return E_INVALIDARG;
169 
170  /* marshal the interface */
171  TRACE("About to marshal the interface\n");
172 
174  if (hres != S_OK) return hres;
175  hres = CoMarshalInterface(stream, riid, pUnk, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLESTRONG);
176  if (hres != S_OK)
177  {
178  IStream_Release(stream);
179  return hres;
180  }
181 
182  zero.QuadPart = 0;
183  IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
184 
185  entry = HeapAlloc(GetProcessHeap(), 0, sizeof(StdGITEntry));
186  if (!entry)
187  {
189  IStream_Release(stream);
190  return E_OUTOFMEMORY;
191  }
192 
194 
195  entry->iid = *riid;
196  entry->stream = stream;
197  entry->cookie = This->nextCookie;
198  This->nextCookie++; /* inc the cookie count */
199 
200  /* insert the new entry at the end of the list */
201  list_add_tail(&This->list, &entry->entry);
202 
203  /* and return the cookie */
204  *pdwCookie = entry->cookie;
205 
207 
208  TRACE("Cookie is 0x%x\n", entry->cookie);
209  return S_OK;
210 }
211 
212 static HRESULT WINAPI
214  IGlobalInterfaceTable* iface, DWORD dwCookie)
215 {
218  HRESULT hr;
219 
220  TRACE("iface=%p, dwCookie=0x%x\n", iface, dwCookie);
221 
223 
225  if (entry == NULL) {
226  TRACE("Entry not found\n");
228  return E_INVALIDARG; /* not found */
229  }
230 
231  list_remove(&entry->entry);
232 
234 
235  /* Free the stream */
236  hr = CoReleaseMarshalData(entry->stream);
237  if (hr != S_OK)
238  {
239  WARN("Failed to release marshal data, hr = 0x%08x\n", hr);
240  return hr;
241  }
242  IStream_Release(entry->stream);
243 
245  return S_OK;
246 }
247 
248 static HRESULT WINAPI
250  IGlobalInterfaceTable* iface, DWORD dwCookie,
251  REFIID riid, void **ppv)
252 {
255  HRESULT hres;
256  IStream *stream;
257 
258  TRACE("dwCookie=0x%x, riid=%s, ppv=%p\n", dwCookie, debugstr_guid(riid), ppv);
259 
261 
263  if (entry == NULL) {
264  WARN("Entry for cookie 0x%x not found\n", dwCookie);
266  return E_INVALIDARG;
267  }
268 
269  TRACE("entry=%p\n", entry);
270 
271  hres = IStream_Clone(entry->stream, &stream);
272 
274 
275  if (hres != S_OK) {
276  WARN("Failed to clone stream with error 0x%08x\n", hres);
277  return hres;
278  }
279 
280  /* unmarshal the interface */
282  IStream_Release(stream);
283 
284  if (hres != S_OK) {
285  WARN("Failed to unmarshal stream\n");
286  return hres;
287  }
288 
289  TRACE("ppv=%p\n", *ppv);
290  return S_OK;
291 }
292 
293 /* Classfactory definition - despite what MSDN says, some programs need this */
294 
295 static HRESULT WINAPI
296 GITCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid, LPVOID *ppv)
297 {
298  *ppv = NULL;
299  if (IsEqualIID(riid, &IID_IUnknown) ||
301  {
302  *ppv = iface;
303  return S_OK;
304  }
305  return E_NOINTERFACE;
306 }
307 
308 static ULONG WINAPI GITCF_AddRef(LPCLASSFACTORY iface)
309 {
310  return 2;
311 }
312 
313 static ULONG WINAPI GITCF_Release(LPCLASSFACTORY iface)
314 {
315  return 1;
316 }
317 
318 static HRESULT WINAPI
319 GITCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pUnk,
320  REFIID riid, LPVOID *ppv)
321 {
323  HRESULT hr = IGlobalInterfaceTable_QueryInterface(git, riid, ppv);
324  IGlobalInterfaceTable_Release(git);
325  return hr;
326 }
327 
328 static HRESULT WINAPI GITCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
329 {
330  FIXME("(%d), stub!\n",fLock);
331  return S_OK;
332 }
333 
334 static const IClassFactoryVtbl GITClassFactoryVtbl = {
336  GITCF_AddRef,
340 };
341 
343 
345 {
346  *ppv = &git_classfactory;
347  TRACE("Returning GIT classfactory\n");
348  return S_OK;
349 }
350 
351 /* Virtual function table */
352 static const IGlobalInterfaceTableVtbl StdGlobalInterfaceTableImpl_Vtbl =
353 {
360 };
361 
363 {
364  if (!std_git)
365  {
367 
368  newGIT = HeapAlloc(GetProcessHeap(), 0, sizeof(StdGlobalInterfaceTableImpl));
369  if (!newGIT) return NULL;
370 
372  list_init(&newGIT->list);
373  newGIT->nextCookie = 0xf100; /* that's where windows starts, so that's where we start */
374 
376  {
377  HeapFree(GetProcessHeap(), 0, newGIT);
378  }
379  else
380  TRACE("Created the GIT at %p\n", newGIT);
381  }
382 
383  return std_git;
384 }
385 
386 void release_std_git(void)
387 {
389  StdGITEntry *entry, *entry2;
390 
391  if (!std_git) return;
392 
395  {
396  list_remove(&entry->entry);
397 
398  CoReleaseMarshalData(entry->stream);
399  IStream_Release(entry->stream);
401  }
402 
403  HeapFree(GetProcessHeap(), 0, git);
404 }
HRESULT WINAPI CoReleaseMarshalData(IStream *pStream)
Definition: marshal.c:2055
static IGlobalInterfaceTable * std_git
Definition: git.c:72
static HRESULT WINAPI GITCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
Definition: git.c:328
void release_std_git(void)
Definition: git.c:386
HRESULT WINAPI CoUnmarshalInterface(IStream *pStream, REFIID riid, LPVOID *ppv)
Definition: marshal.c:1981
#define REFIID
Definition: guiddef.h:118
#define TRUE
Definition: types.h:120
#define E_NOINTERFACE
Definition: winerror.h:2364
static CRITICAL_SECTION git_section
Definition: git.c:74
#define DWORD_PTR
Definition: treelist.c:76
HRESULT hr
Definition: shlfolder.c:183
REFIID riid
Definition: precomp.h:44
#define WARN(fmt,...)
Definition: debug.h:111
static ULONG WINAPI GITCF_AddRef(LPCLASSFACTORY iface)
Definition: git.c:308
REFIID LPVOID * ppv
Definition: atlbase.h:39
HRESULT WINAPI CreateStreamOnHGlobal(HGLOBAL hGlobal, BOOL fDeleteOnRelease, LPSTREAM *ppstm)
HRESULT StdGlobalInterfaceTable_GetFactory(LPVOID *ppv)
Definition: git.c:344
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
WINE_DEFAULT_DEBUG_CHANNEL(ole)
IGlobalInterfaceTable IGlobalInterfaceTable_iface
Definition: git.c:65
__WINE_SERVER_LIST_INLINE void list_add_tail(struct list *list, struct list *elem)
Definition: list.h:102
static HRESULT WINAPI GITCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv)
Definition: git.c:319
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
IGlobalInterfaceTable * get_std_git(void)
Definition: git.c:362
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
unsigned int BOOL
Definition: ntddk_ex.h:94
#define e
Definition: ke_i.h:82
static LPUNKNOWN
Definition: ndr_ole.c:49
#define FIXME(fmt,...)
Definition: debug.h:110
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
#define E_INVALIDARG
Definition: ddrawi.h:101
smooth NULL
Definition: ftsmooth.c:416
#define debugstr_guid
Definition: kernel32.h:35
static HRESULT WINAPI StdGlobalInterfaceTable_QueryInterface(IGlobalInterfaceTable *iface, REFIID riid, void **ppvObject)
Definition: git.c:114
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
__WINE_SERVER_LIST_INLINE void list_remove(struct list *elem)
Definition: list.h:108
#define TRACE(s)
Definition: solgame.cpp:4
static HRESULT WINAPI StdGlobalInterfaceTable_RegisterInterfaceInGlobal(IGlobalInterfaceTable *iface, IUnknown *pUnk, REFIID riid, DWORD *pdwCookie)
Definition: git.c:156
HRESULT hres
Definition: protocol.c:465
static HRESULT WINAPI StdGlobalInterfaceTable_RevokeInterfaceFromGlobal(IGlobalInterfaceTable *iface, DWORD dwCookie)
Definition: git.c:213
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
LONG HRESULT
Definition: typedefs.h:77
const GUID IID_IUnknown
#define WINAPI
Definition: msvc.h:8
unsigned long DWORD
Definition: ntddk_ex.h:95
struct list entry
Definition: git.c:59
static double zero
Definition: j0_y0.c:96
IStream * stream
Definition: git.c:57
Definition: parse.h:22
GLuint GLuint stream
Definition: glext.h:7522
static ULONG WINAPI GITCF_Release(LPCLASSFACTORY iface)
Definition: git.c:313
uint32_t entry
Definition: isohybrid.c:63
static ULONG WINAPI StdGlobalInterfaceTable_AddRef(IGlobalInterfaceTable *iface)
Definition: git.c:140
Definition: _list.h:228
REFIID LPVOID * ppvObject
Definition: precomp.h:44
LIST_ENTRY ProcessLocksList
Definition: winbase.h:855
DWORD cookie
Definition: git.c:55
static CRITICAL_SECTION_DEBUG critsect_debug
Definition: git.c:75
#define S_OK
Definition: intsafe.h:59
static StdGITEntry * StdGlobalInterfaceTable_FindEntry(StdGlobalInterfaceTableImpl *This, DWORD cookie)
Definition: git.c:93
static IClassFactory git_classfactory
Definition: git.c:342
#define LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, list, type, field)
Definition: list.h:204
static HRESULT WINAPI GITCF_QueryInterface(LPCLASSFACTORY iface, REFIID riid, LPVOID *ppv)
Definition: git.c:296
struct StdGlobalInterfaceTableImpl StdGlobalInterfaceTableImpl
struct list list
Definition: git.c:67
__WINE_SERVER_LIST_INLINE void list_init(struct list *list)
Definition: list.h:149
unsigned int ULONG
Definition: retypes.h:1
static ULONG WINAPI StdGlobalInterfaceTable_Release(IGlobalInterfaceTable *iface)
Definition: git.c:146
struct StdGITEntry StdGITEntry
static const IGlobalInterfaceTableVtbl StdGlobalInterfaceTableImpl_Vtbl
Definition: git.c:352
static HRESULT WINAPI StdGlobalInterfaceTable_GetInterfaceFromGlobal(IGlobalInterfaceTable *iface, DWORD dwCookie, REFIID riid, void **ppv)
Definition: git.c:249
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
HRESULT WINAPI CoMarshalInterface(IStream *pStream, REFIID riid, IUnknown *pUnk, DWORD dwDestContext, void *pvDestContext, DWORD mshlFlags)
Definition: marshal.c:1876
const GUID IID_IClassFactory
static const IClassFactoryVtbl GITClassFactoryVtbl
Definition: git.c:334
static void *static void *static LPDIRECTPLAY IUnknown * pUnk
Definition: dplayx.c:30
#define HeapFree(x, y, z)
Definition: compat.h:394
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
static StdGlobalInterfaceTableImpl * impl_from_IGlobalInterfaceTable(IGlobalInterfaceTable *iface)
Definition: git.c:84
IID iid
Definition: git.c:56