ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

git.c
Go to the documentation of this file.
00001 /*
00002  * Implementation of the StdGlobalInterfaceTable object
00003  *
00004  * The GlobalInterfaceTable (GIT) object is used to marshal interfaces between
00005  * threading apartments (contexts). When you want to pass an interface but not
00006  * as a parameter, it wouldn't get marshalled automatically, so you can use this
00007  * object to insert the interface into a table, and you get back a cookie.
00008  * Then when it's retrieved, it'll be unmarshalled into the right apartment.
00009  *
00010  * Copyright 2003 Mike Hearn <mike@theoretic.com>
00011  *
00012  * This library is free software; you can redistribute it and/or
00013  * modify it under the terms of the GNU Lesser General Public
00014  * License as published by the Free Software Foundation; either
00015  * version 2.1 of the License, or (at your option) any later version.
00016  *
00017  * This library is distributed in the hope that it will be useful,
00018  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020  * Lesser General Public License for more details.
00021  *
00022  * You should have received a copy of the GNU Lesser General Public
00023  * License along with this library; if not, write to the Free Software
00024  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00025  */
00026 
00027 #include <stdarg.h>
00028 
00029 #define COBJMACROS
00030 #define NONAMELESSUNION
00031 #define NONAMELESSSTRUCT
00032 
00033 #include "windef.h"
00034 #include "winbase.h"
00035 #include "winuser.h"
00036 #include "objbase.h"
00037 #include "ole2.h"
00038 #include "winerror.h"
00039 
00040 #include "compobj_private.h" 
00041 
00042 #include "wine/list.h"
00043 #include "wine/debug.h"
00044 
00045 WINE_DEFAULT_DEBUG_CHANNEL(ole);
00046 
00047 /****************************************************************************
00048  * StdGlobalInterfaceTable definition
00049  *
00050  * This class implements IGlobalInterfaceTable and is a process-wide singleton
00051  * used for marshalling interfaces between threading apartments using cookies.
00052  */
00053 
00054 /* Each entry in the linked list of GIT entries */
00055 typedef struct StdGITEntry
00056 {
00057   DWORD cookie;
00058   IID iid;         /* IID of the interface */
00059   IStream* stream; /* Holds the marshalled interface */
00060 
00061   struct list entry;
00062 } StdGITEntry;
00063 
00064 /* Class data */
00065 typedef struct StdGlobalInterfaceTableImpl
00066 {
00067   IGlobalInterfaceTable IGlobalInterfaceTable_iface;
00068 
00069   ULONG ref;
00070   struct list list;
00071   ULONG nextCookie;
00072   
00073 } StdGlobalInterfaceTableImpl;
00074 
00075 void* StdGlobalInterfaceTableInstance;
00076 
00077 static CRITICAL_SECTION git_section;
00078 static CRITICAL_SECTION_DEBUG critsect_debug =
00079 {
00080     0, 0, &git_section,
00081     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
00082       0, 0, { (DWORD_PTR)(__FILE__ ": global interface table") }
00083 };
00084 static CRITICAL_SECTION git_section = { &critsect_debug, -1, 0, 0, 0, 0 };
00085 
00086 
00087 static inline StdGlobalInterfaceTableImpl *impl_from_IGlobalInterfaceTable(IGlobalInterfaceTable *iface)
00088 {
00089   return CONTAINING_RECORD(iface, StdGlobalInterfaceTableImpl, IGlobalInterfaceTable_iface);
00090 }
00091 
00093 static void StdGlobalInterfaceTable_Destroy(void* This)
00094 {
00095   TRACE("(%p)\n", This);
00096   FIXME("Revoke held interfaces here\n");
00097   
00098   HeapFree(GetProcessHeap(), 0, This);
00099   StdGlobalInterfaceTableInstance = NULL;
00100 }
00101 
00102 /***
00103  * A helper function to traverse the list and find the entry that matches the cookie.
00104  * Returns NULL if not found. Must be called inside git_section critical section.
00105  */
00106 static StdGITEntry* StdGlobalInterfaceTable_FindEntry(StdGlobalInterfaceTableImpl* This,
00107                 DWORD cookie)
00108 {
00109   StdGITEntry* e;
00110 
00111   TRACE("This=%p, cookie=0x%x\n", This, cookie);
00112 
00113   LIST_FOR_EACH_ENTRY(e, &This->list, StdGITEntry, entry) {
00114     if (e->cookie == cookie)
00115       return e;
00116   }
00117 
00118   TRACE("Entry not found\n");
00119   return NULL;
00120 }
00121 
00122 /***
00123  * Here's the boring boilerplate stuff for IUnknown
00124  */
00125 
00126 static HRESULT WINAPI
00127 StdGlobalInterfaceTable_QueryInterface(IGlobalInterfaceTable* iface,
00128                REFIID riid, void** ppvObject)
00129 {
00130   /* Make sure silly coders can't crash us */
00131   if (ppvObject == 0) return E_INVALIDARG;
00132 
00133   *ppvObject = 0; /* assume we don't have the interface */
00134 
00135   /* Do we implement that interface? */
00136   if (IsEqualIID(&IID_IUnknown, riid) ||
00137       IsEqualIID(&IID_IGlobalInterfaceTable, riid))
00138     *ppvObject = iface;
00139   else
00140     return E_NOINTERFACE;
00141 
00142   /* Now inc the refcount */
00143   IGlobalInterfaceTable_AddRef(iface);
00144   return S_OK;
00145 }
00146 
00147 static ULONG WINAPI
00148 StdGlobalInterfaceTable_AddRef(IGlobalInterfaceTable* iface)
00149 {
00150   StdGlobalInterfaceTableImpl* const This = impl_from_IGlobalInterfaceTable(iface);
00151 
00152   /* InterlockedIncrement(&This->ref); */
00153   return This->ref;
00154 }
00155 
00156 static ULONG WINAPI
00157 StdGlobalInterfaceTable_Release(IGlobalInterfaceTable* iface)
00158 {
00159   StdGlobalInterfaceTableImpl* const This = impl_from_IGlobalInterfaceTable(iface);
00160 
00161   /* InterlockedDecrement(&This->ref); */
00162   if (This->ref == 0) {
00163     /* Hey ho, it's time to go, so long again 'till next weeks show! */
00164     StdGlobalInterfaceTable_Destroy(This);
00165     return 0;
00166   }
00167 
00168   return This->ref;
00169 }
00170 
00171 /***
00172  * Now implement the actual IGlobalInterfaceTable interface
00173  */
00174 
00175 static HRESULT WINAPI
00176 StdGlobalInterfaceTable_RegisterInterfaceInGlobal(
00177                IGlobalInterfaceTable* iface, IUnknown* pUnk,
00178                REFIID riid, DWORD* pdwCookie)
00179 {
00180   StdGlobalInterfaceTableImpl* const This = impl_from_IGlobalInterfaceTable(iface);
00181   IStream* stream = NULL;
00182   HRESULT hres;
00183   StdGITEntry* entry;
00184   LARGE_INTEGER zero;
00185 
00186   TRACE("iface=%p, pUnk=%p, riid=%s, pdwCookie=0x%p\n", iface, pUnk, debugstr_guid(riid), pdwCookie);
00187 
00188   if (pUnk == NULL) return E_INVALIDARG;
00189   
00190   /* marshal the interface */
00191   TRACE("About to marshal the interface\n");
00192 
00193   hres = CreateStreamOnHGlobal(0, TRUE, &stream);
00194   if (hres != S_OK) return hres;
00195   hres = CoMarshalInterface(stream, riid, pUnk, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLESTRONG);
00196   if (hres != S_OK)
00197   {
00198     IStream_Release(stream);
00199     return hres;
00200   }
00201 
00202   zero.QuadPart = 0;
00203   IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
00204 
00205   entry = HeapAlloc(GetProcessHeap(), 0, sizeof(StdGITEntry));
00206   if (entry == NULL) return E_OUTOFMEMORY;
00207 
00208   EnterCriticalSection(&git_section);
00209   
00210   entry->iid = *riid;
00211   entry->stream = stream;
00212   entry->cookie = This->nextCookie;
00213   This->nextCookie++; /* inc the cookie count */
00214 
00215   /* insert the new entry at the end of the list */
00216   list_add_tail(&This->list, &entry->entry);
00217 
00218   /* and return the cookie */
00219   *pdwCookie = entry->cookie;
00220   
00221   LeaveCriticalSection(&git_section);
00222   
00223   TRACE("Cookie is 0x%x\n", entry->cookie);
00224   return S_OK;
00225 }
00226 
00227 static HRESULT WINAPI
00228 StdGlobalInterfaceTable_RevokeInterfaceFromGlobal(
00229                IGlobalInterfaceTable* iface, DWORD dwCookie)
00230 {
00231   StdGlobalInterfaceTableImpl* This = impl_from_IGlobalInterfaceTable(iface);
00232   StdGITEntry* entry;
00233   HRESULT hr;
00234 
00235   TRACE("iface=%p, dwCookie=0x%x\n", iface, dwCookie);
00236 
00237   EnterCriticalSection(&git_section);
00238 
00239   entry = StdGlobalInterfaceTable_FindEntry(This, dwCookie);
00240   if (entry == NULL) {
00241     TRACE("Entry not found\n");
00242     LeaveCriticalSection(&git_section);
00243     return E_INVALIDARG; /* not found */
00244   }
00245 
00246   list_remove(&entry->entry);
00247 
00248   LeaveCriticalSection(&git_section);
00249   
00250   /* Free the stream */
00251   hr = CoReleaseMarshalData(entry->stream);
00252   if (hr != S_OK)
00253   {
00254     WARN("Failed to release marshal data, hr = 0x%08x\n", hr);
00255     return hr;
00256   }
00257   IStream_Release(entry->stream);
00258             
00259   HeapFree(GetProcessHeap(), 0, entry);
00260   return S_OK;
00261 }
00262 
00263 static HRESULT WINAPI
00264 StdGlobalInterfaceTable_GetInterfaceFromGlobal(
00265                IGlobalInterfaceTable* iface, DWORD dwCookie,
00266                REFIID riid, void **ppv)
00267 {
00268   StdGlobalInterfaceTableImpl* This = impl_from_IGlobalInterfaceTable(iface);
00269   StdGITEntry* entry;
00270   HRESULT hres;
00271   IStream *stream;
00272 
00273   TRACE("dwCookie=0x%x, riid=%s, ppv=%p\n", dwCookie, debugstr_guid(riid), ppv);
00274 
00275   EnterCriticalSection(&git_section);
00276 
00277   entry = StdGlobalInterfaceTable_FindEntry(This, dwCookie);
00278   if (entry == NULL) {
00279     WARN("Entry for cookie 0x%x not found\n", dwCookie);
00280     LeaveCriticalSection(&git_section);
00281     return E_INVALIDARG;
00282   }
00283 
00284   TRACE("entry=%p\n", entry);
00285 
00286   hres = IStream_Clone(entry->stream, &stream);
00287 
00288   LeaveCriticalSection(&git_section);
00289 
00290   if (hres != S_OK) {
00291     WARN("Failed to clone stream with error 0x%08x\n", hres);
00292     return hres;
00293   }
00294 
00295   /* unmarshal the interface */
00296   hres = CoUnmarshalInterface(stream, riid, ppv);
00297   IStream_Release(stream);
00298 
00299   if (hres) {
00300     WARN("Failed to unmarshal stream\n");
00301     return hres;
00302   }
00303 
00304   TRACE("ppv=%p\n", *ppv);
00305   return S_OK;
00306 }
00307 
00308 /* Classfactory definition - despite what MSDN says, some programs need this */
00309 
00310 static HRESULT WINAPI
00311 GITCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid, LPVOID *ppv)
00312 {
00313   *ppv = NULL;
00314   if (IsEqualIID(riid,&IID_IUnknown) ||
00315       IsEqualIID(riid,&IID_IGlobalInterfaceTable))
00316   {
00317     *ppv = iface;
00318     return S_OK;
00319   }
00320   return E_NOINTERFACE;
00321 }
00322 
00323 static ULONG WINAPI GITCF_AddRef(LPCLASSFACTORY iface)
00324 {
00325   return 2;
00326 }
00327 
00328 static ULONG WINAPI GITCF_Release(LPCLASSFACTORY iface)
00329 {
00330   return 1;
00331 }
00332 
00333 static HRESULT WINAPI
00334 GITCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pUnk,
00335                      REFIID riid, LPVOID *ppv)
00336 {
00337   if (IsEqualIID(riid,&IID_IGlobalInterfaceTable)) {
00338     if (StdGlobalInterfaceTableInstance == NULL) 
00339       StdGlobalInterfaceTableInstance = StdGlobalInterfaceTable_Construct();
00340     return IGlobalInterfaceTable_QueryInterface( (IGlobalInterfaceTable*) StdGlobalInterfaceTableInstance, riid, ppv);
00341   }
00342 
00343   FIXME("(%s), not supported.\n",debugstr_guid(riid));
00344   return E_NOINTERFACE;
00345 }
00346 
00347 static HRESULT WINAPI GITCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
00348 {
00349     FIXME("(%d), stub!\n",fLock);
00350     return S_OK;
00351 }
00352 
00353 static const IClassFactoryVtbl GITClassFactoryVtbl = {
00354     GITCF_QueryInterface,
00355     GITCF_AddRef,
00356     GITCF_Release,
00357     GITCF_CreateInstance,
00358     GITCF_LockServer
00359 };
00360 
00361 static const IClassFactoryVtbl *PGITClassFactoryVtbl = &GITClassFactoryVtbl;
00362 
00363 HRESULT StdGlobalInterfaceTable_GetFactory(LPVOID *ppv)
00364 {
00365   *ppv = &PGITClassFactoryVtbl;
00366   TRACE("Returning GIT classfactory\n");
00367   return S_OK;
00368 }
00369 
00370 /* Virtual function table */
00371 static const IGlobalInterfaceTableVtbl StdGlobalInterfaceTableImpl_Vtbl =
00372 {
00373   StdGlobalInterfaceTable_QueryInterface,
00374   StdGlobalInterfaceTable_AddRef,
00375   StdGlobalInterfaceTable_Release,
00376   StdGlobalInterfaceTable_RegisterInterfaceInGlobal,
00377   StdGlobalInterfaceTable_RevokeInterfaceFromGlobal,
00378   StdGlobalInterfaceTable_GetInterfaceFromGlobal
00379 };
00380 
00382 void* StdGlobalInterfaceTable_Construct(void)
00383 {
00384   StdGlobalInterfaceTableImpl* newGIT;
00385 
00386   newGIT = HeapAlloc(GetProcessHeap(), 0, sizeof(StdGlobalInterfaceTableImpl));
00387   if (newGIT == 0) return newGIT;
00388 
00389   newGIT->IGlobalInterfaceTable_iface.lpVtbl = &StdGlobalInterfaceTableImpl_Vtbl;
00390   newGIT->ref = 1;      /* Initialise the reference count */
00391   list_init(&newGIT->list);
00392   newGIT->nextCookie = 0xf100; /* that's where windows starts, so that's where we start */
00393   TRACE("Created the GIT at %p\n", newGIT);
00394 
00395   return (void*)newGIT;
00396 }

Generated on Fri May 25 2012 04:23:45 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.