Global Interface Table thread safety, warnings, refcounting

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



ChangeLog:

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


Index: dlls/ole32/git.c
===================================================================
RCS file: /home/wine/wine/dlls/ole32/git.c,v
retrieving revision 1.4
diff -u -r1.4 git.c
--- dlls/ole32/git.c	17 Jun 2003 03:57:18 -0000	1.4
+++ dlls/ole32/git.c	21 Aug 2003 13:45:33 -0000
@@ -26,6 +26,8 @@
 
 #include "config.h"
 
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
 #include <assert.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -55,7 +57,7 @@
 typedef struct StdGITEntry
 {
   DWORD cookie;
-  IID iid;      /* IID of the interface */
+  IID iid;         /* IID of the interface */
   IStream* stream; /* Holds the marshalled interface */
 
   struct StdGITEntry* next;
@@ -98,6 +100,16 @@
   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.
  *
@@ -107,13 +119,11 @@
 void* StdGlobalInterfaceTable_Construct() {
   StdGlobalInterfaceTableImpl* newGIT;
 
-  TRACE("constructing\n");
-
   newGIT = HeapAlloc(GetProcessHeap(), 0, sizeof(StdGlobalInterfaceTableImpl));
   if (newGIT == 0) return newGIT;
 
   newGIT->lpVtbl = &StdGlobalInterfaceTableImpl_Vtbl;
-  newGIT->ref = 0;      /* Initialise the reference count */
+  newGIT->ref = 1;      /* 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 */
@@ -128,6 +138,7 @@
   FIXME("Revoke held interfaces here\n");
   
   HeapFree(GetProcessHeap(), 0, self);
+  StdGlobalInterfaceTableInstance = NULL;
 }
 
 /***
@@ -139,12 +150,15 @@
   StdGITEntry* e;
 
   TRACE("iface=%p, cookie=0x%x\n", iface, (UINT)cookie);
-  
+
+  EnterCriticalSection(&git_section);
   e = self->firstEntry;
   while (e != NULL) {
     if (e->cookie == cookie) return e;
     e = e->next;
   }
+  LeaveCriticalSection(&git_section);
+  
   TRACE("Entry not found\n");
   return NULL;
 }
@@ -169,21 +183,21 @@
   } else return E_NOINTERFACE;
 
   /* Now inc the refcount */
-  /* we don't use refcounts for now: StdGlobalInterfaceTable_AddRef(iface); */
+  StdGlobalInterfaceTable_AddRef(iface);
   return S_OK;
 }
 
 ULONG WINAPI StdGlobalInterfaceTable_AddRef(IGlobalInterfaceTable* iface) {
   StdGlobalInterfaceTableImpl* const self = (StdGlobalInterfaceTableImpl*) iface;
 
-  self->ref++;
+  /* InterlockedIncrement(self->ref); */
   return self->ref;
 }
 
 ULONG WINAPI StdGlobalInterfaceTable_Release(IGlobalInterfaceTable* iface) {
   StdGlobalInterfaceTableImpl* const self = (StdGlobalInterfaceTableImpl*) iface;
 
-  self->ref--;
+  /* InterlockedDecrement(self->ref); */
   if (self->ref == 0) {
     /* Hey ho, it's time to go, so long again 'till next weeks show! */
     StdGlobalInterfaceTable_Destroy(self);
@@ -208,10 +222,13 @@
   if (pUnk == NULL) return E_INVALIDARG;
   
   /* marshal the interface */
+  TRACE("About to marshal the interface\n");
   hres = CoMarshalInterThreadInterfaceInStream(riid, pUnk, &stream);
   if (hres) return hres;
   entry = HeapAlloc(GetProcessHeap(), 0, sizeof(StdGITEntry));
   if (entry == NULL) return E_OUTOFMEMORY;
+
+  EnterCriticalSection(&git_section);
   
   entry->iid = *riid;
   entry->stream = stream;
@@ -227,7 +244,10 @@
 
   /* and return the 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;
 }
 
@@ -242,12 +262,18 @@
     TRACE("Entry not found\n");
     return E_INVALIDARG; /* not found */
   }
-
+  
+  /* Free the stream */
+  IStream_Release(entry->stream);
+		    
   /* chop entry out of the list, and free the memory */
+  EnterCriticalSection(&git_section);
   if (entry->prev) entry->prev->next = entry->next;
   else self->firstEntry = entry->next;
   if (entry->next) entry->next->prev = entry->prev;
   else self->lastEntry = entry->prev;
+  LeaveCriticalSection(&git_section);
+
   HeapFree(GetProcessHeap(), 0, entry);
   return S_OK;
 }
@@ -255,17 +281,36 @@
 HRESULT WINAPI StdGlobalInterfaceTable_GetInterfaceFromGlobal(IGlobalInterfaceTable* iface, DWORD dwCookie, REFIID riid, void **ppv) {
   StdGITEntry* entry;
   HRESULT hres;
-
-  TRACE("dwCookie=0x%lx, riid=%s\n", dwCookie, debugstr_guid(riid));
+  LARGE_INTEGER move;
+  LPUNKNOWN lpUnk;
+  
+  TRACE("dwCookie=0x%lx, riid=%s, ppv=%p\n", dwCookie, debugstr_guid(riid), ppv);
   
   entry = StdGlobalInterfaceTable_FindEntry(iface, dwCookie);
   if (entry == NULL) return E_INVALIDARG;
-  if (!IsEqualIID(&entry->iid, &riid)) return E_INVALIDARG;
-
+  if (!IsEqualIID(&entry->iid, riid)) {
+    WARN("entry->iid (%s) != riid\n", debugstr_guid(&entry->iid));
+    return E_INVALIDARG;
+  }
+  TRACE("entry=%p\n", entry);
+  
   /* unmarshal the interface */
-  hres = CoGetInterfaceAndReleaseStream(entry->stream, riid, *ppv);
-  if (hres) return hres;
+  hres = CoUnmarshalInterface(entry->stream, riid, &lpUnk);
+  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 */
+  IUnknown_AddRef(lpUnk);
   
+  *ppv = lpUnk;
+  TRACE("ppv=%p\n", ppv);
   return S_OK;
 }
 

[Index of Archives]     [Gimp for Windows]     [Red Hat]     [Samba]     [Yosemite Camping]     [Graphics Cards]     [Wine Home]

  Powered by Linux