- Add a new flag SORFP_NOLIFETIMEMGMT to tell the proxy manager not to
  call any IRemUnknown functions.
- Move the low-level unmarshaling code into a new function,
  unmarshal_object, so that it can be easily reused for unmarshaling
  IRemUnknown.

diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h
index b87fabe..3aa9d67 100644
--- a/dlls/ole32/compobj_private.h
+++ b/dlls/ole32/compobj_private.h
@@ -109,6 +109,7 @@
   struct list interfaces;   /* imported interfaces (CS cs) */
   DWORD refs;               /* proxy reference count (LOCK) */
   CRITICAL_SECTION cs;      /* thread safety for this object and children */
+  ULONG sorflags;           /* STDOBJREF flags (RO) */
 };
 
 /* this needs to become a COM object that implements IRemUnknown */
diff --git a/dlls/ole32/marshal.c b/dlls/ole32/marshal.c
index d2a12fa..9fb7675 100644
--- a/dlls/ole32/marshal.c
+++ b/dlls/ole32/marshal.c
@@ -52,6 +52,10 @@
 /* number of refs given out for normal marshaling */
 #define NORMALEXTREFS 1 /* FIXME: this should be 5, but we have to wait for IRemUnknown support first */
 
+/* private flag indicating that the caller does not want to notify the stub
+ * when the proxy disconnects or is destroyed */
+#define SORFP_NOLIFETIMEMGMT SORF_OXRES1
+
 /* Marshalling just passes a unique identifier to the remote client,
  * that makes it possible to find the passed interface again.
  *
@@ -324,7 +328,9 @@
     HeapFree(GetProcessHeap(), 0, This);
 }
 
-static HRESULT proxy_manager_construct(APARTMENT * apt, OXID oxid, OID oid, IRpcChannelBuffer * channel, struct proxy_manager ** proxy_manager)
+static HRESULT proxy_manager_construct(
+    APARTMENT * apt, ULONG sorflags, OXID oxid, OID oid,
+    IRpcChannelBuffer * channel, struct proxy_manager ** proxy_manager)
 {
     struct proxy_manager * This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
     if (!This) return E_OUTOFMEMORY;
@@ -344,6 +350,7 @@
     This->oid = oid;
 
     This->refs = 1;
+    This->sorflags = sorflags;
 
     This->chan = channel; /* FIXME: we should take the binding strings and construct the channel in this function */
 
@@ -355,7 +362,9 @@
     return S_OK;
 }
 
-static HRESULT proxy_manager_create_ifproxy(struct proxy_manager * This, IPID ipid, REFIID riid, ULONG cPublicRefs, struct ifproxy ** iif_out)
+static HRESULT proxy_manager_create_ifproxy(
+    struct proxy_manager * This, IPID ipid, REFIID riid, ULONG cPublicRefs,
+    struct ifproxy ** iif_out)
 {
     HRESULT hr;
     IPSFactoryBuffer * psfb;
@@ -436,7 +445,8 @@
 {
     struct list * cursor;
 
-    TRACE("oid = %s\n", wine_dbgstr_longlong(This->oid));
+    TRACE("oxid = %s, oid = %s\n", wine_dbgstr_longlong(This->oxid),
+        wine_dbgstr_longlong(This->oid));
 
     EnterCriticalSection(&This->cs);
 
@@ -637,6 +647,67 @@
   return S_OK;
 }
 
+/* helper for StdMarshalImpl_UnmarshalInterface - does the unmarshaling with
+ * no questions asked about the rules surrounding same-apartment unmarshals
+ * and table marshaling */
+static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt, REFIID riid, void **object)
+{
+    struct proxy_manager *proxy_manager = NULL;
+    HRESULT hr = S_OK;
+
+    /* create an a new proxy manager if one doesn't already exist for the
+     * object */
+    if (!find_proxy_manager(apt, stdobjref->oxid, stdobjref->oid, &proxy_manager))
+    {
+        IRpcChannelBuffer *chanbuf;
+        wine_marshal_id mid;
+
+        mid.oxid = stdobjref->oxid;
+        mid.oid = stdobjref->oid;
+        mid.ipid = stdobjref->ipid;
+
+        hr = PIPE_GetNewPipeBuf(&mid,&chanbuf);
+        if (hr == S_OK)
+            hr = proxy_manager_construct(apt, stdobjref->flags,
+                                         stdobjref->oxid, stdobjref->oid,
+                                         chanbuf, &proxy_manager);
+    }
+
+    if (hr == S_OK)
+    {
+        /* the IUnknown interface is special because it does not have an
+         * ifproxy associated with it. we simply return the controlling
+         * IUnknown of the proxy manager. */
+        if (IsEqualIID(riid, &IID_IUnknown))
+        {
+            ClientIdentity_AddRef((IInternalUnknown*)&proxy_manager->lpVtbl);
+            *object = (LPVOID)(&proxy_manager->lpVtbl);
+        }
+        else
+        {
+            struct ifproxy * ifproxy;
+            hr = proxy_manager_find_ifproxy(proxy_manager, riid, &ifproxy);
+            if (hr == E_NOINTERFACE)
+                hr = proxy_manager_create_ifproxy(proxy_manager, stdobjref->ipid,
+                                                  riid, stdobjref->cPublicRefs,
+                                                  &ifproxy);
+
+            if (hr == S_OK)
+            {
+                /* FIXME: push this AddRef inside proxy_manager_find_ifproxy/create_ifproxy? */
+                ClientIdentity_AddRef((IInternalUnknown*)&proxy_manager->lpVtbl);
+                *object = ifproxy->iface;
+            }
+        }
+    }
+
+    /* release our reference to the proxy manager - the client/apartment
+     * will hold on to the remaining reference for us */
+    if (proxy_manager) ClientIdentity_Release((IInternalUnknown*)&proxy_manager->lpVtbl);
+
+    return hr;
+}
+
 static HRESULT WINAPI
 StdMarshalImpl_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, void **ppv)
 {
@@ -644,18 +715,19 @@
   STDOBJREF stdobjref;
   ULONG			res;
   HRESULT		hres;
-  struct proxy_manager *proxy_manager = NULL;
   APARTMENT *apt = COM_CurrentApt();
   APARTMENT *stub_apt;
 
   TRACE("(...,%s,....)\n",debugstr_guid(riid));
 
+  /* we need an apartment to unmarshal into */
   if (!apt)
   {
       ERR("Apartment not initialized\n");
       return CO_E_NOTINITIALIZED;
   }
 
+  /* read STDOBJREF from wire */
   hres = IStream_Read(pStm, &stdobjref, sizeof(stdobjref), &res);
   if (hres) return hres;
   
@@ -703,57 +775,13 @@
       TRACE("Treating unmarshal from OXID %s as inter-process\n",
             wine_dbgstr_longlong(stdobjref.oxid));
 
-  if (hres) return hres;
+  if (hres == S_OK)
+    hres = unmarshal_object(&stdobjref, apt, riid, ppv);
 
-  if (!find_proxy_manager(apt, stdobjref.oxid, stdobjref.oid, &proxy_manager))
-  {
-    IRpcChannelBuffer *chanbuf;
-    wine_marshal_id mid;
+  if (hres) WARN("Failed with error 0x%08lx\n", hres);
+  else TRACE("Successfully created proxy %p\n", *ppv);
 
-    mid.oxid = stdobjref.oxid;
-    mid.oid = stdobjref.oid;
-    mid.ipid = stdobjref.ipid;
-
-    hres = PIPE_GetNewPipeBuf(&mid,&chanbuf);
-    if (hres == S_OK)
-      hres = proxy_manager_construct(apt, stdobjref.oxid, stdobjref.oid,
-                                     chanbuf, &proxy_manager);
-  }
-
-    if (hres == S_OK)
-    {
-        /* the IUnknown interface is special because it does not have an
-         * ifproxy associated with it. we simply return the controlling
-         * IUnknown of the proxy manager. */
-        if (IsEqualIID(riid, &IID_IUnknown))
-        {
-            ClientIdentity_AddRef((IInternalUnknown*)&proxy_manager->lpVtbl);
-            *ppv = (LPVOID)(&proxy_manager->lpVtbl);
-        }
-        else
-        {
-            struct ifproxy * ifproxy;
-            hres = proxy_manager_find_ifproxy(proxy_manager, riid, &ifproxy);
-            if (hres == E_NOINTERFACE)
-                hres = proxy_manager_create_ifproxy(proxy_manager, stdobjref.ipid,
-                                                    riid, stdobjref.cPublicRefs,
-                                                    &ifproxy);
-
-            if (hres == S_OK)
-            {
-                /* FIXME: push this AddRef inside proxy_manager_find_ifproxy/create_ifproxy? */
-                ClientIdentity_AddRef((IInternalUnknown*)&proxy_manager->lpVtbl);
-                *ppv = ifproxy->iface;
-            }
-        }
-    }
-
-    if (proxy_manager) ClientIdentity_Release((IInternalUnknown*)&proxy_manager->lpVtbl);
-
-    if (hres) WARN("Failed with error 0x%08lx\n", hres);
-    else TRACE("Successfully created proxy %p\n", *ppv);
-
-    return hres;
+  return hres;
 }
 
 static HRESULT WINAPI