From ac23f2c810d58b5f5bfc2beac43f5bfceeb76f5c Mon Sep 17 00:00:00 2001
From: Robert Shearman <rob@codeweavers.com>
Date: Fri, 11 Mar 2005 10:18:31 +0000
Subject: [PATCH] Add outer unknown support for typelib marshaler.

---
 dlls/oleaut32/tmarshal.c | 78 +++++++++++++++++++++++++++++++---------
 1 file changed, 61 insertions(+), 17 deletions(-)

diff --git a/dlls/oleaut32/tmarshal.c b/dlls/oleaut32/tmarshal.c
index 250e9f86cc9..e341ca53850 100644
--- a/dlls/oleaut32/tmarshal.c
+++ b/dlls/oleaut32/tmarshal.c
@@ -355,6 +355,7 @@ typedef struct _TMProxyImpl {
     IRpcChannelBuffer*			chanbuf;
     IID					iid;
     CRITICAL_SECTION	crit;
+    IUnknown				*outerunknown;
 } TMProxyImpl;
 
 static HRESULT WINAPI
@@ -1426,6 +1427,43 @@ xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */)
     return status;
 }
 
+HRESULT WINAPI ProxyIUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
+{
+    TMProxyImpl *proxy = (TMProxyImpl *)iface;
+
+    TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
+
+    if (proxy->outerunknown)
+        return IUnknown_QueryInterface(proxy->outerunknown, riid, ppv);
+
+    FIXME("No interface\n");
+    return E_NOINTERFACE;
+}
+
+ULONG WINAPI ProxyIUnknown_AddRef(IUnknown *iface)
+{
+    TMProxyImpl *proxy = (TMProxyImpl *)iface;
+
+    TRACE("\n");
+
+    if (proxy->outerunknown)
+        return IUnknown_AddRef(proxy->outerunknown);
+
+    return 2; /* FIXME */
+}
+
+ULONG WINAPI ProxyIUnknown_Release(IUnknown *iface)
+{
+    TMProxyImpl *proxy = (TMProxyImpl *)iface;
+
+    TRACE("\n");
+
+    if (proxy->outerunknown)
+        return IUnknown_Release(proxy->outerunknown);
+
+    return 1; /* FIXME */
+}
+
 static HRESULT WINAPI
 PSFacBuf_CreateProxy(
     LPPSFACTORYBUFFER iface, IUnknown* pUnkOuter, REFIID riid,
@@ -1449,6 +1487,7 @@ PSFacBuf_CreateProxy(
 
     assert(sizeof(TMAsmProxy) == 12);
 
+    proxy->outerunknown = pUnkOuter;
     proxy->asmstubs = VirtualAlloc(NULL, sizeof(TMAsmProxy) * nroffuncs, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
     if (!proxy->asmstubs) {
         ERR("Could not commit pages for proxy thunks\n");
@@ -1460,17 +1499,22 @@ PSFacBuf_CreateProxy(
 
     proxy->lpvtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPBYTE)*nroffuncs);
     for (i=0;i<nroffuncs;i++) {
-	int		nrofargs;
 	TMAsmProxy	*xasm = proxy->asmstubs+i;
 
-	/* nrofargs without This */
 	switch (i) {
-	case 0: nrofargs = 2;
+	case 0:
+		proxy->lpvtbl[i] = ProxyIUnknown_QueryInterface;
+		break;
+	case 1:
+		proxy->lpvtbl[i] = ProxyIUnknown_AddRef;
 		break;
-	case 1: case 2: nrofargs = 0;
+	case 2:
+		proxy->lpvtbl[i] = ProxyIUnknown_Release;
 		break;
 	default: {
 		int j;
+		/* nrofargs without This */
+		int nrofargs;
 		hres = _get_funcdesc(tinfo,i,&fdesc,NULL,NULL);
 		if (hres) {
 		    ERR("GetFuncDesc %lx should not fail here.\n",hres);
@@ -1485,9 +1529,6 @@ PSFacBuf_CreateProxy(
 		    ERR("calling convention is not stdcall????\n");
 		    return E_FAIL;
 		}
-		break;
-	    }
-	}
 /* popl %eax	-	return ptr
  * pushl <nr>
  * pushl %eax
@@ -1497,16 +1538,19 @@ PSFacBuf_CreateProxy(
  *
  * arg3 arg2 arg1 <method> <returnptr>
  */
-	xasm->popleax	= 0x58;
-	xasm->pushlval	= 0x6a;
-	xasm->nr	= i;
-	xasm->pushleax	= 0x50;
-	xasm->lcall	= 0xe8;	/* relative jump */
-	xasm->xcall	= (DWORD)xCall;
-	xasm->xcall     -= (DWORD)&(xasm->lret);
-	xasm->lret	= 0xc2;
-	xasm->bytestopop= (nrofargs+2)*4; /* pop args, This, iMethod */
-	proxy->lpvtbl[i] = xasm;
+		xasm->popleax	= 0x58;
+		xasm->pushlval	= 0x6a;
+		xasm->nr	= i;
+		xasm->pushleax	= 0x50;
+		xasm->lcall	= 0xe8;	/* relative jump */
+		xasm->xcall	= (DWORD)xCall;
+		xasm->xcall     -= (DWORD)&(xasm->lret);
+		xasm->lret	= 0xc2;
+		xasm->bytestopop= (nrofargs+2)*4; /* pop args, This, iMethod */
+		proxy->lpvtbl[i] = xasm;
+		break;
+	    }
+	}
     }
     proxy->lpvtbl2	= &tmproxyvtable;
     /* 1 reference for the proxy and 1 for the object */
-- 
2.24.1