Index: winedefault.reg
===================================================================
RCS file: /cvsroot/rewind/rewind/winedefault.reg,v
retrieving revision 1.39
diff -u -r1.39 winedefault.reg
--- winedefault.reg	30 Jun 2003 16:47:33 -0000	1.39
+++ winedefault.reg	8 Jul 2003 22:11:34 -0000
@@ -139,10 +139,41 @@
 [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Interface\{00000001-0000-0000-C000-000000000046}\ProxyStubClsid32]
 @="{00000320-0000-0000-C000-000000000046}"
 
+# IRemUnknown, internal DCOM interface
+[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Interface\{00000131-0000-0000-C000-000000000046}]
+@="IRemUnknown"
+
+[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Interface\{00000131-0000-0000-C000-000000000046}\NumMethods]
+@="6"
+
+[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Interface\{00000131-0000-0000-C000-000000000046}\ProxyStubClsid32]
+@="{00000320-0000-0000-C000-000000000046}"
+
+# IRemUnknown2, internal DCOM interface
+[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Interface\{00000143-0000-0000-C000-000000000046}]
+@="IRemUnknown2"
+
+[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Interface\{00000143-0000-0000-C000-000000000046}\NumMethods]
+@="7"
+
+[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Interface\{00000143-0000-0000-C000-000000000046}\ProxyStubClsid32]
+@="{00000320-0000-0000-C000-000000000046}"
+
 #
 # Entries for OLEAUT32 (OLE Automation)
 #
 
+# OLE Automation built-in marshalers
+[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{00020420-0000-0000-C000-000000000046}]
+@="PSDispatch"
+
+[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{00020420-0000-0000-C000-000000000046}\InProcServer]
+@="ole2disp.dll"
+
+[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{00020420-0000-0000-C000-000000000046}\InProcServer32]
+@="oleaut32.dll"
+"ThreadingModel"="Both"
+
 # The Universal Marshaler, also known as the Type Library Marshaler.
 # (PSOAInterface = Proxy/Stub OLE Automation interface)
 [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{00020424-0000-0000-C000-000000000046}]
@@ -176,6 +207,16 @@
 
 [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\TypeLib\{00020430-0000-0000-C000-000000000046}\2.0\FLAGS]
 @="0"
+
+# IDispatch, OLE Automation's main interface
+[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Interface\{00020400-0000-0000-C000-000000000046}]
+@="IDispatch"
+
+[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Interface\{00020400-0000-0000-C000-000000000046}\NumMethods]
+@="8"
+
+[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Interface\{00020400-0000-0000-C000-000000000046}\ProxyStubClsid32]
+@="{00020420-0000-0000-C000-000000000046}"
 
 #
 # SHELL32 entries base classes of the desktop/ shelllinks
Index: dlls/ole32/Makefile.in
===================================================================
RCS file: /cvsroot/rewind/rewind/dlls/ole32/Makefile.in,v
retrieving revision 1.19
diff -u -r1.19 Makefile.in
--- dlls/ole32/Makefile.in	23 May 2003 00:56:08 -0000	1.19
+++ dlls/ole32/Makefile.in	8 Jul 2003 22:11:56 -0000
@@ -17,6 +17,7 @@
 	compobj.c \
 	compositemoniker.c \
 	datacache.c \
+	dcom_p.c \
 	defaulthandler.c \
 	errorinfo.c \
 	filemoniker.c \
@@ -24,7 +25,6 @@
 	hglobalstream.c \
 	ifs.c \
 	itemmoniker.c \
-	marshal.c \
 	memlockbytes.c \
 	moniker.c \
 	ole16.c \
@@ -34,12 +34,12 @@
 	ole2nls.c \
 	ole32_main.c \
 	oleobj.c \
-	oleproxy.c \
-	rpc.c \
+	proxy.c \
 	stg_bigblockfile.c \
 	stg_stream.c \
 	storage.c \
-	storage32.c
+	storage32.c \
+	unknwn_p.c
 
 RC_SRCS = \
 	ole32res.rc
Index: dlls/ole32/compobj.c
===================================================================
RCS file: /cvsroot/rewind/rewind/dlls/ole32/compobj.c,v
retrieving revision 1.61
diff -u -r1.61 compobj.c
--- dlls/ole32/compobj.c	30 Jun 2003 14:44:26 -0000	1.61
+++ dlls/ole32/compobj.c	8 Jul 2003 22:11:56 -0000
@@ -21,6 +21,9 @@
 #include "ole2.h"
 #include "ole2ver.h"
 #include "rpc.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
 #include "winerror.h"
 #include "winreg.h"
 #include "wownt32.h"
@@ -40,7 +43,6 @@
  */
 HINSTANCE       COMPOBJ_hInstance32 = 0;
 
-static HRESULT COM_GetRegisteredClassObject(REFCLSID rclsid, DWORD dwClsContext, LPUNKNOWN*  ppUnk);
 static void COM_RevokeAllClasses();
 static void COM_ExternalLockFreeList();
 
@@ -65,11 +67,10 @@
 typedef struct tagRegisteredClass
 {
   CLSID     classIdentifier;
-  LPUNKNOWN classObject;
   DWORD     runContext;
   DWORD     connectFlags;
   DWORD     dwCookie;
-  HANDLE    hThread; /* only for localserver */
+  LPSTREAM  pMarshal;
   struct tagRegisteredClass* nextClass;
 } RegisteredClass;
 
@@ -96,7 +97,6 @@
 static OpenDll *openDllList = NULL; /* linked list of open dlls */
 
 static const char aptWinClass[] = "WINE_OLE32_APT_CLASS";
-static LRESULT CALLBACK COM_AptWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
 
 static void COMPOBJ_DLLList_Add(HANDLE hLibrary);
 static void COMPOBJ_DllList_FreeUnused(int Timeout);
@@ -854,15 +854,17 @@
  *
  * Params:
  *   rclsid        Class ID of the class to find.
- *   dwClsContext  Class context to match.
- *   ppv           [out] returns a pointer to the class object. Complying
+ *   ppUnk         [out] returns a pointer to the class object. Complying
  *                 to normal COM usage, this method will increase the
  *                 reference count on this object.
+ *   pObjRef       [out] DCOM standard object reference
+ *   pMIF          [out] DCOM marshalled interface pointer
  */
-static HRESULT COM_GetRegisteredClassObject(
-	REFCLSID    rclsid,
-	DWORD       dwClsContext,
-	LPUNKNOWN*  ppUnk)
+HRESULT COM_GetRegisteredClassObject(
+	REFCLSID rclsid,
+	LPUNKNOWN* ppUnk,
+	STDOBJREF* pObjRef,
+	MInterfacePointer** ppMIF)
 {
   HRESULT hr = S_FALSE;
   RegisteredClass* curClass;
@@ -870,11 +872,6 @@
   EnterCriticalSection( &csRegisteredClassList );
 
   /*
-   * Sanity check
-   */
-  assert(ppUnk!=0);
-
-  /*
    * Iterate through the whole list and try to match the class ID.
    */
   curClass = firstRegisteredClass;
@@ -887,18 +884,28 @@
     if (IsEqualGUID(&(curClass->classIdentifier), rclsid))
     {
       /*
-       * Since we don't do out-of process or DCOM just right away, let's ignore the
-       * class context.
+       * We have a match, unmarshal the class object reference.
        */
+      if (ppUnk || pObjRef || ppMIF)
+      {
+        LARGE_INTEGER pos;
 
-      /*
-       * We have a match, return the pointer to the class object.
-       */
-      *ppUnk = curClass->classObject;
-
-      IUnknown_AddRef(curClass->classObject);
+        pos.s.LowPart = 0;
+        pos.s.HighPart = 0;
+        IStream_Seek(curClass->pMarshal, pos, 0, NULL);
+      }
+      if (ppUnk) {
+        hr = CoUnmarshalInterface(curClass->pMarshal, &IID_IUnknown, (void**)ppUnk);
+      }
+      else if (pObjRef) {
+        hr = COM_GetStdObjRef(curClass->pMarshal, pObjRef, NULL);
+      }
+      else if (ppMIF) {
+        FIXME("create MInterfacePointer\n");
+        hr = E_FAIL;
+      }
+      else hr = S_OK;
 
-      hr = S_OK;
       goto end;
     }
 
@@ -916,83 +923,6 @@
   return hr;
 }
 
-static DWORD WINAPI
-_LocalServerThread(LPVOID param) {
-    HANDLE		hPipe;
-    char 		pipefn[200];
-    RegisteredClass *newClass = (RegisteredClass*)param;
-    HRESULT		hres;
-    IStream		*pStm;
-    STATSTG		ststg;
-    unsigned char	*buffer;
-    int 		buflen;
-    IClassFactory	*classfac;
-    LARGE_INTEGER	seekto;
-    ULARGE_INTEGER	newpos;
-    ULONG		res;
-
-    TRACE("Starting threader for %s.\n",debugstr_guid(&newClass->classIdentifier));
-    strcpy(pipefn,PIPEPREF);
-    WINE_StringFromCLSID(&newClass->classIdentifier,pipefn+strlen(PIPEPREF));
-
-    hres = IUnknown_QueryInterface(newClass->classObject,&IID_IClassFactory,(LPVOID*)&classfac);
-    if (hres) return hres;
-
-    hres = CreateStreamOnHGlobal(0,TRUE,&pStm);
-    if (hres) {
-	FIXME("Failed to create stream on hglobal.\n");
-	return hres;
-    }
-    hres = CoMarshalInterface(pStm,&IID_IClassFactory,(LPVOID)classfac,0,NULL,0);
-    if (hres) {
-	FIXME("CoMarshalInterface failed, %lx!\n",hres);
-	return hres;
-    }
-    hres = IStream_Stat(pStm,&ststg,0);
-    if (hres) return hres;
-
-    buflen = ststg.cbSize.s.LowPart;
-    buffer = HeapAlloc(GetProcessHeap(),0,buflen);
-    seekto.s.LowPart = 0;
-    seekto.s.HighPart = 0;
-    hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos);
-    if (hres) {
-	FIXME("IStream_Seek failed, %lx\n",hres);
-	return hres;
-    }
-    hres = IStream_Read(pStm,buffer,buflen,&res);
-    if (hres) {
-	FIXME("Stream Read failed, %lx\n",hres);
-	return hres;
-    }
-    IStream_Release(pStm);
-
-    while (1) {
-	hPipe = CreateNamedPipeA(
-	    pipefn,
-	    PIPE_ACCESS_DUPLEX,
-	    PIPE_TYPE_BYTE|PIPE_WAIT,
-	    PIPE_UNLIMITED_INSTANCES,
-	    4096,
-	    4096,
-	    NMPWAIT_USE_DEFAULT_WAIT,
-	    NULL
-	);
-	if (hPipe == INVALID_HANDLE_VALUE) {
-	    FIXME("pipe creation failed for %s, le is %lx\n",pipefn,GetLastError());
-	    return 1;
-	}
-	if (!ConnectNamedPipe(hPipe,NULL)) {
-	    ERR("Failure during ConnectNamedPipe %lx, ABORT!\n",GetLastError());
-	    CloseHandle(hPipe);
-	    continue;
-	}
-	WriteFile(hPipe,buffer,buflen,&res,NULL);
-	CloseHandle(hPipe);
-    }
-    return 0;
-}
-
 /******************************************************************************
  *		CoRegisterClassObject	[OLE32.36]
  *
@@ -1009,11 +939,15 @@
 )
 {
   RegisteredClass* newClass;
-  LPUNKNOWN        foundObject;
+  DWORD            dwCtx;
   HRESULT          hr;
+  char buf[80];
+
+  WINE_StringFromCLSID(rclsid,buf);
 
   TRACE("(%s,%p,0x%08lx,0x%08lx,%p)\n",
-	debugstr_guid(rclsid),pUnk,dwClsContext,flags,lpdwRegister);
+	buf,pUnk,dwClsContext,flags,lpdwRegister);
+  TRACE("vtbl=%p\n", pUnk->lpVtbl);
 
   if ( (lpdwRegister==0) || (pUnk==0) )
     return E_INVALIDARG;
@@ -1024,18 +958,24 @@
    * First, check if the class is already registered.
    * If it is, this should cause an error.
    */
-  hr = COM_GetRegisteredClassObject(rclsid, dwClsContext, &foundObject);
-  if (hr == S_OK) {
-    IUnknown_Release(foundObject);
+  hr = COM_GetRegisteredClassObject(rclsid, NULL, NULL, NULL);
+
+  if (hr == S_OK)
     return CO_E_OBJISREG;
-  }
 
-  newClass = HeapAlloc(GetProcessHeap(), 0, sizeof(RegisteredClass));
+  /*
+   * If it is not registered, we must create a new entry for this class and
+   * append it to the registered class list.
+   * We use the address of the chain node as the cookie since we are sure it's
+   * unique.
+   */
+  newClass = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RegisteredClass));
   if ( newClass == NULL )
     return E_OUTOFMEMORY;
 
-  EnterCriticalSection( &csRegisteredClassList );
-
+  /*
+   * Initialize the node.
+   */
   newClass->classIdentifier = *rclsid;
   newClass->runContext      = dwClsContext;
   newClass->connectFlags    = flags;
@@ -1044,26 +984,46 @@
    * unique.
    */
   newClass->dwCookie        = (DWORD)newClass;
-  newClass->nextClass       = firstRegisteredClass;
 
   /*
-   * Since we're making a copy of the object pointer, we have to increase its
-   * reference count.
+   * Marshal a reference to the class object.
+   */
+  hr = CreateStreamOnHGlobal(0, TRUE, &newClass->pMarshal);
+  if (FAILED(hr)) {
+    HeapFree(GetProcessHeap(), 0, newClass);
+    return hr;
+  }
+
+  if (dwClsContext & CLSCTX_REMOTE_SERVER) dwCtx = MSHCTX_DIFFERENTMACHINE;
+  else if (dwClsContext & CLSCTX_LOCAL_SERVER) dwCtx = MSHCTX_LOCAL;
+  else dwCtx = MSHCTX_INPROC;
+
+  hr = CoMarshalInterface(newClass->pMarshal, &IID_IUnknown, pUnk, dwCtx, NULL, MSHLFLAGS_TABLESTRONG);
+  if (FAILED(hr)) {
+    IStream_Release(newClass->pMarshal);
+    HeapFree(GetProcessHeap(), 0, newClass);
+    return hr;
+  }
+
+  /*
+   * Insert the class into the chain.
    */
-  newClass->classObject     = pUnk;
-  IUnknown_AddRef(newClass->classObject);
+  EnterCriticalSection( &csRegisteredClassList );
 
+  newClass->nextClass       = firstRegisteredClass;
   firstRegisteredClass = newClass;
   LeaveCriticalSection( &csRegisteredClassList );
 
-  *lpdwRegister = newClass->dwCookie;
+  /*
+   * Register the exported object.
+   */
+  COM_RpcExportClass(&newClass->classIdentifier, dwCtx);
 
-  if (dwClsContext & CLSCTX_LOCAL_SERVER) {
-      DWORD tid;
+  /*
+   * Assign the out parameter (cookie)
+   */
+  *lpdwRegister = newClass->dwCookie;
 
-      STUBMGR_Start();
-      newClass->hThread=CreateThread(NULL,0,_LocalServerThread,newClass,0,&tid);
-  }
   return S_OK;
 }
 
@@ -1098,15 +1058,23 @@
      */
     if (curClass->dwCookie == dwRegister)
     {
+      LARGE_INTEGER pos;
+
       /*
        * Remove the class from the chain.
        */
       *prevClassLink = curClass->nextClass;
 
       /*
-       * Release the reference to the class object.
+       * Release the marshalled reference.
        */
-      IUnknown_Release(curClass->classObject);
+      pos.s.LowPart = 0;
+      pos.s.HighPart = 0;
+      IStream_Seek(curClass->pMarshal, pos, 0, NULL);
+
+      CoReleaseMarshalData(curClass->pMarshal);
+
+      IStream_Release(curClass->pMarshal);
 
       /*
        * Free the memory used by the chain node.
@@ -1129,44 +1097,11 @@
   /*
    * If we get to here, we haven't found our class.
    */
-  return hr;
+  return E_INVALIDARG;
 }
 
-static HRESULT WINAPI Remote_CoGetClassObject(
-    REFCLSID rclsid, DWORD dwClsContext, COSERVERINFO *pServerInfo,
-    REFIID iid, LPVOID *ppv
-) {
-  HKEY		key;
-  char 		buf[200];
-  HRESULT	hres = E_UNEXPECTED;
-  char		xclsid[80];
-  WCHAR 	dllName[MAX_PATH+1];
-  DWORD 	dllNameLen = sizeof(dllName);
-  STARTUPINFOW	sinfo;
-  PROCESS_INFORMATION	pinfo;
-
-  WINE_StringFromCLSID((LPCLSID)rclsid,xclsid);
-
-  sprintf(buf,"CLSID\\%s\\LocalServer32",xclsid);
-  hres = RegOpenKeyExA(HKEY_CLASSES_ROOT, buf, 0, KEY_READ, &key);
-
-  if (hres != ERROR_SUCCESS)
-      return REGDB_E_CLASSNOTREG;
-
-  memset(dllName,0,sizeof(dllName));
-  hres= RegQueryValueExW(key,NULL,NULL,NULL,(LPBYTE)dllName,&dllNameLen);
-  if (hres)
-	  return REGDB_E_CLASSNOTREG; /* FIXME: check retval */
-  RegCloseKey(key);
-
-  TRACE("found LocalServer32 exe %s\n", debugstr_w(dllName));
-
-  memset(&sinfo,0,sizeof(sinfo));
-  sinfo.cb = sizeof(sinfo);
-  if (!CreateProcessW(NULL,dllName,NULL,NULL,FALSE,0,NULL,NULL,&sinfo,&pinfo))
-      return E_FAIL;
-  return create_marshalled_proxy(rclsid,iid,ppv);
-}
+typedef HRESULT (CALLBACK *DllGetClassObjectFunc)(REFCLSID clsid,
+			  REFIID iid, LPVOID *ppv);
 
 /***********************************************************************
  *	compobj_RegReadPath	[internal]
@@ -1211,7 +1146,6 @@
     HRESULT	hres = E_UNEXPECTED;
     char	xclsid[80];
     HINSTANCE hLibrary;
-    typedef HRESULT (CALLBACK *DllGetClassObjectFunc)(REFCLSID clsid, REFIID iid, LPVOID *ppv);
     DllGetClassObjectFunc DllGetClassObject;
 
     WINE_StringFromCLSID((LPCLSID)rclsid,xclsid);
@@ -1227,7 +1161,7 @@
      * First, try and see if we can't match the class ID with one of the
      * registered classes.
      */
-    if (S_OK == COM_GetRegisteredClassObject(rclsid, dwClsContext, &regClassObject))
+    if (S_OK == COM_GetRegisteredClassObject(rclsid, &regClassObject, NULL, NULL))
     {
       /*
        * Get the required interface from the retrieved pointer.
@@ -1274,9 +1208,54 @@
     }
 
     /* Next try out of process */
-    if (CLSCTX_LOCAL_SERVER & dwClsContext)
-    {
-        return Remote_CoGetClassObject(rclsid,dwClsContext,pServerInfo,iid,ppv);
+    if (CLSCTX_LOCAL_SERVER & dwClsContext) {
+	char keyname[MAX_PATH];
+	char exepath[MAX_PATH+1];
+	STARTUPINFOA si;
+	PROCESS_INFORMATION pi;
+	int wait;
+
+	hres = COM_RpcImportClass(ppv, rclsid, iid, NULL);
+	if (hres != EPT_S_NOT_REGISTERED)
+	    return hres;
+
+	/* we need to load the server
+	 * (FIXME: this is a job for IRemoteActivation,
+	 * but I haven't implemented that stuff) */
+	/* FIXME: protect this with a named mutex,
+	 * so the local server won't be launched twice */
+	sprintf(keyname,"CLSID\\%s\\LocalServer32",xclsid);
+	if (compobj_RegReadPath(keyname, NULL, exepath, sizeof(exepath)) != ERROR_SUCCESS) {
+	    /* failure: CLSID is not found in registry */
+	    WARN("class %s not registred\n", xclsid);
+	    return REGDB_E_CLASSNOTREG;
+	}
+	TRACE("found LocalServer32 app %s\n", exepath);
+
+	/* create process (FIXME: creation flags?) */
+	memset(&si, 0, sizeof(si));
+	si.cb = sizeof(si);
+	/* FIXME: I think we're supposed to add an argument,
+	 * see MS's COM samples */
+	if (!CreateProcessA(exepath, NULL, NULL, NULL, FALSE, 0,
+			    NULL, NULL, &si, &pi)) {
+	    FIXME("couldn't load LocalServer32 app %s\n", exepath);
+	    return CO_E_APPNOTFOUND;
+	}
+
+	/* wait for the local server to load
+	 * (don't remember how long MS gives it, was it 2 minutes?) */
+	wait = 0;
+	do {
+	    Sleep(1000);
+	    wait++;
+	    hres = COM_RpcImportClass(ppv, rclsid, iid, NULL);
+	} while (hres == EPT_S_NOT_REGISTERED && wait < 120);
+	if (hres == EPT_S_NOT_REGISTERED) {
+	    /* wait failed */
+	    return CO_E_APPDIDNTREG;
+	}
+	return hres;
     }
 
     /* Finally try remote */
Index: dlls/ole32/compobj_private.h
===================================================================
RCS file: /cvsroot/rewind/rewind/dlls/ole32/compobj_private.h,v
retrieving revision 1.5
diff -u -r1.5 compobj_private.h
--- dlls/ole32/compobj_private.h	30 Jun 2003 14:44:26 -0000	1.5
+++ dlls/ole32/compobj_private.h	8 Jul 2003 22:11:56 -0000
@@ -191,7 +191,17 @@
   return apt;
 }
 
+/* proxy.c */
+void COM_RpcInit(void);
+void COM_RpcExportClass(REFCLSID rclsid, DWORD dwCtx);
+HRESULT COM_RpcImportClass(LPVOID *ppv, REFCLSID rclsid, REFIID riid, LPSTR server);
+
+HRESULT COM_GetStdObjRef(IStream *pStm, STDOBJREF *pObjRef, LPIID piid);
+
+LRESULT CALLBACK COM_AptWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
 /* compobj.c */
 HWND COM_GetApartmentWin(OXID oxid);
+HRESULT COM_GetRegisteredClassObject(REFCLSID rclsid, LPUNKNOWN* ppUnk, STDOBJREF* pObjRef, MInterfacePointer** ppMIF);
 
 #endif /* __WINE_OLE_COMPOBJ_H */
--- /dev/null	2003-01-10 01:23:22.000000000 +0100
+++ dlls/ole32/dcom_p.c	2003-05-23 21:15:39.000000000 +0200
@@ -0,0 +1,1889 @@
+/* this ALWAYS GENERATED file contains the proxy stub code */
+
+
+/* File created by MIDL compiler version 5.01.0164 */
+/* at Fri May 23 15:10:07 2003
+ */
+/* Compiler settings for dcom.idl:
+    Os (OptLev=s), W1, Zp8, env=Win32, ms_ext, c_ext
+    error checks: allocation ref bounds_check enum stub_data 
+*/
+//@@MIDL_FILE_HEADING(  )
+
+
+/* verify that the <rpcproxy.h> version is high enough to compile this file*/
+#ifndef __REDQ_RPCPROXY_H_VERSION__
+#define __REQUIRED_RPCPROXY_H_VERSION__ 440
+#endif
+
+
+#undef __WINE__
+#include "rpcproxy.h"
+#ifndef __RPCPROXY_H_VERSION__
+#error this stub requires an updated version of <rpcproxy.h>
+#endif // __RPCPROXY_H_VERSION__
+
+
+#include "dcom.h"
+
+#define TYPE_FORMAT_STRING_SIZE   531                               
+#define PROC_FORMAT_STRING_SIZE   225                               
+
+typedef struct _MIDL_TYPE_FORMAT_STRING
+    {
+    short          Pad;
+    unsigned char  Format[ TYPE_FORMAT_STRING_SIZE ];
+    } MIDL_TYPE_FORMAT_STRING;
+
+typedef struct _MIDL_PROC_FORMAT_STRING
+    {
+    short          Pad;
+    unsigned char  Format[ PROC_FORMAT_STRING_SIZE ];
+    } MIDL_PROC_FORMAT_STRING;
+
+
+extern const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;
+extern const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;
+
+
+/* Standard interface: ObjectRpcBaseTypes, ver. 0.0,
+   GUID={0x99fcfe60,0x5260,0x101b,{0xbb,0xcb,0x00,0xaa,0x00,0x21,0x34,0x7a}} */
+
+
+/* Object interface: IUnknown, ver. 0.0,
+   GUID={0x00000000,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}} */
+
+
+/* Object interface: IRemUnknown, ver. 0.0,
+   GUID={0x00000131,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}} */
+
+
+extern const MIDL_STUB_DESC Object_StubDesc;
+
+
+#pragma code_seg(".orpc")
+
+HRESULT STDMETHODCALLTYPE IRemUnknown_RemQueryInterface_Proxy( 
+    IRemUnknown __RPC_FAR * This,
+    /* [in] */ REFIPID ripid,
+    /* [in] */ unsigned long cRefs,
+    /* [in] */ unsigned short cIids,
+    /* [size_is][in] */ IID __RPC_FAR *iids,
+    /* [size_is][size_is][out] */ REMQIRESULT __RPC_FAR *__RPC_FAR *ppQIResults)
+{
+
+    HRESULT _RetVal;
+    
+    RPC_MESSAGE _RpcMessage;
+    
+    MIDL_STUB_MESSAGE _StubMsg;
+    
+    if(ppQIResults)
+        {
+        *ppQIResults = 0;
+        }
+    RpcTryExcept
+        {
+        NdrProxyInitialize(
+                      ( void __RPC_FAR *  )This,
+                      ( PRPC_MESSAGE  )&_RpcMessage,
+                      ( PMIDL_STUB_MESSAGE  )&_StubMsg,
+                      ( PMIDL_STUB_DESC  )&Object_StubDesc,
+                      3);
+        
+        
+        
+        if(!ripid)
+            {
+            RpcRaiseException(RPC_X_NULL_REF_POINTER);
+            }
+        if(!iids)
+            {
+            RpcRaiseException(RPC_X_NULL_REF_POINTER);
+            }
+        if(!ppQIResults)
+            {
+            RpcRaiseException(RPC_X_NULL_REF_POINTER);
+            }
+        RpcTryFinally
+            {
+            
+            _StubMsg.BufferLength = 0U + 11U + 4U + 7U;
+            NdrSimpleStructBufferSize( (PMIDL_STUB_MESSAGE) &_StubMsg,
+                                       (unsigned char __RPC_FAR *)ripid,
+                                       (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[54] );
+            
+            _StubMsg.MaxCount = cIids;
+            
+            NdrConformantArrayBufferSize( (PMIDL_STUB_MESSAGE) &_StubMsg,
+                                          (unsigned char __RPC_FAR *)iids,
+                                          (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[360] );
+            
+            NdrProxyGetBuffer(This, &_StubMsg);
+            NdrSimpleStructMarshall( (PMIDL_STUB_MESSAGE)& _StubMsg,
+                                     (unsigned char __RPC_FAR *)ripid,
+                                     (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[54] );
+            
+            *(( unsigned long __RPC_FAR * )_StubMsg.Buffer)++ = cRefs;
+            
+            *(( unsigned short __RPC_FAR * )_StubMsg.Buffer)++ = cIids;
+            
+            _StubMsg.MaxCount = cIids;
+            
+            NdrConformantArrayMarshall( (PMIDL_STUB_MESSAGE)& _StubMsg,
+                                        (unsigned char __RPC_FAR *)iids,
+                                        (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[360] );
+            
+            NdrProxySendReceive(This, &_StubMsg);
+            
+            if ( (_RpcMessage.DataRepresentation & 0X0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION )
+                NdrConvert( (PMIDL_STUB_MESSAGE) &_StubMsg, (PFORMAT_STRING) &__MIDL_ProcFormatString.Format[166] );
+            
+            NdrPointerUnmarshall( (PMIDL_STUB_MESSAGE) &_StubMsg,
+                                  (unsigned char __RPC_FAR * __RPC_FAR *)&ppQIResults,
+                                  (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[374],
+                                  (unsigned char)0 );
+            
+            _StubMsg.Buffer = (unsigned char __RPC_FAR *)(((long)_StubMsg.Buffer + 3) & ~ 0x3);
+            _RetVal = *(( HRESULT __RPC_FAR * )_StubMsg.Buffer)++;
+            
+            }
+        RpcFinally
+            {
+            NdrProxyFreeBuffer(This, &_StubMsg);
+            
+            }
+        RpcEndFinally
+        
+        }
+    RpcExcept(_StubMsg.dwStubPhase != PROXY_SENDRECEIVE)
+        {
+        _StubMsg.MaxCount = cIids;
+        
+        NdrClearOutParameters(
+                         ( PMIDL_STUB_MESSAGE  )&_StubMsg,
+                         ( PFORMAT_STRING  )&__MIDL_TypeFormatString.Format[374],
+                         ( void __RPC_FAR * )ppQIResults);
+        _RetVal = NdrProxyErrorHandler(RpcExceptionCode());
+        }
+    RpcEndExcept
+    return _RetVal;
+}
+
+void __RPC_STUB IRemUnknown_RemQueryInterface_Stub(
+    IRpcStubBuffer *This,
+    IRpcChannelBuffer *_pRpcChannelBuffer,
+    PRPC_MESSAGE _pRpcMessage,
+    DWORD *_pdwStubPhase)
+{
+    REMQIRESULT __RPC_FAR *_M21;
+    HRESULT _RetVal;
+    MIDL_STUB_MESSAGE _StubMsg;
+    unsigned short cIids;
+    unsigned long cRefs;
+    IID __RPC_FAR *iids;
+    REMQIRESULT __RPC_FAR *__RPC_FAR *ppQIResults;
+    REFIPID ripid;
+    
+NdrStubInitialize(
+                     _pRpcMessage,
+                     &_StubMsg,
+                     &Object_StubDesc,
+                     _pRpcChannelBuffer);
+    ( REFIPID  )ripid = 0;
+    ( IID __RPC_FAR * )iids = 0;
+    ( REMQIRESULT __RPC_FAR *__RPC_FAR * )ppQIResults = 0;
+    RpcTryFinally
+        {
+        if ( (_pRpcMessage->DataRepresentation & 0X0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION )
+            NdrConvert( (PMIDL_STUB_MESSAGE) &_StubMsg, (PFORMAT_STRING) &__MIDL_ProcFormatString.Format[166] );
+        
+        NdrSimpleStructUnmarshall( (PMIDL_STUB_MESSAGE) &_StubMsg,
+                                   (unsigned char __RPC_FAR * __RPC_FAR *)&ripid,
+                                   (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[54],
+                                   (unsigned char)0 );
+        
+        cRefs = *(( unsigned long __RPC_FAR * )_StubMsg.Buffer)++;
+        
+        cIids = *(( unsigned short __RPC_FAR * )_StubMsg.Buffer)++;
+        
+        NdrConformantArrayUnmarshall( (PMIDL_STUB_MESSAGE) &_StubMsg,
+                                      (unsigned char __RPC_FAR * __RPC_FAR *)&iids,
+                                      (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[360],
+                                      (unsigned char)0 );
+        
+        ppQIResults = &_M21;
+        _M21 = 0;
+        
+        *_pdwStubPhase = STUB_CALL_SERVER;
+        _RetVal = (((IRemUnknown*) ((CStdStubBuffer *)This)->pvServerObject)->lpVtbl) -> RemQueryInterface(
+                     (IRemUnknown *) ((CStdStubBuffer *)This)->pvServerObject,
+                     ripid,
+                     cRefs,
+                     cIids,
+                     iids,
+                     ppQIResults);
+        
+        *_pdwStubPhase = STUB_MARSHAL;
+        
+        _StubMsg.BufferLength = 8U + 8U;
+        _StubMsg.MaxCount = cIids;
+        
+        NdrPointerBufferSize( (PMIDL_STUB_MESSAGE) &_StubMsg,
+                              (unsigned char __RPC_FAR *)ppQIResults,
+                              (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[374] );
+        
+        _StubMsg.BufferLength += 16;
+        
+        NdrStubGetBuffer(This, _pRpcChannelBuffer, &_StubMsg);
+        _StubMsg.MaxCount = cIids;
+        
+        NdrPointerMarshall( (PMIDL_STUB_MESSAGE)& _StubMsg,
+                            (unsigned char __RPC_FAR *)ppQIResults,
+                            (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[374] );
+        
+        _StubMsg.Buffer = (unsigned char __RPC_FAR *)(((long)_StubMsg.Buffer + 3) & ~ 0x3);
+        *(( HRESULT __RPC_FAR * )_StubMsg.Buffer)++ = _RetVal;
+        
+        }
+    RpcFinally
+        {
+        _StubMsg.MaxCount = cIids;
+        
+        NdrPointerFree( &_StubMsg,
+                        (unsigned char __RPC_FAR *)ppQIResults,
+                        &__MIDL_TypeFormatString.Format[374] );
+        
+        }
+    RpcEndFinally
+    _pRpcMessage->BufferLength = 
+        (unsigned int)((long)_StubMsg.Buffer - (long)_pRpcMessage->Buffer);
+    
+}
+
+
+HRESULT STDMETHODCALLTYPE IRemUnknown_RemAddRef_Proxy( 
+    IRemUnknown __RPC_FAR * This,
+    /* [in] */ unsigned short cInterfaceRefs,
+    /* [size_is][in] */ REMINTERFACEREF __RPC_FAR *InterfaceRefs,
+    /* [size_is][out] */ HRESULT __RPC_FAR *pResults)
+{
+
+    HRESULT _RetVal;
+    
+    RPC_MESSAGE _RpcMessage;
+    
+    MIDL_STUB_MESSAGE _StubMsg;
+    
+    RpcTryExcept
+        {
+        NdrProxyInitialize(
+                      ( void __RPC_FAR *  )This,
+                      ( PRPC_MESSAGE  )&_RpcMessage,
+                      ( PMIDL_STUB_MESSAGE  )&_StubMsg,
+                      ( PMIDL_STUB_DESC  )&Object_StubDesc,
+                      4);
+        
+        
+        
+        if(!InterfaceRefs)
+            {
+            RpcRaiseException(RPC_X_NULL_REF_POINTER);
+            }
+        if(!pResults)
+            {
+            RpcRaiseException(RPC_X_NULL_REF_POINTER);
+            }
+        RpcTryFinally
+            {
+            
+            _StubMsg.BufferLength = 2U + 4U;
+            _StubMsg.MaxCount = cInterfaceRefs;
+            
+            NdrConformantArrayBufferSize( (PMIDL_STUB_MESSAGE) &_StubMsg,
+                                          (unsigned char __RPC_FAR *)InterfaceRefs,
+                                          (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[436] );
+            
+            NdrProxyGetBuffer(This, &_StubMsg);
+            *(( unsigned short __RPC_FAR * )_StubMsg.Buffer)++ = cInterfaceRefs;
+            
+            _StubMsg.MaxCount = cInterfaceRefs;
+            
+            NdrConformantArrayMarshall( (PMIDL_STUB_MESSAGE)& _StubMsg,
+                                        (unsigned char __RPC_FAR *)InterfaceRefs,
+                                        (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[436] );
+            
+            NdrProxySendReceive(This, &_StubMsg);
+            
+            if ( (_RpcMessage.DataRepresentation & 0X0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION )
+                NdrConvert( (PMIDL_STUB_MESSAGE) &_StubMsg, (PFORMAT_STRING) &__MIDL_ProcFormatString.Format[184] );
+            
+            NdrConformantArrayUnmarshall( (PMIDL_STUB_MESSAGE) &_StubMsg,
+                                          (unsigned char __RPC_FAR * __RPC_FAR *)&pResults,
+                                          (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[454],
+                                          (unsigned char)0 );
+            
+            _RetVal = *(( HRESULT __RPC_FAR * )_StubMsg.Buffer)++;
+            
+            }
+        RpcFinally
+            {
+            NdrProxyFreeBuffer(This, &_StubMsg);
+            
+            }
+        RpcEndFinally
+        
+        }
+    RpcExcept(_StubMsg.dwStubPhase != PROXY_SENDRECEIVE)
+        {
+        _StubMsg.MaxCount = cInterfaceRefs;
+        
+        NdrClearOutParameters(
+                         ( PMIDL_STUB_MESSAGE  )&_StubMsg,
+                         ( PFORMAT_STRING  )&__MIDL_TypeFormatString.Format[450],
+                         ( void __RPC_FAR * )pResults);
+        _RetVal = NdrProxyErrorHandler(RpcExceptionCode());
+        }
+    RpcEndExcept
+    return _RetVal;
+}
+
+void __RPC_STUB IRemUnknown_RemAddRef_Stub(
+    IRpcStubBuffer *This,
+    IRpcChannelBuffer *_pRpcChannelBuffer,
+    PRPC_MESSAGE _pRpcMessage,
+    DWORD *_pdwStubPhase)
+{
+    REMINTERFACEREF __RPC_FAR *InterfaceRefs;
+    HRESULT _RetVal;
+    MIDL_STUB_MESSAGE _StubMsg;
+    unsigned short cInterfaceRefs;
+    HRESULT __RPC_FAR *pResults;
+    
+NdrStubInitialize(
+                     _pRpcMessage,
+                     &_StubMsg,
+                     &Object_StubDesc,
+                     _pRpcChannelBuffer);
+    ( REMINTERFACEREF __RPC_FAR * )InterfaceRefs = 0;
+    ( HRESULT __RPC_FAR * )pResults = 0;
+    RpcTryFinally
+        {
+        if ( (_pRpcMessage->DataRepresentation & 0X0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION )
+            NdrConvert( (PMIDL_STUB_MESSAGE) &_StubMsg, (PFORMAT_STRING) &__MIDL_ProcFormatString.Format[184] );
+        
+        cInterfaceRefs = *(( unsigned short __RPC_FAR * )_StubMsg.Buffer)++;
+        
+        NdrConformantArrayUnmarshall( (PMIDL_STUB_MESSAGE) &_StubMsg,
+                                      (unsigned char __RPC_FAR * __RPC_FAR *)&InterfaceRefs,
+                                      (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[436],
+                                      (unsigned char)0 );
+        
+        pResults = NdrAllocate(&_StubMsg,cInterfaceRefs * 4);
+        
+        *_pdwStubPhase = STUB_CALL_SERVER;
+        _RetVal = (((IRemUnknown*) ((CStdStubBuffer *)This)->pvServerObject)->lpVtbl) -> RemAddRef(
+             (IRemUnknown *) ((CStdStubBuffer *)This)->pvServerObject,
+             cInterfaceRefs,
+             InterfaceRefs,
+             pResults);
+        
+        *_pdwStubPhase = STUB_MARSHAL;
+        
+        _StubMsg.BufferLength = 4U + 7U;
+        _StubMsg.MaxCount = cInterfaceRefs;
+        
+        NdrConformantArrayBufferSize( (PMIDL_STUB_MESSAGE) &_StubMsg,
+                                      (unsigned char __RPC_FAR *)pResults,
+                                      (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[454] );
+        
+        _StubMsg.BufferLength += 16;
+        
+        NdrStubGetBuffer(This, _pRpcChannelBuffer, &_StubMsg);
+        _StubMsg.MaxCount = cInterfaceRefs;
+        
+        NdrConformantArrayMarshall( (PMIDL_STUB_MESSAGE)& _StubMsg,
+                                    (unsigned char __RPC_FAR *)pResults,
+                                    (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[454] );
+        
+        *(( HRESULT __RPC_FAR * )_StubMsg.Buffer)++ = _RetVal;
+        
+        }
+    RpcFinally
+        {
+        if ( pResults )
+            _StubMsg.pfnFree( pResults );
+        
+        }
+    RpcEndFinally
+    _pRpcMessage->BufferLength = 
+        (unsigned int)((long)_StubMsg.Buffer - (long)_pRpcMessage->Buffer);
+    
+}
+
+
+HRESULT STDMETHODCALLTYPE IRemUnknown_RemRelease_Proxy( 
+    IRemUnknown __RPC_FAR * This,
+    /* [in] */ unsigned short cInterfaceRefs,
+    /* [size_is][in] */ REMINTERFACEREF __RPC_FAR *InterfaceRefs)
+{
+
+    HRESULT _RetVal;
+    
+    RPC_MESSAGE _RpcMessage;
+    
+    MIDL_STUB_MESSAGE _StubMsg;
+    
+    RpcTryExcept
+        {
+        NdrProxyInitialize(
+                      ( void __RPC_FAR *  )This,
+                      ( PRPC_MESSAGE  )&_RpcMessage,
+                      ( PMIDL_STUB_MESSAGE  )&_StubMsg,
+                      ( PMIDL_STUB_DESC  )&Object_StubDesc,
+                      5);
+        
+        
+        
+        if(!InterfaceRefs)
+            {
+            RpcRaiseException(RPC_X_NULL_REF_POINTER);
+            }
+        RpcTryFinally
+            {
+            
+            _StubMsg.BufferLength = 2U + 4U;
+            _StubMsg.MaxCount = cInterfaceRefs;
+            
+            NdrConformantArrayBufferSize( (PMIDL_STUB_MESSAGE) &_StubMsg,
+                                          (unsigned char __RPC_FAR *)InterfaceRefs,
+                                          (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[436] );
+            
+            NdrProxyGetBuffer(This, &_StubMsg);
+            *(( unsigned short __RPC_FAR * )_StubMsg.Buffer)++ = cInterfaceRefs;
+            
+            _StubMsg.MaxCount = cInterfaceRefs;
+            
+            NdrConformantArrayMarshall( (PMIDL_STUB_MESSAGE)& _StubMsg,
+                                        (unsigned char __RPC_FAR *)InterfaceRefs,
+                                        (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[436] );
+            
+            NdrProxySendReceive(This, &_StubMsg);
+            
+            if ( (_RpcMessage.DataRepresentation & 0X0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION )
+                NdrConvert( (PMIDL_STUB_MESSAGE) &_StubMsg, (PFORMAT_STRING) &__MIDL_ProcFormatString.Format[196] );
+            
+            _RetVal = *(( HRESULT __RPC_FAR * )_StubMsg.Buffer)++;
+            
+            }
+        RpcFinally
+            {
+            NdrProxyFreeBuffer(This, &_StubMsg);
+            
+            }
+        RpcEndFinally
+        
+        }
+    RpcExcept(_StubMsg.dwStubPhase != PROXY_SENDRECEIVE)
+        {
+        _RetVal = NdrProxyErrorHandler(RpcExceptionCode());
+        }
+    RpcEndExcept
+    return _RetVal;
+}
+
+void __RPC_STUB IRemUnknown_RemRelease_Stub(
+    IRpcStubBuffer *This,
+    IRpcChannelBuffer *_pRpcChannelBuffer,
+    PRPC_MESSAGE _pRpcMessage,
+    DWORD *_pdwStubPhase)
+{
+    REMINTERFACEREF __RPC_FAR *InterfaceRefs;
+    HRESULT _RetVal;
+    MIDL_STUB_MESSAGE _StubMsg;
+    unsigned short cInterfaceRefs;
+    
+NdrStubInitialize(
+                     _pRpcMessage,
+                     &_StubMsg,
+                     &Object_StubDesc,
+                     _pRpcChannelBuffer);
+    ( REMINTERFACEREF __RPC_FAR * )InterfaceRefs = 0;
+    RpcTryFinally
+        {
+        if ( (_pRpcMessage->DataRepresentation & 0X0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION )
+            NdrConvert( (PMIDL_STUB_MESSAGE) &_StubMsg, (PFORMAT_STRING) &__MIDL_ProcFormatString.Format[196] );
+        
+        cInterfaceRefs = *(( unsigned short __RPC_FAR * )_StubMsg.Buffer)++;
+        
+        NdrConformantArrayUnmarshall( (PMIDL_STUB_MESSAGE) &_StubMsg,
+                                      (unsigned char __RPC_FAR * __RPC_FAR *)&InterfaceRefs,
+                                      (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[436],
+                                      (unsigned char)0 );
+        
+        
+        *_pdwStubPhase = STUB_CALL_SERVER;
+        _RetVal = (((IRemUnknown*) ((CStdStubBuffer *)This)->pvServerObject)->lpVtbl) -> RemRelease(
+              (IRemUnknown *) ((CStdStubBuffer *)This)->pvServerObject,
+              cInterfaceRefs,
+              InterfaceRefs);
+        
+        *_pdwStubPhase = STUB_MARSHAL;
+        
+        _StubMsg.BufferLength = 4U;
+        _StubMsg.BufferLength += 16;
+        
+        NdrStubGetBuffer(This, _pRpcChannelBuffer, &_StubMsg);
+        *(( HRESULT __RPC_FAR * )_StubMsg.Buffer)++ = _RetVal;
+        
+        }
+    RpcFinally
+        {
+        }
+    RpcEndFinally
+    _pRpcMessage->BufferLength = 
+        (unsigned int)((long)_StubMsg.Buffer - (long)_pRpcMessage->Buffer);
+    
+}
+
+const CINTERFACE_PROXY_VTABLE(6) _IRemUnknownProxyVtbl = 
+{
+    &IID_IRemUnknown,
+    IUnknown_QueryInterface_Proxy,
+    IUnknown_AddRef_Proxy,
+    IUnknown_Release_Proxy ,
+    IRemUnknown_RemQueryInterface_Proxy ,
+    IRemUnknown_RemAddRef_Proxy ,
+    IRemUnknown_RemRelease_Proxy
+};
+
+
+static const PRPC_STUB_FUNCTION IRemUnknown_table[] =
+{
+    IRemUnknown_RemQueryInterface_Stub,
+    IRemUnknown_RemAddRef_Stub,
+    IRemUnknown_RemRelease_Stub
+};
+
+const CInterfaceStubVtbl _IRemUnknownStubVtbl =
+{
+    &IID_IRemUnknown,
+    0,
+    6,
+    &IRemUnknown_table[-3],
+    CStdStubBuffer_METHODS
+};
+
+
+/* Object interface: IRemUnknown2, ver. 0.0,
+   GUID={0x00000142,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}} */
+
+
+extern const MIDL_STUB_DESC Object_StubDesc;
+
+
+#pragma code_seg(".orpc")
+
+HRESULT STDMETHODCALLTYPE IRemUnknown2_RemQueryInterface2_Proxy( 
+    IRemUnknown2 __RPC_FAR * This,
+    /* [in] */ REFIPID ripid,
+    /* [in] */ unsigned short cIids,
+    /* [size_is][in] */ IID __RPC_FAR *iids,
+    /* [size_is][out] */ HRESULT __RPC_FAR *phr,
+    /* [size_is][out] */ MInterfacePointer __RPC_FAR *__RPC_FAR *ppMIF)
+{
+
+    HRESULT _RetVal;
+    
+    RPC_MESSAGE _RpcMessage;
+    
+    MIDL_STUB_MESSAGE _StubMsg;
+    
+    if(ppMIF)
+        {
+        *ppMIF = 0;
+        }
+    RpcTryExcept
+        {
+        NdrProxyInitialize(
+                      ( void __RPC_FAR *  )This,
+                      ( PRPC_MESSAGE  )&_RpcMessage,
+                      ( PMIDL_STUB_MESSAGE  )&_StubMsg,
+                      ( PMIDL_STUB_DESC  )&Object_StubDesc,
+                      6);
+        
+        
+        
+        if(!ripid)
+            {
+            RpcRaiseException(RPC_X_NULL_REF_POINTER);
+            }
+        if(!iids)
+            {
+            RpcRaiseException(RPC_X_NULL_REF_POINTER);
+            }
+        if(!phr)
+            {
+            RpcRaiseException(RPC_X_NULL_REF_POINTER);
+            }
+        if(!ppMIF)
+            {
+            RpcRaiseException(RPC_X_NULL_REF_POINTER);
+            }
+        RpcTryFinally
+            {
+            
+            _StubMsg.BufferLength = 0U + 5U + 7U;
+            NdrSimpleStructBufferSize( (PMIDL_STUB_MESSAGE) &_StubMsg,
+                                       (unsigned char __RPC_FAR *)ripid,
+                                       (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[54] );
+            
+            _StubMsg.MaxCount = cIids;
+            
+            NdrConformantArrayBufferSize( (PMIDL_STUB_MESSAGE) &_StubMsg,
+                                          (unsigned char __RPC_FAR *)iids,
+                                          (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[468] );
+            
+            NdrProxyGetBuffer(This, &_StubMsg);
+            NdrSimpleStructMarshall( (PMIDL_STUB_MESSAGE)& _StubMsg,
+                                     (unsigned char __RPC_FAR *)ripid,
+                                     (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[54] );
+            
+            *(( unsigned short __RPC_FAR * )_StubMsg.Buffer)++ = cIids;
+            
+            _StubMsg.MaxCount = cIids;
+            
+            NdrConformantArrayMarshall( (PMIDL_STUB_MESSAGE)& _StubMsg,
+                                        (unsigned char __RPC_FAR *)iids,
+                                        (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[468] );
+            
+            NdrProxySendReceive(This, &_StubMsg);
+            
+            if ( (_RpcMessage.DataRepresentation & 0X0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION )
+                NdrConvert( (PMIDL_STUB_MESSAGE) &_StubMsg, (PFORMAT_STRING) &__MIDL_ProcFormatString.Format[204] );
+            
+            NdrConformantArrayUnmarshall( (PMIDL_STUB_MESSAGE) &_StubMsg,
+                                          (unsigned char __RPC_FAR * __RPC_FAR *)&phr,
+                                          (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[486],
+                                          (unsigned char)0 );
+            
+            NdrConformantArrayUnmarshall( (PMIDL_STUB_MESSAGE) &_StubMsg,
+                                          (unsigned char __RPC_FAR * __RPC_FAR *)&ppMIF,
+                                          (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[500],
+                                          (unsigned char)0 );
+            
+            _StubMsg.Buffer = (unsigned char __RPC_FAR *)(((long)_StubMsg.Buffer + 3) & ~ 0x3);
+            _RetVal = *(( HRESULT __RPC_FAR * )_StubMsg.Buffer)++;
+            
+            }
+        RpcFinally
+            {
+            NdrProxyFreeBuffer(This, &_StubMsg);
+            
+            }
+        RpcEndFinally
+        
+        }
+    RpcExcept(_StubMsg.dwStubPhase != PROXY_SENDRECEIVE)
+        {
+        _StubMsg.MaxCount = cIids;
+        
+        NdrClearOutParameters(
+                         ( PMIDL_STUB_MESSAGE  )&_StubMsg,
+                         ( PFORMAT_STRING  )&__MIDL_TypeFormatString.Format[482],
+                         ( void __RPC_FAR * )phr);
+        _StubMsg.MaxCount = cIids;
+        
+        NdrClearOutParameters(
+                         ( PMIDL_STUB_MESSAGE  )&_StubMsg,
+                         ( PFORMAT_STRING  )&__MIDL_TypeFormatString.Format[496],
+                         ( void __RPC_FAR * )ppMIF);
+        _RetVal = NdrProxyErrorHandler(RpcExceptionCode());
+        }
+    RpcEndExcept
+    return _RetVal;
+}
+
+void __RPC_STUB IRemUnknown2_RemQueryInterface2_Stub(
+    IRpcStubBuffer *This,
+    IRpcChannelBuffer *_pRpcChannelBuffer,
+    PRPC_MESSAGE _pRpcMessage,
+    DWORD *_pdwStubPhase)
+{
+    HRESULT _RetVal;
+    MIDL_STUB_MESSAGE _StubMsg;
+    unsigned short cIids;
+    IID __RPC_FAR *iids;
+    HRESULT __RPC_FAR *phr;
+    MInterfacePointer __RPC_FAR *__RPC_FAR *ppMIF;
+    REFIPID ripid;
+    
+NdrStubInitialize(
+                     _pRpcMessage,
+                     &_StubMsg,
+                     &Object_StubDesc,
+                     _pRpcChannelBuffer);
+    ( REFIPID  )ripid = 0;
+    ( IID __RPC_FAR * )iids = 0;
+    ( HRESULT __RPC_FAR * )phr = 0;
+    ( MInterfacePointer __RPC_FAR *__RPC_FAR * )ppMIF = 0;
+    RpcTryFinally
+        {
+        if ( (_pRpcMessage->DataRepresentation & 0X0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION )
+            NdrConvert( (PMIDL_STUB_MESSAGE) &_StubMsg, (PFORMAT_STRING) &__MIDL_ProcFormatString.Format[204] );
+        
+        NdrSimpleStructUnmarshall( (PMIDL_STUB_MESSAGE) &_StubMsg,
+                                   (unsigned char __RPC_FAR * __RPC_FAR *)&ripid,
+                                   (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[54],
+                                   (unsigned char)0 );
+        
+        cIids = *(( unsigned short __RPC_FAR * )_StubMsg.Buffer)++;
+        
+        NdrConformantArrayUnmarshall( (PMIDL_STUB_MESSAGE) &_StubMsg,
+                                      (unsigned char __RPC_FAR * __RPC_FAR *)&iids,
+                                      (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[468],
+                                      (unsigned char)0 );
+        
+        phr = NdrAllocate(&_StubMsg,cIids * 4);
+        ppMIF = NdrAllocate(&_StubMsg,cIids * 4);
+        
+        *_pdwStubPhase = STUB_CALL_SERVER;
+        _RetVal = (((IRemUnknown2*) ((CStdStubBuffer *)This)->pvServerObject)->lpVtbl) -> RemQueryInterface2(
+                      (IRemUnknown2 *) ((CStdStubBuffer *)This)->pvServerObject,
+                      ripid,
+                      cIids,
+                      iids,
+                      phr,
+                      ppMIF);
+        
+        *_pdwStubPhase = STUB_MARSHAL;
+        
+        _StubMsg.BufferLength = 4U + 7U + 7U;
+        _StubMsg.MaxCount = cIids;
+        
+        NdrConformantArrayBufferSize( (PMIDL_STUB_MESSAGE) &_StubMsg,
+                                      (unsigned char __RPC_FAR *)phr,
+                                      (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[486] );
+        
+        _StubMsg.MaxCount = cIids;
+        
+        NdrConformantArrayBufferSize( (PMIDL_STUB_MESSAGE) &_StubMsg,
+                                      (unsigned char __RPC_FAR *)ppMIF,
+                                      (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[500] );
+        
+        _StubMsg.BufferLength += 16;
+        
+        NdrStubGetBuffer(This, _pRpcChannelBuffer, &_StubMsg);
+        _StubMsg.MaxCount = cIids;
+        
+        NdrConformantArrayMarshall( (PMIDL_STUB_MESSAGE)& _StubMsg,
+                                    (unsigned char __RPC_FAR *)phr,
+                                    (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[486] );
+        
+        _StubMsg.MaxCount = cIids;
+        
+        NdrConformantArrayMarshall( (PMIDL_STUB_MESSAGE)& _StubMsg,
+                                    (unsigned char __RPC_FAR *)ppMIF,
+                                    (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[500] );
+        
+        _StubMsg.Buffer = (unsigned char __RPC_FAR *)(((long)_StubMsg.Buffer + 3) & ~ 0x3);
+        *(( HRESULT __RPC_FAR * )_StubMsg.Buffer)++ = _RetVal;
+        
+        }
+    RpcFinally
+        {
+        if ( phr )
+            _StubMsg.pfnFree( phr );
+        
+        _StubMsg.MaxCount = cIids;
+        
+        NdrPointerFree( &_StubMsg,
+                        (unsigned char __RPC_FAR *)ppMIF,
+                        &__MIDL_TypeFormatString.Format[496] );
+        
+        }
+    RpcEndFinally
+    _pRpcMessage->BufferLength = 
+        (unsigned int)((long)_StubMsg.Buffer - (long)_pRpcMessage->Buffer);
+    
+}
+
+extern const EXPR_EVAL ExprEvalRoutines[];
+
+static const MIDL_STUB_DESC Object_StubDesc = 
+    {
+    0,
+    NdrOleAllocate,
+    NdrOleFree,
+    0,
+    0,
+    0,
+    ExprEvalRoutines,
+    0,
+    __MIDL_TypeFormatString.Format,
+    1, /* -error bounds_check flag */
+    0x10001, /* Ndr library version */
+    0,
+    0x50100a4, /* MIDL Version 5.1.164 */
+    0,
+    0,
+    0,  /* notify & notify_flag routine table */
+    1,  /* Flags */
+    0,  /* Reserved3 */
+    0,  /* Reserved4 */
+    0   /* Reserved5 */
+    };
+
+const CINTERFACE_PROXY_VTABLE(7) _IRemUnknown2ProxyVtbl = 
+{
+    &IID_IRemUnknown2,
+    IUnknown_QueryInterface_Proxy,
+    IUnknown_AddRef_Proxy,
+    IUnknown_Release_Proxy ,
+    IRemUnknown_RemQueryInterface_Proxy ,
+    IRemUnknown_RemAddRef_Proxy ,
+    IRemUnknown_RemRelease_Proxy ,
+    IRemUnknown2_RemQueryInterface2_Proxy
+};
+
+
+static const PRPC_STUB_FUNCTION IRemUnknown2_table[] =
+{
+    IRemUnknown_RemQueryInterface_Stub,
+    IRemUnknown_RemAddRef_Stub,
+    IRemUnknown_RemRelease_Stub,
+    IRemUnknown2_RemQueryInterface2_Stub
+};
+
+const CInterfaceStubVtbl _IRemUnknown2StubVtbl =
+{
+    &IID_IRemUnknown2,
+    0,
+    7,
+    &IRemUnknown2_table[-3],
+    CStdStubBuffer_METHODS
+};
+
+
+/* Standard interface: __MIDL_itf_dcom_0008, ver. 0.0,
+   GUID={0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} */
+
+
+/* Standard interface: IOXIDResolver, ver. 0.0,
+   GUID={0x99fcfec4,0x5260,0x101b,{0xbb,0xcb,0x00,0xaa,0x00,0x21,0x34,0x7a}} */
+
+
+/* Standard interface: IRemoteActivation, ver. 0.0,
+   GUID={0x4d9f4ab8,0x7d1c,0x11cf,{0x86,0x1e,0x00,0x20,0xaf,0x6e,0x7c,0x57}} */
+
+
+/* Standard interface: __MIDL_itf_dcom_0010, ver. 0.0,
+   GUID={0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} */
+
+#pragma data_seg(".rdata")
+
+static void __RPC_USER IRemoteActivation_ORPC_EXTENTExprEval_0000( PMIDL_STUB_MESSAGE pStubMsg )
+{
+    ORPC_EXTENT __RPC_FAR *pS	=	( ORPC_EXTENT __RPC_FAR * )(pStubMsg->StackTop - 20);
+    
+    pStubMsg->Offset = 0;
+    pStubMsg->MaxCount = ( unsigned long ) ( pS->size + 7 & ~7 );
+}
+
+static void __RPC_USER IRemoteActivation_ORPC_EXTENT_ARRAYExprEval_0001( PMIDL_STUB_MESSAGE pStubMsg )
+{
+    ORPC_EXTENT_ARRAY __RPC_FAR *pS	=	( ORPC_EXTENT_ARRAY __RPC_FAR * )pStubMsg->StackTop;
+    
+    pStubMsg->Offset = 0;
+    pStubMsg->MaxCount = ( unsigned long ) ( pS->size + 1 & ~1 );
+}
+
+static const EXPR_EVAL ExprEvalRoutines[] = 
+    {
+    IRemoteActivation_ORPC_EXTENTExprEval_0000
+    ,IRemoteActivation_ORPC_EXTENT_ARRAYExprEval_0001
+    };
+
+
+#if !defined(__RPC_WIN32__)
+#error  Invalid build platform for this stub.
+#endif
+
+static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =
+    {
+        0,
+        {
+			0x4e,		/* FC_IN_PARAM_BASETYPE */
+			0xf,		/* FC_IGNORE */
+/*  2 */	
+			0x4d,		/* FC_IN_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/*  4 */	NdrFcShort( 0x2 ),	/* Type Offset=2 */
+/*  6 */	0x4e,		/* FC_IN_PARAM_BASETYPE */
+			0x6,		/* FC_SHORT */
+/*  8 */	
+			0x4d,		/* FC_IN_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 10 */	NdrFcShort( 0x6 ),	/* Type Offset=6 */
+/* 12 */	
+			0x51,		/* FC_OUT_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 14 */	NdrFcShort( 0x10 ),	/* Type Offset=16 */
+/* 16 */	
+			0x51,		/* FC_OUT_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 18 */	NdrFcShort( 0x2c ),	/* Type Offset=44 */
+/* 20 */	
+			0x51,		/* FC_OUT_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 22 */	NdrFcShort( 0x42 ),	/* Type Offset=66 */
+/* 24 */	0x53,		/* FC_RETURN_PARAM_BASETYPE */
+			0x10,		/* FC_ERROR_STATUS_T */
+/* 26 */	0x4e,		/* FC_IN_PARAM_BASETYPE */
+			0xf,		/* FC_IGNORE */
+/* 28 */	
+			0x4d,		/* FC_IN_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 30 */	NdrFcShort( 0x2 ),	/* Type Offset=2 */
+/* 32 */	0x53,		/* FC_RETURN_PARAM_BASETYPE */
+			0x10,		/* FC_ERROR_STATUS_T */
+/* 34 */	0x4e,		/* FC_IN_PARAM_BASETYPE */
+			0xf,		/* FC_IGNORE */
+/* 36 */	
+			0x50,		/* FC_IN_OUT_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 38 */	NdrFcShort( 0x2 ),	/* Type Offset=2 */
+/* 40 */	0x4e,		/* FC_IN_PARAM_BASETYPE */
+			0x6,		/* FC_SHORT */
+/* 42 */	0x4e,		/* FC_IN_PARAM_BASETYPE */
+			0x6,		/* FC_SHORT */
+/* 44 */	0x4e,		/* FC_IN_PARAM_BASETYPE */
+			0x6,		/* FC_SHORT */
+/* 46 */	
+			0x4d,		/* FC_IN_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 48 */	NdrFcShort( 0x46 ),	/* Type Offset=70 */
+/* 50 */	
+			0x4d,		/* FC_IN_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 52 */	NdrFcShort( 0x54 ),	/* Type Offset=84 */
+/* 54 */	
+			0x51,		/* FC_OUT_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 56 */	NdrFcShort( 0x62 ),	/* Type Offset=98 */
+/* 58 */	0x53,		/* FC_RETURN_PARAM_BASETYPE */
+			0x10,		/* FC_ERROR_STATUS_T */
+/* 60 */	0x4e,		/* FC_IN_PARAM_BASETYPE */
+			0xf,		/* FC_IGNORE */
+/* 62 */	0x53,		/* FC_RETURN_PARAM_BASETYPE */
+			0x10,		/* FC_ERROR_STATUS_T */
+/* 64 */	0x4e,		/* FC_IN_PARAM_BASETYPE */
+			0xf,		/* FC_IGNORE */
+/* 66 */	
+			0x4d,		/* FC_IN_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 68 */	NdrFcShort( 0x2 ),	/* Type Offset=2 */
+/* 70 */	0x4e,		/* FC_IN_PARAM_BASETYPE */
+			0x6,		/* FC_SHORT */
+/* 72 */	
+			0x4d,		/* FC_IN_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 74 */	NdrFcShort( 0x6 ),	/* Type Offset=6 */
+/* 76 */	
+			0x51,		/* FC_OUT_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 78 */	NdrFcShort( 0x10 ),	/* Type Offset=16 */
+/* 80 */	
+			0x51,		/* FC_OUT_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 82 */	NdrFcShort( 0x2c ),	/* Type Offset=44 */
+/* 84 */	
+			0x51,		/* FC_OUT_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 86 */	NdrFcShort( 0x42 ),	/* Type Offset=66 */
+/* 88 */	
+			0x51,		/* FC_OUT_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 90 */	NdrFcShort( 0x66 ),	/* Type Offset=102 */
+/* 92 */	0x53,		/* FC_RETURN_PARAM_BASETYPE */
+			0x10,		/* FC_ERROR_STATUS_T */
+/* 94 */	0x4e,		/* FC_IN_PARAM_BASETYPE */
+			0xf,		/* FC_IGNORE */
+/* 96 */	
+			0x4d,		/* FC_IN_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 98 */	NdrFcShort( 0x72 ),	/* Type Offset=114 */
+/* 100 */	
+			0x51,		/* FC_OUT_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 102 */	NdrFcShort( 0xde ),	/* Type Offset=222 */
+/* 104 */	
+			0x4d,		/* FC_IN_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 106 */	NdrFcShort( 0xf6 ),	/* Type Offset=246 */
+/* 108 */	
+			0x4d,		/* FC_IN_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 110 */	NdrFcShort( 0xfa ),	/* Type Offset=250 */
+/* 112 */	
+			0x4d,		/* FC_IN_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 114 */	NdrFcShort( 0xfe ),	/* Type Offset=254 */
+/* 116 */	0x4e,		/* FC_IN_PARAM_BASETYPE */
+			0x8,		/* FC_LONG */
+/* 118 */	0x4e,		/* FC_IN_PARAM_BASETYPE */
+			0x8,		/* FC_LONG */
+/* 120 */	0x4e,		/* FC_IN_PARAM_BASETYPE */
+			0x8,		/* FC_LONG */
+/* 122 */	
+			0x4d,		/* FC_IN_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 124 */	NdrFcShort( 0x114 ),	/* Type Offset=276 */
+/* 126 */	0x4e,		/* FC_IN_PARAM_BASETYPE */
+			0x6,		/* FC_SHORT */
+/* 128 */	
+			0x4d,		/* FC_IN_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 130 */	NdrFcShort( 0x126 ),	/* Type Offset=294 */
+/* 132 */	
+			0x51,		/* FC_OUT_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 134 */	NdrFcShort( 0x130 ),	/* Type Offset=304 */
+/* 136 */	
+			0x51,		/* FC_OUT_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 138 */	NdrFcShort( 0x10 ),	/* Type Offset=16 */
+/* 140 */	
+			0x51,		/* FC_OUT_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 142 */	NdrFcShort( 0x2c ),	/* Type Offset=44 */
+/* 144 */	
+			0x51,		/* FC_OUT_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 146 */	NdrFcShort( 0x42 ),	/* Type Offset=66 */
+/* 148 */	
+			0x51,		/* FC_OUT_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 150 */	NdrFcShort( 0x66 ),	/* Type Offset=102 */
+/* 152 */	
+			0x51,		/* FC_OUT_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 154 */	NdrFcShort( 0x42 ),	/* Type Offset=66 */
+/* 156 */	
+			0x51,		/* FC_OUT_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 158 */	NdrFcShort( 0x134 ),	/* Type Offset=308 */
+/* 160 */	
+			0x51,		/* FC_OUT_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 162 */	NdrFcShort( 0x156 ),	/* Type Offset=342 */
+/* 164 */	0x53,		/* FC_RETURN_PARAM_BASETYPE */
+			0x8,		/* FC_LONG */
+/* 166 */	
+			0x4d,		/* FC_IN_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 168 */	NdrFcShort( 0xf6 ),	/* Type Offset=246 */
+/* 170 */	0x4e,		/* FC_IN_PARAM_BASETYPE */
+			0x8,		/* FC_LONG */
+/* 172 */	0x4e,		/* FC_IN_PARAM_BASETYPE */
+			0x6,		/* FC_SHORT */
+/* 174 */	
+			0x4d,		/* FC_IN_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 176 */	NdrFcShort( 0x164 ),	/* Type Offset=356 */
+/* 178 */	
+			0x51,		/* FC_OUT_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 180 */	NdrFcShort( 0x176 ),	/* Type Offset=374 */
+/* 182 */	0x53,		/* FC_RETURN_PARAM_BASETYPE */
+			0x8,		/* FC_LONG */
+/* 184 */	0x4e,		/* FC_IN_PARAM_BASETYPE */
+			0x6,		/* FC_SHORT */
+/* 186 */	
+			0x4d,		/* FC_IN_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 188 */	NdrFcShort( 0x1a4 ),	/* Type Offset=420 */
+/* 190 */	
+			0x51,		/* FC_OUT_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 192 */	NdrFcShort( 0x1c2 ),	/* Type Offset=450 */
+/* 194 */	0x53,		/* FC_RETURN_PARAM_BASETYPE */
+			0x8,		/* FC_LONG */
+/* 196 */	0x4e,		/* FC_IN_PARAM_BASETYPE */
+			0x6,		/* FC_SHORT */
+/* 198 */	
+			0x4d,		/* FC_IN_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 200 */	NdrFcShort( 0x1a4 ),	/* Type Offset=420 */
+/* 202 */	0x53,		/* FC_RETURN_PARAM_BASETYPE */
+			0x8,		/* FC_LONG */
+/* 204 */	
+			0x4d,		/* FC_IN_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 206 */	NdrFcShort( 0xf6 ),	/* Type Offset=246 */
+/* 208 */	0x4e,		/* FC_IN_PARAM_BASETYPE */
+			0x6,		/* FC_SHORT */
+/* 210 */	
+			0x4d,		/* FC_IN_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 212 */	NdrFcShort( 0x1d0 ),	/* Type Offset=464 */
+/* 214 */	
+			0x51,		/* FC_OUT_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 216 */	NdrFcShort( 0x1e2 ),	/* Type Offset=482 */
+/* 218 */	
+			0x51,		/* FC_OUT_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/* 220 */	NdrFcShort( 0x1f0 ),	/* Type Offset=496 */
+/* 222 */	0x53,		/* FC_RETURN_PARAM_BASETYPE */
+			0x8,		/* FC_LONG */
+
+			0x0
+        }
+    };
+
+static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =
+    {
+        0,
+        {
+			NdrFcShort( 0x0 ),	/* 0 */
+/*  2 */	
+			0x11, 0x8,	/* FC_RP [simple_pointer] */
+/*  4 */	0xb,		/* FC_HYPER */
+			0x5c,		/* FC_PAD */
+/*  6 */	
+			0x1b,		/* FC_CARRAY */
+			0x1,		/* 1 */
+/*  8 */	NdrFcShort( 0x2 ),	/* 2 */
+/* 10 */	0x27,		/* Corr desc:  parameter, FC_USHORT */
+			0x0,		/*  */
+#ifndef _ALPHA_
+/* 12 */	NdrFcShort( 0x8 ),	/* x86, MIPS, PPC Stack size/offset = 8 */
+#else
+			NdrFcShort( 0x10 ),	/* Alpha Stack size/offset = 16 */
+#endif
+/* 14 */	0x6,		/* FC_SHORT */
+			0x5b,		/* FC_END */
+/* 16 */	
+			0x11, 0x14,	/* FC_RP [alloced_on_stack] */
+/* 18 */	NdrFcShort( 0x2 ),	/* Offset= 2 (20) */
+/* 20 */	
+			0x12, 0x0,	/* FC_UP */
+/* 22 */	NdrFcShort( 0xc ),	/* Offset= 12 (34) */
+/* 24 */	
+			0x1b,		/* FC_CARRAY */
+			0x1,		/* 1 */
+/* 26 */	NdrFcShort( 0x2 ),	/* 2 */
+/* 28 */	0x7,		/* Corr desc: FC_USHORT */
+			0x0,		/*  */
+/* 30 */	NdrFcShort( 0xfffc ),	/* -4 */
+/* 32 */	0x6,		/* FC_SHORT */
+			0x5b,		/* FC_END */
+/* 34 */	
+			0x17,		/* FC_CSTRUCT */
+			0x1,		/* 1 */
+/* 36 */	NdrFcShort( 0x4 ),	/* 4 */
+/* 38 */	NdrFcShort( 0xfffffff2 ),	/* Offset= -14 (24) */
+/* 40 */	0x6,		/* FC_SHORT */
+			0x6,		/* FC_SHORT */
+/* 42 */	0x5c,		/* FC_PAD */
+			0x5b,		/* FC_END */
+/* 44 */	
+			0x11, 0x4,	/* FC_RP [alloced_on_stack] */
+/* 46 */	NdrFcShort( 0x8 ),	/* Offset= 8 (54) */
+/* 48 */	
+			0x1d,		/* FC_SMFARRAY */
+			0x0,		/* 0 */
+/* 50 */	NdrFcShort( 0x8 ),	/* 8 */
+/* 52 */	0x2,		/* FC_CHAR */
+			0x5b,		/* FC_END */
+/* 54 */	
+			0x15,		/* FC_STRUCT */
+			0x3,		/* 3 */
+/* 56 */	NdrFcShort( 0x10 ),	/* 16 */
+/* 58 */	0x8,		/* FC_LONG */
+			0x6,		/* FC_SHORT */
+/* 60 */	0x6,		/* FC_SHORT */
+			0x4c,		/* FC_EMBEDDED_COMPLEX */
+/* 62 */	0x0,		/* 0 */
+			NdrFcShort( 0xfffffff1 ),	/* Offset= -15 (48) */
+			0x5b,		/* FC_END */
+/* 66 */	
+			0x11, 0xc,	/* FC_RP [alloced_on_stack] [simple_pointer] */
+/* 68 */	0x8,		/* FC_LONG */
+			0x5c,		/* FC_PAD */
+/* 70 */	
+			0x12,		/* FC_UP */
+			0x0,		/* 0 */
+/* 72 */	NdrFcShort( 0x2 ),	/* Offset= 2 (74) */
+/* 74 */	
+			0x1b,		/* FC_CARRAY */
+			0x7,		/* 7 */
+/* 76 */	NdrFcShort( 0x8 ),	/* 8 */
+/* 78 */	0x27,		/* Corr desc:  parameter, FC_USHORT */
+			0x0,		/*  */
+#ifndef _ALPHA_
+/* 80 */	NdrFcShort( 0xc ),	/* x86, MIPS, PPC Stack size/offset = 12 */
+#else
+			NdrFcShort( 0x18 ),	/* Alpha Stack size/offset = 24 */
+#endif
+/* 82 */	0xb,		/* FC_HYPER */
+			0x5b,		/* FC_END */
+/* 84 */	
+			0x12,		/* FC_UP */
+			0x0,		/* 0 */
+/* 86 */	NdrFcShort( 0x2 ),	/* Offset= 2 (88) */
+/* 88 */	
+			0x1b,		/* FC_CARRAY */
+			0x7,		/* 7 */
+/* 90 */	NdrFcShort( 0x8 ),	/* 8 */
+/* 92 */	0x27,		/* Corr desc:  parameter, FC_USHORT */
+			0x0,		/*  */
+#ifndef _ALPHA_
+/* 94 */	NdrFcShort( 0x10 ),	/* x86, MIPS, PPC Stack size/offset = 16 */
+#else
+			NdrFcShort( 0x20 ),	/* Alpha Stack size/offset = 32 */
+#endif
+/* 96 */	0xb,		/* FC_HYPER */
+			0x5b,		/* FC_END */
+/* 98 */	
+			0x11, 0xc,	/* FC_RP [alloced_on_stack] [simple_pointer] */
+/* 100 */	0x6,		/* FC_SHORT */
+			0x5c,		/* FC_PAD */
+/* 102 */	
+			0x11, 0x4,	/* FC_RP [alloced_on_stack] */
+/* 104 */	NdrFcShort( 0x2 ),	/* Offset= 2 (106) */
+/* 106 */	
+			0x15,		/* FC_STRUCT */
+			0x1,		/* 1 */
+/* 108 */	NdrFcShort( 0x4 ),	/* 4 */
+/* 110 */	0x6,		/* FC_SHORT */
+			0x6,		/* FC_SHORT */
+/* 112 */	0x5c,		/* FC_PAD */
+			0x5b,		/* FC_END */
+/* 114 */	
+			0x11, 0x0,	/* FC_RP */
+/* 116 */	NdrFcShort( 0x4c ),	/* Offset= 76 (192) */
+/* 118 */	
+			0x1b,		/* FC_CARRAY */
+			0x0,		/* 0 */
+/* 120 */	NdrFcShort( 0x1 ),	/* 1 */
+/* 122 */	0x0,		/* Corr desc:  */
+			0x59,		/* FC_CALLBACK */
+/* 124 */	NdrFcShort( 0x0 ),	/* 0 */
+/* 126 */	0x1,		/* FC_BYTE */
+			0x5b,		/* FC_END */
+/* 128 */	
+			0x17,		/* FC_CSTRUCT */
+			0x3,		/* 3 */
+/* 130 */	NdrFcShort( 0x14 ),	/* 20 */
+/* 132 */	NdrFcShort( 0xfffffff2 ),	/* Offset= -14 (118) */
+/* 134 */	0x4c,		/* FC_EMBEDDED_COMPLEX */
+			0x0,		/* 0 */
+/* 136 */	NdrFcShort( 0xffffffae ),	/* Offset= -82 (54) */
+/* 138 */	0x8,		/* FC_LONG */
+			0x5b,		/* FC_END */
+/* 140 */	
+			0x1b,		/* FC_CARRAY */
+			0x3,		/* 3 */
+/* 142 */	NdrFcShort( 0x4 ),	/* 4 */
+/* 144 */	0x10,		/* Corr desc:  field pointer,  */
+			0x59,		/* FC_CALLBACK */
+/* 146 */	NdrFcShort( 0x1 ),	/* 1 */
+/* 148 */	
+			0x4b,		/* FC_PP */
+			0x5c,		/* FC_PAD */
+/* 150 */	
+			0x48,		/* FC_VARIABLE_REPEAT */
+			0x49,		/* FC_FIXED_OFFSET */
+/* 152 */	NdrFcShort( 0x4 ),	/* 4 */
+/* 154 */	NdrFcShort( 0x0 ),	/* 0 */
+/* 156 */	NdrFcShort( 0x1 ),	/* 1 */
+/* 158 */	NdrFcShort( 0x0 ),	/* 0 */
+/* 160 */	NdrFcShort( 0x0 ),	/* 0 */
+/* 162 */	0x12, 0x0,	/* FC_UP */
+/* 164 */	NdrFcShort( 0xffffffdc ),	/* Offset= -36 (128) */
+/* 166 */	
+			0x5b,		/* FC_END */
+
+			0x8,		/* FC_LONG */
+/* 168 */	0x5c,		/* FC_PAD */
+			0x5b,		/* FC_END */
+/* 170 */	
+			0x16,		/* FC_PSTRUCT */
+			0x3,		/* 3 */
+/* 172 */	NdrFcShort( 0xc ),	/* 12 */
+/* 174 */	
+			0x4b,		/* FC_PP */
+			0x5c,		/* FC_PAD */
+/* 176 */	
+			0x46,		/* FC_NO_REPEAT */
+			0x5c,		/* FC_PAD */
+/* 178 */	NdrFcShort( 0x8 ),	/* 8 */
+/* 180 */	NdrFcShort( 0x8 ),	/* 8 */
+/* 182 */	0x12, 0x0,	/* FC_UP */
+/* 184 */	NdrFcShort( 0xffffffd4 ),	/* Offset= -44 (140) */
+/* 186 */	
+			0x5b,		/* FC_END */
+
+			0x8,		/* FC_LONG */
+/* 188 */	0x8,		/* FC_LONG */
+			0x8,		/* FC_LONG */
+/* 190 */	0x5c,		/* FC_PAD */
+			0x5b,		/* FC_END */
+/* 192 */	
+			0x16,		/* FC_PSTRUCT */
+			0x3,		/* 3 */
+/* 194 */	NdrFcShort( 0x20 ),	/* 32 */
+/* 196 */	
+			0x4b,		/* FC_PP */
+			0x5c,		/* FC_PAD */
+/* 198 */	
+			0x46,		/* FC_NO_REPEAT */
+			0x5c,		/* FC_PAD */
+/* 200 */	NdrFcShort( 0x1c ),	/* 28 */
+/* 202 */	NdrFcShort( 0x1c ),	/* 28 */
+/* 204 */	0x12, 0x0,	/* FC_UP */
+/* 206 */	NdrFcShort( 0xffffffdc ),	/* Offset= -36 (170) */
+/* 208 */	
+			0x5b,		/* FC_END */
+
+			0x4c,		/* FC_EMBEDDED_COMPLEX */
+/* 210 */	0x0,		/* 0 */
+			NdrFcShort( 0xffffff97 ),	/* Offset= -105 (106) */
+			0x8,		/* FC_LONG */
+/* 214 */	0x8,		/* FC_LONG */
+			0x4c,		/* FC_EMBEDDED_COMPLEX */
+/* 216 */	0x0,		/* 0 */
+			NdrFcShort( 0xffffff5d ),	/* Offset= -163 (54) */
+			0x8,		/* FC_LONG */
+/* 220 */	0x5c,		/* FC_PAD */
+			0x5b,		/* FC_END */
+/* 222 */	
+			0x11, 0x4,	/* FC_RP [alloced_on_stack] */
+/* 224 */	NdrFcShort( 0x2 ),	/* Offset= 2 (226) */
+/* 226 */	
+			0x16,		/* FC_PSTRUCT */
+			0x3,		/* 3 */
+/* 228 */	NdrFcShort( 0x8 ),	/* 8 */
+/* 230 */	
+			0x4b,		/* FC_PP */
+			0x5c,		/* FC_PAD */
+/* 232 */	
+			0x46,		/* FC_NO_REPEAT */
+			0x5c,		/* FC_PAD */
+/* 234 */	NdrFcShort( 0x4 ),	/* 4 */
+/* 236 */	NdrFcShort( 0x4 ),	/* 4 */
+/* 238 */	0x12, 0x0,	/* FC_UP */
+/* 240 */	NdrFcShort( 0xffffffba ),	/* Offset= -70 (170) */
+/* 242 */	
+			0x5b,		/* FC_END */
+
+			0x8,		/* FC_LONG */
+/* 244 */	0x8,		/* FC_LONG */
+			0x5b,		/* FC_END */
+/* 246 */	
+			0x11, 0x0,	/* FC_RP */
+/* 248 */	NdrFcShort( 0xffffff3e ),	/* Offset= -194 (54) */
+/* 250 */	
+			0x12, 0x8,	/* FC_UP [simple_pointer] */
+/* 252 */	
+			0x25,		/* FC_C_WSTRING */
+			0x5c,		/* FC_PAD */
+/* 254 */	
+			0x12, 0x0,	/* FC_UP */
+/* 256 */	NdrFcShort( 0xc ),	/* Offset= 12 (268) */
+/* 258 */	
+			0x1b,		/* FC_CARRAY */
+			0x0,		/* 0 */
+/* 260 */	NdrFcShort( 0x1 ),	/* 1 */
+/* 262 */	0x9,		/* Corr desc: FC_ULONG */
+			0x0,		/*  */
+/* 264 */	NdrFcShort( 0xfffc ),	/* -4 */
+/* 266 */	0x2,		/* FC_CHAR */
+			0x5b,		/* FC_END */
+/* 268 */	
+			0x17,		/* FC_CSTRUCT */
+			0x3,		/* 3 */
+/* 270 */	NdrFcShort( 0x4 ),	/* 4 */
+/* 272 */	NdrFcShort( 0xfffffff2 ),	/* Offset= -14 (258) */
+/* 274 */	0x8,		/* FC_LONG */
+			0x5b,		/* FC_END */
+/* 276 */	
+			0x12, 0x0,	/* FC_UP */
+/* 278 */	NdrFcShort( 0x2 ),	/* Offset= 2 (280) */
+/* 280 */	
+			0x1b,		/* FC_CARRAY */
+			0x3,		/* 3 */
+/* 282 */	NdrFcShort( 0x10 ),	/* 16 */
+/* 284 */	0x29,		/* Corr desc:  parameter, FC_ULONG */
+			0x0,		/*  */
+#ifndef _ALPHA_
+/* 286 */	NdrFcShort( 0x20 ),	/* x86, MIPS, PPC Stack size/offset = 32 */
+#else
+			NdrFcShort( 0x40 ),	/* Alpha Stack size/offset = 64 */
+#endif
+/* 288 */	0x4c,		/* FC_EMBEDDED_COMPLEX */
+			0x0,		/* 0 */
+/* 290 */	NdrFcShort( 0xffffff14 ),	/* Offset= -236 (54) */
+/* 292 */	0x5c,		/* FC_PAD */
+			0x5b,		/* FC_END */
+/* 294 */	
+			0x1b,		/* FC_CARRAY */
+			0x1,		/* 1 */
+/* 296 */	NdrFcShort( 0x2 ),	/* 2 */
+/* 298 */	0x27,		/* Corr desc:  parameter, FC_USHORT */
+			0x0,		/*  */
+#ifndef _ALPHA_
+/* 300 */	NdrFcShort( 0x28 ),	/* x86, MIPS, PPC Stack size/offset = 40 */
+#else
+			NdrFcShort( 0x50 ),	/* Alpha Stack size/offset = 80 */
+#endif
+/* 302 */	0x6,		/* FC_SHORT */
+			0x5b,		/* FC_END */
+/* 304 */	
+			0x11, 0xc,	/* FC_RP [alloced_on_stack] [simple_pointer] */
+/* 306 */	0xb,		/* FC_HYPER */
+			0x5c,		/* FC_PAD */
+/* 308 */	
+			0x11, 0x0,	/* FC_RP */
+/* 310 */	NdrFcShort( 0x2 ),	/* Offset= 2 (312) */
+/* 312 */	
+			0x1b,		/* FC_CARRAY */
+			0x3,		/* 3 */
+/* 314 */	NdrFcShort( 0x4 ),	/* 4 */
+/* 316 */	0x29,		/* Corr desc:  parameter, FC_ULONG */
+			0x0,		/*  */
+#ifndef _ALPHA_
+/* 318 */	NdrFcShort( 0x20 ),	/* x86, MIPS, PPC Stack size/offset = 32 */
+#else
+			NdrFcShort( 0x40 ),	/* Alpha Stack size/offset = 64 */
+#endif
+/* 320 */	
+			0x4b,		/* FC_PP */
+			0x5c,		/* FC_PAD */
+/* 322 */	
+			0x48,		/* FC_VARIABLE_REPEAT */
+			0x49,		/* FC_FIXED_OFFSET */
+/* 324 */	NdrFcShort( 0x4 ),	/* 4 */
+/* 326 */	NdrFcShort( 0x0 ),	/* 0 */
+/* 328 */	NdrFcShort( 0x1 ),	/* 1 */
+/* 330 */	NdrFcShort( 0x0 ),	/* 0 */
+/* 332 */	NdrFcShort( 0x0 ),	/* 0 */
+/* 334 */	0x12, 0x0,	/* FC_UP */
+/* 336 */	NdrFcShort( 0xffffffbc ),	/* Offset= -68 (268) */
+/* 338 */	
+			0x5b,		/* FC_END */
+
+			0x8,		/* FC_LONG */
+/* 340 */	0x5c,		/* FC_PAD */
+			0x5b,		/* FC_END */
+/* 342 */	
+			0x11, 0x0,	/* FC_RP */
+/* 344 */	NdrFcShort( 0x2 ),	/* Offset= 2 (346) */
+/* 346 */	
+			0x1b,		/* FC_CARRAY */
+			0x3,		/* 3 */
+/* 348 */	NdrFcShort( 0x4 ),	/* 4 */
+/* 350 */	0x29,		/* Corr desc:  parameter, FC_ULONG */
+			0x0,		/*  */
+#ifndef _ALPHA_
+/* 352 */	NdrFcShort( 0x20 ),	/* x86, MIPS, PPC Stack size/offset = 32 */
+#else
+			NdrFcShort( 0x40 ),	/* Alpha Stack size/offset = 64 */
+#endif
+/* 354 */	0x8,		/* FC_LONG */
+			0x5b,		/* FC_END */
+/* 356 */	
+			0x11, 0x0,	/* FC_RP */
+/* 358 */	NdrFcShort( 0x2 ),	/* Offset= 2 (360) */
+/* 360 */	
+			0x1b,		/* FC_CARRAY */
+			0x3,		/* 3 */
+/* 362 */	NdrFcShort( 0x10 ),	/* 16 */
+/* 364 */	0x27,		/* Corr desc:  parameter, FC_USHORT */
+			0x0,		/*  */
+#ifndef _ALPHA_
+/* 366 */	NdrFcShort( 0xc ),	/* x86, MIPS, PPC Stack size/offset = 12 */
+#else
+			NdrFcShort( 0x18 ),	/* Alpha Stack size/offset = 24 */
+#endif
+/* 368 */	0x4c,		/* FC_EMBEDDED_COMPLEX */
+			0x0,		/* 0 */
+/* 370 */	NdrFcShort( 0xfffffec4 ),	/* Offset= -316 (54) */
+/* 372 */	0x5c,		/* FC_PAD */
+			0x5b,		/* FC_END */
+/* 374 */	
+			0x11, 0x14,	/* FC_RP [alloced_on_stack] */
+/* 376 */	NdrFcShort( 0x2 ),	/* Offset= 2 (378) */
+/* 378 */	
+			0x13, 0x0,	/* FC_OP */
+/* 380 */	NdrFcShort( 0x1a ),	/* Offset= 26 (406) */
+/* 382 */	
+			0x15,		/* FC_STRUCT */
+			0x7,		/* 7 */
+/* 384 */	NdrFcShort( 0x28 ),	/* 40 */
+/* 386 */	0x8,		/* FC_LONG */
+			0x8,		/* FC_LONG */
+/* 388 */	0x39,		/* FC_ALIGNM8 */
+			0xb,		/* FC_HYPER */
+/* 390 */	0xb,		/* FC_HYPER */
+			0x4c,		/* FC_EMBEDDED_COMPLEX */
+/* 392 */	0x0,		/* 0 */
+			NdrFcShort( 0xfffffead ),	/* Offset= -339 (54) */
+			0x5b,		/* FC_END */
+/* 396 */	
+			0x15,		/* FC_STRUCT */
+			0x7,		/* 7 */
+/* 398 */	NdrFcShort( 0x30 ),	/* 48 */
+/* 400 */	0x8,		/* FC_LONG */
+			0x4c,		/* FC_EMBEDDED_COMPLEX */
+/* 402 */	0x4,		/* 4 */
+			NdrFcShort( 0xffffffeb ),	/* Offset= -21 (382) */
+			0x5b,		/* FC_END */
+/* 406 */	
+			0x1b,		/* FC_CARRAY */
+			0x7,		/* 7 */
+/* 408 */	NdrFcShort( 0x30 ),	/* 48 */
+/* 410 */	0x27,		/* Corr desc:  parameter, FC_USHORT */
+			0x0,		/*  */
+#ifndef _ALPHA_
+/* 412 */	NdrFcShort( 0xc ),	/* x86, MIPS, PPC Stack size/offset = 12 */
+#else
+			NdrFcShort( 0x18 ),	/* Alpha Stack size/offset = 24 */
+#endif
+/* 414 */	0x4c,		/* FC_EMBEDDED_COMPLEX */
+			0x0,		/* 0 */
+/* 416 */	NdrFcShort( 0xffffffec ),	/* Offset= -20 (396) */
+/* 418 */	0x5c,		/* FC_PAD */
+			0x5b,		/* FC_END */
+/* 420 */	
+			0x11, 0x0,	/* FC_RP */
+/* 422 */	NdrFcShort( 0xe ),	/* Offset= 14 (436) */
+/* 424 */	
+			0x15,		/* FC_STRUCT */
+			0x3,		/* 3 */
+/* 426 */	NdrFcShort( 0x18 ),	/* 24 */
+/* 428 */	0x4c,		/* FC_EMBEDDED_COMPLEX */
+			0x0,		/* 0 */
+/* 430 */	NdrFcShort( 0xfffffe88 ),	/* Offset= -376 (54) */
+/* 432 */	0x8,		/* FC_LONG */
+			0x8,		/* FC_LONG */
+/* 434 */	0x5c,		/* FC_PAD */
+			0x5b,		/* FC_END */
+/* 436 */	
+			0x1b,		/* FC_CARRAY */
+			0x3,		/* 3 */
+/* 438 */	NdrFcShort( 0x18 ),	/* 24 */
+/* 440 */	0x27,		/* Corr desc:  parameter, FC_USHORT */
+			0x0,		/*  */
+#ifndef _ALPHA_
+/* 442 */	NdrFcShort( 0x4 ),	/* x86, MIPS, PPC Stack size/offset = 4 */
+#else
+			NdrFcShort( 0x8 ),	/* Alpha Stack size/offset = 8 */
+#endif
+/* 444 */	0x4c,		/* FC_EMBEDDED_COMPLEX */
+			0x0,		/* 0 */
+/* 446 */	NdrFcShort( 0xffffffea ),	/* Offset= -22 (424) */
+/* 448 */	0x5c,		/* FC_PAD */
+			0x5b,		/* FC_END */
+/* 450 */	
+			0x11, 0x0,	/* FC_RP */
+/* 452 */	NdrFcShort( 0x2 ),	/* Offset= 2 (454) */
+/* 454 */	
+			0x1b,		/* FC_CARRAY */
+			0x3,		/* 3 */
+/* 456 */	NdrFcShort( 0x4 ),	/* 4 */
+/* 458 */	0x27,		/* Corr desc:  parameter, FC_USHORT */
+			0x0,		/*  */
+#ifndef _ALPHA_
+/* 460 */	NdrFcShort( 0x4 ),	/* x86, MIPS, PPC Stack size/offset = 4 */
+#else
+			NdrFcShort( 0x8 ),	/* Alpha Stack size/offset = 8 */
+#endif
+/* 462 */	0x8,		/* FC_LONG */
+			0x5b,		/* FC_END */
+/* 464 */	
+			0x11, 0x0,	/* FC_RP */
+/* 466 */	NdrFcShort( 0x2 ),	/* Offset= 2 (468) */
+/* 468 */	
+			0x1b,		/* FC_CARRAY */
+			0x3,		/* 3 */
+/* 470 */	NdrFcShort( 0x10 ),	/* 16 */
+/* 472 */	0x27,		/* Corr desc:  parameter, FC_USHORT */
+			0x0,		/*  */
+#ifndef _ALPHA_
+/* 474 */	NdrFcShort( 0x8 ),	/* x86, MIPS, PPC Stack size/offset = 8 */
+#else
+			NdrFcShort( 0x10 ),	/* Alpha Stack size/offset = 16 */
+#endif
+/* 476 */	0x4c,		/* FC_EMBEDDED_COMPLEX */
+			0x0,		/* 0 */
+/* 478 */	NdrFcShort( 0xfffffe58 ),	/* Offset= -424 (54) */
+/* 480 */	0x5c,		/* FC_PAD */
+			0x5b,		/* FC_END */
+/* 482 */	
+			0x11, 0x0,	/* FC_RP */
+/* 484 */	NdrFcShort( 0x2 ),	/* Offset= 2 (486) */
+/* 486 */	
+			0x1b,		/* FC_CARRAY */
+			0x3,		/* 3 */
+/* 488 */	NdrFcShort( 0x4 ),	/* 4 */
+/* 490 */	0x27,		/* Corr desc:  parameter, FC_USHORT */
+			0x0,		/*  */
+#ifndef _ALPHA_
+/* 492 */	NdrFcShort( 0x8 ),	/* x86, MIPS, PPC Stack size/offset = 8 */
+#else
+			NdrFcShort( 0x10 ),	/* Alpha Stack size/offset = 16 */
+#endif
+/* 494 */	0x8,		/* FC_LONG */
+			0x5b,		/* FC_END */
+/* 496 */	
+			0x11, 0x0,	/* FC_RP */
+/* 498 */	NdrFcShort( 0x2 ),	/* Offset= 2 (500) */
+/* 500 */	
+			0x1b,		/* FC_CARRAY */
+			0x3,		/* 3 */
+/* 502 */	NdrFcShort( 0x4 ),	/* 4 */
+/* 504 */	0x27,		/* Corr desc:  parameter, FC_USHORT */
+			0x0,		/*  */
+#ifndef _ALPHA_
+/* 506 */	NdrFcShort( 0x8 ),	/* x86, MIPS, PPC Stack size/offset = 8 */
+#else
+			NdrFcShort( 0x10 ),	/* Alpha Stack size/offset = 16 */
+#endif
+/* 508 */	
+			0x4b,		/* FC_PP */
+			0x5c,		/* FC_PAD */
+/* 510 */	
+			0x48,		/* FC_VARIABLE_REPEAT */
+			0x49,		/* FC_FIXED_OFFSET */
+/* 512 */	NdrFcShort( 0x4 ),	/* 4 */
+/* 514 */	NdrFcShort( 0x0 ),	/* 0 */
+/* 516 */	NdrFcShort( 0x1 ),	/* 1 */
+/* 518 */	NdrFcShort( 0x0 ),	/* 0 */
+/* 520 */	NdrFcShort( 0x0 ),	/* 0 */
+/* 522 */	0x13, 0x0,	/* FC_OP */
+/* 524 */	NdrFcShort( 0xffffff00 ),	/* Offset= -256 (268) */
+/* 526 */	
+			0x5b,		/* FC_END */
+
+			0x8,		/* FC_LONG */
+/* 528 */	0x5c,		/* FC_PAD */
+			0x5b,		/* FC_END */
+
+			0x0
+        }
+    };
+
+const CInterfaceProxyVtbl * _dcom_ProxyVtblList[] = 
+{
+    ( CInterfaceProxyVtbl *) &_IRemUnknownProxyVtbl,
+    ( CInterfaceProxyVtbl *) &_IRemUnknown2ProxyVtbl,
+    0
+};
+
+const CInterfaceStubVtbl * _dcom_StubVtblList[] = 
+{
+    ( CInterfaceStubVtbl *) &_IRemUnknownStubVtbl,
+    ( CInterfaceStubVtbl *) &_IRemUnknown2StubVtbl,
+    0
+};
+
+PCInterfaceName const _dcom_InterfaceNamesList[] = 
+{
+    "IRemUnknown",
+    "IRemUnknown2",
+    0
+};
+
+
+#define _dcom_CHECK_IID(n)	IID_GENERIC_CHECK_IID( _dcom, pIID, n)
+
+int __stdcall _dcom_IID_Lookup( const IID * pIID, int * pIndex )
+{
+    IID_BS_LOOKUP_SETUP
+
+    IID_BS_LOOKUP_INITIAL_TEST( _dcom, 2, 1 )
+    IID_BS_LOOKUP_RETURN_RESULT( _dcom, 2, *pIndex )
+    
+}
+
+const ExtendedProxyFileInfo dcom_ProxyFileInfo = 
+{
+    (PCInterfaceProxyVtblList *) & _dcom_ProxyVtblList,
+    (PCInterfaceStubVtblList *) & _dcom_StubVtblList,
+    (const PCInterfaceName * ) & _dcom_InterfaceNamesList,
+    0, // no delegation
+    & _dcom_IID_Lookup, 
+    2,
+    1,
+    0, /* table of [async_uuid] interfaces */
+    0, /* Filler1 */
+    0, /* Filler2 */
+    0  /* Filler3 */
+};
--- /dev/null	2003-01-10 01:23:22.000000000 +0100
+++ dlls/ole32/proxy.c	2003-05-23 22:24:24.000000000 +0200
@@ -0,0 +1,2269 @@
+/*
+ * Proxy/Stub implementation
+ *
+ * Copyright 2001 Ove Kåven, TransGaming Technologies
+ *
+ */
+
+#include <string.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "winerror.h"
+#include "ole2.h"
+#include "rpcproxy.h"
+#include "wine/unicode.h"
+
+#include "objbase.h"
+#include "compobj_private.h"
+
+#include "debugtools.h"
+
+DEFAULT_DEBUG_CHANNEL(ole);
+
+static void __RPC_STUB COM_RpcDispatch(PRPC_MESSAGE Message);
+static LPRPCCHANNELBUFFER RpcChannel_Create(RPC_BINDING_HANDLE bind, DWORD model, DWORD tid);
+void COM_FindXIf2(APARTMENT *apt, XOBJECT *obj, XIF **xif, REFIID riid);
+void COM_FindXObj(APARTMENT *apt, OID oid, IPID ipid, XOBJECT **xobj, XIF **xif);
+void COM_ExtAddRef(APARTMENT *apt, XOBJECT *xobj, XIF *xif, DWORD refs);
+void COM_ExtRelease(APARTMENT *apt, XOBJECT *xobj, XIF *xif, DWORD refs);
+void COM_CreateIObj(APARTMENT *apt, OXID oxid, OID oid, IPID ipid, IOBJECT **iobj, RPC_BINDING_HANDLE bind);
+static HRESULT COM_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv);
+
+/* the standard marshaller returns a special GUID */
+static const CLSID CLSID_StdMarshal = {
+  0x1B, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}
+};
+
+/* CLSID for ole32's builtin marshalers
+ * (referenced by winedefault.reg) */
+static const CLSID CLSID_PSFactoryBuffer = {
+  0x320, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}
+};
+
+const IID IID_IRemUnknown = {
+  0x131, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}
+};
+
+const IID IID_IRemUnknown2 = {
+  0x142, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}
+};
+
+static LONG initRPC;
+
+static RPC_DISPATCH_FUNCTION rpc_dispatch_table[1] = { COM_RpcDispatch };
+static RPC_DISPATCH_TABLE rpc_dispatch = { 1, rpc_dispatch_table };
+
+typedef struct tagREGIF {
+  struct tagREGIF *next;
+  RPC_SERVER_INTERFACE If;
+} REGIF;
+
+static REGIF *RegIf;
+static CRITICAL_SECTION csRegIf = CRITICAL_SECTION_INIT("csRegIf");
+
+static LPRPCCHANNELBUFFER rpc_server_chan;
+static RPC_IF_HANDLE rpc_IRemUnknown;
+
+/* since I don't know how MS generates IPIDs, I'll just
+ * combine the lower 32 bits of the OXID with the OID
+ * and an interface counter */
+typedef struct tagIIPID {
+  OID oid;
+  DWORD ifc;
+  DWORD oxid;
+} IIPID;
+
+static RPC_IF_HANDLE COM_RpcRegIf(REFIID riid)
+{
+  REGIF *cif;
+  BOOL reg = FALSE;
+  TRACE("(%s)\n", debugstr_guid(riid));
+  EnterCriticalSection(&csRegIf);
+  for (cif = RegIf;
+       cif && !IsEqualGUID(&cif->If.InterfaceId.SyntaxGUID, riid);
+       cif = cif->next);
+  if (!cif) {
+    cif = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(REGIF));
+    cif->If.Length = sizeof(RPC_SERVER_INTERFACE);
+    cif->If.InterfaceId.SyntaxGUID = *riid;
+    cif->If.DispatchTable = &rpc_dispatch;
+    cif->next = RegIf;
+    RegIf = cif;
+    reg = TRUE;
+  }
+  LeaveCriticalSection(&csRegIf);
+  if (reg)
+    RpcServerRegisterIfEx((RPC_IF_HANDLE)&cif->If,
+			  NULL, NULL,
+			  RPC_IF_OLE | RPC_IF_AUTOLISTEN,
+			  RPC_C_LISTEN_MAX_CALLS_DEFAULT,
+			  NULL);
+  return (RPC_IF_HANDLE)&cif->If;
+}
+
+void COM_RpcInit(void)
+{
+  if (!InterlockedExchange(&initRPC, 1)) {
+    LPSTR eps;
+
+    UuidToStringA((UUID*)&MTA.oxid, &eps);
+    RpcServerUseProtseqEpA("ncalrpc",
+                           RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
+                           eps, NULL);
+    RpcStringFreeA(&eps);
+    rpc_server_chan = RpcChannel_Create(0, COINIT_MULTITHREADED, 0);
+    rpc_IRemUnknown = COM_RpcRegIf(&IID_IRemUnknown);
+  }
+}
+
+void COM_RpcExportClass(REFCLSID rclsid, DWORD dwCtx)
+{
+  RPC_BINDING_VECTOR *bind;
+  UUID_VECTOR objs;
+
+  if (dwCtx == MSHCTX_INPROC) return;
+
+  COM_RpcInit();
+  /* I don't think using the RPC endpoint mapper is really the right place to
+   * register class objects, but it'll do for now */
+  objs.Count = 1;
+  objs.Uuid[0] = (UUID*)rclsid;
+  RpcServerInqBindings(&bind);
+  /* FIXME: IRemUnknown is not the right interface for this, we should
+   * rather implement IRemoteActivation, but I don't wanna right now */
+  RpcEpRegisterA(rpc_IRemUnknown, bind, &objs, NULL);
+  RpcBindingVectorFree(&bind);
+}
+
+HRESULT COM_RpcImportClass(LPVOID *ppv, REFCLSID rclsid, REFIID riid, LPSTR server)
+{
+  APARTMENT *apt = COM_CurrentApt();
+  LPSTR uuid = NULL, sbind = NULL;
+  RPC_BINDING_HANDLE bind = NULL;
+  RPC_STATUS status;
+
+  COM_RpcInit(); /* temporary */
+
+  *ppv = NULL;
+  UuidToStringA((UUID*)rclsid, &uuid);
+  /* we only do local connections for now */
+  RpcStringBindingComposeA(uuid, "ncalrpc", NULL, NULL, NULL, &sbind);
+  status = RpcBindingFromStringBindingA(sbind, &bind);
+  RpcStringFreeA(&sbind);
+  if (status != RPC_S_OK) return status;
+  /* use the endpoint mapper entry we made in COM_RpcExportClass */
+  status = RpcEpResolveBinding(bind, rpc_IRemUnknown);
+  if (status == RPC_S_OK) {
+    /* we have a fully bound handle, get the class object */
+    /* as a hack, we use IRemUnknown with the clsid as the ipid,
+     * since we haven't implemented IRemoteActivation yet */
+    IOBJECT *obj;
+
+    COM_CreateIObj(apt, 0, 0, *rclsid, &obj, bind);
+    if (obj) {
+      status = IRemUnknown_QueryInterface((LPREMUNKNOWN)obj, riid, ppv);
+      IRemUnknown_Release((LPREMUNKNOWN)obj);
+    }
+    else status = CO_E_OBJNOTCONNECTED;
+  }
+  else RpcBindingFree(&bind);
+  return status;
+}
+
+static void __RPC_STUB COM_RpcDispatch(PRPC_MESSAGE pMsg)
+{
+  APARTMENT *apt = COM_CurrentApt();
+  PRPC_SERVER_INTERFACE sif;
+  IID iid;
+  STDOBJREF oref;
+  HRESULT hr;
+  XOBJECT *xobj;
+  XIF *xif;
+  LPRPCSTUBBUFFER stub;
+
+  TRACE("(%p)\n", pMsg);
+  sif = pMsg->RpcInterfaceInformation;
+  iid = sif->InterfaceId.SyntaxGUID;
+  RpcBindingInqObject(pMsg->Handle, &oref.ipid);
+  TRACE(" iid  %s\n", debugstr_guid(&iid));
+  TRACE(" method %d\n", pMsg->ProcNum);
+
+  if (!apt) apt = &MTA;
+
+  /* to support the hack we use in COM_RpcImportClass,
+   * first check whether the IPID is an exported clas
+   */
+  hr = COM_GetRegisteredClassObject(&oref.ipid, NULL,
+				    &oref, NULL);
+  /* if found:     hr = S_OK,    oref.ipid replaced
+   * if not found: hr = S_FALSE, oref.ipid unchanged
+   */
+  if (FAILED(hr)) {
+    /* we need to implement IRemoteActivation */
+    FIXME("can't handle custom-marshaled class object\n");
+    return;
+  }
+
+  /* get OID */
+  oref.oid = ((IIPID*)&oref.ipid)->oid;
+  /* recreate OXID (see compobj.c for OXID generation) */
+  oref.oxid = ((IIPID*)&oref.ipid)->oxid | MTA.oxid;
+
+  TRACE(" oxid %llx\n", oref.oxid);
+  TRACE(" oid %llx\n", oref.oid);
+  TRACE(" ipid %s\n", debugstr_guid(&oref.ipid));
+
+  if (oref.oxid != apt->oxid) {
+    HWND win;
+
+    if (oref.oxid == MTA.oxid) {
+      FIXME("mysterious RPC STA found - aiee\n");
+      return;
+    }
+    win = COM_GetApartmentWin(oref.oxid);
+    if (win) {
+      TRACE("dispatching to STA (hwnd=%08x)\n", win);
+      SendMessageA(win, WM_USER, 0, (LPARAM)pMsg);
+    } else {
+      ERR("failed to dispatch to STA\n");
+    }
+    return;
+  }
+
+  COM_FindXObj(apt, oref.oid, oref.ipid, &xobj, NULL);
+  if (!xobj) {
+    ERR("requested object not found\n");
+    return;
+  }
+
+  TRACE(" object=%p\n", xobj->obj);
+
+  /* handle IRemUnknown specially, since we haven't properly
+   * implemented the apartment objects (and IOXIDResolver) yet */
+  if (IsEqualGUID(&iid, &IID_IRemUnknown)) {
+    stub = (LPRPCSTUBBUFFER)xobj;
+  }
+  else {
+    /* our proxies use the same RPC binding for all the interfaces,
+     * so we get the same IPID for them all, so we'll use the IID
+     * instead of the IPID to find the actual interface stub */
+    COM_FindXIf2(apt, xobj, &xif, &iid);
+    if (!xif) {
+      ERR("requested interface not found\n");
+      return;
+    }
+    TRACE(" interface=%p\n", xif->iface);
+    stub = xif->stub;
+  }
+
+  TRACE(" stub=%p\n", stub);
+  if (!stub) {
+    ERR("stub not found\n");
+    return;
+  }
+
+  /* FIXME: handle ORPCTHIS and ORPCTHAT */
+
+  IRpcStubBuffer_Invoke(stub, (RPCOLEMESSAGE*)pMsg, rpc_server_chan);
+}
+
+LRESULT CALLBACK COM_AptWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+  switch (msg) {
+  case WM_USER:
+    TRACE("received RPC message\n");
+    COM_RpcDispatch((PRPC_MESSAGE)lParam);
+    break;
+  default:
+    return DefWindowProcA(hWnd, msg, wParam, lParam);
+  }
+  return 0;
+}
+
+/* COM_GetPSFactory [internal]:
+ * Given an interface ID riid, this function returns an IPSFactoryBuffer
+ * interface which can be used to create marshalling proxies or stubs for
+ * the given interface. */
+static HRESULT COM_GetPSFactory(REFIID riid, LPPSFACTORYBUFFER *pPS)
+{
+  HRESULT hr;
+  CLSID clsid;
+  hr = CoGetPSClsid(riid, &clsid);
+  if (FAILED(hr)) return hr;
+  hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL,
+			&IID_IPSFactoryBuffer, (LPVOID *)pPS);
+  return hr;
+}
+
+/******************** CHANNEL OBJECT ********************/
+
+#define MAX_THREADS 128
+
+typedef struct {
+  ICOM_VTABLE(IRpcChannelBuffer) *lpVtbl;
+  DWORD ref, tid;
+  RPC_BINDING_HANDLE bind;
+  HANDLE done;
+} RpcChannelImpl;
+
+typedef struct _RpcRequest {
+  struct _RpcRequest *next;
+  PRPC_MESSAGE msg;
+  RPC_STATUS ret;
+  HANDLE done;
+} RpcRequest;
+
+static HANDLE worker_sem;
+static DWORD worker_count, worker_free;
+static CRITICAL_SECTION creq_cs = CRITICAL_SECTION_INIT("csRpcRequest");
+static RpcRequest *creq_head;
+static RpcRequest *creq_tail;
+
+static void RpcChannel_push_request(RpcRequest *req)
+{
+  req->next = NULL;
+  req->ret = RPC_S_CALL_IN_PROGRESS; /* ? */
+  EnterCriticalSection(&creq_cs);
+  if (creq_tail) creq_tail->next = req;
+  else {
+    creq_head = req;
+    creq_tail = req;
+  }
+  LeaveCriticalSection(&creq_cs);
+}
+
+static RpcRequest* RpcChannel_pop_request(void)
+{
+  RpcRequest* req;
+  EnterCriticalSection(&creq_cs);
+  req = creq_head;
+  if (req) {
+    creq_head = req->next;
+    if (!creq_head) creq_tail = NULL;
+  }
+  LeaveCriticalSection(&creq_cs);
+  if (req) req->next = NULL;
+  return req;
+}
+
+static DWORD CALLBACK RpcChannel_worker_thread(LPVOID the_arg)
+{
+  HANDLE obj;
+  RpcRequest* req;
+
+  for (;;) {
+    /* idle timeout after 5s */
+    obj = WaitForSingleObject(worker_sem, 5000);
+    if (obj == WAIT_TIMEOUT) {
+      /* if another idle thread exist, self-destruct */
+      if (worker_free > 1) break;
+      continue;
+    }
+    req = RpcChannel_pop_request();
+    if (!req) continue;
+    InterlockedDecrement(&worker_free);
+    for (;;) {
+      req->ret = I_RpcSendReceive(req->msg);
+      SetEvent(req->done);
+      /* try to grab another request here without waiting
+       * on the semaphore, in case it hits max */
+      req = RpcChannel_pop_request();
+      if (!req) break;
+      /* decrement semaphore */
+      WaitForSingleObject(worker_sem, 0);
+    }
+    InterlockedIncrement(&worker_free);
+  }
+  InterlockedDecrement(&worker_free);
+  InterlockedDecrement(&worker_count);
+  return 0;
+}
+
+static void RpcChannel_create_worker_if_needed(void)
+{
+  if (!worker_sem) {
+    HANDLE sem;
+    sem = CreateSemaphoreA(NULL, 0, MAX_THREADS, NULL);
+    if (InterlockedCompareExchange((PLONG)&worker_sem, sem, 0))
+      CloseHandle(sem); /* somebody beat us to it */
+  }
+  if (!worker_free && worker_count < MAX_THREADS) {
+    HANDLE thread;
+    InterlockedIncrement(&worker_count);
+    InterlockedIncrement(&worker_free);
+    thread = CreateThread(NULL, 0, RpcChannel_worker_thread, NULL, 0, NULL);
+    if (thread) CloseHandle(thread);
+    else {
+      InterlockedDecrement(&worker_free);
+      InterlockedDecrement(&worker_count);
+    }
+  }
+}
+
+static HRESULT WINAPI RpcChannel_QueryInterface(LPRPCCHANNELBUFFER iface,
+						REFIID riid,
+						LPVOID *obj)
+{
+  ICOM_THIS(RpcChannelImpl,iface);
+  TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(riid),obj);
+  if (IsEqualGUID(&IID_IUnknown,riid) ||
+      IsEqualGUID(&IID_IRpcChannelBuffer,riid)) {
+    *obj = This;
+    This->ref++;
+    return S_OK;
+  }
+  return E_NOINTERFACE;
+}
+
+static ULONG WINAPI RpcChannel_AddRef(LPRPCCHANNELBUFFER iface)
+{
+  ICOM_THIS(RpcChannelImpl,iface);
+  TRACE("(%p)->AddRef()\n",This);
+  return ++(This->ref);
+}
+
+static ULONG WINAPI RpcChannel_Release(LPRPCCHANNELBUFFER iface)
+{
+  ICOM_THIS(RpcChannelImpl,iface);
+  TRACE("(%p)->Release()\n",This);
+  if (!--(This->ref)) {
+    if (This->done) CloseHandle(This->done);
+    RpcBindingFree(&This->bind);
+    HeapFree(GetProcessHeap(),0,This);
+    return 0;
+  }
+  return This->ref;
+}
+
+static inline HRESULT RPC2HR(RPC_STATUS status)
+{
+  switch (status) {
+  case RPC_S_OK:
+    return S_OK;
+  default:
+    return E_FAIL;
+  }
+}
+
+static HRESULT WINAPI RpcChannel_GetBuffer(LPRPCCHANNELBUFFER iface,
+					   PRPCOLEMESSAGE pMessage,
+					   REFIID riid)
+{
+  ICOM_THIS(RpcChannelImpl,iface);
+  PRPC_MESSAGE pmsg = (PRPC_MESSAGE)pMessage;
+  PRPC_CLIENT_INTERFACE cif;
+  RPC_STATUS status;
+
+  TRACE("(%p)->GetBuffer(%p,%p)\n",This,pMessage,riid);
+
+  if (This->bind) {
+    cif = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RPC_CLIENT_INTERFACE));
+    cif->Length = sizeof(RPC_CLIENT_INTERFACE);
+    cif->InterfaceId.SyntaxGUID = *riid;
+    pmsg->RpcInterfaceInformation = cif;
+    pmsg->Handle = This->bind;
+  }
+
+  status = I_RpcGetBuffer(pmsg);
+  return RPC2HR(status);
+}
+
+static HRESULT WINAPI RpcChannel_SendReceive(LPRPCCHANNELBUFFER iface,
+					     PRPCOLEMESSAGE pMessage,
+					     ULONG *pStatus)
+{
+  ICOM_THIS(RpcChannelImpl,iface);
+  PRPC_MESSAGE pmsg = (PRPC_MESSAGE)pMessage;
+  RPC_STATUS status;
+
+  TRACE("(%p)->SendReceive(%p,%p)\n",This,pMessage,pStatus);
+  if (This->done) {
+    RpcRequest req;
+    DWORD w;
+    MSG msg;
+
+    req.msg = pmsg;
+    req.done = This->done;
+    RpcChannel_create_worker_if_needed();
+    RpcChannel_push_request(&req);
+    ReleaseSemaphore(worker_sem, 1, NULL);
+    do {
+      while (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE)) {
+        TranslateMessage(&msg);
+        DispatchMessageW(&msg);
+        TRACE("message %04x dispatched\n", msg.message);
+      }
+      w = MsgWaitForMultipleObjectsEx(1, &This->done, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE);
+      TRACE("MsgWaitForMultipleObjects returns %ld\n", w);
+      if (w == WAIT_OBJECT_0) break;
+    } while (TRUE);
+    status = req.ret;
+  } else {
+    status = I_RpcSendReceive(pmsg);
+  }
+  return RPC2HR(status);
+}
+
+static HRESULT WINAPI RpcChannel_FreeBuffer(LPRPCCHANNELBUFFER iface,
+					    PRPCOLEMESSAGE pMessage)
+{
+  ICOM_THIS(RpcChannelImpl,iface);
+  PRPC_MESSAGE pmsg = (PRPC_MESSAGE)pMessage;
+  RPC_STATUS status;
+
+  TRACE("(%p)->FreeBuffer(%p)\n",This,pMessage);
+  status = I_RpcFreeBuffer(pmsg);
+  if (This->bind) {
+    HeapFree(GetProcessHeap(), 0, pmsg->RpcInterfaceInformation);
+    pmsg->RpcInterfaceInformation = NULL;
+  }
+  return RPC2HR(status);
+}
+
+static HRESULT WINAPI RpcChannel_GetDestCtx(LPRPCCHANNELBUFFER iface,
+					    DWORD *pdwDestContext,
+					    LPVOID *ppvDestContext)
+{
+  ICOM_THIS(RpcChannelImpl,iface);
+  FIXME("(%p)->GetDestCtx(%p,%p)\n",This,pdwDestContext,ppvDestContext);
+  return E_FAIL;
+}
+
+static HRESULT WINAPI RpcChannel_IsConnected(LPRPCCHANNELBUFFER iface)
+{
+  ICOM_THIS(RpcChannelImpl,iface);
+  FIXME("(%p)->IsConnected()\n",This);
+  return S_OK;
+}
+
+static ICOM_VTABLE(IRpcChannelBuffer) RpcChannel_VTable = {
+  RpcChannel_QueryInterface,
+  RpcChannel_AddRef,
+  RpcChannel_Release,
+  RpcChannel_GetBuffer,
+  RpcChannel_SendReceive,
+  RpcChannel_FreeBuffer,
+  RpcChannel_GetDestCtx,
+  RpcChannel_IsConnected
+};
+
+static LPRPCCHANNELBUFFER RpcChannel_Create(RPC_BINDING_HANDLE bind, DWORD model, DWORD tid)
+{
+  RpcChannelImpl *chan;
+
+  chan = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(RpcChannelImpl));
+  if (!chan) return NULL;
+  chan->lpVtbl = &RpcChannel_VTable;
+  chan->ref = 1;
+  chan->tid = tid;
+  chan->bind = bind;
+  if (bind && (model & COINIT_APARTMENTTHREADED)) {
+    chan->done = CreateEventA(NULL, FALSE, FALSE, NULL);
+  }
+  return (LPRPCCHANNELBUFFER)chan;
+}
+
+
+/* COM tracks interfaces with three kinds of IDs:
+ *  OXID = Object Exporter ID, one for each apartment (unique within network)
+ *  OID = Object ID, one for each object (unique within apartment)
+ *  IPID = Interface Pointer ID, one for each interface (unique within apartment)
+ *
+ * Hence, each "stub manager" would correspond to an OID, and each
+ * of the interface stubs would correspond to an IPID.
+ */
+
+/******************** STUB MANAGER ********************/
+/* (FIXME: it is incorrect for the stub manager to implement
+ * IRemUnknown, it's rather a job for the OXID object,
+ * but this will do for now) */
+
+void COM_FindXIf(APARTMENT *apt, IPID ipid, XOBJECT *obj, XIF **xif)
+{
+  XIF *iface;
+  EnterCriticalSection(&apt->cs);
+  if (xif) {
+    for (iface = obj->ifaces; iface && !IsEqualGUID(&iface->ipid, &ipid); iface = iface->next);
+    *xif = iface;
+  }
+  LeaveCriticalSection(&apt->cs);
+}
+
+void COM_FindXIf2(APARTMENT *apt, XOBJECT *obj, XIF **xif, REFIID riid)
+{
+  XIF *iface;
+  EnterCriticalSection(&apt->cs);
+  if (xif) {
+    for (iface = obj->ifaces; iface && !IsEqualGUID(&iface->iid, riid); iface = iface->next);
+    *xif = iface;
+  }
+  LeaveCriticalSection(&apt->cs);
+}
+
+void COM_CreateXIf(APARTMENT *apt, XOBJECT *obj, XIF **xif, REFIID riid, LPVOID pv)
+{
+  XIF *iface;
+
+  EnterCriticalSection(&apt->cs);
+  for (iface = obj->ifaces; iface && !IsEqualGUID(&iface->iid, riid); iface = iface->next);
+  if (!iface) {
+    LPPSFACTORYBUFFER pPSF;
+    iface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(XIF));
+    iface->iface = pv;
+    iface->iid = *riid;
+    /* generate IPID */
+    ((IIPID*)&iface->ipid)->oxid = apt->oxid;
+    ((IIPID*)&iface->ipid)->oid = obj->oid;
+    ((IIPID*)&iface->ipid)->ifc = obj->ifc++;
+    if (!IsEqualGUID(riid, &IID_IUnknown)) {
+      /* register RPC interface */
+      COM_RpcRegIf(riid);
+      iface->hres = COM_GetPSFactory(riid, &pPSF);
+      /* attempt to create an interface stub */
+      if (SUCCEEDED(iface->hres)) {
+	iface->hres = IPSFactoryBuffer_CreateStub(pPSF, riid, pv,
+						  &iface->stub);
+	IPSFactoryBuffer_Release(pPSF);
+	TRACE(" oid %llx ipid %s iface=%p stub=%p\n",
+	      obj->oid, debugstr_guid(&iface->ipid), iface->iface,
+	      iface->stub);
+      }
+    }
+    iface->next = obj->ifaces;
+    obj->ifaces = iface;
+  }
+#if 0 /* I don't think we AddRef-ed it? */
+  else IUnknown_Release((LPUNKNOWN)pv);
+#endif
+  if (xif) *xif = iface;
+  LeaveCriticalSection(&apt->cs);
+}
+
+static HRESULT WINAPI StubMan_QueryInterface(LPRPCSTUBBUFFER iface,
+					     REFIID riid,
+					     LPVOID *obj)
+{
+  ICOM_THIS(XOBJECT,iface);
+  TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(riid),obj);
+  if (IsEqualGUID(&IID_IUnknown,riid) ||
+      IsEqualGUID(&IID_IRpcStubBuffer,riid)) {
+    *obj = This;
+    return S_OK;
+  }
+  return E_NOINTERFACE;
+}
+
+static ULONG WINAPI StubMan_AddRef(LPRPCSTUBBUFFER iface)
+{
+  ICOM_THIS(XOBJECT,iface);
+  TRACE("(%p)->AddRef()\n",This);
+  return 2;
+}
+
+static ULONG WINAPI StubMan_Release(LPRPCSTUBBUFFER iface)
+{
+  ICOM_THIS(XOBJECT,iface);
+  TRACE("(%p)->Release()\n",This);
+  return 1;
+}
+
+static HRESULT WINAPI StubMan_Connect(LPRPCSTUBBUFFER iface,
+				      LPUNKNOWN lpUnkServer)
+{
+  ICOM_THIS(XOBJECT,iface);
+  TRACE("(%p)->Connect(%p)\n",This,lpUnkServer);
+  return S_OK;
+}
+
+static void WINAPI StubMan_Disconnect(LPRPCSTUBBUFFER iface)
+{
+  ICOM_THIS(XOBJECT,iface);
+  TRACE("(%p)->Disconnect()\n",This);
+}
+
+static HRESULT WINAPI StubMan_Invoke(LPRPCSTUBBUFFER iface,
+				     PRPCOLEMESSAGE pMsg,
+				     LPRPCCHANNELBUFFER pChannel)
+{
+  ICOM_THIS(XOBJECT,iface);
+  APARTMENT *apt = COM_CurrentApt();
+  /* DWORD dwPhase = 0; */
+  ULONG iMethod = pMsg->iMethod;
+  XIF *xiface;
+  LPVOID ipv;
+  LPBYTE buf = pMsg->Buffer;
+  DWORD count;
+  ULONG cRefs;
+  USHORT cIids;
+  IID iid, *piid;
+
+  TRACE("(%p)->Invoke(%p,%p) method %ld\n",This,pMsg,pChannel,iMethod);
+  switch (iMethod) {
+  case 3: /* RemQueryInterface */
+    /* FIXME: use rpcrt4's NDR marshaller library
+     * (NdrSimpleTypeUnmarshall etc) */
+#if 0
+    COM_FindXIf(apt, *(IPID*)buf, This, &xiface);
+    if (!xiface) {
+      ERR("RemQueryInterface on invalid interface %s\n", debugstr_guid((IPID*)buf));
+      break;
+    }
+    ipv = xiface->iface;
+#else
+    xiface = NULL;
+    ipv = This->obj;
+#endif
+    buf += sizeof(IPID);
+    memcpy(&cRefs, buf, sizeof(ULONG));
+    buf += sizeof(ULONG);
+    memcpy(&cIids, buf, sizeof(USHORT));
+    buf += sizeof(USHORT);
+    TRACE("RemQueryInterface(%p,%ld,%d,...)\n", ipv, cRefs, cIids);
+    if (cIids == 1) {
+      piid = &iid;
+    }
+    else {
+      FIXME("handle more than one IID\n");
+      break;
+    }
+    memcpy(piid, buf, cIids*sizeof(IID));
+    /* compose reply */
+    pMsg->cbBuffer = cIids*sizeof(REMQIRESULT);
+    I_RpcGetBuffer((PRPC_MESSAGE)pMsg);
+    buf = pMsg->Buffer;
+    for (count=0; count<cIids; count++) {
+      REMQIRESULT *qi = (REMQIRESULT*)buf;
+      XIF *xif;
+      LPVOID pv = NULL;
+
+      qi->hResult = E_FAIL;
+      TRACE(" querying IID %s\n", debugstr_guid(&piid[count]));
+      COM_FindXIf2(apt, This, &xif, &piid[count]);
+      if (!xif) {
+	qi->hResult = IUnknown_QueryInterface((LPUNKNOWN)ipv,
+					      &piid[count],
+					      &pv);
+	if (qi->hResult == S_OK)
+	  COM_CreateXIf(apt, This, &xif, &piid[count], pv);
+      }
+      if (xif) {
+	qi->hResult = xif->hres;
+	if (qi->hResult == S_OK) {
+	  qi->std.flags = 0;
+	  qi->std.cPublicRefs = cRefs;
+	  qi->std.oxid = apt->oxid;
+	  qi->std.oid = This->oid;
+	  qi->std.ipid = xif->ipid;
+	  COM_ExtAddRef(apt, This, xif, cRefs);
+	  TRACE(" returning IPID %s for iface %p\n",
+		debugstr_guid(&qi->std.ipid), xif->iface);
+	}
+      }
+      buf += sizeof(REMQIRESULT);
+    }
+    break;
+  case 4: /* RemAddRef */
+    memcpy(&cIids, buf, sizeof(USHORT));
+    buf += sizeof(USHORT);
+    TRACE("RemAddRef(%d,...)\n", cIids);
+    for (count=0; count<cIids; count++) {
+      REMINTERFACEREF *ir = (REMINTERFACEREF*)buf;
+      TRACE(" on IPID %s\n", debugstr_guid(&ir->ipid));
+      COM_FindXIf(apt, ir->ipid, This, &xiface);
+      if (!xiface)
+        ERR("RemAddRef on invalid interface %s\n", debugstr_guid(&ir->ipid));
+      else
+        COM_ExtAddRef(apt, This, xiface, ir->cPublicRefs);
+      buf += sizeof(REMINTERFACEREF);
+    }
+    pMsg->cbBuffer = cIids * sizeof(HRESULT);
+    I_RpcGetBuffer((PRPC_MESSAGE)pMsg);
+    buf = pMsg->Buffer;
+    /* S_OK on all addrefs */
+    memset(buf, 0, cIids * sizeof(HRESULT));
+    break;
+  case 5: /* RemRelease */
+    memcpy(&cIids, buf, sizeof(USHORT));
+    buf += sizeof(USHORT);
+    TRACE("RemRelease(%d,...)\n", cIids);
+    for (count=0; count<cIids; count++) {
+      REMINTERFACEREF *ir = (REMINTERFACEREF*)buf;
+      TRACE(" on IPID %s\n", debugstr_guid(&ir->ipid));
+      COM_FindXIf(apt, ir->ipid, This, &xiface);
+      if (!xiface)
+        ERR("RemRelease on invalid interface %s\n", debugstr_guid(&ir->ipid));
+      else
+        COM_ExtRelease(apt, This, xiface, ir->cPublicRefs);
+      buf += sizeof(REMINTERFACEREF);
+    }
+    pMsg->cbBuffer = 0;
+    I_RpcGetBuffer((PRPC_MESSAGE)pMsg);
+    buf = pMsg->Buffer;
+    break;
+  }
+  return S_OK;
+}
+
+static LPRPCSTUBBUFFER WINAPI StubMan_IsIIDSupported(LPRPCSTUBBUFFER iface,
+						     REFIID riid)
+{
+  ICOM_THIS(XOBJECT,iface);
+  TRACE("(%p)->IsIIDSupported(%s)\n",This,debugstr_guid(riid));
+  return IsEqualGUID(&IID_IRemUnknown, riid) ? iface : NULL;
+}
+
+static ULONG WINAPI StubMan_CountRefs(LPRPCSTUBBUFFER iface)
+{
+  ICOM_THIS(XOBJECT,iface);
+  TRACE("(%p)->CountRefs()\n",This);
+  return This->refs;
+}
+
+static HRESULT WINAPI StubMan_DebugServerQueryInterface(LPRPCSTUBBUFFER iface,
+							LPVOID *ppv)
+{
+  ICOM_THIS(XOBJECT,iface);
+  TRACE("(%p)->DebugServerQueryInterface(%p)\n",This,ppv);
+  return S_OK;
+}
+
+static void WINAPI StubMan_DebugServerRelease(LPRPCSTUBBUFFER iface,
+					      LPVOID pv)
+{
+  ICOM_THIS(XOBJECT,iface);
+  TRACE("(%p)->DebugServerRelease(%p)\n",This,pv);
+}
+
+static ICOM_VTABLE(IRpcStubBuffer) StubMan_VTable =
+{
+  ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+  StubMan_QueryInterface,
+  StubMan_AddRef,
+  StubMan_Release,
+  StubMan_Connect,
+  StubMan_Disconnect,
+  StubMan_Invoke,
+  StubMan_IsIIDSupported,
+  StubMan_CountRefs,
+  StubMan_DebugServerQueryInterface,
+  StubMan_DebugServerRelease
+};
+
+void COM_FindXObj(APARTMENT *apt, OID oid, IPID ipid, XOBJECT **xobj, XIF **xif)
+{
+  XOBJECT *obj;
+  EnterCriticalSection(&apt->cs);
+  for (obj = apt->objs; obj && obj->oid != oid; obj = obj->next);
+  if (xobj) *xobj = obj;
+  if (obj) {
+    if (xif) COM_FindXIf(apt, ipid, obj, xif);
+  }
+  else if (xif) *xif = NULL;
+  LeaveCriticalSection(&apt->cs);
+}
+
+void COM_CreateXObj(APARTMENT *apt, XOBJECT **xobj, XIF **xif, REFIID riid, LPVOID pv)
+{
+  LPUNKNOWN pUnk = NULL;
+  XOBJECT *obj;
+
+  IUnknown_QueryInterface((LPUNKNOWN)pv, &IID_IUnknown, (LPVOID*)&pUnk);
+  EnterCriticalSection(&apt->cs);
+  for (obj = apt->objs; obj && obj->obj != pUnk; obj = obj->next);
+  if (!obj) {
+    obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(XOBJECT));
+    obj->lpVtbl = &StubMan_VTable;
+    obj->parent = apt;
+    IUnknown_AddRef(pUnk);
+    obj->obj = pUnk;
+    /* generate OID */
+    obj->oid = apt->oidc++;
+    obj->next = apt->objs;
+    apt->objs = obj;
+    TRACE(" oid=%llx\n", obj->oid);
+    /* add the IUnknown interface first */
+#if 0
+    IUnknown_AddRef(pUnk);
+#endif
+    COM_CreateXIf(apt, obj, NULL, &IID_IUnknown, pUnk);
+  }
+  if (xobj) *xobj = obj;
+  if (obj) COM_CreateXIf(apt, obj, xif, riid, pv);
+  else {
+#if 0 /* I don't think we AddRef-ed it? */
+    IUnknown_Release((LPUNKNOWN)pv);
+#endif
+    if (xif) *xif = NULL;
+  }
+  LeaveCriticalSection(&apt->cs);
+  IUnknown_Release(pUnk);
+}
+
+void COM_ExtAddRef(APARTMENT *apt, XOBJECT *xobj, XIF *xif, DWORD refs)
+{
+  EnterCriticalSection(&apt->cs);
+  xif->refs += refs;
+  xobj->refs += refs;
+  LeaveCriticalSection(&apt->cs);
+}
+
+void COM_ExtRelease(APARTMENT *apt, XOBJECT *xobj, XIF *xif, DWORD refs)
+{
+  EnterCriticalSection(&apt->cs);
+  xif->refs -= refs;
+  xobj->refs -= refs;
+  if (!xobj->refs) {
+    XOBJECT *cobj, *pobj;
+    XIF *cif, *pif;
+
+    TRACE("destroying stub manager %p\n", xobj);
+    TRACE(" oid=%llx\n", xobj->oid);
+
+    /* unlink exported object */
+    for (pobj = NULL, cobj = apt->objs;
+	 cobj && cobj != xobj;
+	 pobj = cobj, cobj = cobj->next);
+    if (cobj) {
+      if (pobj) pobj->next = cobj->next;
+      else apt->objs = cobj->next;
+      cobj->next = NULL;
+    }
+    LeaveCriticalSection(&apt->cs);
+
+    /* destroy interface stubs */
+    cif = xobj->ifaces;
+    while (cif) {
+      pif = cif;
+      cif = cif->next;
+
+      TRACE(" ipid %s iface=%p stub=%p\n",
+	    debugstr_guid(&pif->ipid), pif->iface, pif->stub);
+
+      /* maybe call something like RpcUnreg? */
+      if (pif->stub)
+        IRpcStubBuffer_Release(pif->stub);
+#if 0 /* I don't think we AddRef-ed it */
+      IUnknown_Release((LPUNKNOWN)pif->iface);
+#endif
+      HeapFree(GetProcessHeap(), 0, pif);
+    }
+    /* destroy stub manager */
+    IUnknown_Release(xobj->obj);
+    HeapFree(GetProcessHeap(), 0, xobj);
+    return;
+  }
+  LeaveCriticalSection(&apt->cs);
+}
+
+/******************** PROXY MANAGER ********************/
+/* (FIXME: it is incorrect for the proxy manager to implement
+ * IRemUnknown, it's rather a job for the OXID object,
+ * but this will do for now) */
+/* FIXME: the proxy manager should implement IMarshal,
+ * so that proxies to proxies can't occur */
+
+void COM_CreateIIf(APARTMENT *apt, IPID ipid, IOBJECT *obj, IIF **iif, REFIID riid)
+{
+  IIF *iface;
+  EnterCriticalSection(&apt->cs);
+  for (iface = obj->ifaces; iface && !IsEqualGUID(&iface->ipid, &ipid); iface = iface->next);
+  if (!iface) {
+    LPPSFACTORYBUFFER pPSF;
+    iface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IIF));
+    iface->iid = *riid;
+    iface->ipid = ipid;
+    if (!IsEqualGUID(riid, &IID_IUnknown)) {
+      /* attempt to aggregate an interface proxy
+       * into the imported object identity */
+      iface->hres = COM_GetPSFactory(riid, &pPSF);
+      if (SUCCEEDED(iface->hres)) {
+	iface->hres = IPSFactoryBuffer_CreateProxy(pPSF, (LPUNKNOWN)obj, riid,
+						   &iface->proxy, &iface->iface);
+	IPSFactoryBuffer_Release(pPSF);
+	/* if successful, connect the interface proxy */
+	if (SUCCEEDED(iface->hres) && obj->chan)
+	  IRpcProxyBuffer_Connect(iface->proxy, obj->chan);
+      }
+    }
+    else iface->iface = obj;
+    iface->next = obj->ifaces;
+    obj->ifaces = iface;
+  }
+  if (iif) *iif = iface;
+  LeaveCriticalSection(&apt->cs);
+}
+
+static HRESULT WINAPI ProxyMan_QueryInterface(LPREMUNKNOWN iface,
+					      REFIID riid,
+					      LPVOID *obj)
+{
+  ICOM_THIS(IOBJECT,iface);
+  TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(riid),obj);
+  if (IsEqualGUID(&IID_IUnknown,riid)) {
+    *obj = This;
+    EnterCriticalSection(&This->parent->cs);
+    This->refs++;
+    LeaveCriticalSection(&This->parent->cs);
+    return S_OK;
+  }
+  else {
+    IIF *iif;
+    REMQIRESULT *qres = NULL;
+    HRESULT hr;
+
+    EnterCriticalSection(&This->parent->cs);
+    iif = This->ifaces;
+    while (iif) {
+      if (IsEqualGUID(&iif->iid,riid)) {
+	*obj = iif->iface;
+	IUnknown_AddRef((LPUNKNOWN)*obj);
+	LeaveCriticalSection(&This->parent->cs);
+	return S_OK;
+      }
+      iif = iif->next;
+    }
+    LeaveCriticalSection(&This->parent->cs);
+
+    /* not found locally, ask server for interface */
+    hr = IRemUnknown_RemQueryInterface(iface, &This->ipid, 5,
+				       1, (IID*)riid, &qres);
+    if (SUCCEEDED(hr)) hr = qres->hResult;
+    if (SUCCEEDED(hr)) {
+      EnterCriticalSection(&This->parent->cs);
+      COM_CreateIIf(This->parent, qres->std.ipid, This, &iif, riid);
+      if (iif) {
+	iif->refs += qres->std.cPublicRefs;
+	hr = iif->hres;
+
+	/* unmarshal complete */
+	if (SUCCEEDED(hr)) {
+	  *obj = iif->iface;
+	  IUnknown_AddRef((LPUNKNOWN)*obj);
+	}
+      }
+      LeaveCriticalSection(&This->parent->cs);
+    }
+    if (qres) CoTaskMemFree(qres);
+    return hr;
+  }
+  return E_NOINTERFACE;
+}
+
+static ULONG WINAPI ProxyMan_AddRef(LPREMUNKNOWN iface)
+{
+  ICOM_THIS(IOBJECT,iface);
+  ULONG refs;
+
+  TRACE("(%p)->AddRef()\n",This);
+  EnterCriticalSection(&This->parent->cs);
+  refs = ++(This->refs);
+  LeaveCriticalSection(&This->parent->cs);
+  return refs;
+}
+
+static ULONG WINAPI ProxyMan_Release(LPREMUNKNOWN iface)
+{
+  ICOM_THIS(IOBJECT,iface);
+  ULONG refs;
+
+  TRACE("(%p)->Release()\n",This);
+  EnterCriticalSection(&This->parent->cs);
+  refs = --(This->refs);
+  if (!refs) {
+    IOBJECT *cobj, *pobj;
+    IIF *cif, *pif;
+    DWORD icnt, icur;
+    REMINTERFACEREF *iref;
+
+    /* unlink imported object */
+    for (pobj = NULL, cobj = This->parent->proxies;
+	 cobj && cobj != This;
+	 pobj = cobj, cobj = cobj->next);
+    if (cobj) {
+      if (pobj) pobj->next = cobj->next;
+      else This->parent->proxies = cobj->next;
+      cobj->next = NULL;
+    }
+    LeaveCriticalSection(&This->parent->cs);
+
+    /* count interface proxies */
+    for (icnt = 0, cif = This->ifaces; cif; cif = cif->next, icnt++);
+    if (icnt) {
+      iref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(REMINTERFACEREF)*icnt);
+
+      /* destroy interface proxies */
+      icur = 0;
+      cif = This->ifaces;
+      while (cif) {
+	iref[icur].ipid = cif->ipid;
+	iref[icur].cPublicRefs = cif->refs;
+	iref[icur].cPrivateRefs = 0;
+
+	pif = cif;
+	cif = cif->next;
+	icur++;
+
+	if (pif->proxy) IRpcProxyBuffer_Release(pif->proxy);
+	HeapFree(GetProcessHeap(), 0, pif);
+      }
+
+      if (icur != icnt) {
+	ERR("icur != icnt, bad stuff\n");
+      }
+
+      IRemUnknown_RemRelease(iface, icur, iref);
+      HeapFree(GetProcessHeap(), 0, iref);
+    }
+    HeapFree(GetProcessHeap(), 0, This);
+    return 0;
+  }
+  LeaveCriticalSection(&This->parent->cs);
+  return refs;
+}
+
+static HRESULT WINAPI ProxyMan_RemQueryInterface(LPREMUNKNOWN iface,
+						 REFIPID ripid,
+						 ULONG cRefs,
+						 USHORT cIids,
+						 IID* iids,
+						 REMQIRESULT** ppQIResults)
+{
+  ICOM_THIS(IOBJECT,iface);
+  RPCOLEMESSAGE msg;
+  HRESULT hr = S_OK;
+  ULONG status;
+
+  TRACE("(%p)->(%s,%ld,%d,%p,%p)\n",This,
+	debugstr_guid(ripid),cRefs,cIids,iids,ppQIResults);
+
+  *ppQIResults = NULL;
+  memset(&msg, 0, sizeof(msg));
+  msg.iMethod = 3;
+  msg.cbBuffer = sizeof(IPID) + sizeof(ULONG) +
+    sizeof(USHORT) + cIids*sizeof(IID);
+  hr = IRpcChannelBuffer_GetBuffer(This->chan, &msg, &IID_IRemUnknown);
+  if (SUCCEEDED(hr)) {
+    LPBYTE buf = msg.Buffer;
+    /* FIXME: use rpcrt4's NDR marshaller library
+     * (NdrSimpleTypeMarshall etc) */
+    memcpy(buf, ripid, sizeof(IPID));
+    buf += sizeof(IPID);
+    memcpy(buf, &cRefs, sizeof(ULONG));
+    buf += sizeof(ULONG);
+    memcpy(buf, &cIids, sizeof(USHORT));
+    buf += sizeof(USHORT);
+    memcpy(buf, iids, cIids*sizeof(IID));
+
+    hr = IRpcChannelBuffer_SendReceive(This->chan, &msg, &status);
+
+    if (SUCCEEDED(hr)) {
+      buf = msg.Buffer;
+      *ppQIResults = CoTaskMemAlloc(cIids*sizeof(REMQIRESULT));
+      memcpy(*ppQIResults, buf, cIids*sizeof(REMQIRESULT));
+    }
+
+    IRpcChannelBuffer_FreeBuffer(This->chan, &msg);
+  }
+
+  return hr;
+}
+
+static HRESULT WINAPI ProxyMan_RemAddRef(LPREMUNKNOWN iface,
+					 USHORT cInterfaceRefs,
+					 REMINTERFACEREF* InterfaceRefs,
+					 HRESULT* pResults)
+{
+  ICOM_THIS(IOBJECT,iface);
+  RPCOLEMESSAGE msg;
+  HRESULT hr = S_OK;
+  ULONG status;
+
+  TRACE("(%p)->(%d,%p,%p)\n",This,
+	cInterfaceRefs,InterfaceRefs,pResults);
+
+  memset(&msg, 0, sizeof(msg));
+  msg.iMethod = 4;
+  msg.cbBuffer = sizeof(USHORT) + cInterfaceRefs*sizeof(REMINTERFACEREF);
+  hr = IRpcChannelBuffer_GetBuffer(This->chan, &msg, &IID_IRemUnknown);
+  if (SUCCEEDED(hr)) {
+    LPBYTE buf = msg.Buffer;
+    /* FIXME: use rpcrt4's NDR marshaller library
+     * (NdrSimpleTypeMarshall etc) */
+    memcpy(buf, &cInterfaceRefs, sizeof(USHORT));
+    buf += sizeof(USHORT);
+    memcpy(buf, InterfaceRefs, cInterfaceRefs*sizeof(REMINTERFACEREF));
+
+    hr = IRpcChannelBuffer_SendReceive(This->chan, &msg, &status);
+
+    if (SUCCEEDED(hr)) {
+      buf = msg.Buffer;
+      memcpy(pResults, buf, cInterfaceRefs*sizeof(HRESULT));
+    }
+
+    IRpcChannelBuffer_FreeBuffer(This->chan, &msg);
+  }
+
+  return hr;
+}
+
+static HRESULT WINAPI ProxyMan_RemRelease(LPREMUNKNOWN iface,
+					  USHORT cInterfaceRefs,
+					  REMINTERFACEREF* InterfaceRefs)
+{
+  ICOM_THIS(IOBJECT,iface);
+  RPCOLEMESSAGE msg;
+  HRESULT hr = S_OK;
+  ULONG status;
+
+  TRACE("(%p)->(%d,%p)\n",This,
+	cInterfaceRefs,InterfaceRefs);
+
+  memset(&msg, 0, sizeof(msg));
+  msg.iMethod = 5;
+  msg.cbBuffer = sizeof(USHORT) + cInterfaceRefs*sizeof(REMINTERFACEREF);
+  hr = IRpcChannelBuffer_GetBuffer(This->chan, &msg, &IID_IRemUnknown);
+  if (SUCCEEDED(hr)) {
+    LPBYTE buf = msg.Buffer;
+    /* FIXME: use rpcrt4's NDR marshaller library
+     * (NdrSimpleTypeMarshall etc) */
+    memcpy(buf, &cInterfaceRefs, sizeof(USHORT));
+    buf += sizeof(USHORT);
+    memcpy(buf, InterfaceRefs, cInterfaceRefs*sizeof(REMINTERFACEREF));
+
+    hr = IRpcChannelBuffer_SendReceive(This->chan, &msg, &status);
+
+    IRpcChannelBuffer_FreeBuffer(This->chan, &msg);
+  }
+
+  return hr;
+}
+
+static ICOM_VTABLE(IRemUnknown) ProxyMan_VTable =
+{
+  ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+  ProxyMan_QueryInterface,
+  ProxyMan_AddRef,
+  ProxyMan_Release,
+  ProxyMan_RemQueryInterface,
+  ProxyMan_RemAddRef,
+  ProxyMan_RemRelease
+};
+
+void COM_FindIObj(APARTMENT *apt, OXID oxid, OID oid, IPID ipid, IOBJECT **iobj, IIF **iif)
+{
+  IOBJECT *obj;
+  IIF *iface;
+  EnterCriticalSection(&apt->cs);
+  for (obj = apt->proxies; obj && (obj->oxid != oxid || obj->oid != oid); obj = obj->next);
+  if (iobj) *iobj = obj;
+  if (obj) {
+    if (iif) {
+      for (iface = obj->ifaces; iface && !IsEqualGUID(&iface->ipid, &ipid); iface = iface->next);
+      *iif = iface;
+    }
+  }
+  else if (iif) *iif = NULL;
+  LeaveCriticalSection(&apt->cs);
+}
+
+void COM_CreateIObj(APARTMENT *apt, OXID oxid, OID oid, IPID ipid, IOBJECT **iobj, RPC_BINDING_HANDLE bind)
+{
+  IOBJECT *obj;
+  RpcBindingSetObject(bind, &ipid);
+  EnterCriticalSection(&apt->cs);
+  for (obj = apt->proxies; obj && (obj->oxid != oxid || obj->oid != oid); obj = obj->next);
+  if (!obj) {
+    obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IOBJECT));
+    obj->lpVtbl = &ProxyMan_VTable;
+    obj->parent = apt;
+    obj->oxid = oxid;
+    obj->oid = oid;
+    obj->ipid = ipid;
+    if (bind)
+      if ((obj->chan = RpcChannel_Create(bind, apt->model, apt->tid)) != NULL) bind = 0;
+    obj->refs = 1;
+    obj->next = apt->proxies;
+    apt->proxies = obj;
+  }
+  if (iobj) *iobj = obj;
+  LeaveCriticalSection(&apt->cs);
+  if (bind) RpcBindingFree(&bind);
+}
+
+/******************** STANDARD MARSHALER ********************/
+
+typedef struct StdMarshalImpl {
+  ICOM_VTABLE(IMarshal) *lpVtbl;
+  DWORD ref;
+} StdMarshalImpl;
+
+static HRESULT WINAPI StdMarshal_QueryInterface(LPMARSHAL iface,
+						REFIID riid,
+						LPVOID *obj)
+{
+  ICOM_THIS(StdMarshalImpl,iface);
+  TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(riid),obj);
+  if (IsEqualGUID(&IID_IUnknown,riid) ||
+      IsEqualGUID(&IID_IMarshal,riid)) {
+    *obj = This;
+    This->ref++;
+    return S_OK;
+  }
+  return E_NOINTERFACE;
+}
+
+static ULONG WINAPI StdMarshal_AddRef(LPMARSHAL iface)
+{
+  ICOM_THIS(StdMarshalImpl,iface);
+  TRACE("(%p)->AddRef()\n",This);
+  return ++(This->ref);
+}
+
+static ULONG WINAPI StdMarshal_Release(LPMARSHAL iface)
+{
+  ICOM_THIS(StdMarshalImpl,iface);
+  TRACE("(%p)->Release()\n",This);
+  if (!--(This->ref)) {
+    HeapFree(GetProcessHeap(),0,This);
+    return 0;
+  }
+  return This->ref;
+}
+
+static DWORD GetDualStringArray(LPWSTR *binds, DWORD *sec_ofs)
+{
+  RPC_BINDING_VECTOR *bind = NULL;
+  DWORD count, len = 0;
+  STRINGBINDING **sbind = NULL;
+  unsigned u;
+
+  if (binds) *binds = NULL;
+  if (sec_ofs) *sec_ofs = 0;
+  RpcServerInqBindings(&bind);
+  count = bind->Count;
+  if (binds) sbind = HeapAlloc(GetProcessHeap(), 0, count*sizeof(STRINGBINDING*));
+  for (u=0; u<count; u++) {
+    LPWSTR sb, protseq, nsb;
+    RPC_BINDING_HANDLE bindh = bind->BindingH[u];
+    DWORD clen;
+
+    /* get string binding */
+    RpcBindingToStringBindingW(bindh, &sb);
+    /* skip the object, if any */
+    protseq = strchrW(sb, '@');
+    if (protseq) protseq++; else protseq = sb;
+    /* grab the protseq */
+    nsb = strchrW(protseq, ':');
+    if (nsb) { *nsb++ = 0; }
+    TRACE("protseq: %s\n", debugstr_w(protseq));
+    TRACE("net-addr: %s\n", debugstr_w(nsb));
+    /* the rest becomes the marshaled string binding */
+    /* (the null terminator is included in sizeof(STRINGBINDING)) */
+    clen = sizeof(STRINGBINDING) + strlenW(nsb)*sizeof(WCHAR);
+    len += clen;
+    if (sbind) {
+      STRINGBINDING *cbind = HeapAlloc(GetProcessHeap(), 0, clen);
+      sbind[u] = cbind;
+      /* FIXME: lookup the protseq tower id... */
+      cbind->wTowerId = 0;
+      strcpyW(cbind->aNetworkAddr, nsb);
+      RpcStringFreeW(&sb);
+    }
+  }
+  len += sizeof(WCHAR);
+  if (sec_ofs) *sec_ofs = len;
+  /* FIXME: security bindings */
+  RpcBindingVectorFree(&bind);
+  if (sbind) {
+    LPBYTE ptr;
+    *binds = HeapAlloc(GetProcessHeap(), 0, len);
+    ptr = (LPBYTE)*binds;
+    for (u=0; u<count; u++) {
+      STRINGBINDING *cbind = sbind[u];
+      DWORD clen = sizeof(STRINGBINDING) + strlenW(cbind->aNetworkAddr)*sizeof(WCHAR);
+      memcpy(ptr, cbind, clen);
+      ptr += clen;
+      HeapFree(GetProcessHeap(), 0, cbind);
+    }
+    *(WCHAR*)ptr = 0;
+    ptr += sizeof(WCHAR);
+    TRACE("len=%ld (%d)\n", len, ptr-(LPBYTE)*binds);
+    HeapFree(GetProcessHeap(), 0, sbind);
+  }
+  else {
+    TRACE("len=%ld\n", len);
+  }
+  return len;
+}
+
+static RPC_BINDING_HANDLE ParseDualStringArray(LPWSTR binds, DWORD len, DWORD sec_ofs)
+{
+  RPC_BINDING_HANDLE bind = 0;
+  RPC_STATUS status;
+  LPBYTE ptr;
+  LPWSTR sb;
+  STRINGBINDING *cbind;
+  DWORD pos, lim, clen, plen, slen;
+  static const WCHAR def_protseq[] = {'n','c','a','l','r','p','c',0};
+
+  TRACE("(%p,%ld,%ld)\n", binds, len, sec_ofs);
+
+  if (!len) return 0;
+  if (sec_ofs >= len) sec_ofs = 0;
+
+  ptr = (LPBYTE)binds;
+  pos = 0;
+  lim = (sec_ofs ? sec_ofs : len) - 1;
+  while ((!bind) && (pos < lim)) {
+    cbind = (STRINGBINDING *)(ptr+pos);
+
+    pos += sizeof(STRINGBINDING) + strlenW(cbind->aNetworkAddr)*sizeof(WCHAR);
+    if (pos > lim) {
+      ERR("malformed dual string array (%ld > %ld)\n", pos, lim);
+      return 0;
+    }
+    TRACE("protseq: %s\n", debugstr_w(def_protseq));
+    TRACE("net-addr: %s\n", debugstr_w(cbind->aNetworkAddr));
+
+    /* FIXME: lookup the protseq tower id... */
+    plen = strlenW(def_protseq);
+    clen = strlenW(cbind->aNetworkAddr) + 1;
+    slen = plen + 1 + clen;
+    sb = HeapAlloc(GetProcessHeap(), 0, slen*sizeof(WCHAR));
+    strcpyW(sb, def_protseq);
+    sb[plen] = ':';
+    strcpyW(sb + plen + 1, cbind->aNetworkAddr);
+
+    /* try to get a RPC binding */
+    status = RpcBindingFromStringBindingW(sb, &bind);
+
+    HeapFree(GetProcessHeap(), 0, sb);
+  }
+
+  if (!bind) return 0;
+
+  /* make sure string binding array is null-terminated */
+  if (*(WCHAR*)(ptr + pos)) {
+    ERR("malformed dual string array (not terminated)\n");
+    RpcBindingFree(&bind);
+    return 0;
+  }
+  ptr += sizeof(WCHAR);
+
+  /* FIXME: security bindings */
+
+  return bind;
+}
+
+static HRESULT WINAPI StdMarshal_GetUnmarshalClass(LPMARSHAL iface,
+						   REFIID riid,
+						   LPVOID pv,
+						   DWORD dwDestContext,
+						   LPVOID pvDestContext,
+						   DWORD mshlFlags,
+						   CLSID *pCid)
+{
+  ICOM_THIS(StdMarshalImpl,iface);
+  TRACE("(%p)->GetUnmarshalClass(%s,%p,%lx,%p,%lx,%p)\n",This,
+	debugstr_guid(riid),pv,dwDestContext,pvDestContext,mshlFlags,pCid);
+  /* return CLSID of the standard marshaller */
+  memcpy(pCid, &CLSID_StdMarshal,sizeof(*pCid));
+  return S_OK;
+}
+
+static HRESULT WINAPI StdMarshal_GetMarshalSizeMax(LPMARSHAL iface,
+						   REFIID riid,
+						   LPVOID pv,
+						   DWORD dwDestContext,
+						   LPVOID pvDestContext,
+						   DWORD mshlFlags,
+						   DWORD *pSize)
+{
+  ICOM_THIS(StdMarshalImpl,iface);
+  APARTMENT *apt = COM_CurrentApt();
+  DWORD size;
+
+  TRACE("(%p)->GetMarshalSizeMax(%s,%p,%lx,%p,%lx,%p)\n",This,
+	debugstr_guid(riid),pv,dwDestContext,pvDestContext,mshlFlags,pSize);
+  if (!apt) return CO_E_NOTINITIALIZED;
+
+  COM_RpcInit();
+
+  size = sizeof(struct OR_STANDARD);
+  size += GetDualStringArray(NULL, NULL);
+  *pSize = size;
+  return S_OK;
+}
+
+static HRESULT WINAPI StdMarshal_MarshalInterface(LPMARSHAL iface,
+						  LPSTREAM pStm,
+						  REFIID riid,
+						  LPVOID pv,
+						  DWORD dwDestContext,
+						  LPVOID pvDestContext,
+						  DWORD mshlFlags)
+{
+  ICOM_THIS(StdMarshalImpl,iface);
+  APARTMENT *apt = COM_CurrentApt();
+  struct OR_STANDARD obj;
+  LPWSTR dsastr;
+  DWORD dsalen, secofs;
+  HRESULT hr;
+  XOBJECT *xobj;
+  XIF *xif;
+
+  TRACE("(%p)->MarshalInterface(%p,%s,%p,%lx,%p,%lx)\n",This,pStm,
+	debugstr_guid(riid),pv,dwDestContext,pvDestContext,mshlFlags);
+  if (!apt) return CO_E_NOTINITIALIZED;
+
+  COM_RpcInit();
+
+  memset(&obj, 0, sizeof(obj));
+  if (mshlFlags & MSHLFLAGS_TABLEWEAK) {
+    /* marshaled data is 0 external refs */
+    obj.std.cPublicRefs = 0;
+    FIXME("table-weak marshal\n");
+  }
+  else if (mshlFlags & MSHLFLAGS_TABLESTRONG) {
+    /* marshaled data is 1 external ref */
+    obj.std.cPublicRefs = 0;
+    FIXME("table-strong marshal\n");
+  }
+  else {
+    /* 5 external refs transferred in marshaled data */
+    obj.std.cPublicRefs = 5;
+  }
+  if (mshlFlags & MSHLFLAGS_NOPING)
+    obj.std.flags |= SORF_NOPING;
+
+  EnterCriticalSection(&apt->cs);
+  COM_CreateXObj(apt, &xobj, &xif, riid, pv);
+  if (xif) {
+    obj.std.oxid = apt->oxid;
+    obj.std.oid  = xobj->oid;
+    obj.std.ipid = xif->ipid;
+    COM_ExtAddRef(apt, xobj, xif, obj.std.cPublicRefs);
+    hr = xif->hres;
+    if (FAILED(hr))
+      COM_ExtRelease(apt, xobj, xif, obj.std.cPublicRefs);
+  }
+  else hr = E_OUTOFMEMORY;
+  LeaveCriticalSection(&apt->cs);
+
+  if (FAILED(hr)) return hr;
+
+  dsalen = GetDualStringArray(&dsastr, &secofs);
+  obj.saResAddr.wNumEntries = dsalen / sizeof(WCHAR);
+  obj.saResAddr.wSecurityOffset = secofs / sizeof(WCHAR);
+
+  hr = IStream_Write(pStm, &obj, sizeof(obj), NULL);
+  if (SUCCEEDED(hr)) {
+    hr = IStream_Write(pStm, dsastr, dsalen, NULL);
+  }
+
+  HeapFree(GetProcessHeap(), 0, dsastr);
+
+  return hr;
+}
+
+static HRESULT WINAPI StdMarshal_UnmarshalInterface(LPMARSHAL iface,
+						    LPSTREAM pStm,
+						    REFIID riid,
+						    LPVOID *ppv)
+{
+  ICOM_THIS(StdMarshalImpl,iface);
+  APARTMENT *apt = COM_CurrentApt();
+  struct OR_STANDARD obj;
+  LPWSTR dsastr = NULL;
+  DWORD dsalen = 0, secofs = 0;
+  HRESULT hr;
+  IOBJECT *iobj;
+  IIF *iif;
+
+  TRACE("(%p)->UnmarshalInterface(%p,%s,%p)\n",This,pStm,
+	debugstr_guid(riid),ppv);
+  *ppv = NULL;
+  if (!apt) return CO_E_NOTINITIALIZED;
+
+  hr = IStream_Read(pStm, &obj, sizeof(obj), NULL);
+  if (FAILED(hr)) return hr;
+  if (obj.saResAddr.wNumEntries) {
+    dsalen = obj.saResAddr.wNumEntries*sizeof(WCHAR);
+    secofs = obj.saResAddr.wSecurityOffset*sizeof(WCHAR);
+    dsastr = HeapAlloc(GetProcessHeap(), 0, dsalen);
+    hr = IStream_Read(pStm, dsastr, dsalen, NULL);
+    if (FAILED(hr)) goto finito;
+  }
+
+  if (obj.std.oxid == apt->oxid) {
+    XOBJECT *xobj;
+    XIF *xif;
+    /* dude, we're still in the same apartment...
+     * we don't need no stinkin' proxy */
+    EnterCriticalSection(&apt->cs);
+    COM_FindXObj(apt, obj.std.oid, obj.std.ipid, &xobj, &xif);
+    if (xif) {
+      IUnknown_AddRef((LPUNKNOWN)xif->iface);
+      *ppv = xif->iface;
+      COM_ExtRelease(apt, xobj, xif, obj.std.cPublicRefs);
+      hr = S_OK;
+    }
+    else hr = CO_E_OBJNOTCONNECTED;
+    LeaveCriticalSection(&apt->cs);
+    goto finito;
+  }
+
+  hr = E_FAIL;
+
+  /* see if object has already been imported */
+  EnterCriticalSection(&apt->cs);
+  COM_FindIObj(apt, obj.std.oxid, obj.std.oid, obj.std.ipid, &iobj, &iif);
+
+  if (!iobj) {
+    /* object not already imported, connect to it */
+    RPC_BINDING_HANDLE bind = ParseDualStringArray(dsastr, dsalen, secofs);
+    if (bind) /* register new connection */
+      COM_CreateIObj(apt, obj.std.oxid, obj.std.oid, obj.std.ipid, &iobj, bind);
+    else
+      hr = CO_E_OBJNOTCONNECTED;
+  }
+  else iobj->refs++;
+  if (iobj && !iif) {
+    /* object imported, register new interface */
+    COM_CreateIIf(apt, obj.std.ipid, iobj, &iif, riid);
+  }
+
+  if (iif) {
+    iif->refs += obj.std.cPublicRefs;
+    hr = iif->hres;
+
+    /* unmarshal complete */
+    *ppv = iif->iface;
+  }
+
+  LeaveCriticalSection(&apt->cs);
+
+finito:
+  if (dsastr) HeapFree(GetProcessHeap(), 0, dsastr);
+  return hr;
+}
+
+static HRESULT WINAPI StdMarshal_ReleaseMarshalData(LPMARSHAL iface,
+						    LPSTREAM pStm)
+{
+  ICOM_THIS(StdMarshalImpl,iface);
+  APARTMENT *apt = COM_CurrentApt();
+  struct OR_STANDARD obj;
+  HRESULT hr;
+
+  TRACE("(%p)->ReleaseMarshalData(%p)\n",This,pStm);
+  if (!apt) return CO_E_NOTINITIALIZED;
+
+  hr = IStream_Read(pStm, &obj, sizeof(obj), NULL);
+  if (FAILED(hr)) return hr;
+  /* FIXME: read string bindings */
+  /* FIXME: read security bindings */
+
+  if (obj.std.oxid == apt->oxid) {
+    XOBJECT *xobj;
+    XIF *xif;
+    EnterCriticalSection(&apt->cs);
+    COM_FindXObj(apt, obj.std.oid, obj.std.ipid, &xobj, &xif);
+    if (xif) {
+      COM_ExtRelease(apt, xobj, xif, obj.std.cPublicRefs);
+      hr = S_OK;
+    }
+    else hr = CO_E_OBJNOTCONNECTED;
+    LeaveCriticalSection(&apt->cs);
+    return hr;
+  }
+
+  FIXME("interapartment marshal release\n");
+  return RPC_E_WRONG_THREAD;
+}
+
+static HRESULT WINAPI StdMarshal_DisconnectObject(LPMARSHAL iface,
+						  DWORD dwReserved)
+{
+  ICOM_THIS(StdMarshalImpl,iface);
+  TRACE("(%p)->DisconnectObject(%ld)\n",This,dwReserved);
+  /* FIXME */
+  return S_OK;
+}
+
+static ICOM_VTABLE(IMarshal) StdMarshalImpl_VTable =
+{
+  ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+  StdMarshal_QueryInterface,
+  StdMarshal_AddRef,
+  StdMarshal_Release,
+  StdMarshal_GetUnmarshalClass,
+  StdMarshal_GetMarshalSizeMax,
+  StdMarshal_MarshalInterface,
+  StdMarshal_UnmarshalInterface,
+  StdMarshal_ReleaseMarshalData,
+  StdMarshal_DisconnectObject
+};
+
+static HRESULT COM_GetMarshal(REFIID riid,
+			      IUnknown *pUnk,
+			      DWORD dwDestContext,
+			      void *pvDestContext,
+			      DWORD mshlFlags,
+			      LPMARSHAL *pMarshal)
+{
+  HRESULT hr;
+  hr = IUnknown_QueryInterface(pUnk, &IID_IMarshal, (LPVOID*)pMarshal);
+  if (hr == E_NOINTERFACE) {
+    TRACE("no custom marshaler found, using standard marshaler\n");
+    hr = CoGetStandardMarshal(riid, pUnk, dwDestContext, pvDestContext,
+			      mshlFlags, pMarshal);
+  }
+  return hr;
+}
+
+static HRESULT COM_GetUnmarshal(IStream *pStm,
+				LPMARSHAL *pMarshal,
+				LPIID piid)
+{
+  HRESULT hr;
+  OBJREF obj;
+  struct OR_CUSTOM cobj;
+  ULONG count;
+
+  /* get administrative data */
+  hr = IStream_Read(pStm, &obj, sizeof(obj), &count);
+  if (FAILED(hr)) return hr;
+  if (count != sizeof(obj)) return E_FAIL;
+
+  if (piid) memcpy(piid, &obj.iid, sizeof(obj.iid));
+
+  /* get unmarshal class instance */
+  if (obj.flags & OBJREF_CUSTOM) {
+    hr = IStream_Read(pStm, &cobj, sizeof(cobj), &count);
+    if (FAILED(hr)) return hr;
+    if (count != sizeof(cobj)) return E_FAIL;
+
+    hr = CoCreateInstance(&cobj.clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMarshal, (LPVOID*)pMarshal);
+  }
+  else {
+    hr = CoGetStandardMarshal(NULL, NULL, 0, NULL, 0, pMarshal);
+  }
+  return hr;
+}
+
+HRESULT COM_GetStdObjRef(IStream *pStm,
+			 STDOBJREF *pObjRef,
+			 LPIID piid)
+{
+  HRESULT hr;
+  OBJREF obj;
+  LARGE_INTEGER move, opos;
+  ULONG count;
+
+  /* save initial position */
+  move.s.LowPart = 0;
+  move.s.HighPart = 0;
+  hr = IStream_Seek(pStm, move, STREAM_SEEK_CUR, (ULARGE_INTEGER*)&opos);
+  if (FAILED(hr)) return hr;
+
+  /* get administrative data */
+  hr = IStream_Read(pStm, &obj, sizeof(obj), &count);
+  if (FAILED(hr)) return hr;
+  if (count != sizeof(obj)) return E_FAIL;
+
+  if (piid) memcpy(piid, &obj.iid, sizeof(obj.iid));
+
+  /* read objref */
+  if (obj.flags & OBJREF_CUSTOM) {
+    hr = E_INVALIDARG;
+  }
+  else {
+    hr = IStream_Read(pStm, pObjRef, sizeof(STDOBJREF), &count);
+  }
+
+  /* return to initial position */
+  IStream_Seek(pStm, opos, STREAM_SEEK_SET, NULL);
+
+  return hr;
+}
+
+/******************** API FUNCTIONS ********************/
+
+HRESULT WINAPI CoGetStandardMarshal(REFIID riid,
+				    IUnknown *pUnk,
+				    DWORD dwDestContext,
+				    LPVOID pvDestContext,
+				    DWORD mshlFlags,
+				    LPMARSHAL *ppMarshal)
+{
+  StdMarshalImpl *pMarshal;
+  pMarshal = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(StdMarshalImpl));
+  if (!pMarshal) return E_OUTOFMEMORY;
+  pMarshal->lpVtbl = &StdMarshalImpl_VTable;
+  pMarshal->ref = 1;
+  *ppMarshal = (LPMARSHAL)pMarshal;
+  return S_OK;
+}
+
+HRESULT WINAPI CoGetMarshalSizeMax(ULONG *pulSize,
+				   REFIID riid,
+				   IUnknown *pUnk,
+				   DWORD dwDestContext,
+				   void *pvDestContext,
+				   DWORD mshlFlags)
+{
+  HRESULT hr = S_OK;
+  CLSID clsid;
+  ULONG size = 0;
+  LPMARSHAL pMarshal;
+
+  *pulSize = 0;
+
+  /* get an IMarshal interface */
+  hr = COM_GetMarshal(riid, pUnk, dwDestContext, pvDestContext, mshlFlags, &pMarshal);
+  if (FAILED(hr)) return hr;
+
+  /* get unmarshal class */
+  hr = IMarshal_GetUnmarshalClass(pMarshal, riid, pUnk, dwDestContext, pvDestContext,
+				  mshlFlags, &clsid);
+  if (FAILED(hr)) goto fail;
+
+  /* get marshal size */
+  hr = IMarshal_GetMarshalSizeMax(pMarshal, riid, pUnk, dwDestContext, pvDestContext,
+				  mshlFlags, &size);
+  if (FAILED(hr)) goto fail;
+
+  if (!IsEqualGUID(&clsid, &CLSID_StdMarshal)) size += sizeof(struct OR_CUSTOM);
+  *pulSize = sizeof(OBJREF) + size;
+
+fail:
+  IMarshal_Release(pMarshal);
+
+  return hr;
+}
+
+HRESULT WINAPI CoMarshalInterface(IStream *pStm,
+				  REFIID riid,
+				  IUnknown *pUnk,
+				  DWORD dwDestContext,
+				  void *pvDestContext,
+				  DWORD mshlFlags)
+{
+  HRESULT hr;
+  CLSID clsid;
+  LPMARSHAL pMarshal;
+  OBJREF obj;
+  struct OR_CUSTOM cobj;
+  ULONG count;
+
+  /* get an IMarshal interface */
+  hr = COM_GetMarshal(riid, pUnk, dwDestContext, pvDestContext, mshlFlags, &pMarshal);
+  if (FAILED(hr)) return hr;
+
+  /* get unmarshal class */
+  hr = IMarshal_GetUnmarshalClass(pMarshal, riid, pUnk, dwDestContext, pvDestContext,
+				  mshlFlags, &clsid);
+  if (FAILED(hr)) goto fail;
+
+  /* write marshal header */
+  obj.signature = OBJREF_SIGNATURE;
+  if (!IsEqualGUID(&clsid, &CLSID_StdMarshal))
+    obj.flags = OBJREF_CUSTOM;
+  else
+    obj.flags = OBJREF_STANDARD;
+  memcpy(&obj.iid, riid, sizeof(obj.iid));
+
+  hr = IStream_Write(pStm, &obj, sizeof(obj), &count);
+  if (FAILED(hr)) goto fail;
+  if (count != sizeof(obj)) {
+    hr = E_FAIL;
+    goto fail;
+  }
+
+  if (obj.flags == OBJREF_CUSTOM) {
+    memcpy(&cobj.clsid, &clsid, sizeof(cobj.clsid));
+    cobj.cbExtension = 0;
+    cobj.size = 0;
+
+    hr = IStream_Write(pStm, &cobj, sizeof(cobj), &count);
+    if (FAILED(hr)) goto fail;
+    if (count != sizeof(cobj)) {
+      hr = E_FAIL;
+      goto fail;
+    }
+  }
+
+  /* perform the marshaling */
+  hr = IMarshal_MarshalInterface(pMarshal, pStm, riid, pUnk, dwDestContext, pvDestContext,
+				 mshlFlags);
+
+
+  if (obj.flags == OBJREF_CUSTOM) {
+    FIXME("update custom-marshal size\n");
+  }
+
+fail:
+  IMarshal_Release(pMarshal);
+
+  return hr;
+}
+
+HRESULT WINAPI CoUnmarshalInterface(IStream *pStm,
+				    REFIID riid,
+				    void **ppv)
+{
+  HRESULT hr;
+  LPMARSHAL pMarshal;
+  IID iid;
+  void *pv;
+
+  hr = COM_GetUnmarshal(pStm, &pMarshal, &iid);
+  if (FAILED(hr)) return hr;
+
+  hr = IMarshal_UnmarshalInterface(pMarshal, pStm, &iid, &pv);
+  IMarshal_Release(pMarshal);
+  if (FAILED(hr)) return hr;
+
+  if (IsEqualGUID(riid, &IID_NULL) ||
+      IsEqualGUID(riid, &iid)) {
+    *ppv = pv;
+  } else {
+    hr = IUnknown_QueryInterface((LPUNKNOWN)pv, riid, ppv);
+    IUnknown_Release((LPUNKNOWN)pv);
+  }
+  return hr;
+}
+
+HRESULT WINAPI CoReleaseMarshalData(IStream *pStm)
+{
+  HRESULT hr;
+  LPMARSHAL pMarshal;
+
+  hr = COM_GetUnmarshal(pStm, &pMarshal, NULL);
+  if (FAILED(hr)) return hr;
+
+  hr = IMarshal_ReleaseMarshalData(pMarshal, pStm);
+
+  IMarshal_Release(pMarshal);
+
+  return hr;
+}
+
+/* #define FAKE_INTERTHREAD */
+
+HRESULT WINAPI CoMarshalInterThreadInterfaceInStream(REFIID riid,
+						     LPUNKNOWN pUnk,
+						     LPSTREAM *ppStm)
+{
+  HRESULT hr = CreateStreamOnHGlobal(0, TRUE, ppStm);
+  if (SUCCEEDED(hr)) {
+    LARGE_INTEGER pos;
+#ifdef FAKE_INTERTHREAD
+    hr = IStream_Write(*ppStm, &pUnk, sizeof(pUnk), NULL);
+    if (SUCCEEDED(hr)) IUnknown_AddRef(pUnk);
+    TRACE("<= %p\n", pUnk);
+#else
+    hr = CoMarshalInterface(*ppStm, riid, pUnk, MSHCTX_INPROC, 0, MSHLFLAGS_NORMAL);
+#endif
+    pos.s.LowPart = 0;
+    pos.s.HighPart = 0;
+    IStream_Seek(*ppStm, pos, 0, NULL);
+  }
+  return hr;
+}
+
+HRESULT WINAPI CoGetInterfaceAndReleaseStream(LPSTREAM pStm,
+					      REFIID riid,
+					      LPVOID *ppv)
+{
+#ifdef FAKE_INTERTHREAD
+  LPUNKNOWN pUnk;
+  HRESULT hr = IStream_Read(pStm, &pUnk, sizeof(pUnk), NULL);
+  if (SUCCEEDED(hr)) {
+    hr = IUnknown_QueryInterface(pUnk, riid, ppv);
+    TRACE("=> %p\n", *ppv);
+    IUnknown_Release(pUnk);
+  }
+#else
+  HRESULT hr = CoUnmarshalInterface(pStm, riid, ppv);
+#endif
+  IStream_Release(pStm);
+  return hr;
+}
+
+/******************** BUILT-IN P/S MARSHALERS ********************/
+
+HRESULT CALLBACK IClassFactory_CreateInstance_Proxy(
+    IClassFactory* This,
+    IUnknown* pUnkOuter,
+    REFIID riid,
+    void** ppvObject)
+{
+  HRESULT hr;
+  IUnknown* proxy = NULL;
+  TRACE("(%p,%p,%s,%p)\n", This, pUnkOuter, debugstr_guid(riid), ppvObject);
+  hr = IClassFactory_RemoteCreateInstance_Proxy(This, riid, &proxy);
+  *ppvObject = proxy;
+  if (pUnkOuter) {
+    /* I'm not sure yet how to handle this, I think we're supposed
+     * to let the proxy manager aggregate into pUnkOuter */
+    FIXME("remote aggregation not supported yet\n");
+  }
+  return hr;
+}
+
+HRESULT __RPC_STUB IClassFactory_CreateInstance_Stub(
+    IClassFactory* This,
+    REFIID riid,
+    IUnknown** ppvObject)
+{
+  HRESULT hr;
+  TRACE("(%p,%s,%p)\n", This, debugstr_guid(riid), ppvObject);
+  *ppvObject = NULL;
+  hr = IClassFactory_CreateInstance(This, NULL, riid, ppvObject);
+  return hr;
+}
+
+HRESULT CALLBACK IClassFactory_LockServer_Proxy(
+    IClassFactory* This,
+    BOOL fLock)
+{
+  TRACE("(%p,%d)\n", This, fLock);
+  return IClassFactory_RemoteLockServer_Proxy(This, fLock);
+}
+
+HRESULT __RPC_STUB IClassFactory_LockServer_Stub(
+    IClassFactory* This,
+    BOOL fLock)
+{
+  TRACE("(%p,%d)\n", This, fLock);
+  return IClassFactory_LockServer(This, fLock);
+}
+
+#if 0
+/* we need to create an IDL compiler for Wine that can generate
+ * most of these automatically */
+
+const MIDL_STUB_DESC Object_StubDesc = {
+  0,
+  NdrOleAllocate,
+  NdrOleFree,
+  {0}, 0, 0, 0, 0,
+  0 /* __MIDL_TypeFormatString.Format */
+};
+
+#define INTERFACES 2
+
+HRESULT WINAPI IClassFactory_CreateInstance_Proxy(LPCLASSFACTORY This,
+						  LPUNKNOWN pUnkOuter,
+						  REFIID riid,
+						  LPVOID *ppv)
+{
+  HRESULT ret = E_FAIL;
+  RPC_MESSAGE Msg;
+  MIDL_STUB_MESSAGE StubMsg;
+  LPUNKNOWN pvObj = NULL;
+  BOOL not_null;
+
+  TRACE("(%p,%p,%s,%p)\n", This, pUnkOuter, debugstr_guid(riid), ppv);
+  *ppv = NULL;
+
+  NdrProxyInitialize(This, &Msg, &StubMsg, &Object_StubDesc, 3);
+
+  StubMsg.BufferLength = sizeof(IID);
+  NdrProxyGetBuffer(This, &StubMsg);
+
+  /* FIXME: use NdrSimpleStructMarshall instead of memcpy */
+  memcpy(StubMsg.Buffer, riid, sizeof(IID));
+  StubMsg.Buffer += sizeof(IID);
+
+  NdrProxySendReceive(This, &StubMsg);
+
+  /* FIXME: NdrPointerUnmarshall */
+  memcpy(&not_null, StubMsg.Buffer, sizeof(BOOL));
+  StubMsg.Buffer += sizeof(BOOL);
+  if (not_null)
+    NdrInterfacePointerUnmarshall(&StubMsg,
+				  (unsigned char**)&pvObj,
+				  NULL,
+				  0);
+  memcpy(&ret, StubMsg.Buffer, sizeof(HRESULT));
+  StubMsg.Buffer += sizeof(HRESULT);
+
+  NdrProxyFreeBuffer(This, &StubMsg);
+
+  if (pvObj)
+    ret = IUnknown_QueryInterface(pvObj, riid, ppv);
+
+  return ret;
+}
+
+HRESULT WINAPI IClassFactory_LockServer_Proxy(LPCLASSFACTORY This,
+					      BOOL fLock)
+{
+  FIXME("(%p,%d):stub\n", This, fLock);
+  return S_OK;
+}
+
+const CINTERFACE_PROXY_VTABLE(5) IClassFactoryProxyVtbl = {
+  {&IID_IClassFactory},
+  {IUnknown_QueryInterface_Proxy,
+   IUnknown_AddRef_Proxy,
+   IUnknown_Release_Proxy,
+   IClassFactory_CreateInstance_Proxy,
+   IClassFactory_LockServer_Proxy}
+};
+
+/* FIXME: this marshalling is not done exactly like MS's,
+ * so it needs to be fixed for real DCOM, but for real DCOM
+ * we should probably implement a real IDL compiler anyway */
+
+void __RPC_STUB IClassFactory_RemoteCreateInstance_Stub(LPRPCSTUBBUFFER This,
+							LPRPCCHANNELBUFFER pChannel,
+							PRPC_MESSAGE pMsg,
+							DWORD *pdwPhase)
+{
+  LPCLASSFACTORY pServer = (LPCLASSFACTORY)((CStdStubBuffer*)This)->pvServerObject;
+  HRESULT ret = E_FAIL;
+  MIDL_STUB_MESSAGE StubMsg;
+  IID iid;
+  LPVOID pvObj = NULL;
+  BOOL not_null;
+
+  TRACE("(%p,%p,%p,%p)\n", This, pChannel, pMsg, pdwPhase);
+
+  NdrStubInitialize(pMsg, &StubMsg, &Object_StubDesc, pChannel);
+  /* FIXME: use NdrSimpleStructUnmarshall instead of memcpy */
+  memcpy(&iid, StubMsg.Buffer, sizeof(IID));
+  StubMsg.Buffer += sizeof(IID);
+
+  *pdwPhase = STUB_CALL_SERVER;
+  TRACE("->(%p,NULL,%s,%p)\n", pServer, debugstr_guid(&iid), &pvObj);
+  TRACE("vtbl=%p\n", pServer->lpVtbl);
+  ret = IClassFactory_CreateInstance(pServer, NULL, &iid, &pvObj);
+  TRACE("<-(%p) %08lx\n", pvObj, ret);
+  not_null = (pvObj != NULL);
+  *pdwPhase = STUB_MARSHAL;
+
+  StubMsg.BufferLength = sizeof(BOOL);
+  if (not_null) {
+    /* seems MaxCount is used to store the riid for interface marshaling */
+    StubMsg.MaxCount = (ULONG_PTR)&iid;
+    NdrInterfacePointerBufferSize(&StubMsg,
+				  (unsigned char*)pvObj,
+				  NULL);
+  }
+  StubMsg.BufferLength += sizeof(HRESULT);
+  NdrStubGetBuffer(This, pChannel, &StubMsg);
+  /* FIXME: NdrPointerMarshall */
+  memcpy(StubMsg.Buffer, &not_null, sizeof(BOOL));
+  StubMsg.Buffer += sizeof(BOOL);
+  if (not_null) {
+    StubMsg.MaxCount = (ULONG_PTR)&iid;
+    NdrInterfacePointerMarshall(&StubMsg,
+				(unsigned char*)pvObj,
+				NULL);
+  }
+  memcpy(StubMsg.Buffer, &ret, sizeof(HRESULT));
+  StubMsg.Buffer += sizeof(HRESULT);
+}
+
+void __RPC_STUB IClassFactory_RemoteLockServer_Stub(LPRPCSTUBBUFFER This,
+						    LPRPCCHANNELBUFFER pChannel,
+						    PRPC_MESSAGE pMsg,
+						    DWORD *pdwPhase)
+{
+  FIXME("(%p,%p,%p,%p):stub\n", This, pChannel, pMsg, pdwPhase);
+}
+
+const PRPC_STUB_FUNCTION IClassFactory_table[] = {
+  IClassFactory_RemoteCreateInstance_Stub,
+  IClassFactory_RemoteLockServer_Stub
+};
+
+const CInterfaceStubVtbl IClassFactoryStubVtbl = {
+  {&IID_IClassFactory,
+   0,
+   5,
+   &IClassFactory_table[-3]},
+  {CStdStubBuffer_METHODS}
+};
+
+const CInterfaceProxyVtbl* _compobj_ProxyVtblList[INTERFACES+1] = {
+  0,
+  (CInterfaceProxyVtbl*)&IClassFactoryProxyVtbl,
+  0
+};
+
+const CInterfaceStubVtbl* _compobj_StubVtblList[INTERFACES+1] = {
+  0,
+  (CInterfaceStubVtbl*)&IClassFactoryStubVtbl,
+  0
+};
+
+const PCInterfaceName _compobj_InterfaceNamesList[INTERFACES+1] = {
+  "IRemUnknown",
+  "IClassFactory",
+  0
+};
+
+int __stdcall _compobj_IID_Lookup(const IID *pIID, int *pIndex)
+{
+  unsigned u;
+  /* the purpose of this routine is probably to "unroll"
+   * this kind of for loop, but without an IDL compiler,
+   * maintainability is more important */
+  for (u=1; u<INTERFACES; u++) {
+    if (!IID_GENERIC_CHECK_IID(_compobj, pIID, u)) {
+      *pIndex = u;
+      return 1;
+    }
+  }
+  return 0;
+}
+
+const ExtendedProxyFileInfo compobj_ProxyFileInfo = {
+  (PCInterfaceProxyVtblList*)&_compobj_ProxyVtblList,
+  (PCInterfaceStubVtblList*)&_compobj_StubVtblList,
+  (const PCInterfaceName*)&_compobj_InterfaceNamesList,
+  0, /* pDelegatedIIDs */
+  &_compobj_IID_Lookup,
+  INTERFACES, /* TableSize */
+  1  /* TableVersion */
+};
+#endif
+
+extern const ExtendedProxyFileInfo dcom_ProxyFileInfo;
+extern const ExtendedProxyFileInfo unknwn_ProxyFileInfo;
+
+const ProxyFileInfo* OLE32_ProxyFileList[] = {
+  &unknwn_ProxyFileInfo,
+  &dcom_ProxyFileInfo,
+  NULL
+};
+
+static CStdPSFactoryBuffer PSFactoryBuffer;
+
+CSTDSTUBBUFFERRELEASE(&PSFactoryBuffer)
+
+static HRESULT COM_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
+{
+  return NdrDllGetClassObject(rclsid, riid, ppv, OLE32_ProxyFileList,
+			      &CLSID_PSFactoryBuffer, &PSFactoryBuffer);
+}
+
+
+/***********************************************************************
+ *           DllGetClassObject [OLE32.63]
+ */
+HRESULT WINAPI OLE32_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
+{
+  if (IsEqualGUID(rclsid, &CLSID_PSFactoryBuffer)) {
+    return COM_DllGetClassObject(rclsid, riid, ppv);
+  }
+  FIXME("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(riid));
+  return CLASS_E_CLASSNOTAVAILABLE;
+}
--- /dev/null	2003-01-10 01:23:22.000000000 +0100
+++ dlls/ole32/unknwn_p.c	2003-05-23 21:30:28.000000000 +0200
@@ -0,0 +1,505 @@
+/* this ALWAYS GENERATED file contains the proxy stub code */
+
+
+/* File created by MIDL compiler version 5.01.0164 */
+/* at Fri May 23 15:29:11 2003
+ */
+/* Compiler settings for unknwn.idl:
+    Os (OptLev=s), W1, Zp8, env=Win32, ms_ext, c_ext
+    error checks: allocation ref bounds_check enum stub_data 
+*/
+//@@MIDL_FILE_HEADING(  )
+
+
+/* verify that the <rpcproxy.h> version is high enough to compile this file*/
+#ifndef __REDQ_RPCPROXY_H_VERSION__
+#define __REQUIRED_RPCPROXY_H_VERSION__ 440
+#endif
+
+
+#undef __WINE__
+#include "rpcproxy.h"
+#ifndef __RPCPROXY_H_VERSION__
+#error this stub requires an updated version of <rpcproxy.h>
+#endif // __RPCPROXY_H_VERSION__
+
+
+#include "unknwn.h"
+
+#define TYPE_FORMAT_STRING_SIZE   35                                
+#define PROC_FORMAT_STRING_SIZE   15                                
+
+typedef struct _MIDL_TYPE_FORMAT_STRING
+    {
+    short          Pad;
+    unsigned char  Format[ TYPE_FORMAT_STRING_SIZE ];
+    } MIDL_TYPE_FORMAT_STRING;
+
+typedef struct _MIDL_PROC_FORMAT_STRING
+    {
+    short          Pad;
+    unsigned char  Format[ PROC_FORMAT_STRING_SIZE ];
+    } MIDL_PROC_FORMAT_STRING;
+
+
+extern const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;
+extern const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;
+
+
+/* Standard interface: __MIDL_itf_unknwn_0000, ver. 0.0,
+   GUID={0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} */
+
+
+/* Object interface: IUnknown, ver. 0.0,
+   GUID={0x00000000,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}} */
+
+
+/* Object interface: IClassFactory, ver. 0.0,
+   GUID={0x00000001,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}} */
+
+
+extern const MIDL_STUB_DESC Object_StubDesc;
+
+
+#pragma code_seg(".orpc")
+
+/* [call_as] */ HRESULT STDMETHODCALLTYPE IClassFactory_RemoteCreateInstance_Proxy( 
+    IClassFactory __RPC_FAR * This,
+    /* [in] */ REFIID riid,
+    /* [iid_is][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppvObject)
+{
+
+    HRESULT _RetVal;
+    
+    RPC_MESSAGE _RpcMessage;
+    
+    MIDL_STUB_MESSAGE _StubMsg;
+    
+    if(ppvObject)
+        {
+        MIDL_memset(
+               ppvObject,
+               0,
+               sizeof( IUnknown __RPC_FAR *__RPC_FAR * ));
+        }
+    RpcTryExcept
+        {
+        NdrProxyInitialize(
+                      ( void __RPC_FAR *  )This,
+                      ( PRPC_MESSAGE  )&_RpcMessage,
+                      ( PMIDL_STUB_MESSAGE  )&_StubMsg,
+                      ( PMIDL_STUB_DESC  )&Object_StubDesc,
+                      3);
+        
+        
+        
+        if(!riid)
+            {
+            RpcRaiseException(RPC_X_NULL_REF_POINTER);
+            }
+        if(!ppvObject)
+            {
+            RpcRaiseException(RPC_X_NULL_REF_POINTER);
+            }
+        RpcTryFinally
+            {
+            
+            _StubMsg.BufferLength = 0U;
+            NdrSimpleStructBufferSize( (PMIDL_STUB_MESSAGE) &_StubMsg,
+                                       (unsigned char __RPC_FAR *)riid,
+                                       (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[12] );
+            
+            NdrProxyGetBuffer(This, &_StubMsg);
+            NdrSimpleStructMarshall( (PMIDL_STUB_MESSAGE)& _StubMsg,
+                                     (unsigned char __RPC_FAR *)riid,
+                                     (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[12] );
+            
+            NdrProxySendReceive(This, &_StubMsg);
+            
+            if ( (_RpcMessage.DataRepresentation & 0X0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION )
+                NdrConvert( (PMIDL_STUB_MESSAGE) &_StubMsg, (PFORMAT_STRING) &__MIDL_ProcFormatString.Format[0] );
+            
+            NdrPointerUnmarshall( (PMIDL_STUB_MESSAGE) &_StubMsg,
+                                  (unsigned char __RPC_FAR * __RPC_FAR *)&ppvObject,
+                                  (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[24],
+                                  (unsigned char)0 );
+            
+            _StubMsg.Buffer = (unsigned char __RPC_FAR *)(((long)_StubMsg.Buffer + 3) & ~ 0x3);
+            _RetVal = *(( HRESULT __RPC_FAR * )_StubMsg.Buffer)++;
+            
+            }
+        RpcFinally
+            {
+            NdrProxyFreeBuffer(This, &_StubMsg);
+            
+            }
+        RpcEndFinally
+        
+        }
+    RpcExcept(_StubMsg.dwStubPhase != PROXY_SENDRECEIVE)
+        {
+        _StubMsg.MaxCount = (unsigned long) ( riid );
+        
+        NdrClearOutParameters(
+                         ( PMIDL_STUB_MESSAGE  )&_StubMsg,
+                         ( PFORMAT_STRING  )&__MIDL_TypeFormatString.Format[24],
+                         ( void __RPC_FAR * )ppvObject);
+        _RetVal = NdrProxyErrorHandler(RpcExceptionCode());
+        }
+    RpcEndExcept
+    return _RetVal;
+}
+
+void __RPC_STUB IClassFactory_RemoteCreateInstance_Stub(
+    IRpcStubBuffer *This,
+    IRpcChannelBuffer *_pRpcChannelBuffer,
+    PRPC_MESSAGE _pRpcMessage,
+    DWORD *_pdwStubPhase)
+{
+    IUnknown __RPC_FAR *__RPC_FAR *_M0;
+    HRESULT _RetVal;
+    MIDL_STUB_MESSAGE _StubMsg;
+    IUnknown __RPC_FAR *__RPC_FAR *ppvObject;
+    REFIID riid;
+    
+NdrStubInitialize(
+                     _pRpcMessage,
+                     &_StubMsg,
+                     &Object_StubDesc,
+                     _pRpcChannelBuffer);
+    ( REFIID  )riid = 0;
+    ( IUnknown __RPC_FAR *__RPC_FAR * )ppvObject = 0;
+    RpcTryFinally
+        {
+        if ( (_pRpcMessage->DataRepresentation & 0X0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION )
+            NdrConvert( (PMIDL_STUB_MESSAGE) &_StubMsg, (PFORMAT_STRING) &__MIDL_ProcFormatString.Format[0] );
+        
+        NdrSimpleStructUnmarshall( (PMIDL_STUB_MESSAGE) &_StubMsg,
+                                   (unsigned char __RPC_FAR * __RPC_FAR *)&riid,
+                                   (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[12],
+                                   (unsigned char)0 );
+        
+        ppvObject = &_M0;
+        _M0 = 0;
+        
+        *_pdwStubPhase = STUB_CALL_SERVER;
+        
+        
+        _RetVal = IClassFactory_CreateInstance_Stub(
+                                            (IClassFactory *) ((CStdStubBuffer *)This)->pvServerObject,
+                                            riid,
+                                            ppvObject);
+        
+        *_pdwStubPhase = STUB_MARSHAL;
+        
+        _StubMsg.BufferLength = 0U + 4U;
+        _StubMsg.MaxCount = (unsigned long) ( riid );
+        
+        NdrPointerBufferSize( (PMIDL_STUB_MESSAGE) &_StubMsg,
+                              (unsigned char __RPC_FAR *)ppvObject,
+                              (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[24] );
+        
+        _StubMsg.BufferLength += 16;
+        
+        NdrStubGetBuffer(This, _pRpcChannelBuffer, &_StubMsg);
+        _StubMsg.MaxCount = (unsigned long) ( riid );
+        
+        NdrPointerMarshall( (PMIDL_STUB_MESSAGE)& _StubMsg,
+                            (unsigned char __RPC_FAR *)ppvObject,
+                            (PFORMAT_STRING) &__MIDL_TypeFormatString.Format[24] );
+        
+        _StubMsg.Buffer = (unsigned char __RPC_FAR *)(((long)_StubMsg.Buffer + 3) & ~ 0x3);
+        *(( HRESULT __RPC_FAR * )_StubMsg.Buffer)++ = _RetVal;
+        
+        }
+    RpcFinally
+        {
+        _StubMsg.MaxCount = (unsigned long) ( riid );
+        
+        NdrPointerFree( &_StubMsg,
+                        (unsigned char __RPC_FAR *)ppvObject,
+                        &__MIDL_TypeFormatString.Format[24] );
+        
+        }
+    RpcEndFinally
+    _pRpcMessage->BufferLength = 
+        (unsigned int)((long)_StubMsg.Buffer - (long)_pRpcMessage->Buffer);
+    
+}
+
+
+/* [call_as] */ HRESULT __stdcall IClassFactory_RemoteLockServer_Proxy( 
+    IClassFactory __RPC_FAR * This,
+    /* [in] */ BOOL fLock)
+{
+
+    HRESULT _RetVal;
+    
+    RPC_MESSAGE _RpcMessage;
+    
+    MIDL_STUB_MESSAGE _StubMsg;
+    
+    RpcTryExcept
+        {
+        NdrProxyInitialize(
+                      ( void __RPC_FAR *  )This,
+                      ( PRPC_MESSAGE  )&_RpcMessage,
+                      ( PMIDL_STUB_MESSAGE  )&_StubMsg,
+                      ( PMIDL_STUB_DESC  )&Object_StubDesc,
+                      4);
+        
+        
+        
+        RpcTryFinally
+            {
+            
+            _StubMsg.BufferLength = 4U;
+            NdrProxyGetBuffer(This, &_StubMsg);
+            *(( BOOL __RPC_FAR * )_StubMsg.Buffer)++ = fLock;
+            
+            NdrProxySendReceive(This, &_StubMsg);
+            
+            if ( (_RpcMessage.DataRepresentation & 0X0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION )
+                NdrConvert( (PMIDL_STUB_MESSAGE) &_StubMsg, (PFORMAT_STRING) &__MIDL_ProcFormatString.Format[10] );
+            
+            _RetVal = *(( HRESULT __RPC_FAR * )_StubMsg.Buffer)++;
+            
+            }
+        RpcFinally
+            {
+            NdrProxyFreeBuffer(This, &_StubMsg);
+            
+            }
+        RpcEndFinally
+        
+        }
+    RpcExcept(_StubMsg.dwStubPhase != PROXY_SENDRECEIVE)
+        {
+        _RetVal = NdrProxyErrorHandler(RpcExceptionCode());
+        }
+    RpcEndExcept
+    return _RetVal;
+}
+
+void __RPC_STUB IClassFactory_RemoteLockServer_Stub(
+    IRpcStubBuffer *This,
+    IRpcChannelBuffer *_pRpcChannelBuffer,
+    PRPC_MESSAGE _pRpcMessage,
+    DWORD *_pdwStubPhase)
+{
+    HRESULT _RetVal;
+    MIDL_STUB_MESSAGE _StubMsg;
+    BOOL fLock;
+    
+NdrStubInitialize(
+                     _pRpcMessage,
+                     &_StubMsg,
+                     &Object_StubDesc,
+                     _pRpcChannelBuffer);
+    RpcTryFinally
+        {
+        if ( (_pRpcMessage->DataRepresentation & 0X0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION )
+            NdrConvert( (PMIDL_STUB_MESSAGE) &_StubMsg, (PFORMAT_STRING) &__MIDL_ProcFormatString.Format[10] );
+        
+        fLock = *(( BOOL __RPC_FAR * )_StubMsg.Buffer)++;
+        
+        
+        *_pdwStubPhase = STUB_CALL_SERVER;
+        
+        
+        _RetVal = IClassFactory_LockServer_Stub((IClassFactory *) ((CStdStubBuffer *)This)->pvServerObject,fLock);
+        
+        *_pdwStubPhase = STUB_MARSHAL;
+        
+        _StubMsg.BufferLength = 4U;
+        NdrStubGetBuffer(This, _pRpcChannelBuffer, &_StubMsg);
+        *(( HRESULT __RPC_FAR * )_StubMsg.Buffer)++ = _RetVal;
+        
+        }
+    RpcFinally
+        {
+        }
+    RpcEndFinally
+    _pRpcMessage->BufferLength = 
+        (unsigned int)((long)_StubMsg.Buffer - (long)_pRpcMessage->Buffer);
+    
+}
+
+
+static const MIDL_STUB_DESC Object_StubDesc = 
+    {
+    0,
+    NdrOleAllocate,
+    NdrOleFree,
+    0,
+    0,
+    0,
+    0,
+    0,
+    __MIDL_TypeFormatString.Format,
+    1, /* -error bounds_check flag */
+    0x10001, /* Ndr library version */
+    0,
+    0x50100a4, /* MIDL Version 5.1.164 */
+    0,
+    0,
+    0,  /* notify & notify_flag routine table */
+    1,  /* Flags */
+    0,  /* Reserved3 */
+    0,  /* Reserved4 */
+    0   /* Reserved5 */
+    };
+
+const CINTERFACE_PROXY_VTABLE(5) _IClassFactoryProxyVtbl = 
+{
+    &IID_IClassFactory,
+    IUnknown_QueryInterface_Proxy,
+    IUnknown_AddRef_Proxy,
+    IUnknown_Release_Proxy ,
+    IClassFactory_CreateInstance_Proxy ,
+    IClassFactory_LockServer_Proxy
+};
+
+
+static const PRPC_STUB_FUNCTION IClassFactory_table[] =
+{
+    IClassFactory_RemoteCreateInstance_Stub,
+    IClassFactory_RemoteLockServer_Stub
+};
+
+const CInterfaceStubVtbl _IClassFactoryStubVtbl =
+{
+    &IID_IClassFactory,
+    0,
+    5,
+    &IClassFactory_table[-3],
+    CStdStubBuffer_METHODS
+};
+
+#pragma data_seg(".rdata")
+
+#if !defined(__RPC_WIN32__)
+#error  Invalid build platform for this stub.
+#endif
+
+static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =
+    {
+        0,
+        {
+			
+			0x4d,		/* FC_IN_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/*  2 */	NdrFcShort( 0x2 ),	/* Type Offset=2 */
+/*  4 */	
+			0x51,		/* FC_OUT_PARAM */
+#ifndef _ALPHA_
+			0x1,		/* x86, MIPS & PPC Stack size = 1 */
+#else
+			0x2,		/* Alpha Stack size = 2 */
+#endif
+/*  6 */	NdrFcShort( 0x18 ),	/* Type Offset=24 */
+/*  8 */	0x53,		/* FC_RETURN_PARAM_BASETYPE */
+			0x8,		/* FC_LONG */
+/* 10 */	0x4e,		/* FC_IN_PARAM_BASETYPE */
+			0x8,		/* FC_LONG */
+/* 12 */	0x53,		/* FC_RETURN_PARAM_BASETYPE */
+			0x8,		/* FC_LONG */
+
+			0x0
+        }
+    };
+
+static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =
+    {
+        0,
+        {
+			NdrFcShort( 0x0 ),	/* 0 */
+/*  2 */	
+			0x11, 0x0,	/* FC_RP */
+/*  4 */	NdrFcShort( 0x8 ),	/* Offset= 8 (12) */
+/*  6 */	
+			0x1d,		/* FC_SMFARRAY */
+			0x0,		/* 0 */
+/*  8 */	NdrFcShort( 0x8 ),	/* 8 */
+/* 10 */	0x2,		/* FC_CHAR */
+			0x5b,		/* FC_END */
+/* 12 */	
+			0x15,		/* FC_STRUCT */
+			0x3,		/* 3 */
+/* 14 */	NdrFcShort( 0x10 ),	/* 16 */
+/* 16 */	0x8,		/* FC_LONG */
+			0x6,		/* FC_SHORT */
+/* 18 */	0x6,		/* FC_SHORT */
+			0x4c,		/* FC_EMBEDDED_COMPLEX */
+/* 20 */	0x0,		/* 0 */
+			NdrFcShort( 0xfffffff1 ),	/* Offset= -15 (6) */
+			0x5b,		/* FC_END */
+/* 24 */	
+			0x11, 0x14,	/* FC_RP [alloced_on_stack] */
+/* 26 */	NdrFcShort( 0x2 ),	/* Offset= 2 (28) */
+/* 28 */	
+			0x2f,		/* FC_IP */
+			0x5c,		/* FC_PAD */
+/* 30 */	0x28,		/* Corr desc:  parameter, FC_LONG */
+			0x0,		/*  */
+#ifndef _ALPHA_
+/* 32 */	NdrFcShort( 0x4 ),	/* x86, MIPS, PPC Stack size/offset = 4 */
+#else
+			NdrFcShort( 0x8 ),	/* Alpha Stack size/offset = 8 */
+#endif
+
+			0x0
+        }
+    };
+
+const CInterfaceProxyVtbl * _unknwn_ProxyVtblList[] = 
+{
+    ( CInterfaceProxyVtbl *) &_IClassFactoryProxyVtbl,
+    0
+};
+
+const CInterfaceStubVtbl * _unknwn_StubVtblList[] = 
+{
+    ( CInterfaceStubVtbl *) &_IClassFactoryStubVtbl,
+    0
+};
+
+PCInterfaceName const _unknwn_InterfaceNamesList[] = 
+{
+    "IClassFactory",
+    0
+};
+
+
+#define _unknwn_CHECK_IID(n)	IID_GENERIC_CHECK_IID( _unknwn, pIID, n)
+
+int __stdcall _unknwn_IID_Lookup( const IID * pIID, int * pIndex )
+{
+    
+    if(!_unknwn_CHECK_IID(0))
+        {
+        *pIndex = 0;
+        return 1;
+        }
+
+    return 0;
+}
+
+const ExtendedProxyFileInfo unknwn_ProxyFileInfo = 
+{
+    (PCInterfaceProxyVtblList *) & _unknwn_ProxyVtblList,
+    (PCInterfaceStubVtblList *) & _unknwn_StubVtblList,
+    (const PCInterfaceName * ) & _unknwn_InterfaceNamesList,
+    0, // no delegation
+    & _unknwn_IID_Lookup, 
+    1,
+    1,
+    0, /* table of [async_uuid] interfaces */
+    0, /* Filler1 */
+    0, /* Filler2 */
+    0  /* Filler3 */
+};
Index: dlls/oleaut32/Makefile.in
===================================================================
RCS file: /cvsroot/rewind/rewind/dlls/oleaut32/Makefile.in,v
retrieving revision 1.28
diff -u -r1.28 Makefile.in
--- dlls/oleaut32/Makefile.in	20 May 2003 13:52:07 -0000	1.28
+++ dlls/oleaut32/Makefile.in	8 Jul 2003 22:12:01 -0000
@@ -19,6 +19,7 @@
 	olefont.c \
 	olepicture.c \
 	parsedt.c \
+	proxy.c \
 	safearray.c \
 	stubs.c \
 	tmarshal.c \
Index: dlls/oleaut32/oleaut.c
===================================================================
RCS file: /cvsroot/rewind/rewind/dlls/oleaut32/oleaut.c,v
retrieving revision 1.25
diff -u -r1.25 oleaut.c
--- dlls/oleaut32/oleaut.c	20 May 2003 13:59:55 -0000	1.25
+++ dlls/oleaut32/oleaut.c	8 Jul 2003 22:12:02 -0000
@@ -14,13 +14,11 @@
 #include "olectl.h"
 #include "oleauto.h"
 #include "wine/obj_olefont.h"
-
-#include "tmarshal.h"
-
 #include "debugtools.h"
 
 DEFAULT_DEBUG_CHANNEL(ole);
 
+extern const CLSID CLSID_PSDispatch;
 extern const CLSID CLSID_PSOAInterface;
 
 /* IDispatch marshaler */
@@ -158,6 +156,7 @@
 extern HRESULT OLEAUTPS_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv);
 
 extern void _get_STDFONT_CF(LPVOID);
+extern void _get_OLEAUT_PSF(LPVOID);
 
 /***********************************************************************
  *		DllGetClassObject (OLEAUT32.1)
@@ -176,9 +175,11 @@
 	return OLEAUTPS_DllGetClassObject(rclsid,iid,ppv);
     }
     if (IsEqualGUID(rclsid,&CLSID_PSOAInterface)) {
-	if (S_OK==TypeLibFac_DllGetClassObject(rclsid,iid,ppv))
+	if (IsEqualGUID(iid,&IID_IPSFactoryBuffer)) {
+	    _get_OLEAUT_PSF(ppv);
+	    IPSFactoryBuffer_AddRef((IPSFactoryBuffer*)*ppv);
 	    return S_OK;
-	/*FALLTHROUGH*/
+	}
     }
     FIXME("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(iid));
     return CLASS_E_CLASSNOTAVAILABLE;
Index: dlls/rpcrt4/rpc_binding.c
===================================================================
RCS file: /cvsroot/rewind/rewind/dlls/rpcrt4/rpc_binding.c,v
retrieving revision 1.12
diff -u -r1.12 rpc_binding.c
--- dlls/rpcrt4/rpc_binding.c	20 Apr 2003 03:03:08 -0000	1.12
+++ dlls/rpcrt4/rpc_binding.c	8 Jul 2003 22:12:14 -0000
@@ -113,9 +113,13 @@
 
   EnterCriticalSection(&conn_cache_cs);
   PrevConnection = conn_cache;
-  while (PrevConnection && PrevConnection->Next != Connection)
-    PrevConnection = PrevConnection->Next;
-  if (PrevConnection) PrevConnection->Next = Connection->Next;
+  if (PrevConnection == Connection) {
+    conn_cache = Connection->Next;
+  } else {
+    while (PrevConnection && PrevConnection->Next != Connection)
+      PrevConnection = PrevConnection->Next;
+    if (PrevConnection) PrevConnection->Next = Connection->Next;
+  }
   LeaveCriticalSection(&conn_cache_cs);
 
   RPCRT4_CloseConnection(Connection);
Index: dlls/rpcrt4/rpc_server.c
===================================================================
RCS file: /cvsroot/rewind/rewind/dlls/rpcrt4/rpc_server.c,v
retrieving revision 1.17
diff -u -r1.17 rpc_server.c
--- dlls/rpcrt4/rpc_server.c	22 May 2003 19:01:06 -0000	1.17
+++ dlls/rpcrt4/rpc_server.c	8 Jul 2003 22:12:14 -0000
@@ -17,16 +17,17 @@
 #include "winreg.h"
 
 #include "rpc.h"
-#include "msvcrt/excpt.h"
 
 #include "wine/debug.h"
 #include "wine/exception.h"
+#include "msvcrt/excpt.h"
 
 #include "rpc_server.h"
 #include "rpc_misc.h"
 #include "rpc_defs.h"
 
-#define MAX_THREADS 128
+#define MAX_THREADS 20
+#define MAX_IDLE_THREADS 4
 
 WINE_DEFAULT_DEBUG_CHANNEL(ole);
 
@@ -99,11 +100,18 @@
   return packet;
 }
 
+typedef struct {
+  PRPC_MESSAGE msg;
+  void* buf;
+} packet_state;
+
 static WINE_EXCEPTION_FILTER(rpc_filter)
 {
+  packet_state* state;
   PRPC_MESSAGE msg;
-  msg = TlsGetValue(worker_tls);
-  I_RpcFreeBuffer(msg);
+  state = TlsGetValue(worker_tls);
+  msg = state->msg;
+  if (msg->Buffer != state->buf) I_RpcFreeBuffer(msg);
   msg->RpcFlags |= WINE_RPCFLAG_EXCEPTION;
   msg->BufferLength = sizeof(DWORD);
   I_RpcGetBuffer(msg);
@@ -117,8 +125,11 @@
   RPC_MESSAGE msg;
   RpcServerInterface* sif;
   RPC_DISPATCH_FUNCTION func;
+  packet_state state;
 
-  TlsSetValue(worker_tls, &msg);
+  state.msg = &msg;
+  state.buf = buf;
+  TlsSetValue(worker_tls, &state);
   memset(&msg, 0, sizeof(msg));
   msg.BufferLength = hdr->len;
   msg.Buffer = buf;
@@ -188,7 +199,7 @@
 
 static DWORD CALLBACK RPCRT4_worker_thread(LPVOID the_arg)
 {
-  DWORD obj;
+  HANDLE obj;
   RpcPacket* pkt;
 
   for (;;) {
@@ -196,7 +207,7 @@
     obj = WaitForSingleObject(server_sem, 5000);
     if (obj == WAIT_TIMEOUT) {
       /* if another idle thread exist, self-destruct */
-      if (worker_free > 1) break;
+      if (worker_free > MAX_IDLE_THREADS) break;
       continue;
     }
     pkt = RPCRT4_pop_packet();
Index: include/objidl.idl
===================================================================
RCS file: /cvsroot/rewind/rewind/include/objidl.idl,v
retrieving revision 1.1
diff -u -r1.1 objidl.idl
--- include/objidl.idl	20 Dec 2002 10:01:43 -0000	1.1
+++ include/objidl.idl	8 Jul 2003 22:12:19 -0000
@@ -5,7 +5,9 @@
 import "unknwn.idl";
 
 interface IStream;
+#ifdef __WIDL__
 interface IStream16;
+#endif
 interface IEnumString;
 interface IRunningObjectTable;
 interface IMoniker;
@@ -795,7 +797,9 @@
     [out] IStream **ppstm);
 }
 
+#ifdef __WIDL__
 [
+  local,
   object,
   pointer_default(unique)
 ]
@@ -868,6 +872,7 @@
   HRESULT Clone(
     [out] IStream16 **ppstm);
 }
+#endif /* __WIDL__ */
 
 [
   object,
@@ -1015,7 +1020,9 @@
     [in] DWORD grfStatFlag);
 }
 
+#ifdef __WIDL__
 [
+  local,
   object,
   pointer_default(unique)
 ]
@@ -1127,6 +1134,7 @@
     [out] STATSTG *pstatstg,
     [in] DWORD grfStatFlag);
 }
+#endif /* __WIDL__ */
 
 [
   object,
--- /dev/null	2003-01-10 01:23:22.000000000 +0100
+++ dlls/oleaut32/proxy.c	2003-02-13 21:40:50.000000000 +0100
@@ -0,0 +1,1404 @@
+/*
+ * Typelib Marshaler
+ *
+ * Copyright 2001 TransGaming Technologies, Ove Kåven
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winreg.h"
+#include "debugtools.h"
+#include "ole2.h"
+#include "oleauto.h"
+
+DEFAULT_DEBUG_CHANNEL(ole);
+
+static HRESULT OA_LoadInterfaceTypeLib(REFIID riid, LPTYPELIB *ppTlib)
+{
+  HKEY key;
+  char keyName[100], ver[100];
+  WCHAR keyVal[100];
+  int Maj, Min;
+  GUID iid;
+  DWORD len;
+  HRESULT hr;
+  sprintf(keyName, "Interface\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\TypeLib",
+	  riid->Data1, riid->Data2, riid->Data3,
+	  riid->Data4[0], riid->Data4[1], riid->Data4[2], riid->Data4[3],
+	  riid->Data4[4], riid->Data4[5], riid->Data4[6], riid->Data4[7]);
+  if (RegCreateKeyExA(HKEY_CLASSES_ROOT,keyName,0,NULL,0,KEY_READ,NULL,&key,NULL)) {
+    ERR("typelib entry not found for interface %s\n", debugstr_guid(riid));
+    return E_FAIL;
+  }
+  len = sizeof(keyVal);
+  if (RegQueryValueExW(key,NULL,NULL,NULL,(LPBYTE)&keyVal,&len)) {
+    ERR("typelib GUID not found for interface %s\n", debugstr_guid(riid));
+    RegCloseKey(key);
+    return E_FAIL;
+  }
+  hr = CLSIDFromString(keyVal, &iid);
+  if (FAILED(hr)) {
+    ERR("unparsable typelib GUID for interface %s\n", debugstr_guid(riid));
+    RegCloseKey(key);
+    return hr;
+  }
+  len = sizeof(ver);
+  if (RegQueryValueExA(key,"Version",NULL,NULL,ver,&len)) {
+    ERR("typelib version not found for interface %s\n", debugstr_guid(riid));
+    RegCloseKey(key);
+    return hr;
+  }
+  if (sscanf(ver,"%d.%d",&Maj,&Min)!=2) {
+    ERR("unparsable typelib version for interface %s\n", debugstr_guid(riid));
+    RegCloseKey(key);
+    return hr;
+  }
+  RegCloseKey(key);
+  return LoadRegTypeLib(&iid, Maj, Min, 0, ppTlib);
+}
+
+/******************** MARSHALLER ********************/
+/* FIXME: should layer on top of rpcrt4 */
+
+static DWORD TL_SizeOfType(LPTYPEINFO pInfo,
+			   TYPEDESC *pType)
+{
+  switch (pType->vt) {
+  case VT_I1:
+  case VT_UI1:
+    return sizeof(BYTE);
+  case VT_I2:
+  case VT_UI2:
+    return sizeof(WORD);
+  case VT_I4:
+  case VT_UI4:
+  case VT_INT:
+  case VT_UINT:
+    return sizeof(DWORD);
+  case VT_BOOL:
+    return sizeof(VARIANT_BOOL);
+  case VT_VARIANT:
+    return sizeof(VARIANT);
+  case VT_BSTR:
+  case VT_PTR:
+  case VT_DISPATCH:
+  case VT_UNKNOWN:
+    return sizeof(LPVOID);
+  case VT_USERDEFINED:
+    {
+      HREFTYPE hType = pType->u.hreftype;
+      LPTYPEINFO pTInfo;
+      LPTYPEATTR pAttr;
+      DWORD size = 0;
+      if (FAILED(ITypeInfo_GetRefTypeInfo(pInfo, hType, &pTInfo))) return 0;
+      if (FAILED(ITypeInfo_GetTypeAttr(pTInfo, &pAttr))) {
+	ITypeInfo_Release(pTInfo);
+	return 0;
+      }
+      switch (pAttr->typekind) {
+      case TKIND_RECORD:
+        size = pAttr->cbSizeInstance;
+        break;
+      case TKIND_INTERFACE:
+	size = 0; /* must not be handled here */
+	break;
+      default:
+	ERR("unknown size for typekind %d\n", pAttr->typekind);
+      }
+      ITypeInfo_ReleaseTypeAttr(pTInfo, pAttr);
+      ITypeInfo_Release(pTInfo);
+      return size;
+    }
+    break;
+  default:
+    FIXME("unknown type size for type %d\n", pType->vt);
+  case VT_VOID:
+    return 0;
+  }
+}
+
+static DWORD TL_ArgSiz(DWORD size)
+{
+  return (size+3)/4;
+}
+
+static WCHAR magic_guid[] = {'G','U','I','D',0};
+static WCHAR magic_riid[] = {'r','i','i','d',0};
+
+static HRESULT TL_MarshalType(LPSTREAM pStm,
+			      LPTYPEINFO pInfo,
+			      TYPEDESC *pType,
+			      DWORD *args,
+			      BOOL first,
+			      GUID *is_iid)
+{
+  HRESULT hr = S_OK;
+  switch (pType->vt) {
+  case VT_I1:
+  case VT_UI1:
+    {
+      BYTE v = *(BYTE*)args;
+      TRACE("   marshaling byte %d\n", v);
+      IStream_Write(pStm, &v, sizeof(v), NULL);
+    }
+    break;
+  case VT_I2:
+  case VT_UI2:
+    {
+      WORD v = *(WORD*)args;
+      TRACE("   marshaling short %d\n", v);
+      IStream_Write(pStm, &v, sizeof(v), NULL);
+    }
+    break;
+  case VT_I4:
+  case VT_UI4:
+  case VT_INT:
+  case VT_UINT:
+    {
+      DWORD v = *(DWORD*)args;
+      TRACE("   marshaling int %ld\n", v);
+      IStream_Write(pStm, &v, sizeof(v), NULL);
+    }
+    break;
+  case VT_BOOL:
+    {
+      VARIANT_BOOL v = *(VARIANT_BOOL*)args;
+      TRACE("   marshaling bool %d\n", v);
+      IStream_Write(pStm, &v, sizeof(v), NULL);
+    }
+    break;
+  case VT_VARIANT:
+    {
+      LPVARIANT v = (LPVARIANT)args;
+      TYPEDESC vType;
+      vType.vt = V_VT(v);
+      vType.u.hreftype = 0;
+      TRACE("   marshaling VARIANT %p type %d\n", v, vType.vt);
+      IStream_Write(pStm, &vType.vt, sizeof(vType.vt), NULL);
+      hr = TL_MarshalType(pStm, pInfo, &vType, (DWORD*)&V_UNION(v,cVal), FALSE, is_iid);
+    }
+    break;
+  case VT_BSTR:
+    {
+      BSTR v = *(BSTR*)args;
+      int len = SysStringLen(v);
+      TRACE("   marshaling BSTR %s\n", debugstr_w(v));
+      IStream_Write(pStm, &len, sizeof(len), NULL);
+      if (len) IStream_Write(pStm, v, len*sizeof(OLECHAR), NULL);
+    }
+    break;
+  case VT_PTR:
+    {
+      LPVOID v = *(LPVOID*)args;
+      DWORD valid = (v != NULL);
+      TRACE("   dereferencing PTR %p <= %p\n", v, args);
+      IStream_Write(pStm, &valid, sizeof(valid), NULL);
+      if (valid) hr = TL_MarshalType(pStm, pInfo, pType->u.lptdesc, (DWORD*)v, FALSE, is_iid);
+    }
+    break;
+  case VT_DISPATCH:
+  case VT_UNKNOWN:
+  case VT_VOID: /* <= InstallShield hack */
+    {
+      LPVOID pv = *(LPVOID*)args;
+      const IID *piid;
+      if (pType->vt == VT_DISPATCH) piid = &IID_IDispatch; else
+      if (pType->vt == VT_UNKNOWN) piid = &IID_IUnknown; else
+      {
+        pv = (LPVOID)args;
+        piid = is_iid;
+      }
+      TRACE("   marshaling INTERFACE %p %s\n", pv, debugstr_guid(piid));
+      hr = CoMarshalInterface(pStm, piid, pv, CLSCTX_LOCAL_SERVER, NULL, MSHLFLAGS_NORMAL);
+    }
+    break;
+  case VT_USERDEFINED:
+    {
+      LPVOID pv = (LPVOID)args;
+      HREFTYPE hType = pType->u.hreftype;
+      LPTYPEINFO pTInfo;
+      LPTYPEATTR pAttr;
+      BSTR tname = NULL;
+      BOOL is_guid = FALSE;
+      TRACE("   reftype: %ld\n", hType);
+      hr = ITypeInfo_GetRefTypeInfo(pInfo, hType, &pTInfo);
+      if (FAILED(hr)) {
+	ERR("failed to retrieve reftype %ld\n", hType);
+	return hr;
+      }
+      ITypeInfo_GetDocumentation(pTInfo, -1, &tname, NULL, NULL, NULL);
+      if (tname) {
+        TRACE("   name   : %s\n", debugstr_w(tname));
+        is_guid = tname ? (lstrcmpW(tname,magic_guid)==0) : FALSE;
+        SysFreeString(tname);
+      }
+      hr = ITypeInfo_GetTypeAttr(pTInfo, &pAttr);
+      if (FAILED(hr)) {
+	ITypeInfo_Release(pTInfo);
+	return hr;
+      }
+      TRACE("   kind   : %d\n", pAttr->typekind);
+      switch (pAttr->typekind) {
+      case TKIND_RECORD:
+        {
+	  /* hope that the record contains no pointers */
+	  TRACE("   marshaling RECORD %p [size=%ld]\n", pv, pAttr->cbSizeInstance);
+	  if (is_guid)
+	    TRACE("    guid=%s\n", debugstr_guid((GUID*)pv));
+	  IStream_Write(pStm, pv, pAttr->cbSizeInstance, NULL);
+        }
+        break;
+      case TKIND_INTERFACE:
+	{
+	  TRACE("   marshaling INTERFACE %p %s\n", pv, debugstr_guid(&pAttr->guid));
+	  hr = CoMarshalInterface(pStm, &pAttr->guid, pv, CLSCTX_LOCAL_SERVER, NULL, MSHLFLAGS_NORMAL);
+	}
+	break;
+      default:
+	ERR("unhandled typekind %d\n", pAttr->typekind);
+      }
+      ITypeInfo_ReleaseTypeAttr(pTInfo, pAttr);
+      ITypeInfo_Release(pTInfo);
+    }
+    break;
+  default:
+    FIXME("marshal type %d\n", pType->vt);
+  }
+  return hr;
+}
+
+static HRESULT TL_CleanupType(LPTYPEINFO pInfo,
+			      TYPEDESC *pType,
+			      DWORD *args,
+			      BOOL first)
+{
+  HRESULT hr = S_OK;
+  switch (pType->vt) {
+  case VT_VARIANT:
+    {
+      LPVARIANT v = (LPVARIANT)args;
+#if 0
+      TYPEDESC vType;
+      vType.vt = V_VT(v);
+      vType.u.hreftype = 0;
+#endif
+      TRACE("   freeing VARIANT %p type %d\n", v, V_VT(v));
+#if 0
+      hr = TL_CleanupType(pInfo, &vType, (DWORD*)&V_UNION(v,cVal), FALSE);
+#endif
+      VariantClear(v);
+    }
+    break;
+  case VT_BSTR:
+    {
+      BSTR v = *(BSTR*)args;
+      TRACE("   freeing BSTR %p\n", v);
+      SysFreeString(v);
+    }
+    break;
+  case VT_PTR:
+    {
+      LPVOID v = *(LPVOID*)args;
+      TRACE("   freeing PTR %p\n", v);
+      if (v) {
+        hr = TL_CleanupType(pInfo, pType->u.lptdesc, (DWORD*)v, FALSE);
+        if (hr == S_OK) CoTaskMemFree(v);
+      }
+    }
+    break;
+  case VT_DISPATCH:
+  case VT_UNKNOWN:
+    {
+      LPVOID pv = *(LPVOID*)args;
+      IUnknown_Release((LPUNKNOWN)pv);
+    }
+    break;
+  case VT_VOID: /* <= InstallShield hack */
+    {
+      LPVOID pv = (LPVOID)args;
+      IUnknown_Release((LPUNKNOWN)pv);
+      hr = S_FALSE;
+    }
+    break;
+  case VT_USERDEFINED:
+    {
+      LPVOID pv = (LPVOID)args;
+      HREFTYPE hType = pType->u.hreftype;
+      LPTYPEINFO pTInfo;
+      LPTYPEATTR pAttr;
+      if (FAILED(ITypeInfo_GetRefTypeInfo(pInfo, hType, &pTInfo))) return 0;
+      if (FAILED(ITypeInfo_GetTypeAttr(pTInfo, &pAttr))) {
+	ITypeInfo_Release(pTInfo);
+	return 0;
+      }
+      switch (pAttr->typekind) {
+      case TKIND_RECORD:
+	/* hope that the record contains no pointers */
+	break;
+      case TKIND_INTERFACE:
+	IUnknown_Release((LPUNKNOWN)pv);
+	hr = S_FALSE;
+	break;
+      default:
+	ERR("unknown cleanup for typekind %d\n", pAttr->typekind);
+      }
+      ITypeInfo_ReleaseTypeAttr(pTInfo, pAttr);
+      ITypeInfo_Release(pTInfo);
+    }
+    break;
+  default:
+  }
+  return hr;
+}
+
+static HRESULT TL_Marshal(LPSTREAM pStm,
+			  LPTYPEINFO pInfo,
+			  LPFUNCDESC pDesc,
+			  DWORD dwFlag,
+			  DWORD *args,
+			  HRESULT res,
+			  GUID *is_iid)
+{
+  int p, cc;
+  BSTR names[16];
+  UINT mnames = 0;
+  BOOL is_riid;
+  TRACE(" Marshaling %p\n", args);
+  args++;
+  ITypeInfo_GetNames(pInfo, pDesc->memid, names, 16, &mnames);
+  if (mnames) SysFreeString(names[0]);
+  for (p=0; p<pDesc->cParams; p++) {
+    ELEMDESC *par = &pDesc->lprgelemdescParam[p];
+    USHORT wFlag = par->u.paramdesc.wParamFlags;
+    TRACE("  parameter %d\n", p);
+    if (p<=mnames) {
+      TRACE("   name   : %s\n", debugstr_w(names[p+1]));
+      is_riid = names[p+1] ? (lstrcmpW(names[p+1],magic_riid)==0) : FALSE;
+      SysFreeString(names[p+1]);
+    }
+    else is_riid = FALSE;
+    TRACE("   type   : %d\n", par->tdesc.vt);
+    TRACE("   flags  : %02x\n", wFlag);
+    if (par->u.paramdesc.pparamdescex)
+      TRACE("   bytes  : %ld\n", par->u.paramdesc.pparamdescex->cBytes);
+    if (is_riid) {
+      memcpy(is_iid, *(GUID**)args, sizeof(GUID));
+      TRACE(" is_riid=%s\n", debugstr_guid(is_iid));
+    }
+    if (wFlag & dwFlag) {
+      TL_MarshalType(pStm, pInfo, &par->tdesc, args, FALSE, is_iid);
+    }
+    if (dwFlag & PARAMFLAG_FOUT) {
+      /* cleanup after Unmarshal etc */
+      TL_CleanupType(pInfo, &par->tdesc, args, TRUE);
+    }
+    cc = TL_ArgSiz(TL_SizeOfType(pInfo, &par->tdesc));
+    args += cc;
+  }
+  if (dwFlag & PARAMFLAG_FOUT) {
+    /* marshal HRESULT */
+    IStream_Write(pStm, &res, sizeof(res), NULL);
+  }
+  return S_OK;
+}
+
+static HRESULT TL_UnmarshalType(LPSTREAM pStm,
+				LPTYPEINFO pInfo,
+				TYPEDESC *pType,
+				DWORD *args,
+				BOOL first,
+	 			LPVOID *argp,
+ 				LPRPCCHANNELBUFFER chan,
+ 				GUID *is_iid)
+{
+  HRESULT hr = S_OK;
+  switch (pType->vt) {
+  case VT_I1:
+  case VT_UI1:
+    {
+      BYTE v;
+      IStream_Read(pStm, &v, sizeof(v), NULL);
+      TRACE("   unmarshaled byte %d\n", v);
+      *args = v;
+    }
+    break;
+  case VT_I2:
+  case VT_UI2:
+    {
+      WORD v;
+      IStream_Read(pStm, &v, sizeof(v), NULL);
+      TRACE("   unmarshaled short %d\n", v);
+      *args = v;
+    }
+    break;
+  case VT_I4:
+  case VT_UI4:
+  case VT_INT:
+  case VT_UINT:
+    {
+      DWORD v;
+      IStream_Read(pStm, &v, sizeof(v), NULL);
+      TRACE("   unmarshaled int %ld\n", v);
+      *args = v;
+    }
+    break;
+  case VT_BOOL:
+    {
+      VARIANT_BOOL v;
+      IStream_Read(pStm, &v, sizeof(v), NULL);
+      TRACE("   unmarshaled bool %d\n", v);
+      *args = v;
+    }
+    break;
+  case VT_VARIANT:
+    {
+      LPVARIANT v = (LPVARIANT)args;
+      TYPEDESC vType;
+      vType.vt = VT_EMPTY;
+      vType.u.hreftype = 0;
+      IStream_Read(pStm, &vType.vt, sizeof(vType.vt), NULL);
+      TRACE("   variant type: %d\n", vType.vt);
+      VariantInit(v);
+      V_VT(v) = vType.vt;
+      hr = TL_UnmarshalType(pStm, pInfo, &vType, (DWORD*)&V_UNION(v,cVal), FALSE, NULL, chan, is_iid);
+    }
+    break;
+  case VT_BSTR:
+    {
+      BSTR v;
+      int len;
+      IStream_Read(pStm, &len, sizeof(len), NULL);
+      v = SysAllocStringLen(NULL, len);
+      if (len) IStream_Read(pStm, v, len*sizeof(OLECHAR), NULL);
+      TRACE("   unmarshaled BSTR %s => %p\n", debugstr_w(v), v);
+      *(BSTR*)args = v;
+    }
+    break;
+  case VT_PTR:
+    {
+      LPVOID v;
+      DWORD valid;
+      IStream_Read(pStm, &valid, sizeof(valid), NULL);
+      if (first) {
+	v = *(LPVOID*)args;
+	TRACE("   dereferenced PTR %p <= %p\n", v, args);
+      }
+      else {
+	DWORD size = valid ? TL_SizeOfType(pInfo, pType->u.lptdesc) : 0;
+	if (size) v = CoTaskMemAlloc(size);
+	else v = NULL;
+	*(LPVOID*)args = v;
+	TRACE("   allocated PTR [size=%ld] => %p => %p\n", size, v, args);
+      }
+      if (valid) hr = TL_UnmarshalType(pStm, pInfo, pType->u.lptdesc, (DWORD*)v, FALSE, (LPVOID*)args, chan, is_iid);
+    }
+    break;
+  case VT_DISPATCH:
+  case VT_UNKNOWN:
+  case VT_VOID: /* <= InstallShield hack */
+    {
+      LPVOID *iptr = (LPVOID*)args;
+      const IID *piid;
+      if (pType->vt == VT_DISPATCH) piid = &IID_IDispatch; else
+      if (pType->vt == VT_UNKNOWN) piid = &IID_IUnknown; else
+      {
+        iptr = argp ? argp : (LPVOID*)args;
+        piid = is_iid;
+      }
+      hr = CoUnmarshalInterface(pStm, piid, iptr);
+      TRACE("   unmarshaled INTERFACE %s => %p => %p\n", debugstr_guid(piid), *iptr, iptr);
+    }
+    break;
+  case VT_USERDEFINED:
+    {
+      LPVOID pv = (LPVOID)args;
+      HREFTYPE hType = pType->u.hreftype;
+      LPTYPEINFO pTInfo;
+      LPTYPEATTR pAttr;
+      BSTR tname = NULL;
+      BOOL is_guid = FALSE;
+      TRACE("   reftype: %ld\n", hType);
+      hr = ITypeInfo_GetRefTypeInfo(pInfo, hType, &pTInfo);
+      if (FAILED(hr)) {
+	ERR("failed to retrieve reftype %ld\n", hType);
+	return hr;
+      }
+      ITypeInfo_GetDocumentation(pTInfo, -1, &tname, NULL, NULL, NULL);
+      if (tname) {
+        TRACE("   name   : %s\n", debugstr_w(tname));
+        is_guid = tname ? (lstrcmpW(tname,magic_guid)==0) : FALSE;
+        SysFreeString(tname);
+      }
+      hr = ITypeInfo_GetTypeAttr(pTInfo, &pAttr);
+      if (FAILED(hr)) {
+	ITypeInfo_Release(pTInfo);
+	return hr;
+      }
+      TRACE("   kind   : %d\n", pAttr->typekind);
+      switch (pAttr->typekind) {
+      case TKIND_RECORD:
+        {
+	  /* hope that the record contains no pointers */
+	  IStream_Read(pStm, pv, pAttr->cbSizeInstance, NULL);
+	  TRACE("   unmarshaled RECORD %p [size=%ld]\n", pv, pAttr->cbSizeInstance);
+	  if (is_guid)
+	    TRACE("    guid=%s\n", debugstr_guid((GUID*)pv));
+        }
+        break;
+      case TKIND_INTERFACE:
+	{
+	  LPVOID *iptr = argp ? argp : (LPVOID*)args;
+	  hr = CoUnmarshalInterface(pStm, &pAttr->guid, iptr);
+	  TRACE("   unmarshaled INTERFACE %s => %p => %p\n", debugstr_guid(&pAttr->guid), *iptr, iptr);
+	}
+	break;
+      default:
+	ERR("unhandled typekind %d\n", pAttr->typekind);
+      }
+      ITypeInfo_ReleaseTypeAttr(pTInfo, pAttr);
+      ITypeInfo_Release(pTInfo);
+    }
+    break;
+  default:
+    FIXME("unmarshal type %d\n", pType->vt);
+  }
+  return hr;
+}
+
+static HRESULT TL_Unmarshal(LPSTREAM pStm,
+			    LPTYPEINFO pInfo,
+			    LPFUNCDESC pDesc,
+			    DWORD dwFlag,
+			    DWORD *args,
+			    HRESULT *ret,
+			    LPRPCCHANNELBUFFER chan,
+			    GUID *is_iid)
+{
+  int p, pc, cc;
+  BSTR names[16];
+  UINT mnames = 0;
+  BOOL is_riid;
+  TRACE(" Unmarshaling %p\n", args);
+  args++; pc=1;
+  ITypeInfo_GetNames(pInfo, pDesc->memid, names, 16, &mnames);
+  if (mnames) SysFreeString(names[0]);
+  for (p=0; p<pDesc->cParams; p++) {
+    ELEMDESC *par = &pDesc->lprgelemdescParam[p];
+    USHORT wFlag = par->u.paramdesc.wParamFlags;
+    TRACE("  parameter %d\n", p);
+    if (p<=mnames) {
+      TRACE("   name   : %s\n", debugstr_w(names[p+1]));
+      is_riid = names[p+1] ? (lstrcmpW(names[p+1],magic_riid)==0) : FALSE;
+      SysFreeString(names[p+1]);
+    }
+    else is_riid = FALSE;
+    TRACE("   type   : %d\n", par->tdesc.vt);
+    TRACE("   flags  : %02x\n", wFlag);
+    if (par->u.paramdesc.pparamdescex)
+      TRACE("   bytes  : %ld\n", par->u.paramdesc.pparamdescex->cBytes);
+    if (wFlag & dwFlag) {
+      TL_UnmarshalType(pStm, pInfo, &par->tdesc, args, !(dwFlag & PARAMFLAG_FIN), NULL, chan, is_iid);
+    }
+    else if (dwFlag & PARAMFLAG_FIN) {
+      /* for out parameters, we must still initialize pointers */
+      switch (par->tdesc.vt) {
+      case VT_PTR:
+	{
+	  TYPEDESC *pType = par->tdesc.u.lptdesc;
+	  DWORD size = TL_SizeOfType(pInfo, pType);
+	  LPVOID v = CoTaskMemAlloc(size);
+	  TRACE("   initialize PTR [size=%ld] type=%d => %p\n", size, pType->vt, v);
+	  memset(v, 0, size); /* just in case */
+	  *(LPVOID*)args = v;
+	}
+	break;
+      default:
+      }
+    }
+    if (is_riid) {
+      memcpy(is_iid, *(GUID**)args, sizeof(GUID));
+      TRACE(" is_riid=%s\n", debugstr_guid(is_iid));
+    }
+    cc = TL_ArgSiz(TL_SizeOfType(pInfo, &par->tdesc));
+    args += cc; pc += cc;
+  }
+  if (dwFlag & PARAMFLAG_FOUT) {
+    /* unmarshal HRESULT */
+    IStream_Read(pStm, ret, sizeof(*ret), NULL);
+  }
+  else *ret = pc;
+  return S_OK;
+}
+
+/******************** STUB ********************/
+/* FIXME: should layer on top of rpcrt4 */
+
+typedef struct {
+  ICOM_VTABLE(IRpcStubBuffer) *lpVtbl;
+  DWORD ref;
+  IID iid;
+  LPUNKNOWN pUnkServer;
+  LPTYPEINFO pInfo;
+  int fs;
+} PSOAStubImpl;
+
+static HRESULT WINAPI PSOAStub_QueryInterface(LPRPCSTUBBUFFER iface,
+					      REFIID riid,
+					      LPVOID *obj)
+{
+  ICOM_THIS(PSOAStubImpl,iface);
+  TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(riid),obj);
+  if (IsEqualGUID(&IID_IUnknown,riid) ||
+      IsEqualGUID(&IID_IRpcStubBuffer,riid)) {
+    *obj = This;
+    This->ref++;
+    return S_OK;
+  }
+  return E_NOINTERFACE;
+}
+
+static ULONG WINAPI PSOAStub_AddRef(LPRPCSTUBBUFFER iface)
+{
+  ICOM_THIS(PSOAStubImpl,iface);
+  TRACE("(%p)->AddRef()\n",This);
+  return ++(This->ref);
+}
+
+static ULONG WINAPI PSOAStub_Release(LPRPCSTUBBUFFER iface)
+{
+  ICOM_THIS(PSOAStubImpl,iface);
+  TRACE("(%p)->Release()\n",This);
+  if (!--(This->ref)) {
+    DWORD rc = IUnknown_Release(This->pUnkServer);
+    TRACE("server=%p, refcount=%ld\n", This->pUnkServer, rc);
+    HeapFree(GetProcessHeap(),0,This);
+    return 0;
+  }
+  return This->ref;
+}
+
+static HRESULT WINAPI PSOAStub_Connect(LPRPCSTUBBUFFER iface,
+				       LPUNKNOWN lpUnkServer)
+{
+  ICOM_THIS(PSOAStubImpl,iface);
+  TRACE("(%p)->Connect(%p)\n",This,lpUnkServer);
+  This->pUnkServer = lpUnkServer;
+  return S_OK;
+}
+
+static void WINAPI PSOAStub_Disconnect(LPRPCSTUBBUFFER iface)
+{
+  ICOM_THIS(PSOAStubImpl,iface);
+  TRACE("(%p)->Disconnect()\n",This);
+  This->pUnkServer = NULL;
+}
+
+typedef HRESULT WINAPI (*HRESULT_FARPROC)();
+
+static HRESULT WINAPI PSOAStub_Invoke(LPRPCSTUBBUFFER iface,
+				      PRPCOLEMESSAGE pMsg,
+				      LPRPCCHANNELBUFFER pChannel)
+{
+  ICOM_THIS(PSOAStubImpl,iface);
+  int fn = pMsg->iMethod & 0xfff;
+  int rec = pMsg->iMethod >> 12;
+  int fs = This->fs;
+  LPTYPEINFO pInfo;
+  LPFUNCDESC pDesc;
+  HRESULT hr;
+  GUID is_iid;
+
+  TRACE("(%p)->(%d:%d)(...)\n",This,rec,fn);
+
+if (pMsg->iMethod == (ULONG)-1) {
+  /* QueryInterface */
+  IID iid;
+  LPVOID pvObject = NULL;
+  HRESULT hr;
+  TRACE("RemoteQueryInterface(...)\n");
+  if (pMsg->cbBuffer<sizeof(iid)) return E_FAIL;
+  memcpy(&iid,pMsg->Buffer,sizeof(iid));
+  TRACE("riid=%s, server=%p\n", debugstr_guid(&iid), This->pUnkServer);
+  hr = IUnknown_QueryInterface(This->pUnkServer, &iid, &pvObject);
+  TRACE("returns %p\n", pvObject);
+  if (pvObject) {
+    LPSTREAM pStm = NULL;
+    STATSTG stat;
+    HGLOBAL hGlobal = 0;
+    CreateStreamOnHGlobal(0, TRUE, &pStm);
+    CoMarshalInterface(pStm, &iid, pvObject, MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL);
+    IUnknown_Release((LPUNKNOWN)pvObject);
+    IStream_Stat(pStm, &stat, 0);
+    pMsg->cbBuffer = stat.cbSize.s.LowPart;
+    IRpcChannelBuffer_GetBuffer(pChannel, pMsg, &This->iid);
+    GetHGlobalFromStream(pStm, &hGlobal);
+    memcpy(pMsg->Buffer, GlobalLock(hGlobal), pMsg->cbBuffer);
+    GlobalUnlock(hGlobal);
+    IStream_Release(pStm);
+  } else {
+    HeapFree(GetProcessHeap(),0,pMsg->Buffer);
+    pMsg->Buffer = NULL;
+    pMsg->cbBuffer = 0;
+  }
+  return S_OK;
+}
+
+  pInfo = This->pInfo;
+  ITypeInfo_AddRef(pInfo);
+  for (; rec; rec--) {
+    HREFTYPE hType;
+    /* find ancestor interface */
+    hr = ITypeInfo_GetRefTypeOfImplType(pInfo, 0, &hType);
+    if (SUCCEEDED(hr)) {
+      LPTYPEINFO pParInfo;
+      hr = ITypeInfo_GetRefTypeInfo(pInfo, hType, &pParInfo);
+      if (SUCCEEDED(hr)) {
+	LPTYPEATTR pAttr;
+        TRACE("located ancestor (%ld) for IID %s\n", hType, debugstr_guid(&This->iid));
+        ITypeInfo_Release(pInfo);
+        pInfo = pParInfo;
+	hr = ITypeInfo_GetTypeAttr(pInfo, &pAttr);
+	if (FAILED(hr)) {
+	  ERR("could not get type attr for IID %s\n", debugstr_guid(&This->iid));
+	  ITypeInfo_Release(pInfo);
+	  return hr;
+	}
+	fs -= pAttr->cFuncs;
+	ITypeInfo_ReleaseTypeAttr(pInfo, pAttr);
+        continue;
+      }
+    }
+    ERR("failed to locate ancestor (%ld) for IID %s\n", hType, debugstr_guid(&This->iid));
+    ITypeInfo_Release(pInfo);
+    return hr;
+  }
+  memcpy(&is_iid, &IID_IUnknown, sizeof(GUID));
+  hr = ITypeInfo_GetFuncDesc(pInfo, fn, &pDesc);
+  if (SUCCEEDED(hr)) {
+    LPSTREAM pStm = NULL;
+    STATSTG stat;
+    HGLOBAL hGlobal = 0;
+    DWORD args[32];
+    HRESULT argc;
+    LPVOID vtbl = This->pUnkServer->lpVtbl;
+    DWORD idx = fn + fs;
+#ifdef ICOM_MSVTABLE_COMPAT
+    idx += 2;
+#endif
+
+    CreateStreamOnHGlobal(0, TRUE, &pStm);
+    stat.cbSize.s.HighPart = 0;
+    stat.cbSize.s.LowPart = pMsg->cbBuffer;
+    IStream_SetSize(pStm, stat.cbSize);
+    GetHGlobalFromStream(pStm, &hGlobal);
+    if (pMsg->cbBuffer) {
+      memcpy(GlobalLock(hGlobal), pMsg->Buffer, pMsg->cbBuffer);
+      GlobalUnlock(hGlobal);
+    }
+    memset(args, 0, sizeof(args));
+    args[0] = (DWORD)This->pUnkServer;
+    TL_Unmarshal(pStm, pInfo, pDesc, PARAMFLAG_FIN, args, &argc, pChannel, &is_iid);
+
+    /* Invoke! */
+    hr = E_FAIL;
+    TRACE("invoking method idx %ld (argc=%ld) => %p\n", idx, argc, ((LPVOID*)vtbl)[idx]);
+    if (pDesc->callconv == CC_STDCALL) {
+      HRESULT_FARPROC func;
+      func = ((LPVOID*)vtbl)[idx];
+      switch (argc) {
+      case 1: hr = func(args[0]); break;
+      case 2: hr = func(args[0],args[1]); break;
+      case 3: hr = func(args[0],args[1],args[2]); break;
+      case 4: hr = func(args[0],args[1],args[2],args[3]); break;
+      case 5: hr = func(args[0],args[1],args[2],args[3],args[4]); break;
+      case 6: hr = func(args[0],args[1],args[2],args[3],args[4],args[5]); break;
+      case 7: hr = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]); break;
+      case 8: hr = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]); break;
+      case 9: hr = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]); break;
+      default:
+	FIXME("unimplemented nr of args: %ld\n", argc);
+      }
+    }
+    else FIXME("callconv %d not supported\n", pDesc->callconv);
+    TRACE("invoked method returned with HRESULT %08lx\n", hr);
+
+    stat.cbSize.s.HighPart = 0;
+    stat.cbSize.s.LowPart = 0;
+    IStream_Seek(pStm, *(LARGE_INTEGER*)&stat.cbSize, STREAM_SEEK_SET, NULL);
+    IStream_SetSize(pStm, stat.cbSize);
+    TL_Marshal(pStm, pInfo, pDesc, PARAMFLAG_FOUT, args, hr, &is_iid);
+    IStream_Stat(pStm, &stat, 0);
+    GetHGlobalFromStream(pStm, &hGlobal);
+    pMsg->cbBuffer = stat.cbSize.s.LowPart;
+    IRpcChannelBuffer_GetBuffer(pChannel, pMsg, &This->iid);
+    if (pMsg->cbBuffer) {
+      memcpy(pMsg->Buffer, GlobalLock(hGlobal), pMsg->cbBuffer);
+      GlobalUnlock(hGlobal);
+    }
+    IStream_Release(pStm);
+    ITypeInfo_ReleaseFuncDesc(pInfo, pDesc);
+    hr = S_OK;
+  }
+  ITypeInfo_Release(pInfo);
+  return hr;
+}
+
+static LPRPCSTUBBUFFER WINAPI PSOAStub_IsIIDSupported(LPRPCSTUBBUFFER iface,
+						      REFIID riid)
+{
+  ICOM_THIS(PSOAStubImpl,iface);
+  TRACE("(%p)->IsIIDSupported(%s)\n",This,debugstr_guid(riid));
+  return IsEqualGUID(&This->iid,riid) ? iface : NULL;
+}
+
+static ULONG WINAPI PSOAStub_CountRefs(LPRPCSTUBBUFFER iface)
+{
+  ICOM_THIS(PSOAStubImpl,iface);
+  TRACE("(%p)->CountRefs()\n",This);
+  return This->ref;
+}
+
+static HRESULT WINAPI PSOAStub_DebugServerQueryInterface(LPRPCSTUBBUFFER iface,
+							 LPVOID *ppv)
+{
+  ICOM_THIS(PSOAStubImpl,iface);
+  TRACE("(%p)->DebugServerQueryInterface(%p)\n",This,ppv);
+  return S_OK;
+}
+
+static void WINAPI PSOAStub_DebugServerRelease(LPRPCSTUBBUFFER iface,
+					       LPVOID pv)
+{
+  ICOM_THIS(PSOAStubImpl,iface);
+  TRACE("(%p)->DebugServerRelease(%p)\n",This,pv);
+}
+
+static ICOM_VTABLE(IRpcStubBuffer) PSOAStub_VTable =
+{
+  ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+  PSOAStub_QueryInterface,
+  PSOAStub_AddRef,
+  PSOAStub_Release,
+  PSOAStub_Connect,
+  PSOAStub_Disconnect,
+  PSOAStub_Invoke,
+  PSOAStub_IsIIDSupported,
+  PSOAStub_CountRefs,
+  PSOAStub_DebugServerQueryInterface,
+  PSOAStub_DebugServerRelease
+};
+
+/******************** PROXY ********************/
+/* FIXME: should layer on top of rpcrt4 */
+
+typedef struct {
+  void *lpVtbl;
+  ICOM_VTABLE(IRpcProxyBuffer) *pVtbl;
+  DWORD ref;
+  IID iid;
+  LPUNKNOWN pUnkOuter;
+  LPTYPEINFO pInfo;
+  LPRPCCHANNELBUFFER pChannel;
+} PSOAProxyImpl;
+
+#define VTBL_OFS(impl) (((LPBYTE)(&((impl*)0)->pVtbl)) - (LPBYTE)0)
+#define VTBL_UPCAST(impl,iface) (impl*)(((LPBYTE)iface) - VTBL_OFS(impl))
+
+static HRESULT WINAPI PSOAProxy_QueryInterface(LPRPCPROXYBUFFER iface,
+					       REFIID riid,
+					       LPVOID *obj)
+{
+  PSOAProxyImpl *This = VTBL_UPCAST(PSOAProxyImpl,iface);
+  TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(riid),obj);
+  if (IsEqualGUID(&IID_IUnknown,riid) ||
+      IsEqualGUID(&This->iid,riid)) {
+    *obj = &This->lpVtbl;
+    This->ref++;
+    return S_OK;
+  }
+  if (IsEqualGUID(&IID_IRpcProxyBuffer,riid)) {
+    *obj = &This->pVtbl;
+    This->ref++;
+    return S_OK;
+  }
+  return E_NOINTERFACE;
+}
+
+static ULONG WINAPI PSOAProxy_AddRef(LPRPCPROXYBUFFER iface)
+{
+  PSOAProxyImpl *This = VTBL_UPCAST(PSOAProxyImpl,iface);
+  TRACE("(%p)->AddRef()\n",This);
+  return ++(This->ref);
+}
+
+static ULONG WINAPI PSOAProxy_Release(LPRPCPROXYBUFFER iface)
+{
+  PSOAProxyImpl *This = VTBL_UPCAST(PSOAProxyImpl,iface);
+  TRACE("(%p)->Release()\n",This);
+  if (!--(This->ref)) {
+    HeapFree(GetProcessHeap(),0,This);
+    return 0;
+  }
+  return This->ref;
+}
+
+static HRESULT WINAPI PSOAProxy_Connect(LPRPCPROXYBUFFER iface,
+					LPRPCCHANNELBUFFER pChannel)
+{
+  PSOAProxyImpl *This = VTBL_UPCAST(PSOAProxyImpl,iface);
+  TRACE("(%p)->Connect(%p)\n",This,pChannel);
+  This->pChannel = pChannel;
+  return S_OK;
+}
+
+static VOID WINAPI PSOAProxy_Disconnect(LPRPCPROXYBUFFER iface)
+{
+  PSOAProxyImpl *This = VTBL_UPCAST(PSOAProxyImpl,iface);
+  TRACE("(%p)->Disconnect()\n",This);
+  This->pChannel = NULL;
+}
+
+static ICOM_VTABLE(IRpcProxyBuffer) PSOAProxy_VTable =
+{
+  ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+  PSOAProxy_QueryInterface,
+  PSOAProxy_AddRef,
+  PSOAProxy_Release,
+  PSOAProxy_Connect,
+  PSOAProxy_Disconnect
+};
+
+static HRESULT WINAPI OAProxy_QueryInterface(LPRPCPROXYBUFFER iface,
+                                              REFIID riid,
+                                              LPVOID *obj)
+{
+  ICOM_THIS(PSOAProxyImpl,iface);
+  TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(riid),obj);
+  return IUnknown_QueryInterface(This->pUnkOuter,riid,obj);
+}
+
+static ULONG WINAPI OAProxy_AddRef(LPRPCPROXYBUFFER iface)
+{
+  ICOM_THIS(PSOAProxyImpl,iface);
+  TRACE("(%p)\n",This);
+  return IUnknown_AddRef(This->pUnkOuter);
+}
+
+static ULONG WINAPI OAProxy_Release(LPRPCPROXYBUFFER iface)
+{
+  ICOM_THIS(PSOAProxyImpl,iface);
+  TRACE("(%p)\n",This);
+  return IUnknown_Release(This->pUnkOuter);
+}
+
+static HRESULT WINAPI TLProxy(DWORD meth)
+{
+  DWORD *args = &meth + 2;
+  LPRPCPROXYBUFFER iface = (LPRPCPROXYBUFFER)(args[0]);
+  ICOM_THIS(PSOAProxyImpl,iface);
+  int fn = meth & 0xfff;
+  int rec = meth >> 12;
+  LPTYPEINFO pInfo;
+  LPFUNCDESC pDesc;
+  HRESULT hr;
+  BSTR name, desc;
+  GUID is_iid;
+
+  TRACE("(%p)->(%d:%d)(...) ret=%08lx\n",This,rec,fn,*(&meth + 1));
+  pInfo = This->pInfo;
+  name = NULL;
+  desc = NULL;
+  ITypeInfo_AddRef(pInfo);
+  hr = ITypeInfo_GetDocumentation(pInfo, -1, &name, &desc, NULL, NULL);
+  if (SUCCEEDED(hr)) {
+    TRACE(" interface name: %s\n", name ? debugstr_w(name) : "(unknown)");
+    if (desc)
+      TRACE(" interface desc: %s\n", debugstr_w(desc));
+    SysFreeString(name);
+    SysFreeString(desc);
+  }
+  for (; rec; rec--) {
+    HREFTYPE hType;
+    /* find ancestor interface */
+    hr = ITypeInfo_GetRefTypeOfImplType(pInfo, 0, &hType);
+    if (SUCCEEDED(hr)) {
+      LPTYPEINFO pParInfo;
+      hr = ITypeInfo_GetRefTypeInfo(pInfo, hType, &pParInfo);
+      if (SUCCEEDED(hr)) {
+        TRACE("located ancestor (%ld) for IID %s\n", hType, debugstr_guid(&This->iid));
+        ITypeInfo_Release(pInfo);
+        pInfo = pParInfo;
+        continue;
+      }
+    }
+    ERR("failed to locate ancestor (%ld) for IID %s\n", hType, debugstr_guid(&This->iid));
+    ITypeInfo_Release(pInfo);
+    return hr;
+  }
+  memcpy(&is_iid, &IID_IUnknown, sizeof(GUID));
+  hr = ITypeInfo_GetFuncDesc(pInfo, fn, &pDesc);
+  if (SUCCEEDED(hr)) {
+    LPSTREAM pStm = NULL;
+    STATSTG stat;
+    HGLOBAL hGlobal = 0;
+    RPCOLEMESSAGE msg;
+    ULONG status;
+
+    name = NULL;
+    desc = NULL;
+    hr = ITypeInfo_GetDocumentation(pInfo, pDesc->memid, &name, &desc, NULL, NULL);
+    if (SUCCEEDED(hr)) {
+      TRACE(" method name: %s\n", name ? debugstr_w(name) : "(unknown)");
+      if (desc)
+	TRACE(" method desc: %s\n", debugstr_w(desc));
+      SysFreeString(name);
+      SysFreeString(desc);
+    }
+
+    msg.reserved1 = This; /* BAD hack */
+    msg.iMethod = meth;
+    msg.Buffer = NULL;
+
+    CreateStreamOnHGlobal(0, TRUE, &pStm);
+    GetHGlobalFromStream(pStm, &hGlobal);
+    TL_Marshal(pStm, pInfo, pDesc, PARAMFLAG_FIN, args, 0, &is_iid);
+    IStream_Stat(pStm, &stat, 0);
+    msg.cbBuffer = stat.cbSize.s.LowPart;
+    IRpcChannelBuffer_GetBuffer(This->pChannel, &msg, &This->iid);
+    memcpy(msg.Buffer, GlobalLock(hGlobal), msg.cbBuffer);
+    GlobalUnlock(hGlobal);
+
+    hr = IRpcChannelBuffer_SendReceive(This->pChannel, &msg, &status);
+    if (FAILED(hr)) goto proxy_error;
+
+    stat.cbSize.s.HighPart = 0;
+    stat.cbSize.s.LowPart = 0;
+    IStream_Seek(pStm, *(LARGE_INTEGER*)&stat.cbSize, STREAM_SEEK_SET, NULL);
+    stat.cbSize.s.HighPart = 0;
+    stat.cbSize.s.LowPart = msg.cbBuffer;
+    IStream_SetSize(pStm, stat.cbSize);
+    GetHGlobalFromStream(pStm, &hGlobal);
+    memcpy(GlobalLock(hGlobal), msg.Buffer, msg.cbBuffer);
+    GlobalUnlock(hGlobal);
+    hr = E_FAIL;
+    TL_Unmarshal(pStm, pInfo, pDesc, PARAMFLAG_FOUT, args, &hr, This->pChannel, &is_iid);
+proxy_error:
+    IStream_Release(pStm);
+    IRpcChannelBuffer_FreeBuffer(This->pChannel, &msg);
+    ITypeInfo_ReleaseFuncDesc(pInfo, pDesc);
+  }
+  ITypeInfo_Release(pInfo);
+  TRACE("returning %08lx\n", hr);
+  return hr;
+}
+
+typedef struct {
+  BYTE push WINE_PACKED;
+  DWORD meth WINE_PACKED;
+  BYTE call WINE_PACKED;
+  int handler WINE_PACKED;
+  BYTE ret WINE_PACKED;
+  WORD bytes WINE_PACKED;
+  BYTE pad0, pad1, pad2;
+} TLThunk;
+
+static TLThunk TLstdcall = {
+  0x68, 0,          /* pushl $0 */
+  0xe8, -10,        /* call 0 */
+  0xc2, 0,          /* ret $0 */
+  0x8d, 0x76, 0x00  /* leal (%esi),%esi */
+};
+
+static LPVOID OA_BuildProxyVtbl(LPTYPEINFO pInfo, int *pfs, int rec)
+{
+  LPVOID vtbl = NULL;
+  IID iid;
+  LPTYPEATTR pAttr;
+  TYPEKIND kind;
+  int types, funcs, tfs, fs = pfs ? *pfs : 0;
+  int fn, p, pb;
+  MEMBERID mid;
+  HREFTYPE hType;
+  BSTR name, desc;
+  HRESULT hr;
+
+  hr = ITypeInfo_GetTypeAttr(pInfo, &pAttr);
+  if (FAILED(hr)) {
+    ERR("could not get type attr for interface\n");
+    return NULL;
+  }
+  memcpy(&iid, &pAttr->guid, sizeof(iid));
+  kind = pAttr->typekind;
+  types = pAttr->cImplTypes;
+  funcs = pAttr->cFuncs;
+  ITypeInfo_ReleaseTypeAttr(pInfo, pAttr);
+  /* FIXME: we could handle TKIND_DISPATCH by looking for
+   * its associated TKIND_INTERFACE with GetRefTypeOfImplType */
+  if (kind != TKIND_INTERFACE) {
+    ERR("invalid type kind %d for IID %s\n", kind, debugstr_guid(&iid));
+    return NULL;
+  }
+  tfs = funcs + fs;
+  /* find ancestor interface */
+  hr = ITypeInfo_GetRefTypeOfImplType(pInfo, 0, &hType);
+  if (SUCCEEDED(hr)) {
+    LPTYPEINFO pParInfo;
+    hr = ITypeInfo_GetRefTypeInfo(pInfo, hType, &pParInfo);
+    if (SUCCEEDED(hr)) {
+      int nfs = funcs + fs;
+      TRACE("located ancestor (%ld) for IID %s\n", hType, debugstr_guid(&iid));
+      vtbl = OA_BuildProxyVtbl(pParInfo, &nfs, rec+1);
+      ITypeInfo_Release(pParInfo);
+      fs = nfs;
+    } else {
+      ERR("failed to locate ancestor (%ld) for IID %s\n", hType, debugstr_guid(&iid));
+      MESSAGE("Please make sure a copy of stdole32.tlb is installed.\n");
+      tfs += 3; /* assume IUnknown for now, but it could be IDispatch, don't know how to find out */
+      fs = 3;
+    }
+  }
+  else {
+    TRACE("no ancestor for IID %s\n", debugstr_guid(&iid));
+    fs = 0;
+  }
+  if (pfs) *pfs = fs + funcs;
+  /* if we have no ancestor, allocate vtable */
+  if (!vtbl) {
+    ICOM_VTABLE(IUnknown) *vt;
+    vt = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(LPVOID)*tfs);
+    vt->QueryInterface = OAProxy_QueryInterface;
+    vt->AddRef = OAProxy_AddRef;
+    vt->Release = OAProxy_Release;
+    vtbl = vt;
+    TRACE("  vtbl IUnknown entries filled\n");
+    if (IsEqualGUID(&iid, &IID_IUnknown)) return vtbl;
+  }
+  /* parse descendant interface */
+  TRACE("typelib data for IID %s:\n", debugstr_guid(&iid));
+  name = NULL;
+  desc = NULL;
+  hr = ITypeInfo_GetDocumentation(pInfo, -1, &name, &desc, NULL, NULL);
+  if (SUCCEEDED(hr)) {
+    TRACE(" name: %s\n", name ? debugstr_w(name) : "(unknown)");
+    if (desc)
+      TRACE(" desc: %s\n", debugstr_w(desc));
+    SysFreeString(name);
+    SysFreeString(desc);
+  }
+  TRACE(" types: %d\n", types);
+  TRACE(" funcs: %d\n", funcs);
+  for (fn=0; fn<funcs; fn++) {
+    LPFUNCDESC pDesc;
+    hr = ITypeInfo_GetFuncDesc(pInfo, fn, &pDesc);
+    if (SUCCEEDED(hr)) {
+      BSTR names[16];
+      UINT mnames = 0;
+      mid = pDesc->memid;
+      TRACE(" function %d (member ID %ld) (vofs %d)\n", fn, mid, (fn+fs)*sizeof(FARPROC));
+      name = NULL;
+      desc = NULL;
+      hr = ITypeInfo_GetDocumentation(pInfo, mid, &name, &desc, NULL, NULL);
+      if (SUCCEEDED(hr)) {
+	TRACE("  name: %s\n", name ? debugstr_w(name) : "(unknown)");
+	if (desc)
+	  TRACE("  desc: %s\n", debugstr_w(desc));
+	SysFreeString(name);
+	SysFreeString(desc);
+      }
+      TRACE("  funckind: %d\n", pDesc->funckind); /* 1 = PURE VIRTUAL */
+      TRACE("  invkind : %d\n", pDesc->invkind);  /* 1 = FUNC, 2 = PROPGET, 3 = PROPPUT */
+      TRACE("  callconv: %d\n", pDesc->callconv); /* 4 = STDCALL */
+      TRACE("  params  : %d\n", pDesc->cParams);
+      TRACE("  params 2: %d\n", pDesc->cParamsOpt);
+      TRACE("  vft     : %d\n", pDesc->oVft);
+      TRACE("  scodes  : %d\n", pDesc->cScodes);
+      TRACE("  flags   : %x\n", pDesc->wFuncFlags);
+      TRACE("  return type: %d\n", pDesc->elemdescFunc.tdesc.vt); /* 25 = HRESULT */
+      ITypeInfo_GetNames(pInfo, mid, names, 16, &mnames);
+      if (mnames) SysFreeString(names[0]);
+      pb = sizeof(LPVOID); /* count argument bytes */
+      for (p=0; p<pDesc->cParams; p++) {
+	ELEMDESC *par = &pDesc->lprgelemdescParam[p];
+	TRACE("  parameter %d\n", p);
+	if (p<=mnames) {
+	  TRACE("   name   : %s\n", debugstr_w(names[p+1]));
+	  SysFreeString(names[p+1]);
+	}
+	TRACE("   type   : %d\n", par->tdesc.vt);
+	TRACE("   flags  : %02x\n", par->u.paramdesc.wParamFlags);
+	if (par->u.paramdesc.pparamdescex)
+	  TRACE("   bytes  : %ld\n", par->u.paramdesc.pparamdescex->cBytes);
+	pb += sizeof(DWORD)*TL_ArgSiz(TL_SizeOfType(pInfo, &par->tdesc));
+      }
+      if ((fn + fs) < 3) {
+	/* this better not happen */
+      }
+      else if (pDesc->callconv == CC_STDCALL) {
+	/* OK, create thunk */
+	TLThunk *thunk = HeapAlloc(GetProcessHeap(),0,sizeof(TLThunk));
+	DWORD idx = fn + fs;
+	memcpy(thunk, &TLstdcall, sizeof(TLThunk));
+	thunk->meth = fn | (rec << 12);
+	thunk->handler += (LPBYTE)TLProxy - (LPBYTE)thunk;
+	thunk->bytes = pb;
+	TRACE("  vtbl entry %ld -> thunk %p, argsiz %d\n", idx, thunk, pb);
+#ifdef ICOM_MSVTABLE_COMPAT
+	idx += 2;
+#endif
+	((LPVOID*)vtbl)[idx] = thunk;
+      }
+      else FIXME("callconv %d not supported\n", pDesc->callconv);
+      ITypeInfo_ReleaseFuncDesc(pInfo, pDesc);
+    }
+  }
+  return vtbl;
+}
+
+/*******************************************************************************
+ * PSOAFactoryBuffer
+ */
+static HRESULT WINAPI PSOAFactory_QueryInterface(LPPSFACTORYBUFFER iface,
+						 REFIID riid,
+						 LPVOID *obj) {
+  TRACE("(%p)->QueryInterface(%s,%p)\n",iface,debugstr_guid(riid),obj);
+  if (IsEqualGUID(&IID_IUnknown,riid) ||
+      IsEqualGUID(&IID_IPSFactoryBuffer,riid)) {
+    *obj = iface;
+    return S_OK;
+  }
+  return E_NOINTERFACE;
+}
+
+static ULONG WINAPI PSOAFactory_AddRef(LPPSFACTORYBUFFER iface) {
+  TRACE("(%p)->AddRef()\n",iface);
+  return 2;
+}
+
+static ULONG WINAPI PSOAFactory_Release(LPPSFACTORYBUFFER iface) {
+  TRACE("(%p)->Release()\n",iface);
+  return 1;
+}
+
+static HRESULT WINAPI PSOAFactory_CreateProxy(LPPSFACTORYBUFFER iface,
+					      LPUNKNOWN pUnkOuter,
+					      REFIID riid,
+					      LPRPCPROXYBUFFER *ppProxy,
+					      LPVOID *ppv)
+{
+  PSOAProxyImpl *proxy;
+  LPTYPELIB pTlib;
+  LPTYPEINFO pInfo;
+  HRESULT hr;
+  TRACE("(%p)->CreateProxy(%p,%s,%p,%p)\n",iface,pUnkOuter,
+        debugstr_guid(riid),ppProxy,ppv);
+  hr = OA_LoadInterfaceTypeLib(riid, &pTlib);
+  if (SUCCEEDED(hr)) {
+    hr = ITypeLib_GetTypeInfoOfGuid(pTlib, riid, &pInfo);
+    ITypeLib_Release(pTlib);
+    if (FAILED(hr)) {
+      return E_FAIL;
+    }
+    proxy = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(PSOAProxyImpl));
+    if (!proxy) {
+      ITypeInfo_Release(pInfo);
+      return E_OUTOFMEMORY;
+    }
+    proxy->pVtbl = &PSOAProxy_VTable;
+    proxy->ref = 1;
+    memcpy(&proxy->iid, riid, sizeof(proxy->iid));
+    proxy->pUnkOuter = pUnkOuter;
+    proxy->pInfo = pInfo;
+    proxy->lpVtbl = OA_BuildProxyVtbl(pInfo, NULL, 0);
+    *ppProxy = (LPRPCPROXYBUFFER)&proxy->pVtbl;
+    *ppv = proxy;
+    TRACE("created typelib-based interface proxy\n");
+    return S_OK;
+  }
+  return E_FAIL;
+}
+
+static HRESULT WINAPI PSOAFactory_CreateStub(LPPSFACTORYBUFFER iface,
+					     REFIID riid,
+					     LPUNKNOWN pUnkServer,
+					     LPRPCSTUBBUFFER *ppStub)
+{
+  PSOAStubImpl *stub;
+  LPTYPELIB pTlib;
+  LPTYPEINFO pInfo;
+  HRESULT hr;
+  TRACE("(%p)->CreateStub(%s,%p,%p)\n",iface,debugstr_guid(riid),
+        pUnkServer,ppStub);
+  hr = OA_LoadInterfaceTypeLib(riid, &pTlib);
+  if (SUCCEEDED(hr)) {
+    hr = ITypeLib_GetTypeInfoOfGuid(pTlib, riid, &pInfo);
+    ITypeLib_Release(pTlib);
+    if (FAILED(hr)) {
+      return E_FAIL;
+    }
+    stub = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(PSOAStubImpl));
+    if (!stub) {
+      ITypeInfo_Release(pInfo);
+      return E_OUTOFMEMORY;
+    }
+    stub->lpVtbl = &PSOAStub_VTable;
+    stub->ref = 1;
+    memcpy(&stub->iid, riid, sizeof(stub->iid));
+    IUnknown_AddRef(pUnkServer);
+    stub->pUnkServer = pUnkServer;
+    stub->pInfo = pInfo;
+    stub->fs = 0;
+    /* count methods in ancestor classes */
+    ITypeInfo_AddRef(pInfo);
+    while (TRUE) {
+      HREFTYPE hType;
+      HRESULT hr = ITypeInfo_GetRefTypeOfImplType(pInfo, 0, &hType);
+      if (SUCCEEDED(hr)) {
+	LPTYPEINFO pParInfo;
+	hr = ITypeInfo_GetRefTypeInfo(pInfo, hType, &pParInfo);
+	if (SUCCEEDED(hr)) {
+	  LPTYPEATTR pAttr;
+	  ITypeInfo_Release(pInfo);
+	  pInfo = pParInfo;
+	  hr = ITypeInfo_GetTypeAttr(pInfo, &pAttr);
+	  if (FAILED(hr)) {
+	    ERR("could not get type attr for interface\n");
+	    break;
+	  }
+	  stub->fs += pAttr->cFuncs;
+	  ITypeInfo_ReleaseTypeAttr(pInfo, pAttr);
+	} else {
+	  stub->fs += 3; /* assume IUnknown for now */
+	  break;
+	}
+      }
+      else break;
+    }
+    ITypeInfo_Release(pInfo);
+    TRACE(" pfs=%d\n", stub->fs);
+    /* done */
+    *ppStub = (LPRPCSTUBBUFFER)stub;
+    TRACE("created typelib-based interface stub\n");
+    return S_OK;
+  }
+  return E_FAIL;
+}
+
+static ICOM_VTABLE(IPSFactoryBuffer) PSOAFactoryBuffer_VTable =
+{
+  ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+  PSOAFactory_QueryInterface,
+  PSOAFactory_AddRef,
+  PSOAFactory_Release,
+  PSOAFactory_CreateProxy,
+  PSOAFactory_CreateStub
+};
+
+static ICOM_VTABLE(IPSFactoryBuffer) *PSOAFactoryBuffer = &PSOAFactoryBuffer_VTable;
+
+void _get_OLEAUT_PSF(LPVOID *ppv) { *ppv = (LPVOID)&PSOAFactoryBuffer; }
