Stubbed out StdGlobalInterfaceTable

Mike Hearn mike at theoretic.com
Sat Mar 8 16:01:40 CST 2003


This patch is a stub implementation of the StdGlobalInterfaceTable
object, in ole32.dll

It's my first COM object for Wine, so it may well have silly errors in
... in particular I'm not sure if using a global variable is the best
way to make it a process-wide singleton.

I wanted to submit this tonight before debugging another app - if I have
time tomorrow I'll try implementing it, as unfortunately MSXML has the
cheek to actually use the object after requesting it, so simply stubbing
it doesn't make my app work any better.

License: LGPL

thanks -mike
-------------- next part --------------
Index: winedefault.reg
===================================================================
RCS file: /home/wine/wine/winedefault.reg,v
retrieving revision 1.62
diff -u -r1.62 winedefault.reg
--- winedefault.reg	21 Jan 2003 20:15:14 -0000	1.62
+++ winedefault.reg	8 Mar 2003 21:47:54 -0000
@@ -146,6 +146,14 @@
 # Entries for OLE32 (COM/OLE base)
 #
 
+# The GlobalInterfaceTable is used for marshalling interfaces between threading contexts by cookie lookup table
+[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{00000323-0000-0000-c000-000000000046}]
+@="StdGlobalInterfaceTable"
+
+[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{00000323-0000-0000-c000-000000000046}\InProcServer32]
+@="ole32.dll"
+"ThreadingModel"="Apartment"
+
 # OLE32's built-in marshaler, handles standard interfaces such as IClassFactory.
 # (PSFactoryBuffer = Proxy/Stub factory)
 [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{00000320-0000-0000-C000-000000000046}]
? dlls/ole32/config.log
? dlls/ole32/git.c
Index: dlls/ole32/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/ole32/Makefile.in,v
retrieving revision 1.26
diff -u -r1.26 Makefile.in
--- dlls/ole32/Makefile.in	5 Jan 2003 01:04:34 -0000	1.26
+++ dlls/ole32/Makefile.in	8 Mar 2003 21:48:11 -0000
@@ -22,6 +22,7 @@
 	errorinfo.c \
 	filemoniker.c \
 	ftmarshal.c \
+	git.c \
 	hglobalstream.c \
 	ifs.c \
 	itemmoniker.c \
Index: dlls/ole32/compobj_private.h
===================================================================
RCS file: /home/wine/wine/dlls/ole32/compobj_private.h,v
retrieving revision 1.5
diff -u -r1.5 compobj_private.h
--- dlls/ole32/compobj_private.h	3 Aug 2002 00:17:10 -0000	1.5
+++ dlls/ole32/compobj_private.h	8 Mar 2003 21:48:13 -0000
@@ -27,6 +27,13 @@
 
 #include "wtypes.h"
 
+/* The GIT is a process-wide singleton, store the instance here */
+void* StdGlobalInterfaceTableInstance;
+
+void* StdGlobalInterfaceTable_Construct();
+void  StdGlobalInterfaceTable_Destroy(void* self);
+
+
 extern HRESULT WINE_StringFromCLSID(const CLSID *id,LPSTR idstr);
 extern HRESULT create_marshalled_proxy(REFCLSID rclsid, REFIID iid, LPVOID *ppv);
 
Index: dlls/ole32/ole32_main.c
===================================================================
RCS file: /home/wine/wine/dlls/ole32/ole32_main.c,v
retrieving revision 1.11
diff -u -r1.11 ole32_main.c
--- dlls/ole32/ole32_main.c	5 Dec 2002 20:33:08 -0000	1.11
+++ dlls/ole32/ole32_main.c	8 Mar 2003 21:48:14 -0000
@@ -23,6 +23,8 @@
 #include "ole32_main.h"
 #include "wine/debug.h"
 
+#include "compobj_private.h"
+
 WINE_DEFAULT_DEBUG_CHANNEL(ole);
 
 HINSTANCE OLE32_hInstance = 0;
@@ -35,6 +37,9 @@
 {
     TRACE("%p 0x%lx %p\n", hinstDLL, fdwReason, fImpLoad);
 
+    /* Clear the global instance variable here */
+    StdGlobalInterfaceTableInstance = NULL;
+    
     switch(fdwReason) {
     case DLL_PROCESS_ATTACH:
         OLE32_hInstance = hinstDLL;
Index: dlls/ole32/oleproxy.c
===================================================================
RCS file: /home/wine/wine/dlls/ole32/oleproxy.c,v
retrieving revision 1.6
diff -u -r1.6 oleproxy.c
--- dlls/ole32/oleproxy.c	7 Jan 2003 20:36:27 -0000	1.6
+++ dlls/ole32/oleproxy.c	8 Mar 2003 21:48:15 -0000
@@ -53,8 +53,9 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(ole);
 
-const CLSID CLSID_DfMarshal       = { 0x0000030b, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46} };
-const CLSID CLSID_PSFactoryBuffer = { 0x00000320, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46} };
+const CLSID CLSID_DfMarshal               = { 0x0000030b, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46} };
+const CLSID CLSID_PSFactoryBuffer         = { 0x00000320, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46} };
+const CLSID CLSID_StdGlobalInterfaceTable = { 0x00000323, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46} };
 
 /* From: http://msdn.microsoft.com/library/en-us/com/cmi_m_4lda.asp
  *
@@ -515,6 +516,16 @@
 	)
     )
 	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;
 }
--- /dev/null	Sat Mar 23 19:46:34 2002
+++ dlls/ole32/git.c	Sat Mar  8 21:39:09 2003
@@ -0,0 +1,170 @@
+/*
+ * 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 1999 Mike Hearn <mike at 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
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "windef.h"
+#include "objbase.h"
+#include "ole2.h"
+#include "winbase.h"
+#include "winerror.h"
+#include "winternl.h"
+
+#include "compobj_private.h" 
+
+#include "wine/debug.h"
+
+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.
+ */
+typedef struct StdGlobalInterfaceTableImpl
+{
+  ICOM_VFIELD(IGlobalInterfaceTable);
+
+  ULONG ref;
+  
+  /* 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);
+static ULONG   WINAPI StdGlobalInterfaceTable_Release(IGlobalInterfaceTable* iface);
+/* IGlobalInterfaceTable */
+static HRESULT WINAPI StdGlobalInterfaceTable_RegisterInterfaceInGlobal(IGlobalInterfaceTable* iface, IUnknown* pUnk, REFIID riid, DWORD* pdwCookie);
+static HRESULT WINAPI StdGlobalInterfaceTable_RevokeInterfaceFromGlobal(IGlobalInterfaceTable* iface, DWORD dwCookie);
+static HRESULT WINAPI StdGlobalInterfaceTable_GetInterfaceFromGlobal(IGlobalInterfaceTable* iface, DWORD dwCookie, REFIID riid, void **ppv);
+
+/* Virtual function table */
+static ICOM_VTABLE(IGlobalInterfaceTable) StdGlobalInterfaceTableImpl_Vtbl =
+{
+  ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+  StdGlobalInterfaceTable_QueryInterface,
+  StdGlobalInterfaceTable_AddRef,
+  StdGlobalInterfaceTable_Release,
+  StdGlobalInterfaceTable_RegisterInterfaceInGlobal,
+  StdGlobalInterfaceTable_RevokeInterfaceFromGlobal,
+  StdGlobalInterfaceTable_GetInterfaceFromGlobal
+};
+
+/***
+ * Let's go! Here is the constructor and destructor for the class.
+ *
+ */
+
+/** This function constructs the GIT. It should only be called once **/
+void* StdGlobalInterfaceTable_Construct() {
+  StdGlobalInterfaceTableImpl* newGIT;
+
+  newGIT = HeapAlloc(GetProcessHeap(), 0, sizeof(StdGlobalInterfaceTableImpl));
+  if (newGIT == 0) return newGIT;
+
+  ICOM_VTBL(newGIT) = &StdGlobalInterfaceTableImpl_Vtbl;
+  
+  newGIT->ref = 0; /* Initialise the reference count */
+  TRACE("Created the GIT at %p\n", newGIT);
+
+  return (void*)newGIT;
+}
+
+/** This destroys it again. It should revoke all the held interfaces first **/
+void StdGlobalInterfaceTable_Destroy(void* self) {
+  TRACE("(%p)\n", self);
+  FIXME("Revoke held interfaces here\n");
+  HeapFree(GetProcessHeap(), 0, self);
+}
+
+/***
+ * 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;
+
+  *ppvObject = 0; /* assume we don't have the interface */
+
+  /* Do we implement that interface? */
+  if (IsEqualIID(&IID_IUnknown, riid)) {
+    *ppvObject = (IGlobalInterfaceTable*) self;
+  } else if (IsEqualIID(&IID_IGlobalInterfaceTable, riid)) {
+    *ppvObject = (IGlobalInterfaceTable*) self;
+  } else return E_NOINTERFACE;
+
+  /* Now inc the refcount */
+  StdGlobalInterfaceTable_AddRef(iface);
+  return S_OK;
+}
+
+ULONG WINAPI StdGlobalInterfaceTable_AddRef(IGlobalInterfaceTable* iface) {
+  StdGlobalInterfaceTableImpl* const self = (StdGlobalInterfaceTableImpl*) iface;
+
+  self->ref++;
+  return self->ref;
+}
+
+ULONG WINAPI StdGlobalInterfaceTable_Release(IGlobalInterfaceTable* iface) {
+  StdGlobalInterfaceTableImpl* const self = (StdGlobalInterfaceTableImpl*) iface;
+
+  self->ref--;
+  if (self->ref == 0) {
+    /* Hey ho, it's time to go, so long again 'till next weeks show! */
+    StdGlobalInterfaceTable_Destroy(self);
+    return 0;
+  }
+
+  return self->ref;
+}
+
+/***
+ * Now implement the actual IGlobalInterfaceTable interface
+ */
+
+HRESULT WINAPI StdGlobalInterfaceTable_RegisterInterfaceInGlobal(IGlobalInterfaceTable* iface, IUnknown* pUnk, REFIID riid, DWORD* pdwCookie) {
+  FIXME("stub\n");
+  return E_NOTIMPL;
+}
+
+HRESULT WINAPI StdGlobalInterfaceTable_RevokeInterfaceFromGlobal(IGlobalInterfaceTable* iface, DWORD dwCookie) {
+  FIXME("stub\n");
+  return E_NOTIMPL;
+}
+
+HRESULT WINAPI StdGlobalInterfaceTable_GetInterfaceFromGlobal(IGlobalInterfaceTable* iface, DWORD dwCookie, REFIID riid, void **ppv) {
+  FIXME("stub\n");
+  return E_NOTIMPL;
+}


More information about the wine-patches mailing list