Authors: Mike Hearn <mh@codeweavers.com>, Robert Shearman <rob@codeweavers.com>
Change stub manager to track the number of normal marshals instead of
using the state machine so that multiple marshals of the same object
and interface work correctly.

diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h
index 04231e3..88d251b 100644
--- a/dlls/ole32/compobj_private.h
+++ b/dlls/ole32/compobj_private.h
@@ -71,6 +71,7 @@
     IID               iid;        /* RO */
     IPID              ipid;       /* RO */
     IUnknown         *iface;      /* RO */
+    MSHLFLAGS         flags;      /* so we can enforce process-local marshalling rules (RO) */
 };
 
 
@@ -87,7 +88,14 @@
     OID               oid;        /* apartment-scoped unique identifier (RO) */
     IUnknown         *object;     /* the object we are managing the stub for (RO) */
     ULONG             next_ipid;  /* currently unused (LOCK) */
-    STUB_STATE        state;      /* state machine (CS lock) */
+
+    /* We need to keep a count of the outstanding marshals, so we can enforce the
+     * marshalling rules (ie, you can only unmarshal normal marshals once). Note
+     * that these counts do NOT include unmarshalled interfaces, once a stream is
+     * unmarshalled and a proxy set up, this count is decremented.
+     */
+
+    ULONG             norm_refs;  /* refcount of normal marshals (CS lock) */
 };
 
 /* imported interface proxy */
@@ -170,15 +178,16 @@
 
 ULONG stub_manager_int_addref(struct stub_manager *This);
 ULONG stub_manager_int_release(struct stub_manager *This);
-struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object, MSHLFLAGS mshlflags);
+struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object);
 ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs);
 ULONG stub_manager_ext_release(struct stub_manager *m, ULONG refs);
-struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, IUnknown *iptr, REFIID iid);
+struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, IUnknown *iptr, REFIID iid, MSHLFLAGS flags);
+struct ifstub *stub_manager_find_ifstub(struct stub_manager *m, REFIID iid, MSHLFLAGS flags);
 struct stub_manager *get_stub_manager(APARTMENT *apt, OID oid);
 struct stub_manager *get_stub_manager_from_object(APARTMENT *apt, void *object);
-BOOL stub_manager_notify_unmarshal(struct stub_manager *m);
-BOOL stub_manager_is_table_marshaled(struct stub_manager *m);
-void stub_manager_release_marshal_data(struct stub_manager *m, ULONG refs);
+BOOL stub_manager_notify_unmarshal(struct stub_manager *m, const IPID *ipid);
+BOOL stub_manager_is_table_marshaled(struct stub_manager *m, const IPID *ipid);
+void stub_manager_release_marshal_data(struct stub_manager *m, ULONG refs, const IPID *ipid);
 HRESULT ipid_to_stub_manager(const IPID *ipid, APARTMENT **stub_apt, struct stub_manager **stubmgr_ret);
 IRpcStubBuffer *ipid_to_apt_and_stubbuffer(const IPID *ipid, APARTMENT **stub_apt);
 HRESULT start_apartment_remote_unknown(void);