[OLE32] Sync with Wine Staging 1.7.55. CORE-10536
authorAmine Khaldi <amine.khaldi@reactos.org>
Tue, 17 Nov 2015 10:30:40 +0000 (10:30 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Tue, 17 Nov 2015 10:30:40 +0000 (10:30 +0000)
svn path=/trunk/; revision=69908

16 files changed:
reactos/dll/win32/ole32/compobj.c
reactos/dll/win32/ole32/compobj_private.h
reactos/dll/win32/ole32/datacache.c
reactos/dll/win32/ole32/defaulthandler.c
reactos/dll/win32/ole32/filemoniker.c
reactos/dll/win32/ole32/marshal.c
reactos/dll/win32/ole32/ole2.c
reactos/dll/win32/ole32/ole2impl.c
reactos/dll/win32/ole32/ole2stubs.c
reactos/dll/win32/ole32/ole32.spec
reactos/dll/win32/ole32/ole32_main.c
reactos/dll/win32/ole32/rpc.c
reactos/dll/win32/ole32/storage32.c
reactos/dll/win32/ole32/stubmanager.c
reactos/dll/win32/ole32/usrmarshal.c
reactos/media/doc/README.WINE

index 89a6a47..40ceb77 100644 (file)
@@ -1003,7 +1003,7 @@ static HRESULT get_local_server_stream(APARTMENT *apt, IStream **ret)
  * SEE ALSO
  *  CoRegisterClassObject
  */
-HRESULT WINAPI CoRevokeClassObject(
+HRESULT WINAPI DECLSPEC_HOTPATCH CoRevokeClassObject(
         DWORD dwRegister)
 {
   HRESULT hr = E_INVALIDARG;
@@ -1851,7 +1851,7 @@ HRESULT WINAPI CoInitialize(LPVOID lpReserved)
  * SEE ALSO
  *   CoUninitialize
  */
-HRESULT WINAPI CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit)
+HRESULT WINAPI DECLSPEC_HOTPATCH CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit)
 {
   struct oletls *info = COM_CurrentInfo();
   HRESULT hr = S_OK;
@@ -1997,6 +1997,7 @@ void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
  */
 HRESULT WINAPI CoDisconnectObject( LPUNKNOWN lpUnk, DWORD reserved )
 {
+    struct stub_manager *manager;
     HRESULT hr;
     IMarshal *marshal;
     APARTMENT *apt;
@@ -2017,7 +2018,13 @@ HRESULT WINAPI CoDisconnectObject( LPUNKNOWN lpUnk, DWORD reserved )
     if (!apt)
         return CO_E_NOTINITIALIZED;
 
-    apartment_disconnectobject(apt, lpUnk);
+    manager = get_stub_manager_from_object(apt, lpUnk, FALSE);
+    if (manager) {
+        stub_manager_disconnect(manager);
+        /* Release stub manager twice, to remove the apartment reference. */
+        stub_manager_int_release(manager);
+        stub_manager_int_release(manager);
+    }
 
     /* Note: native is pretty broken here because it just silently
      * fails, without returning an appropriate error code if the object was
@@ -3158,10 +3165,8 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(
     REFIID iid,
     LPVOID *ppv)
 {
+    MULTI_QI multi_qi = { iid };
     HRESULT hres;
-    LPCLASSFACTORY lpclf = 0;
-    APARTMENT *apt;
-    CLSID clsid;
 
     TRACE("(rclsid=%s, pUnkOuter=%p, dwClsContext=%08x, riid=%s, ppv=%p)\n", debugstr_guid(rclsid),
           pUnkOuter, dwClsContext, debugstr_guid(iid), ppv);
@@ -3169,65 +3174,8 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(
     if (ppv==0)
         return E_POINTER;
 
-    hres = CoGetTreatAsClass(rclsid, &clsid);
-    if(FAILED(hres))
-        clsid = *rclsid;
-
-    *ppv = 0;
-
-    if (!(apt = COM_CurrentApt()))
-    {
-        if (!(apt = apartment_find_multi_threaded()))
-        {
-            ERR("apartment not initialised\n");
-            return CO_E_NOTINITIALIZED;
-        }
-        apartment_release(apt);
-    }
-
-    /*
-     * The Standard Global Interface Table (GIT) object is a process-wide singleton.
-     */
-    if (IsEqualIID(&clsid, &CLSID_StdGlobalInterfaceTable))
-    {
-        IGlobalInterfaceTable *git = get_std_git();
-        hres = IGlobalInterfaceTable_QueryInterface(git, iid, ppv);
-        if (hres != S_OK) return hres;
-
-        TRACE("Retrieved GIT (%p)\n", *ppv);
-        return S_OK;
-    }
-
-    if (IsEqualCLSID(&clsid, &CLSID_ManualResetEvent))
-        return ManualResetEvent_Construct(pUnkOuter, iid, ppv);
-
-    /*
-     * Get a class factory to construct the object we want.
-     */
-    hres = CoGetClassObject(&clsid,
-                            dwClsContext,
-                            NULL,
-                            &IID_IClassFactory,
-                            (LPVOID)&lpclf);
-
-    if (FAILED(hres))
-        return hres;
-
-    /*
-     * Create the object and don't forget to release the factory
-     */
-    hres = IClassFactory_CreateInstance(lpclf, pUnkOuter, iid, ppv);
-    IClassFactory_Release(lpclf);
-    if (FAILED(hres))
-    {
-        if (hres == CLASS_E_NOAGGREGATION && pUnkOuter)
-            FIXME("Class %s does not support aggregation\n", debugstr_guid(&clsid));
-        else
-            FIXME("no instance created for interface %s of class %s, hres is 0x%08x\n",
-                  debugstr_guid(iid),
-                  debugstr_guid(&clsid),hres);
-    }
-
+    hres = CoCreateInstanceEx(rclsid, pUnkOuter, dwClsContext, NULL, 1, &multi_qi);
+    *ppv = multi_qi.pItf;
     return hres;
 }
 
@@ -3242,18 +3190,26 @@ static void init_multi_qi(DWORD count, MULTI_QI *mqi)
   }
 }
 
-static HRESULT return_multi_qi(IUnknown *unk, DWORD count, MULTI_QI *mqi)
+static HRESULT return_multi_qi(IUnknown *unk, DWORD count, MULTI_QI *mqi, BOOL include_unk)
 {
-  ULONG index, fetched = 0;
+  ULONG index = 0, fetched = 0;
 
-  for (index = 0; index < count; index++)
+  if (include_unk)
+  {
+    mqi[0].hr = S_OK;
+    mqi[0].pItf = unk;
+    index = fetched = 1;
+  }
+
+  for (; index < count; index++)
   {
     mqi[index].hr = IUnknown_QueryInterface(unk, mqi[index].pIID, (void**)&mqi[index].pItf);
     if (mqi[index].hr == S_OK)
       fetched++;
   }
 
-  IUnknown_Release(unk);
+  if (!include_unk)
+      IUnknown_Release(unk);
 
   if (fetched == 0)
     return E_NOINTERFACE;
@@ -3272,39 +3228,83 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstanceEx(
   ULONG         cmq,
   MULTI_QI*     pResults)
 {
-  IUnknown* pUnk = NULL;
-  HRESULT   hr;
+    IUnknown *unk = NULL;
+    IClassFactory *cf;
+    APARTMENT *apt;
+    CLSID clsid;
+    HRESULT hres;
 
-  /*
-   * Sanity check
-   */
-  if ( (cmq==0) || (pResults==NULL))
-    return E_INVALIDARG;
+    TRACE("(%s %p %x %p %u %p)\n", debugstr_guid(rclsid), pUnkOuter, dwClsContext, pServerInfo, cmq, pResults);
 
-  if (pServerInfo!=NULL)
-    FIXME("() non-NULL pServerInfo not supported!\n");
+    if (!cmq || !pResults)
+        return E_INVALIDARG;
 
-  init_multi_qi(cmq, pResults);
+    if (pServerInfo)
+        FIXME("() non-NULL pServerInfo not supported!\n");
 
-  /*
-   * Get the object and get its IUnknown pointer.
-   */
-  hr = CoCreateInstance(rclsid,
-                       pUnkOuter,
-                       dwClsContext,
-                       &IID_IUnknown,
-                       (VOID**)&pUnk);
+    init_multi_qi(cmq, pResults);
 
-  if (hr != S_OK)
-    return hr;
+    hres = CoGetTreatAsClass(rclsid, &clsid);
+    if(FAILED(hres))
+        clsid = *rclsid;
+
+    if (!(apt = COM_CurrentApt()))
+    {
+        if (!(apt = apartment_find_multi_threaded()))
+        {
+            ERR("apartment not initialised\n");
+            return CO_E_NOTINITIALIZED;
+        }
+        apartment_release(apt);
+    }
+
+    /*
+     * The Standard Global Interface Table (GIT) object is a process-wide singleton.
+     */
+    if (IsEqualIID(&clsid, &CLSID_StdGlobalInterfaceTable))
+    {
+        IGlobalInterfaceTable *git = get_std_git();
+        TRACE("Retrieving GIT\n");
+        return return_multi_qi((IUnknown*)git, cmq, pResults, FALSE);
+    }
+
+    if (IsEqualCLSID(&clsid, &CLSID_ManualResetEvent)) {
+        hres = ManualResetEvent_Construct(pUnkOuter, pResults[0].pIID, (void**)&unk);
+        if (FAILED(hres))
+            return hres;
+        return return_multi_qi(unk, cmq, pResults, TRUE);
+    }
+
+    /*
+     * Get a class factory to construct the object we want.
+     */
+    hres = CoGetClassObject(&clsid, dwClsContext, NULL, &IID_IClassFactory, (void**)&cf);
+    if (FAILED(hres))
+        return hres;
 
-  return return_multi_qi(pUnk, cmq, pResults);
+    /*
+     * Create the object and don't forget to release the factory
+     */
+    hres = IClassFactory_CreateInstance(cf, pUnkOuter, pResults[0].pIID, (void**)&unk);
+    IClassFactory_Release(cf);
+    if (FAILED(hres))
+    {
+        if (hres == CLASS_E_NOAGGREGATION && pUnkOuter)
+            FIXME("Class %s does not support aggregation\n", debugstr_guid(&clsid));
+        else
+            FIXME("no instance created for interface %s of class %s, hres is 0x%08x\n",
+                  debugstr_guid(pResults[0].pIID),
+                  debugstr_guid(&clsid),hres);
+        return hres;
+    }
+
+    return return_multi_qi(unk, cmq, pResults, TRUE);
 }
 
 /***********************************************************************
  *           CoGetInstanceFromFile [OLE32.@]
  */
-HRESULT WINAPI CoGetInstanceFromFile(
+HRESULT WINAPI DECLSPEC_HOTPATCH CoGetInstanceFromFile(
   COSERVERINFO *server_info,
   CLSID        *rclsid,
   IUnknown     *outer,
@@ -3361,7 +3361,7 @@ HRESULT WINAPI CoGetInstanceFromFile(
       IPersistFile_Release(pf);
   }
 
-  return return_multi_qi(unk, count, results);
+  return return_multi_qi(unk, count, results, FALSE);
 }
 
 /***********************************************************************
@@ -3424,7 +3424,7 @@ HRESULT WINAPI CoGetInstanceFromIStorage(
       IPersistStorage_Release(ps);
   }
 
-  return return_multi_qi(unk, count, results);
+  return return_multi_qi(unk, count, results, FALSE);
 }
 
 /***********************************************************************
@@ -3583,32 +3583,8 @@ HRESULT WINAPI CoLockObjectExternal(
     apt = COM_CurrentApt();
     if (!apt) return CO_E_NOTINITIALIZED;
 
-    stubmgr = get_stub_manager_from_object(apt, pUnk);
-    
-    if (stubmgr)
-    {
-        if (fLock)
-            stub_manager_ext_addref(stubmgr, 1, FALSE);
-        else
-            stub_manager_ext_release(stubmgr, 1, FALSE, fLastUnlockReleases);
-        
-        stub_manager_int_release(stubmgr);
-
-        return S_OK;
-    }
-    else if (fLock)
-    {
-        stubmgr = new_stub_manager(apt, pUnk);
-
-        if (stubmgr)
-        {
-            stub_manager_ext_addref(stubmgr, 1, FALSE);
-            stub_manager_int_release(stubmgr);
-        }
-
-        return S_OK;
-    }
-    else
+    stubmgr = get_stub_manager_from_object(apt, pUnk, fLock);
+    if (!stubmgr)
     {
         WARN("stub object not found %p\n", pUnk);
         /* Note: native is pretty broken here because it just silently
@@ -3616,6 +3592,14 @@ HRESULT WINAPI CoLockObjectExternal(
          * think that the object was disconnected, when it actually wasn't */
         return S_OK;
     }
+
+    if (fLock)
+        stub_manager_ext_addref(stubmgr, 1, FALSE);
+    else
+        stub_manager_ext_release(stubmgr, 1, FALSE, fLastUnlockReleases);
+
+    stub_manager_int_release(stubmgr);
+    return S_OK;
 }
 
 /***********************************************************************
@@ -4366,7 +4350,7 @@ HRESULT WINAPI CoRevertToSelf(void)
 static BOOL COM_PeekMessage(struct apartment *apt, MSG *msg)
 {
     /* first try to retrieve messages for incoming COM calls to the apartment window */
-    return PeekMessageW(msg, apt->win, 0, 0, PM_REMOVE|PM_NOYIELD) ||
+    return (apt->win && PeekMessageW(msg, apt->win, 0, 0, PM_REMOVE|PM_NOYIELD)) ||
            /* next retrieve other messages necessary for the app to remain responsive */
            PeekMessageW(msg, NULL, WM_DDE_FIRST, WM_DDE_LAST, PM_REMOVE|PM_NOYIELD) ||
            PeekMessageW(msg, NULL, 0, 0, PM_QS_PAINT|PM_QS_SENDMESSAGE|PM_REMOVE|PM_NOYIELD);
index 5dc8eb8..64f3cf6 100644 (file)
@@ -96,6 +96,7 @@ struct stub_manager
      */
 
     ULONG             norm_refs;  /* refcount of normal marshals (CS lock) */
+    BOOL              disconnected; /* CoDisconnectObject has been called (CS lock) */
 };
 
 /* imported interface proxy */
@@ -174,18 +175,19 @@ HRESULT FTMarshalCF_Create(REFIID riid, LPVOID *ppv) DECLSPEC_HIDDEN;
 /* Stub Manager */
 
 ULONG stub_manager_int_release(struct stub_manager *This) DECLSPEC_HIDDEN;
-struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object) DECLSPEC_HIDDEN;
 ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs, BOOL tableweak) DECLSPEC_HIDDEN;
 ULONG stub_manager_ext_release(struct stub_manager *m, ULONG refs, BOOL tableweak, BOOL last_unlock_releases) DECLSPEC_HIDDEN;
-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, REFIID iid,
      DWORD dest_context, void *dest_context_data, MSHLFLAGS flags) DECLSPEC_HIDDEN;
 struct ifstub *stub_manager_find_ifstub(struct stub_manager *m, REFIID iid, MSHLFLAGS flags) DECLSPEC_HIDDEN;
 struct stub_manager *get_stub_manager(APARTMENT *apt, OID oid) DECLSPEC_HIDDEN;
-struct stub_manager *get_stub_manager_from_object(APARTMENT *apt, void *object) DECLSPEC_HIDDEN;
+struct stub_manager *get_stub_manager_from_object(APARTMENT *apt, IUnknown *object, BOOL alloc) DECLSPEC_HIDDEN;
 BOOL stub_manager_notify_unmarshal(struct stub_manager *m, const IPID *ipid) DECLSPEC_HIDDEN;
 BOOL stub_manager_is_table_marshaled(struct stub_manager *m, const IPID *ipid) DECLSPEC_HIDDEN;
 void stub_manager_release_marshal_data(struct stub_manager *m, ULONG refs, const IPID *ipid, BOOL tableweak) DECLSPEC_HIDDEN;
-HRESULT ipid_get_dispatch_params(const IPID *ipid, APARTMENT **stub_apt, IRpcStubBuffer **stub, IRpcChannelBuffer **chan, IID *iid, IUnknown **iface) DECLSPEC_HIDDEN;
+void stub_manager_disconnect(struct stub_manager *m) DECLSPEC_HIDDEN;
+HRESULT ipid_get_dispatch_params(const IPID *ipid, APARTMENT **stub_apt, struct stub_manager **manager, IRpcStubBuffer **stub,
+                                 IRpcChannelBuffer **chan, IID *iid, IUnknown **iface) DECLSPEC_HIDDEN;
 HRESULT start_apartment_remote_unknown(void) DECLSPEC_HIDDEN;
 
 HRESULT marshal_object(APARTMENT *apt, STDOBJREF *stdobjref, REFIID riid, IUnknown *obj, DWORD dest_context, void *dest_context_data, MSHLFLAGS mshlflags) DECLSPEC_HIDDEN;
@@ -202,7 +204,7 @@ HRESULT RPC_CreateClientChannel(const OXID *oxid, const IPID *ipid,
 HRESULT RPC_CreateServerChannel(DWORD dest_context, void *dest_context_data, IRpcChannelBuffer **chan) DECLSPEC_HIDDEN;
 void    RPC_ExecuteCall(struct dispatch_params *params) DECLSPEC_HIDDEN;
 HRESULT RPC_RegisterInterface(REFIID riid) DECLSPEC_HIDDEN;
-void    RPC_UnregisterInterface(REFIID riid) DECLSPEC_HIDDEN;
+void    RPC_UnregisterInterface(REFIID riid, BOOL wait) DECLSPEC_HIDDEN;
 HRESULT RPC_StartLocalServer(REFCLSID clsid, IStream *stream, BOOL multi_use, void **registration) DECLSPEC_HIDDEN;
 void    RPC_StopLocalServer(void *registration) DECLSPEC_HIDDEN;
 HRESULT RPC_GetLocalClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv) DECLSPEC_HIDDEN;
@@ -225,7 +227,6 @@ APARTMENT *apartment_findfromoxid(OXID oxid, BOOL ref) DECLSPEC_HIDDEN;
 APARTMENT *apartment_findfromtid(DWORD tid) DECLSPEC_HIDDEN;
 DWORD apartment_release(struct apartment *apt) DECLSPEC_HIDDEN;
 HRESULT apartment_disconnectproxies(struct apartment *apt) DECLSPEC_HIDDEN;
-void apartment_disconnectobject(struct apartment *apt, void *object) DECLSPEC_HIDDEN;
 static inline HRESULT apartment_getoxid(const struct apartment *apt, OXID *oxid)
 {
     *oxid = apt->oxid;
@@ -306,6 +307,8 @@ extern LSTATUS open_classes_key(HKEY, const WCHAR *, REGSAM, HKEY *) DECLSPEC_HI
 
 extern BOOL actctx_get_miscstatus(const CLSID*, DWORD, DWORD*) DECLSPEC_HIDDEN;
 
+extern const char *debugstr_formatetc(const FORMATETC *formatetc) DECLSPEC_HIDDEN;
+
 static inline void *heap_alloc(size_t len)
 {
     return HeapAlloc(GetProcessHeap(), 0, len);
index 48b173f..2da1b6f 100644 (file)
@@ -202,7 +202,7 @@ static inline DataCache *impl_from_IAdviseSink( IAdviseSink *iface )
     return CONTAINING_RECORD(iface, DataCache, IAdviseSink_iface);
 }
 
-static const char * debugstr_formatetc(const FORMATETC *formatetc)
+const char *debugstr_formatetc(const FORMATETC *formatetc)
 {
     return wine_dbg_sprintf("{ cfFormat = 0x%x, ptd = %p, dwAspect = %d, lindex = %d, tymed = %d }",
         formatetc->cfFormat, formatetc->ptd, formatetc->dwAspect,
@@ -268,10 +268,10 @@ static DataCacheEntry *DataCache_GetEntryForFormatEtc(DataCache *This, const FOR
 /* checks that the clipformat and tymed are valid and returns an error if they
 * aren't and CACHE_S_NOTSUPPORTED if they are valid, but can't be rendered by
 * DataCache_Draw */
-static HRESULT check_valid_clipformat_and_tymed(CLIPFORMAT cfFormat, DWORD tymed)
+static HRESULT check_valid_clipformat_and_tymed(CLIPFORMAT cfFormat, DWORD tymed, BOOL load)
 {
     if (!cfFormat || !tymed ||
-        (cfFormat == CF_METAFILEPICT && tymed == TYMED_MFPICT) ||
+        (cfFormat == CF_METAFILEPICT && (tymed == TYMED_MFPICT || load)) ||
         (cfFormat == CF_BITMAP && tymed == TYMED_GDI) ||
         (cfFormat == CF_DIB && tymed == TYMED_HGLOBAL) ||
         (cfFormat == CF_ENHMETAFILE && tymed == TYMED_ENHMF))
@@ -285,11 +285,11 @@ static HRESULT check_valid_clipformat_and_tymed(CLIPFORMAT cfFormat, DWORD tymed
     }
 }
 
-static HRESULT DataCache_CreateEntry(DataCache *This, const FORMATETC *formatetc, DataCacheEntry **cache_entry)
+static HRESULT DataCache_CreateEntry(DataCache *This, const FORMATETC *formatetc, DataCacheEntry **cache_entry, BOOL load)
 {
     HRESULT hr;
 
-    hr = check_valid_clipformat_and_tymed(formatetc->cfFormat, formatetc->tymed);
+    hr = check_valid_clipformat_and_tymed(formatetc->cfFormat, formatetc->tymed, load);
     if (FAILED(hr))
         return hr;
     if (hr == CACHE_S_FORMATETC_NOTSUPPORTED)
@@ -394,7 +394,7 @@ static HRESULT read_clipformat(IStream *stream, CLIPFORMAT *clipformat)
     if (length == -1)
     {
         DWORD cf;
-        hr = IStream_Read(stream, &cf, sizeof(cf), 0);
+        hr = IStream_Read(stream, &cf, sizeof(cf), &read);
         if (hr != S_OK || read != sizeof(cf))
             return DV_E_CLIPFORMAT;
         *clipformat = cf;
@@ -1245,7 +1245,7 @@ static HRESULT add_cache_entry( DataCache *This, const FORMATETC *fmt, IStream *
 
     cache_entry = DataCache_GetEntryForFormatEtc( This, fmt );
     if (!cache_entry)
-        hr = DataCache_CreateEntry( This, fmt, &cache_entry );
+        hr = DataCache_CreateEntry( This, fmt, &cache_entry, TRUE );
     if (SUCCEEDED( hr ))
     {
         DataCacheEntry_DiscardData( cache_entry );
@@ -1319,7 +1319,10 @@ static HRESULT parse_contents_stream( DataCache *This, IStorage *stg, IStream *s
     if (IsEqualCLSID( &stat.clsid, &CLSID_Picture_Dib ))
         fmt = &static_dib_fmt;
     else
+    {
+        FIXME("unsupported format %s\n", debugstr_guid( &stat.clsid ));
         return E_FAIL;
+    }
 
     return add_cache_entry( This, fmt, stm, contents_stream );
 }
@@ -1351,7 +1354,8 @@ static HRESULT WINAPI DataCache_Load( IPersistStorage *iface, IStorage *pStg )
         hr = parse_contents_stream( This, pStg, stm );
         IStream_Release( stm );
     }
-    else
+
+    if (FAILED(hr))
         hr = parse_pres_streams( This, pStg );
 
     if (SUCCEEDED( hr ))
@@ -1989,7 +1993,7 @@ static HRESULT WINAPI DataCache_Cache(
         return CACHE_S_SAMECACHE;
     }
 
-    hr = DataCache_CreateEntry(This, pformatetc, &cache_entry);
+    hr = DataCache_CreateEntry(This, pformatetc, &cache_entry, FALSE);
 
     if (SUCCEEDED(hr))
     {
index e54bb25..4e5bb21 100644 (file)
@@ -61,7 +61,8 @@ enum storage_state
 enum object_state
 {
     object_state_not_running,
-    object_state_running
+    object_state_running,
+    object_state_deferred_close
 };
 
 /****************************************************************************
@@ -117,6 +118,7 @@ struct DefaultHandler
   /* IDataObject delegate */
   IDataObject *pDataDelegate;
   enum object_state object_state;
+  ULONG in_call;
 
   /* connection cookie for the advise on the delegate OLE object */
   DWORD dwAdvConn;
@@ -170,6 +172,20 @@ static inline BOOL object_is_running(DefaultHandler *This)
     return IRunnableObject_IsRunning(&This->IRunnableObject_iface);
 }
 
+static void DefaultHandler_Stop(DefaultHandler *This);
+
+static inline void start_object_call(DefaultHandler *This)
+{
+    This->in_call++;
+}
+
+static inline void end_object_call(DefaultHandler *This)
+{
+    This->in_call--;
+    if (This->in_call == 0 && This->object_state == object_state_deferred_close)
+        DefaultHandler_Stop( This );
+}
+
 /*********************************************************
  * Method implementation for the  non delegating IUnknown
  * part of the DefaultHandler class.
@@ -336,7 +352,11 @@ static HRESULT WINAPI DefaultHandler_SetClientSite(
   TRACE("(%p, %p)\n", iface, pClientSite);
 
   if (object_is_running(This))
+  {
+    start_object_call( This );
     hr = IOleObject_SetClientSite(This->pOleDelegate, pClientSite);
+    end_object_call( This );
+  }
 
   /*
    * Make sure we release the previous client site if there
@@ -399,7 +419,11 @@ static HRESULT WINAPI DefaultHandler_SetHostNames(
        debugstr_w(szContainerObj));
 
   if (object_is_running(This))
+  {
+    start_object_call( This );
     IOleObject_SetHostNames(This->pOleDelegate, szContainerApp, szContainerObj);
+    end_object_call( This );
+  }
 
   /* Be sure to cleanup before re-assigning the strings. */
   HeapFree( GetProcessHeap(), 0, This->containerApp );
@@ -445,17 +469,26 @@ static void release_delegates(DefaultHandler *This)
 /* undoes the work done by DefaultHandler_Run */
 static void DefaultHandler_Stop(DefaultHandler *This)
 {
-  if (!object_is_running(This))
+  IOleCacheControl *cache_ctrl;
+  HRESULT hr;
+
+  if (This->object_state == object_state_not_running)
     return;
 
-  IOleObject_Unadvise(This->pOleDelegate, This->dwAdvConn);
+  hr = IUnknown_QueryInterface( This->dataCache, &IID_IOleCacheControl, (void **)&cache_ctrl );
+  if (SUCCEEDED(hr))
+  {
+    hr = IOleCacheControl_OnStop( cache_ctrl );
+    IOleCacheControl_Release( cache_ctrl );
+  }
 
-  /* FIXME: call IOleCache_OnStop */
+  IOleObject_Unadvise(This->pOleDelegate, This->dwAdvConn);
 
   if (This->dataAdviseHolder)
     DataAdviseHolder_OnDisconnect(This->dataAdviseHolder);
 
   This->object_state = object_state_not_running;
+  release_delegates( This );
 }
 
 /************************************************************************
@@ -478,10 +511,11 @@ static HRESULT WINAPI DefaultHandler_Close(
   if (!object_is_running(This))
     return S_OK;
 
+  start_object_call( This );
   hr = IOleObject_Close(This->pOleDelegate, dwSaveOption);
+  end_object_call( This );
 
   DefaultHandler_Stop(This);
-  release_delegates(This);
 
   return hr;
 }
@@ -499,16 +533,18 @@ static HRESULT WINAPI DefaultHandler_SetMoniker(
            IMoniker*          pmk)
 {
   DefaultHandler *This = impl_from_IOleObject(iface);
+  HRESULT hr = S_OK;
 
-  TRACE("(%p, %d, %p)\n",
-       iface,
-       dwWhichMoniker,
-       pmk);
+  TRACE("(%p, %d, %p)\n", iface, dwWhichMoniker, pmk);
 
   if (object_is_running(This))
-    return IOleObject_SetMoniker(This->pOleDelegate, dwWhichMoniker, pmk);
+  {
+    start_object_call( This );
+    hr = IOleObject_SetMoniker(This->pOleDelegate, dwWhichMoniker, pmk);
+    end_object_call( This );
+  }
 
-  return S_OK;
+  return hr;
 }
 
 /************************************************************************
@@ -525,13 +561,19 @@ static HRESULT WINAPI DefaultHandler_GetMoniker(
            IMoniker**         ppmk)
 {
   DefaultHandler *This = impl_from_IOleObject(iface);
+  HRESULT hr;
 
   TRACE("(%p, %d, %d, %p)\n",
        iface, dwAssign, dwWhichMoniker, ppmk);
 
   if (object_is_running(This))
-    return IOleObject_GetMoniker(This->pOleDelegate, dwAssign, dwWhichMoniker,
-                                 ppmk);
+  {
+    start_object_call( This );
+    hr = IOleObject_GetMoniker(This->pOleDelegate, dwAssign, dwWhichMoniker,
+                               ppmk);
+    end_object_call( This );
+    return hr;
+  }
 
   /* FIXME: dwWhichMoniker == OLEWHICHMK_CONTAINER only? */
   if (This->clientSite)
@@ -560,14 +602,20 @@ static HRESULT WINAPI DefaultHandler_InitFromData(
            DWORD              dwReserved)
 {
   DefaultHandler *This = impl_from_IOleObject(iface);
+  HRESULT hr = OLE_E_NOTRUNNING;
 
   TRACE("(%p, %p, %d, %d)\n",
        iface, pDataObject, fCreation, dwReserved);
 
   if (object_is_running(This))
-    return IOleObject_InitFromData(This->pOleDelegate, pDataObject, fCreation,
+  {
+    start_object_call( This );
+    hr = IOleObject_InitFromData(This->pOleDelegate, pDataObject, fCreation,
                                   dwReserved);
-  return OLE_E_NOTRUNNING;
+    end_object_call( This );
+  }
+
+  return hr;
 }
 
 /************************************************************************
@@ -583,15 +631,20 @@ static HRESULT WINAPI DefaultHandler_GetClipboardData(
            IDataObject**      ppDataObject)
 {
   DefaultHandler *This = impl_from_IOleObject(iface);
+  HRESULT hr = OLE_E_NOTRUNNING;
 
   TRACE("(%p, %d, %p)\n",
        iface, dwReserved, ppDataObject);
 
   if (object_is_running(This))
-    return IOleObject_GetClipboardData(This->pOleDelegate, dwReserved,
+  {
+    start_object_call( This );
+    hr = IOleObject_GetClipboardData(This->pOleDelegate, dwReserved,
                                        ppDataObject);
+    end_object_call( This );
+  }
 
-  return OLE_E_NOTRUNNING;
+  return hr;
 }
 
 static HRESULT WINAPI DefaultHandler_DoVerb(
@@ -612,8 +665,12 @@ static HRESULT WINAPI DefaultHandler_DoVerb(
   hr = IRunnableObject_Run(pRunnableObj, NULL);
   if (FAILED(hr)) return hr;
 
-  return IOleObject_DoVerb(This->pOleDelegate, iVerb, lpmsg, pActiveSite,
+  start_object_call( This );
+  hr = IOleObject_DoVerb(This->pOleDelegate, iVerb, lpmsg, pActiveSite,
                            lindex, hwndParent, lprcPosRect);
+  end_object_call( This );
+
+  return hr;
 }
 
 /************************************************************************
@@ -634,7 +691,11 @@ static HRESULT WINAPI DefaultHandler_EnumVerbs(
   TRACE("(%p, %p)\n", iface, ppEnumOleVerb);
 
   if (object_is_running(This))
+  {
+    start_object_call( This );
     hr = IOleObject_EnumVerbs(This->pOleDelegate, ppEnumOleVerb);
+    end_object_call( This );
+  }
 
   if (hr == OLE_S_USEREG)
     return OleRegEnumVerbs(&This->clsid, ppEnumOleVerb);
@@ -646,6 +707,8 @@ static HRESULT WINAPI DefaultHandler_Update(
            IOleObject*        iface)
 {
     DefaultHandler *This = impl_from_IOleObject(iface);
+    HRESULT hr;
+
     TRACE("(%p)\n", iface);
 
     if (!object_is_running(This))
@@ -653,7 +716,12 @@ static HRESULT WINAPI DefaultHandler_Update(
         FIXME("Should run object\n");
         return E_NOTIMPL;
     }
-    return IOleObject_Update(This->pOleDelegate);
+
+    start_object_call( This );
+    hr = IOleObject_Update(This->pOleDelegate);
+    end_object_call( This );
+
+    return hr;
 }
 
 /************************************************************************
@@ -667,12 +735,17 @@ static HRESULT WINAPI DefaultHandler_IsUpToDate(
            IOleObject*        iface)
 {
     DefaultHandler *This = impl_from_IOleObject(iface);
+    HRESULT hr = OLE_E_NOTRUNNING;
     TRACE("(%p)\n", iface);
 
     if (object_is_running(This))
-        return IOleObject_IsUpToDate(This->pOleDelegate);
+    {
+        start_object_call( This );
+        hr = IOleObject_IsUpToDate(This->pOleDelegate);
+        end_object_call( This );
+    }
 
-    return OLE_E_NOTRUNNING;
+    return hr;
 }
 
 /************************************************************************
@@ -687,11 +760,17 @@ static HRESULT WINAPI DefaultHandler_GetUserClassID(
            CLSID*             pClsid)
 {
   DefaultHandler *This = impl_from_IOleObject(iface);
+  HRESULT hr;
 
   TRACE("(%p, %p)\n", iface, pClsid);
 
   if (object_is_running(This))
-    return IOleObject_GetUserClassID(This->pOleDelegate, pClsid);
+  {
+    start_object_call( This );
+    hr = IOleObject_GetUserClassID(This->pOleDelegate, pClsid);
+    end_object_call( This );
+    return hr;
+  }
 
   if (!pClsid)
     return E_POINTER;
@@ -715,10 +794,16 @@ static HRESULT WINAPI DefaultHandler_GetUserType(
            LPOLESTR*          pszUserType)
 {
   DefaultHandler *This = impl_from_IOleObject(iface);
+  HRESULT hr;
 
   TRACE("(%p, %d, %p)\n", iface, dwFormOfType, pszUserType);
   if (object_is_running(This))
-    return IOleObject_GetUserType(This->pOleDelegate, dwFormOfType, pszUserType);
+  {
+    start_object_call( This );
+    hr = IOleObject_GetUserType(This->pOleDelegate, dwFormOfType, pszUserType);
+    end_object_call( This );
+    return hr;
+  }
 
   return OleRegGetUserType(&This->clsid, dwFormOfType, pszUserType);
 }
@@ -736,14 +821,19 @@ static HRESULT WINAPI DefaultHandler_SetExtent(
            SIZEL*             psizel)
 {
   DefaultHandler *This = impl_from_IOleObject(iface);
+  HRESULT hr = OLE_E_NOTRUNNING;
 
   TRACE("(%p, %x, (%d x %d))\n", iface,
         dwDrawAspect, psizel->cx, psizel->cy);
 
   if (object_is_running(This))
-    return IOleObject_SetExtent(This->pOleDelegate, dwDrawAspect, psizel);
+  {
+    start_object_call( This );
+    hr = IOleObject_SetExtent(This->pOleDelegate, dwDrawAspect, psizel);
+    end_object_call( This );
+  }
 
-  return OLE_E_NOTRUNNING;
+  return hr;
 }
 
 /************************************************************************
@@ -768,7 +858,12 @@ static HRESULT WINAPI DefaultHandler_GetExtent(
   TRACE("(%p, %x, %p)\n", iface, dwDrawAspect, psizel);
 
   if (object_is_running(This))
-    return IOleObject_GetExtent(This->pOleDelegate, dwDrawAspect, psizel);
+  {
+    start_object_call( This );
+    hres = IOleObject_GetExtent(This->pOleDelegate, dwDrawAspect, psizel);
+    end_object_call( This );
+    return hres;
+  }
 
   hres = IUnknown_QueryInterface(This->dataCache, &IID_IViewObject2, (void**)&cacheView);
   if (FAILED(hres))
@@ -898,7 +993,12 @@ static HRESULT WINAPI DefaultHandler_GetMiscStatus(
   TRACE("(%p, %x, %p)\n", iface, dwAspect, pdwStatus);
 
   if (object_is_running(This))
-    return IOleObject_GetMiscStatus(This->pOleDelegate, dwAspect, pdwStatus);
+  {
+    start_object_call( This );
+    hres = IOleObject_GetMiscStatus(This->pOleDelegate, dwAspect, pdwStatus);
+    end_object_call( This );
+    return hres;
+  }
 
   hres = OleRegGetMiscStatus(&This->clsid, dwAspect, pdwStatus);
 
@@ -920,13 +1020,18 @@ static HRESULT WINAPI DefaultHandler_SetColorScheme(
            struct tagLOGPALETTE* pLogpal)
 {
   DefaultHandler *This = impl_from_IOleObject(iface);
+  HRESULT hr = OLE_E_NOTRUNNING;
 
   TRACE("(%p, %p))\n", iface, pLogpal);
 
   if (object_is_running(This))
-    return IOleObject_SetColorScheme(This->pOleDelegate, pLogpal);
+  {
+    start_object_call( This );
+    hr = IOleObject_SetColorScheme(This->pOleDelegate, pLogpal);
+    end_object_call( This );
+  }
 
-  return OLE_E_NOTRUNNING;
+  return hr;
 }
 
 /*********************************************************
@@ -1007,8 +1112,19 @@ static HRESULT WINAPI DefaultHandler_GetData(
 
   IDataObject_Release(cacheDataObject);
 
-  if (FAILED(hres) && This->pDataDelegate)
+  if (hres == S_OK) return hres;
+
+  if (object_is_running( This ))
+  {
+    start_object_call(This);
     hres = IDataObject_GetData(This->pDataDelegate, pformatetcIn, pmedium);
+    end_object_call(This);
+    if (hres == S_OK) return hres;
+  }
+
+  /* Query running state again, as the object may have closed during _GetData call */
+  if (!object_is_running( This ))
+    hres = OLE_E_NOTRUNNING;
 
   return hres;
 }
@@ -1053,8 +1169,19 @@ static HRESULT WINAPI DefaultHandler_QueryGetData(
 
   IDataObject_Release(cacheDataObject);
 
-  if (FAILED(hres) && This->pDataDelegate)
+  if (hres == S_OK) return hres;
+
+  if (object_is_running( This ))
+  {
+    start_object_call( This );
     hres = IDataObject_QueryGetData(This->pDataDelegate, pformatetc);
+    end_object_call( This );
+    if (hres == S_OK) return hres;
+  }
+
+  /* Query running state again, as the object may have closed during _QueryGetData call */
+  if (!object_is_running( This ))
+    hres = OLE_E_NOTRUNNING;
 
   return hres;
 }
@@ -1072,13 +1199,18 @@ static HRESULT WINAPI DefaultHandler_GetCanonicalFormatEtc(
            LPFORMATETC      pformatetcOut)
 {
   DefaultHandler *This = impl_from_IDataObject(iface);
+  HRESULT hr;
 
   TRACE("(%p, %p, %p)\n", iface, pformatetcIn, pformatetcOut);
 
-  if (!This->pDataDelegate)
+  if (!object_is_running( This ))
     return OLE_E_NOTRUNNING;
 
-  return IDataObject_GetCanonicalFormatEtc(This->pDataDelegate, pformatetcIn, pformatetcOut);
+  start_object_call( This );
+  hr = IDataObject_GetCanonicalFormatEtc(This->pDataDelegate, pformatetcIn, pformatetcOut);
+  end_object_call( This );
+
+  return hr;
 }
 
 /************************************************************************
@@ -1163,8 +1295,12 @@ static HRESULT WINAPI DefaultHandler_DAdvise(
   if (!This->dataAdviseHolder)
   {
     hres = CreateDataAdviseHolder(&This->dataAdviseHolder);
-    if (SUCCEEDED(hres) && This->pDataDelegate)
+    if (SUCCEEDED(hres) && object_is_running( This ))
+    {
+      start_object_call( This );
       DataAdviseHolder_OnConnect(This->dataAdviseHolder, This->pDataDelegate);
+      end_object_call( This );
+    }
   }
 
   if (SUCCEEDED(hres))
@@ -1299,6 +1435,7 @@ static HRESULT WINAPI DefaultHandler_Run(
 {
   DefaultHandler *This = impl_from_IRunnableObject(iface);
   HRESULT hr;
+  IOleCacheControl *cache_ctrl;
 
   FIXME("(%p): semi-stub\n", pbc);
 
@@ -1313,49 +1450,59 @@ static HRESULT WINAPI DefaultHandler_Run(
   if (FAILED(hr))
     return hr;
 
-  This->object_state = object_state_running;
-
   hr = IOleObject_Advise(This->pOleDelegate, &This->IAdviseSink_iface, &This->dwAdvConn);
+  if (FAILED(hr)) goto fail;
 
-  if (SUCCEEDED(hr) && This->clientSite)
-    hr = IOleObject_SetClientSite(This->pOleDelegate, This->clientSite);
-
-  if (SUCCEEDED(hr))
+  if (This->clientSite)
   {
-    IOleObject_QueryInterface(This->pOleDelegate, &IID_IPersistStorage,
-                              (void **)&This->pPSDelegate);
-    if (This->pPSDelegate)
-    {
-      if(This->storage_state == storage_state_initialised)
-        hr = IPersistStorage_InitNew(This->pPSDelegate, This->storage);
-      else if(This->storage_state == storage_state_loaded)
-        hr = IPersistStorage_Load(This->pPSDelegate, This->storage);
-    }
+    hr = IOleObject_SetClientSite(This->pOleDelegate, This->clientSite);
+    if (FAILED(hr)) goto fail;
   }
 
-  if (SUCCEEDED(hr) && This->containerApp)
+  hr = IOleObject_QueryInterface(This->pOleDelegate, &IID_IPersistStorage,
+                                 (void **)&This->pPSDelegate);
+  if (FAILED(hr)) goto fail;
+
+  if (This->storage_state == storage_state_initialised)
+      hr = IPersistStorage_InitNew(This->pPSDelegate, This->storage);
+  else if (This->storage_state == storage_state_loaded)
+      hr = IPersistStorage_Load(This->pPSDelegate, This->storage);
+  if (FAILED(hr)) goto fail;
+
+  if (This->containerApp)
+  {
     hr = IOleObject_SetHostNames(This->pOleDelegate, This->containerApp,
                                  This->containerObj);
+    if (FAILED(hr)) goto fail;
+  }
 
   /* FIXME: do more stuff here:
    * - IOleObject_GetMiscStatus
    * - IOleObject_GetMoniker
-   * - IOleCache_OnRun
    */
 
-  if (SUCCEEDED(hr))
-    hr = IOleObject_QueryInterface(This->pOleDelegate, &IID_IDataObject,
-                                   (void **)&This->pDataDelegate);
+  hr = IOleObject_QueryInterface(This->pOleDelegate, &IID_IDataObject,
+                                 (void **)&This->pDataDelegate);
+  if (FAILED(hr)) goto fail;
 
-  if (SUCCEEDED(hr) && This->dataAdviseHolder)
-    hr = DataAdviseHolder_OnConnect(This->dataAdviseHolder, This->pDataDelegate);
+  This->object_state = object_state_running;
 
-  if (FAILED(hr))
+  if (This->dataAdviseHolder)
   {
-    DefaultHandler_Stop(This);
-    release_delegates(This);
+    hr = DataAdviseHolder_OnConnect(This->dataAdviseHolder, This->pDataDelegate);
+    if (FAILED(hr)) goto fail;
   }
 
+  hr = IUnknown_QueryInterface( This->dataCache, &IID_IOleCacheControl, (void **)&cache_ctrl );
+  if (FAILED(hr)) goto fail;
+  hr = IOleCacheControl_OnRun( cache_ctrl, This->pDataDelegate );
+  IOleCacheControl_Release( cache_ctrl );
+  if (FAILED(hr)) goto fail;
+
+  return hr;
+
+fail:
+  DefaultHandler_Stop(This);
   return hr;
 }
 
@@ -1485,10 +1632,15 @@ static void WINAPI DefaultHandler_IAdviseSink_OnClose(
     if (This->oleAdviseHolder)
         IOleAdviseHolder_SendOnClose(This->oleAdviseHolder);
 
-    DefaultHandler_Stop(This);
+    if(!This->in_call)
+        DefaultHandler_Stop(This);
+    else
+    {
+        TRACE("OnClose during call.  Deferring shutdown\n");
+        This->object_state = object_state_deferred_close;
+    }
 }
 
-
 /************************************************************************
  * DefaultHandler_IPersistStorage_QueryInterface
  *
@@ -1541,7 +1693,11 @@ static HRESULT WINAPI DefaultHandler_IPersistStorage_GetClassID(
     TRACE("(%p)->(%p)\n", iface, clsid);
 
     if(object_is_running(This))
+    {
+        start_object_call( This );
         hr = IPersistStorage_GetClassID(This->pPSDelegate, clsid);
+        end_object_call( This );
+    }
     else
         hr = IPersistStorage_GetClassID(This->dataCache_PersistStg, clsid);
 
@@ -1564,7 +1720,11 @@ static HRESULT WINAPI DefaultHandler_IPersistStorage_IsDirty(
     if(hr != S_FALSE) return hr;
 
     if(object_is_running(This))
+    {
+        start_object_call( This );
         hr = IPersistStorage_IsDirty(This->pPSDelegate);
+        end_object_call( This );
+    }
 
     return hr;
 }
@@ -1648,7 +1808,11 @@ static HRESULT WINAPI DefaultHandler_IPersistStorage_InitNew(
     hr = IPersistStorage_InitNew(This->dataCache_PersistStg, pStg);
 
     if(SUCCEEDED(hr) && object_is_running(This))
+    {
+        start_object_call( This );
         hr = IPersistStorage_InitNew(This->pPSDelegate, pStg);
+        end_object_call( This );
+    }
 
     if(SUCCEEDED(hr))
     {
@@ -1680,7 +1844,11 @@ static HRESULT WINAPI DefaultHandler_IPersistStorage_Load(
         hr = IPersistStorage_Load(This->dataCache_PersistStg, pStg);
 
     if(SUCCEEDED(hr) && object_is_running(This))
+    {
+        start_object_call( This );
         hr = IPersistStorage_Load(This->pPSDelegate, pStg);
+        end_object_call( This );
+    }
 
     if(SUCCEEDED(hr))
     {
@@ -1708,7 +1876,11 @@ static HRESULT WINAPI DefaultHandler_IPersistStorage_Save(
 
     hr = IPersistStorage_Save(This->dataCache_PersistStg, pStgSave, fSameAsLoad);
     if(SUCCEEDED(hr) && object_is_running(This))
+    {
+        start_object_call( This );
         hr = IPersistStorage_Save(This->pPSDelegate, pStgSave, fSameAsLoad);
+        end_object_call( This );
+    }
 
     return hr;
 }
@@ -1730,7 +1902,11 @@ static HRESULT WINAPI DefaultHandler_IPersistStorage_SaveCompleted(
     hr = IPersistStorage_SaveCompleted(This->dataCache_PersistStg, pStgNew);
 
     if(SUCCEEDED(hr) && object_is_running(This))
+    {
+        start_object_call( This );
         hr = IPersistStorage_SaveCompleted(This->pPSDelegate, pStgNew);
+        end_object_call( This );
+    }
 
     if(pStgNew)
     {
@@ -1759,7 +1935,11 @@ static HRESULT WINAPI DefaultHandler_IPersistStorage_HandsOffStorage(
     hr = IPersistStorage_HandsOffStorage(This->dataCache_PersistStg);
 
     if(SUCCEEDED(hr) && object_is_running(This))
+    {
+        start_object_call( This );
         hr = IPersistStorage_HandsOffStorage(This->pPSDelegate);
+        end_object_call( This );
+    }
 
     if(This->storage) IStorage_Release(This->storage);
     This->storage = NULL;
@@ -1940,6 +2120,7 @@ static DefaultHandler* DefaultHandler_Construct(
   This->pPSDelegate = NULL;
   This->pDataDelegate = NULL;
   This->object_state = object_state_not_running;
+  This->in_call = 0;
 
   This->dwAdvConn = 0;
   This->storage = NULL;
@@ -1984,7 +2165,6 @@ static void DefaultHandler_Destroy(
 
   /* release delegates */
   DefaultHandler_Stop(This);
-  release_delegates(This);
 
   HeapFree( GetProcessHeap(), 0, This->containerApp );
   This->containerApp = NULL;
index 757df82..aa77662 100644 (file)
@@ -484,12 +484,12 @@ FileMonikerImpl_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft
             /* if the requested class was loaded before ! we don't need to reload it */
             res = IRunningObjectTable_GetObject(prot,iface,&pObj);
 
-            if (res==S_FALSE){
+            if (res != S_OK){
                 /* first activation of this class */
                 res=GetClassFile(This->filePathName,&clsID);
                 if (SUCCEEDED(res)){
 
-                    res=CoCreateInstance(&clsID,NULL,CLSCTX_ALL,&IID_IPersistFile,(void**)&ppf);
+                    res=CoCreateInstance(&clsID,NULL,CLSCTX_SERVER,&IID_IPersistFile,(void**)&ppf);
                     if (SUCCEEDED(res)){
 
                         res=IPersistFile_Load(ppf,This->filePathName,STGM_READ);
index 3de95d7..fee74ef 100644 (file)
@@ -106,9 +106,7 @@ HRESULT marshal_object(APARTMENT *apt, STDOBJREF *stdobjref, REFIID riid, IUnkno
     struct stub_manager *manager;
     struct ifstub       *ifstub;
     BOOL                 tablemarshal;
-    IRpcStubBuffer      *stub = NULL;
     HRESULT              hr;
-    IUnknown            *iobject = NULL; /* object of type riid */
 
     hr = apartment_getoxid(apt, &stdobjref->oxid);
     if (hr != S_OK)
@@ -118,78 +116,57 @@ HRESULT marshal_object(APARTMENT *apt, STDOBJREF *stdobjref, REFIID riid, IUnkno
     if (hr != S_OK)
         return hr;
 
-    hr = IUnknown_QueryInterface(object, riid, (void **)&iobject);
-    if (hr != S_OK)
-    {
-        ERR("object doesn't expose interface %s, failing with error 0x%08x\n",
-            debugstr_guid(riid), hr);
-        return E_NOINTERFACE;
-    }
-  
-    /* IUnknown doesn't require a stub buffer, because it never goes out on
-     * the wire */
-    if (!IsEqualIID(riid, &IID_IUnknown))
-    {
-        IPSFactoryBuffer *psfb;
-
-        hr = get_facbuf_for_iid(riid, &psfb);
-        if (hr != S_OK)
-        {
-            ERR("couldn't get IPSFactory buffer for interface %s\n", debugstr_guid(riid));
-            IUnknown_Release(iobject);
-            return hr;
-        }
-    
-        hr = IPSFactoryBuffer_CreateStub(psfb, riid, iobject, &stub);
-        IPSFactoryBuffer_Release(psfb);
-        if (hr != S_OK)
-        {
-            ERR("Failed to create an IRpcStubBuffer from IPSFactory for %s with error 0x%08x\n",
-                debugstr_guid(riid), hr);
-            IUnknown_Release(iobject);
-            return hr;
-        }
-    }
+    if (!(manager = get_stub_manager_from_object(apt, object, TRUE)))
+        return E_OUTOFMEMORY;
 
     stdobjref->flags = SORF_NULL;
     if (mshlflags & MSHLFLAGS_TABLEWEAK)
         stdobjref->flags |= SORFP_TABLEWEAK;
     if (mshlflags & MSHLFLAGS_NOPING)
         stdobjref->flags |= SORF_NOPING;
-
-    if ((manager = get_stub_manager_from_object(apt, object)))
-        TRACE("registering new ifstub on pre-existing manager\n");
-    else
-    {
-        TRACE("constructing new stub manager\n");
-
-        manager = new_stub_manager(apt, object);
-        if (!manager)
-        {
-            if (stub) IRpcStubBuffer_Release(stub);
-            IUnknown_Release(iobject);
-            return E_OUTOFMEMORY;
-        }
-    }
     stdobjref->oid = manager->oid;
 
     tablemarshal = ((mshlflags & MSHLFLAGS_TABLESTRONG) || (mshlflags & MSHLFLAGS_TABLEWEAK));
 
     /* make sure ifstub that we are creating is unique */
     ifstub = stub_manager_find_ifstub(manager, riid, mshlflags);
-    if (!ifstub)
-        ifstub = stub_manager_new_ifstub(manager, stub, iobject, riid, dest_context, dest_context_data, mshlflags);
+    if (!ifstub) {
+        IRpcStubBuffer *stub = NULL;
 
-    if (stub) IRpcStubBuffer_Release(stub);
-    IUnknown_Release(iobject);
+        /* IUnknown doesn't require a stub buffer, because it never goes out on
+         * the wire */
+        if (!IsEqualIID(riid, &IID_IUnknown))
+        {
+            IPSFactoryBuffer *psfb;
+
+            hr = get_facbuf_for_iid(riid, &psfb);
+            if (hr == S_OK) {
+                hr = IPSFactoryBuffer_CreateStub(psfb, riid, manager->object, &stub);
+                IPSFactoryBuffer_Release(psfb);
+                if (hr != S_OK)
+                    ERR("Failed to create an IRpcStubBuffer from IPSFactory for %s with error 0x%08x\n",
+                        debugstr_guid(riid), hr);
+            }else {
+                ERR("couldn't get IPSFactory buffer for interface %s\n", debugstr_guid(riid));
+                hr = E_NOINTERFACE;
+            }
 
-    if (!ifstub)
-    {
-        stub_manager_int_release(manager);
-        /* destroy the stub manager if it has no ifstubs by releasing
-         * zero external references */
-        stub_manager_ext_release(manager, 0, FALSE, TRUE);
-        return E_OUTOFMEMORY;
+        }
+
+        if (hr == S_OK) {
+            ifstub = stub_manager_new_ifstub(manager, stub, riid, dest_context, dest_context_data, mshlflags);
+            if (!ifstub)
+                hr = E_OUTOFMEMORY;
+        }
+        if (stub) IRpcStubBuffer_Release(stub);
+
+        if (hr != S_OK) {
+            stub_manager_int_release(manager);
+            /* destroy the stub manager if it has no ifstubs by releasing
+             * zero external references */
+            stub_manager_ext_release(manager, 0, FALSE, TRUE);
+            return hr;
+        }
     }
 
     if (!tablemarshal)
@@ -1717,7 +1694,7 @@ HRESULT WINAPI CoMarshalInterface(IStream *pStream, REFIID riid, IUnknown *pUnk,
     OBJREF objref;
     LPMARSHAL pMarshal;
 
-    TRACE("(%p, %s, %p, %x, %p,", pStream, debugstr_guid(riid), pUnk,
+    TRACE("(%p, %s, %p, %x, %p, ", pStream, debugstr_guid(riid), pUnk,
         dwDestContext, pvDestContext);
     dump_MSHLFLAGS(mshlFlags);
     TRACE(")\n");
index 354d4bd..0c843fe 100644 (file)
@@ -146,7 +146,7 @@ DWORD WINAPI OleBuildVersion(void)
 /***********************************************************************
  *           OleInitialize       (OLE32.@)
  */
-HRESULT WINAPI OleInitialize(LPVOID reserved)
+HRESULT WINAPI DECLSPEC_HOTPATCH OleInitialize(LPVOID reserved)
 {
   HRESULT hr;
 
@@ -1210,7 +1210,7 @@ HRESULT WINAPI OleSetContainedObject(
  *  Success: S_OK.
  *  Failure: Any HRESULT code.
  */
-HRESULT WINAPI OleRun(LPUNKNOWN pUnknown)
+HRESULT WINAPI DECLSPEC_HOTPATCH OleRun(LPUNKNOWN pUnknown)
 {
     IRunnableObject *runable;
     HRESULT hres;
@@ -3016,7 +3016,7 @@ HRESULT WINAPI PropVariantCopy(PROPVARIANT *pvarDest,      /* [out] */
 
     hr = PROPVARIANT_ValidateType(pvarSrc->vt);
     if (FAILED(hr))
-        return hr;
+        return DISP_E_BADVARTYPE;
 
     /* this will deal with most cases */
     *pvarDest = *pvarSrc;
index 12d3c01..10b7d5b 100644 (file)
@@ -84,7 +84,7 @@ static inline void init_fmtetc(FORMATETC *fmt, CLIPFORMAT cf, TYMED tymed)
  *
  * FIXME: CF_FILENAME.
  */
-static HRESULT get_storage(IDataObject *data, IStorage *stg, UINT *src_cf)
+static HRESULT get_storage(IDataObject *data, IStorage *stg, UINT *src_cf, BOOL other_fmts)
 {
     static const UINT fmt_id[] = { CF_METAFILEPICT, CF_BITMAP, CF_DIB };
     UINT i;
@@ -94,16 +94,17 @@ static HRESULT get_storage(IDataObject *data, IStorage *stg, UINT *src_cf)
     IPersistStorage *persist;
     CLSID clsid;
 
-    *src_cf = 0;
+    if (src_cf) *src_cf = 0;
 
     /* CF_EMBEDEDOBJECT */
     init_fmtetc(&fmt, embedded_object_clipboard_format, TYMED_ISTORAGE);
     med.tymed = TYMED_ISTORAGE;
     med.u.pstg = stg;
+    med.pUnkForRelease = NULL;
     hr = IDataObject_GetDataHere(data, &fmt, &med);
     if(SUCCEEDED(hr))
     {
-        *src_cf = embedded_object_clipboard_format;
+        if (src_cf) *src_cf = embedded_object_clipboard_format;
         return hr;
     }
 
@@ -111,21 +112,25 @@ static HRESULT get_storage(IDataObject *data, IStorage *stg, UINT *src_cf)
     init_fmtetc(&fmt, embed_source_clipboard_format, TYMED_ISTORAGE);
     med.tymed = TYMED_ISTORAGE;
     med.u.pstg = stg;
+    med.pUnkForRelease = NULL;
     hr = IDataObject_GetDataHere(data, &fmt, &med);
     if(SUCCEEDED(hr))
     {
-        *src_cf = embed_source_clipboard_format;
+        if (src_cf) *src_cf = embed_source_clipboard_format;
         return hr;
     }
 
-    for (i = 0; i < sizeof(fmt_id)/sizeof(fmt_id[0]); i++)
+    if (other_fmts)
     {
-        init_fmtetc(&fmt, fmt_id[i], TYMED_ISTORAGE);
-        hr = IDataObject_QueryGetData(data, &fmt);
-        if(SUCCEEDED(hr))
+        for (i = 0; i < sizeof(fmt_id)/sizeof(fmt_id[0]); i++)
         {
-            *src_cf = fmt_id[i];
-            return hr;
+            init_fmtetc(&fmt, fmt_id[i], TYMED_ISTORAGE);
+            hr = IDataObject_QueryGetData(data, &fmt);
+            if (SUCCEEDED(hr))
+            {
+                if (src_cf) *src_cf = fmt_id[i];
+                return hr;
+            }
         }
     }
 
@@ -168,7 +173,7 @@ HRESULT WINAPI OleCreateFromDataEx(IDataObject *data, REFIID iid, DWORD flags,
           data, debugstr_guid(iid), flags, renderopt, num_cache_fmts, adv_flags, cache_fmts,
           sink, conns, client_site, stg, obj);
 
-    hr = get_storage(data, stg, &src_cf);
+    hr = get_storage(data, stg, &src_cf, TRUE);
     if(FAILED(hr)) return hr;
 
     hr = OleLoad(stg, iid, client_site, obj);
@@ -219,6 +224,84 @@ HRESULT WINAPI OleCreateStaticFromData(IDataObject *data, REFIID iid,
     return OleCreateFromData(data, iid, renderopt, fmt, client_site, stg, obj);
 }
 
+/******************************************************************************
+ *              OleCreateFromFileEx        [OLE32.@]
+ */
+HRESULT WINAPI OleCreateFromFileEx(REFCLSID clsid, const OLECHAR *filename, REFIID iid, DWORD flags,
+                                   DWORD renderopt, ULONG num_fmts, DWORD *adv_flags, FORMATETC *fmts, IAdviseSink *sink,
+                                   DWORD *conns, IOleClientSite *client_site, IStorage *stg, void **obj)
+{
+    HRESULT hr;
+    IMoniker *mon;
+    IDataObject *data;
+    IUnknown *unk = NULL;
+    IOleCache *cache = NULL;
+    ULONG i;
+
+    TRACE("cls %s, %s, iid %s, flags %d, render opts %d, num fmts %d, adv flags %p, fmts %p\n", debugstr_guid(clsid),
+          debugstr_w(filename), debugstr_guid(iid), flags, renderopt, num_fmts, adv_flags, fmts);
+    TRACE("sink %p, conns %p, client site %p, storage %p, obj %p\n", sink, conns, client_site, stg, obj);
+    for (i = 0; i < num_fmts; i++)
+        TRACE("\t%d: fmt %s adv flags %d\n", i, debugstr_formatetc(fmts + i), adv_flags[i]);
+
+    hr = CreateFileMoniker( filename, &mon );
+    if (FAILED(hr)) return hr;
+
+    hr = BindMoniker( mon, 0, &IID_IDataObject, (void**)&data );
+    IMoniker_Release( mon );
+    if (FAILED(hr)) return hr;
+
+    hr = get_storage( data, stg, NULL, FALSE );
+    if (FAILED(hr)) goto end;
+
+    hr = OleLoad( stg, &IID_IUnknown, client_site, (void**)&unk );
+    if (FAILED(hr)) goto end;
+
+    if (renderopt == OLERENDER_FORMAT)
+    {
+        hr = IUnknown_QueryInterface( unk, &IID_IOleCache, (void**)&cache );
+        if (FAILED(hr)) goto end;
+
+        for (i = 0; i < num_fmts; i++)
+        {
+            STGMEDIUM med;
+            DWORD dummy_conn;
+
+            memset( &med, 0, sizeof(med) );
+            hr = IDataObject_GetData( data, fmts + i, &med );
+            if (FAILED(hr)) goto end;
+            hr = IOleCache_Cache( cache, fmts + i, adv_flags[i], &dummy_conn );
+            if (SUCCEEDED(hr))
+                hr = IOleCache_SetData( cache, fmts + i, &med, TRUE );
+            if (FAILED(hr))
+            {
+                ReleaseStgMedium( &med );
+                goto end;
+            }
+        }
+    }
+
+    hr = IUnknown_QueryInterface( unk, iid, obj );
+
+end:
+    if (cache) IOleCache_Release( cache );
+    if (unk) IUnknown_Release( unk );
+    IDataObject_Release( data );
+    return hr;
+}
+
+/******************************************************************************
+ *              OleCreateFromFile        [OLE32.@]
+ */
+HRESULT WINAPI OleCreateFromFile(REFCLSID clsid, const OLECHAR *filename, REFIID iid, DWORD renderopt,
+                                 FORMATETC *fmt, IOleClientSite *client_site, IStorage *storage, void **obj)
+{
+    DWORD advf = ADVF_PRIMEFIRST;
+
+    return OleCreateFromFileEx(clsid, filename, iid, 0, renderopt, fmt ? 1 : 0, fmt ? &advf : NULL, fmt,
+                               NULL, NULL, client_site, storage, obj);
+}
+
 /******************************************************************************
  *              OleDuplicateData        [OLE32.@]
  *
index 47b5f7e..2d5cbed 100644 (file)
@@ -44,17 +44,6 @@ HRESULT WINAPI OleCreateLink(LPMONIKER pmkLinkSrc, REFIID riid, DWORD renderopt,
   return E_NOTIMPL;
 }
 
-/******************************************************************************
- *              OleCreateFromFile        [OLE32.@]
- */
-HRESULT WINAPI OleCreateFromFile(REFCLSID rclsid, LPCOLESTR lpszFileName, REFIID riid,
-            DWORD renderopt, LPFORMATETC lpFormatEtc, LPOLECLIENTSITE pClientSite, LPSTORAGE pStg, LPVOID* ppvObj)
-{
-  FIXME("(not shown), stub!\n");
-  return E_NOTIMPL;
-}
-
-
 /******************************************************************************
  *              OleGetIconOfClass        [OLE32.@]
  */
@@ -67,7 +56,7 @@ HGLOBAL WINAPI OleGetIconOfClass(REFCLSID rclsid, LPOLESTR lpszLabel, BOOL fUseT
 /***********************************************************************
  *           OleRegEnumFormatEtc    [OLE32.@]
  */
-HRESULT     WINAPI OleRegEnumFormatEtc (
+HRESULT WINAPI DECLSPEC_HOTPATCH OleRegEnumFormatEtc (
   REFCLSID clsid,
   DWORD    dwDirection,
   LPENUMFORMATETC* ppenumFormatetc)
index 9dc51fb..baa2209 100644 (file)
 @ stub OleCreateEx
 @ stdcall OleCreateFromData(ptr ptr long ptr ptr ptr ptr)
 @ stdcall OleCreateFromDataEx(ptr ptr long long long ptr ptr ptr ptr ptr ptr ptr)
-@ stdcall OleCreateFromFile(ptr ptr ptr long ptr ptr ptr ptr)
-@ stub OleCreateFromFileEx
+@ stdcall OleCreateFromFile(ptr wstr ptr long ptr ptr ptr ptr)
+@ stdcall OleCreateFromFileEx(ptr wstr ptr long long long ptr ptr ptr ptr ptr ptr ptr)
 @ stdcall OleCreateLink(ptr ptr long ptr ptr ptr ptr)
 @ stub OleCreateLinkEx
 @ stdcall OleCreateLinkFromData(ptr ptr long ptr ptr ptr ptr)
index edfceac..cf21eef 100644 (file)
@@ -147,3 +147,21 @@ HGLOBAL WINAPI OleMetafilePictFromIconAndLabel(HICON hIcon, LPOLESTR lpszLabel,
 
        return hmem;
 }
+
+/***********************************************************************
+ *      CoGetActivationState (ole32.@)
+ */
+HRESULT WINAPI CoGetActivationState(GUID guid, DWORD unknown, DWORD *unknown2)
+{
+    FIXME("%s, %x, %p\n", debugstr_guid(&guid), unknown, unknown2);
+    return E_NOTIMPL;
+}
+
+/***********************************************************************
+ *      CoGetCallState (ole32.@)
+ */
+HRESULT WINAPI CoGetCallState(int unknown, PULONG unknown2)
+{
+    FIXME("%d, %p\n", unknown, unknown2);
+    return E_NOTIMPL;
+}
index 45ee59e..750955b 100644 (file)
@@ -661,7 +661,7 @@ static HRESULT WINAPI ClientRpcChannelBuffer_GetBuffer(LPRPCCHANNELBUFFER iface,
     }
 
     RpcBindingInqObject(message_state->binding_handle, &ipid);
-    hr = ipid_get_dispatch_params(&ipid, &apt, &message_state->params.stub,
+    hr = ipid_get_dispatch_params(&ipid, &apt, NULL, &message_state->params.stub,
                                   &message_state->params.chan,
                                   &message_state->params.iid,
                                   &message_state->params.iface);
@@ -1420,6 +1420,7 @@ exit:
 static void __RPC_STUB dispatch_rpc(RPC_MESSAGE *msg)
 {
     struct dispatch_params *params;
+    struct stub_manager *stub_manager;
     APARTMENT *apt;
     IPID ipid;
     HRESULT hr;
@@ -1435,7 +1436,7 @@ static void __RPC_STUB dispatch_rpc(RPC_MESSAGE *msg)
         return;
     }
 
-    hr = ipid_get_dispatch_params(&ipid, &apt, &params->stub, &params->chan,
+    hr = ipid_get_dispatch_params(&ipid, &apt, &stub_manager, &params->stub, &params->chan,
                                   &params->iid, &params->iface);
     if (hr != S_OK)
     {
@@ -1493,6 +1494,7 @@ static void __RPC_STUB dispatch_rpc(RPC_MESSAGE *msg)
         IRpcStubBuffer_Release(params->stub);
     HeapFree(GetProcessHeap(), 0, params);
 
+    stub_manager_int_release(stub_manager);
     apartment_release(apt);
 
     /* if IRpcStubBuffer_Invoke fails, we should raise an exception to tell
@@ -1558,7 +1560,7 @@ HRESULT RPC_RegisterInterface(REFIID riid)
 }
 
 /* stub unregistration */
-void RPC_UnregisterInterface(REFIID riid)
+void RPC_UnregisterInterface(REFIID riid, BOOL wait)
 {
     struct registered_if *rif;
     EnterCriticalSection(&csRegIf);
@@ -1568,7 +1570,7 @@ void RPC_UnregisterInterface(REFIID riid)
         {
             if (!--rif->refs)
             {
-                RpcServerUnregisterIf((RPC_IF_HANDLE)&rif->If, NULL, TRUE);
+                RpcServerUnregisterIf((RPC_IF_HANDLE)&rif->If, NULL, wait);
                 list_remove(&rif->entry);
                 HeapFree(GetProcessHeap(), 0, rif);
             }
index 9b2f0cd..a151f70 100644 (file)
@@ -858,7 +858,7 @@ static HRESULT removeFromTree(
  * IEnumSTATSTGImpl definitions.
  *
  * Definition of the implementation structure for the IEnumSTATSTGImpl interface.
- * This class allows iterating through the content of a storage and to find
+ * This class allows iterating through the content of a storage and finding
  * specific items inside it.
  */
 struct IEnumSTATSTGImpl
@@ -890,6 +890,8 @@ static HRESULT WINAPI IEnumSTATSTGImpl_QueryInterface(
 {
   IEnumSTATSTGImpl* const This = impl_from_IEnumSTATSTG(iface);
 
+  TRACE("%p,%s,%p\n", iface, debugstr_guid(riid), ppvObject);
+
   if (ppvObject==0)
     return E_INVALIDARG;
 
@@ -900,9 +902,11 @@ static HRESULT WINAPI IEnumSTATSTGImpl_QueryInterface(
   {
     *ppvObject = &This->IEnumSTATSTG_iface;
     IEnumSTATSTG_AddRef(&This->IEnumSTATSTG_iface);
+    TRACE("<-- %p\n", *ppvObject);
     return S_OK;
   }
 
+  TRACE("<-- E_NOINTERFACE\n");
   return E_NOINTERFACE;
 }
 
@@ -940,6 +944,8 @@ static HRESULT IEnumSTATSTGImpl_GetNextRef(
   HRESULT hr;
   WCHAR result_name[DIRENTRY_NAME_MAX_LEN];
 
+  TRACE("%p,%p\n", This, ref);
+
   hr = StorageBaseImpl_ReadDirEntry(This->parentStorage,
     This->parentStorage->storageDirEntry, &entry);
   searchNode = entry.dirRootEntry;
@@ -972,6 +978,7 @@ static HRESULT IEnumSTATSTGImpl_GetNextRef(
       memcpy(This->name, result_name, sizeof(result_name));
   }
 
+  TRACE("<-- %08x\n", hr);
   return hr;
 }
 
@@ -989,11 +996,16 @@ static HRESULT WINAPI IEnumSTATSTGImpl_Next(
   DirRef      currentSearchNode;
   HRESULT     hr=S_OK;
 
+  TRACE("%p,%u,%p,%p\n", iface, celt, rgelt, pceltFetched);
+
   if ( (rgelt==0) || ( (celt!=1) && (pceltFetched==0) ) )
     return E_INVALIDARG;
 
   if (This->parentStorage->reverted)
+  {
+    TRACE("<-- STG_E_REVERTED\n");
     return STG_E_REVERTED;
+  }
 
   /*
    * To avoid the special case, get another pointer to a ULONG value if
@@ -1013,14 +1025,18 @@ static HRESULT WINAPI IEnumSTATSTGImpl_Next(
     hr = IEnumSTATSTGImpl_GetNextRef(This, &currentSearchNode);
 
     if (FAILED(hr) || currentSearchNode == DIRENTRY_NULL)
+    {
+      memset(currentReturnStruct, 0, sizeof(*currentReturnStruct));
       break;
+    }
 
     /*
      * Read the entry from the storage.
      */
-    StorageBaseImpl_ReadDirEntry(This->parentStorage,
+    hr = StorageBaseImpl_ReadDirEntry(This->parentStorage,
       currentSearchNode,
       &currentEntry);
+    if (FAILED(hr)) break;
 
     /*
      * Copy the information to the return buffer.
@@ -1040,6 +1056,7 @@ static HRESULT WINAPI IEnumSTATSTGImpl_Next(
   if (SUCCEEDED(hr) && *pceltFetched != celt)
     hr = S_FALSE;
 
+  TRACE("<-- %08x (asked %u, got %u)\n", hr, celt, *pceltFetched);
   return hr;
 }
 
@@ -1054,8 +1071,13 @@ static HRESULT WINAPI IEnumSTATSTGImpl_Skip(
   DirRef      currentSearchNode;
   HRESULT     hr=S_OK;
 
+  TRACE("%p,%u\n", iface, celt);
+
   if (This->parentStorage->reverted)
+  {
+    TRACE("<-- STG_E_REVERTED\n");
     return STG_E_REVERTED;
+  }
 
   while ( (objectFetched < celt) )
   {
@@ -1070,6 +1092,7 @@ static HRESULT WINAPI IEnumSTATSTGImpl_Skip(
   if (SUCCEEDED(hr) && objectFetched != celt)
     return S_FALSE;
 
+  TRACE("<-- %08x\n", hr);
   return hr;
 }
 
@@ -1078,8 +1101,13 @@ static HRESULT WINAPI IEnumSTATSTGImpl_Reset(
 {
   IEnumSTATSTGImpl* const This = impl_from_IEnumSTATSTG(iface);
 
+  TRACE("%p\n", iface);
+
   if (This->parentStorage->reverted)
+  {
+    TRACE("<-- STG_E_REVERTED\n");
     return STG_E_REVERTED;
+  }
 
   This->name[0] = 0;
 
@@ -1095,8 +1123,13 @@ static HRESULT WINAPI IEnumSTATSTGImpl_Clone(
   IEnumSTATSTGImpl* const This = impl_from_IEnumSTATSTG(iface);
   IEnumSTATSTGImpl* newClone;
 
+  TRACE("%p,%p\n", iface, ppenum);
+
   if (This->parentStorage->reverted)
+  {
+    TRACE("<-- STG_E_REVERTED\n");
     return STG_E_REVERTED;
+  }
 
   if (ppenum==0)
     return E_INVALIDARG;
@@ -1186,6 +1219,8 @@ static HRESULT WINAPI StorageBaseImpl_QueryInterface(
 {
   StorageBaseImpl *This = impl_from_IStorage(iface);
 
+  TRACE("%p,%s,%p\n", iface, debugstr_guid(riid), ppvObject);
+
   if (!ppvObject)
     return E_INVALIDARG;
 
@@ -1206,10 +1241,13 @@ static HRESULT WINAPI StorageBaseImpl_QueryInterface(
     *ppvObject = &This->IDirectWriterLock_iface;
   }
   else
+  {
+    TRACE("<-- E_NOINTERFACE\n");
     return E_NOINTERFACE;
+  }
 
   IStorage_AddRef(iface);
-
+  TRACE("<-- %p\n", *ppvObject);
   return S_OK;
 }
 
@@ -1392,6 +1430,7 @@ static HRESULT StorageBaseImpl_CopyChildEntryTo(StorageBaseImpl *This,
     hr = StorageBaseImpl_CopyChildEntryTo( This, data.rightChild, skip_storage,
                                            skip_stream, snbExclude, pstgDest );
 
+  TRACE("<-- %08x\n", hr);
   return hr;
 }
 
@@ -1399,6 +1438,8 @@ static BOOL StorageBaseImpl_IsStreamOpen(StorageBaseImpl * stg, DirRef streamEnt
 {
   StgStreamImpl *strm;
 
+  TRACE("%p,%d\n", stg, streamEntry);
+
   LIST_FOR_EACH_ENTRY(strm, &stg->strmHead, StgStreamImpl, StrmListEntry)
   {
     if (strm->dirEntry == streamEntry)
@@ -1414,6 +1455,8 @@ static BOOL StorageBaseImpl_IsStorageOpen(StorageBaseImpl * stg, DirRef storageE
 {
   StorageInternalImpl *childstg;
 
+  TRACE("%p,%d\n", stg, storageEntry);
+
   LIST_FOR_EACH_ENTRY(childstg, &stg->storageHead, StorageInternalImpl, ParentListEntry)
   {
     if (childstg->base.storageDirEntry == storageEntry)
@@ -2218,6 +2261,7 @@ static HRESULT StorageBaseImpl_CopyStorageEntryTo(StorageBaseImpl *This,
     hr = StorageBaseImpl_CopyChildEntryTo( This, data.dirRootEntry, skip_storage,
       skip_stream, snbExclude, pstgDest );
 
+  TRACE("<-- %08x\n", hr);
   return hr;
 }
 
@@ -2374,6 +2418,8 @@ static HRESULT deleteStorageContents(
   HRESULT      destroyHr = S_OK;
   StorageInternalImpl *stg, *stg2;
 
+  TRACE("%p,%d\n", parentStorage, indexToDelete);
+
   /* Invalidate any open storage objects. */
   LIST_FOR_EACH_ENTRY_SAFE(stg, stg2, &parentStorage->storageHead, StorageInternalImpl, ParentListEntry)
   {
@@ -2397,6 +2443,7 @@ static HRESULT deleteStorageContents(
 
   if (hr != S_OK)
   {
+    TRACE("<-- %08x\n", hr);
     return hr;
   }
 
@@ -2407,6 +2454,7 @@ static HRESULT deleteStorageContents(
   if (FAILED(hr))
   {
     IStorage_Release(childStorage);
+    TRACE("<-- %08x\n", hr);
     return hr;
   }
 
@@ -2434,6 +2482,7 @@ static HRESULT deleteStorageContents(
   IStorage_Release(childStorage);
   IEnumSTATSTG_Release(elements);
 
+  TRACE("%08x\n", hr);
   return destroyHr;
 }
 
@@ -2473,6 +2522,7 @@ static HRESULT deleteStreamContents(
 
   if (hr!=S_OK)
   {
+    TRACE("<-- %08x\n", hr);
     return(hr);
   }
 
@@ -2483,6 +2533,7 @@ static HRESULT deleteStreamContents(
 
   if(hr != S_OK)
   {
+    TRACE("<-- %08x\n", hr);
     return hr;
   }
 
@@ -2490,7 +2541,7 @@ static HRESULT deleteStreamContents(
    * Release the stream object.
    */
   IStream_Release(pis);
-
+  TRACE("<-- %08x\n", hr);
   return S_OK;
 }
 
@@ -2500,7 +2551,7 @@ static HRESULT deleteStreamContents(
  * Strategy: This implementation is built this way for simplicity not for speed.
  *          I always delete the topmost element of the enumeration and adjust
  *          the deleted element pointer all the time.  This takes longer to
- *          do but allow to reinvoke DestroyElement whenever we encounter a
+ *          do but allows reinvoking DestroyElement whenever we encounter a
  *          storage object.  The optimisation resides in the usage of another
  *          enumeration strategy that would give all the leaves of a storage
  *          first. (postfix order)
@@ -2536,6 +2587,7 @@ static HRESULT WINAPI StorageBaseImpl_DestroyElement(
 
   if ( entryToDeleteRef == DIRENTRY_NULL )
   {
+    TRACE("<-- STG_E_FILENOTFOUND\n");
     return STG_E_FILENOTFOUND;
   }
 
@@ -2555,7 +2607,10 @@ static HRESULT WINAPI StorageBaseImpl_DestroyElement(
   }
 
   if (hr!=S_OK)
+  {
+    TRACE("<-- %08x\n", hr);
     return hr;
+  }
 
   /*
    * Remove the entry from its parent storage
@@ -2574,6 +2629,7 @@ static HRESULT WINAPI StorageBaseImpl_DestroyElement(
   if (SUCCEEDED(hr))
     hr = StorageBaseImpl_Flush(This);
 
+  TRACE("<-- %08x\n", hr);
   return hr;
 }
 
@@ -3428,10 +3484,18 @@ static HRESULT StorageImpl_ReadDirEntry(
       OFFSET_PS_SIZE,
       &buffer->size.u.LowPart);
 
-    StorageUtl_ReadDWord(
-      currentEntry,
-      OFFSET_PS_SIZE_HIGH,
-      &buffer->size.u.HighPart);
+    if (This->bigBlockSize < 4096)
+    {
+      /* Version 3 files may have junk in the high part of size. */
+      buffer->size.u.HighPart = 0;
+    }
+    else
+    {
+      StorageUtl_ReadDWord(
+        currentEntry,
+        OFFSET_PS_SIZE_HIGH,
+        &buffer->size.u.HighPart);
+    }
   }
 
   return readRes;
@@ -6004,6 +6068,7 @@ end:
     StorageBaseImpl_UnlockTransaction(This->transactedParent, TRUE);
   }
 
+  TRACE("<-- %08x\n", hr);
   return hr;
 }
 
@@ -6110,7 +6175,11 @@ static HRESULT TransactedSnapshotImpl_WriteDirEntry(StorageBaseImpl *base,
   TRACE("%x %s l=%x r=%x d=%x\n", index, debugstr_w(data->name), data->leftChild, data->rightChild, data->dirRootEntry);
 
   hr = TransactedSnapshotImpl_EnsureReadEntry(This, index);
-  if (FAILED(hr)) return hr;
+  if (FAILED(hr))
+  {
+    TRACE("<-- %08x\n", hr);
+    return hr;
+  }
 
   memcpy(&This->entries[index].data, data, sizeof(DirEntry));
 
@@ -6132,7 +6201,7 @@ static HRESULT TransactedSnapshotImpl_WriteDirEntry(StorageBaseImpl *base,
       This->entries[index].transactedParentEntry = This->entries[index].newTransactedParentEntry = DIRENTRY_NULL;
     }
   }
-
+  TRACE("<-- S_OK\n");
   return S_OK;
 }
 
@@ -6143,7 +6212,11 @@ static HRESULT TransactedSnapshotImpl_ReadDirEntry(StorageBaseImpl *base,
   HRESULT hr;
 
   hr = TransactedSnapshotImpl_EnsureReadEntry(This, index);
-  if (FAILED(hr)) return hr;
+  if (FAILED(hr))
+  {
+    TRACE("<-- %08x\n", hr);
+    return hr;
+  }
 
   memcpy(data, &This->entries[index].data, sizeof(DirEntry));
 
@@ -6205,10 +6278,18 @@ static HRESULT TransactedSnapshotImpl_StreamWriteAt(StorageBaseImpl *base,
   HRESULT hr;
 
   hr = TransactedSnapshotImpl_EnsureReadEntry(This, index);
-  if (FAILED(hr)) return hr;
+  if (FAILED(hr))
+  {
+    TRACE("<-- %08x\n", hr);
+    return hr;
+  }
 
   hr = TransactedSnapshotImpl_MakeStreamDirty(This, index);
-  if (FAILED(hr)) return hr;
+  if (FAILED(hr))
+  {
+    TRACE("<-- %08x\n", hr);
+    return hr;
+  }
 
   hr = StorageBaseImpl_StreamWriteAt(This->scratch,
     This->entries[index].stream_entry, offset, size, buffer, bytesWritten);
@@ -6218,6 +6299,7 @@ static HRESULT TransactedSnapshotImpl_StreamWriteAt(StorageBaseImpl *base,
         This->entries[index].data.size.QuadPart,
         offset.QuadPart + size);
 
+  TRACE("<-- %08x\n", hr);
   return hr;
 }
 
@@ -6228,7 +6310,11 @@ static HRESULT TransactedSnapshotImpl_StreamSetSize(StorageBaseImpl *base,
   HRESULT hr;
 
   hr = TransactedSnapshotImpl_EnsureReadEntry(This, index);
-  if (FAILED(hr)) return hr;
+  if (FAILED(hr))
+  {
+    TRACE("<-- %08x\n", hr);
+    return hr;
+  }
 
   if (This->entries[index].data.size.QuadPart == newsize.QuadPart)
     return S_OK;
@@ -6269,6 +6355,7 @@ static HRESULT TransactedSnapshotImpl_StreamSetSize(StorageBaseImpl *base,
   if (SUCCEEDED(hr))
     This->entries[index].data.size = newsize;
 
+  TRACE("<-- %08x\n", hr);
   return hr;
 }
 
@@ -6280,10 +6367,18 @@ static HRESULT TransactedSnapshotImpl_StreamLink(StorageBaseImpl *base,
   TransactedDirEntry *dst_entry, *src_entry;
 
   hr = TransactedSnapshotImpl_EnsureReadEntry(This, src);
-  if (FAILED(hr)) return hr;
+  if (FAILED(hr))
+  {
+    TRACE("<-- %08x\n", hr);
+    return hr;
+  }
 
   hr = TransactedSnapshotImpl_EnsureReadEntry(This, dst);
-  if (FAILED(hr)) return hr;
+  if (FAILED(hr))
+  {
+    TRACE("<-- %08x\n", hr);
+    return hr;
+  }
 
   dst_entry = &This->entries[dst];
   src_entry = &This->entries[src];
@@ -6638,7 +6733,7 @@ static HRESULT WINAPI TransactedSharedImpl_Commit(
       This->lastTransactionSig = transactionSig+1;
     }
   }
-
+  TRACE("<-- %08x\n", hr);
   return hr;
 }
 
@@ -9165,7 +9260,10 @@ static HRESULT STREAM_ReadString( IStream *stm, LPWSTR *string )
     count = 0;
     r = IStream_Read( stm, str, len, &count );
     if( FAILED( r ) )
+    {
+        CoTaskMemFree( str );
         return r;
+    }
     if( count != len )
     {
         CoTaskMemFree( str );
index 9d96899..07d5d65 100644 (file)
@@ -25,6 +25,8 @@
 
 #include "precomp.h"
 
+#include <wine/exception.h>
+
 WINE_DEFAULT_DEBUG_CHANNEL(ole);
 
 /* generates an ipid in the following format (similar to native version):
@@ -51,21 +53,28 @@ static inline HRESULT generate_ipid(struct stub_manager *m, IPID *ipid)
 }
 
 /* registers a new interface stub COM object with the stub manager and returns registration record */
-struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, IUnknown *iptr, REFIID iid, DWORD dest_context,
+struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, REFIID iid, DWORD dest_context,
     void *dest_context_data, MSHLFLAGS flags)
 {
     struct ifstub *stub;
     HRESULT hr;
 
-    TRACE("oid=%s, stubbuffer=%p, iptr=%p, iid=%s\n",
-          wine_dbgstr_longlong(m->oid), sb, iptr, debugstr_guid(iid));
+    TRACE("oid=%s, stubbuffer=%p, iid=%s\n", wine_dbgstr_longlong(m->oid), sb, debugstr_guid(iid));
 
     stub = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct ifstub));
     if (!stub) return NULL;
 
+    hr = IUnknown_QueryInterface(m->object, iid, (void **)&stub->iface);
+    if (hr != S_OK)
+    {
+        HeapFree(GetProcessHeap(), 0, stub);
+        return NULL;
+    }
+
     hr = RPC_CreateServerChannel(dest_context, dest_context_data, &stub->chan);
     if (hr != S_OK)
     {
+        IUnknown_Release(stub->iface);
         HeapFree(GetProcessHeap(), 0, stub);
         return NULL;
     }
@@ -73,8 +82,6 @@ struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *s
     stub->stubbuffer = sb;
     if (sb) IRpcStubBuffer_AddRef(sb);
 
-    IUnknown_AddRef(iptr);
-    stub->iface = iptr;
     stub->flags = flags;
     stub->iid = *iid;
 
@@ -102,7 +109,8 @@ static void stub_manager_delete_ifstub(struct stub_manager *m, struct ifstub *if
 
     list_remove(&ifstub->entry);
 
-    RPC_UnregisterInterface(&ifstub->iid);
+    if (!m->disconnected)
+        RPC_UnregisterInterface(&ifstub->iid, TRUE);
 
     if (ifstub->stubbuffer) IRpcStubBuffer_Release(ifstub->stubbuffer);
     IUnknown_Release(ifstub->iface);
@@ -154,7 +162,7 @@ struct ifstub *stub_manager_find_ifstub(struct stub_manager *m, REFIID iid, MSHL
 /* creates a new stub manager and adds it into the apartment. caller must
  * release stub manager when it is no longer required. the apartment and
  * external refs together take one implicit ref */
-struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object)
+static struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object)
 {
     struct stub_manager *sm;
     HRESULT hres;
@@ -202,6 +210,7 @@ struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object)
      * the marshalled ifptr.
      */
     sm->extrefs = 0;
+    sm->disconnected = FALSE;
 
     hres = IUnknown_QueryInterface(object, &IID_IExternalConnection, (void**)&sm->extern_conn);
     if(FAILED(hres))
@@ -217,6 +226,21 @@ struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object)
     return sm;
 }
 
+void stub_manager_disconnect(struct stub_manager *m)
+{
+    struct ifstub *ifstub;
+
+    EnterCriticalSection(&m->lock);
+    if (!m->disconnected)
+    {
+        LIST_FOR_EACH_ENTRY(ifstub, &m->ifstubs, struct ifstub, entry)
+            RPC_UnregisterInterface(&ifstub->iid, FALSE);
+
+        m->disconnected = TRUE;
+    }
+    LeaveCriticalSection(&m->lock);
+}
+
 /* caller must remove stub manager from apartment prior to calling this function */
 static void stub_manager_delete(struct stub_manager *m)
 {
@@ -235,7 +259,18 @@ static void stub_manager_delete(struct stub_manager *m)
         IExternalConnection_Release(m->extern_conn);
 
     CoTaskMemFree(m->oxid_info.psa);
-    IUnknown_Release(m->object);
+
+    /* Some broken apps crash in object destructors. We have a test showing
+     * that on winxp+ those crashes are caught and ignored. */
+    __TRY
+    {
+        IUnknown_Release(m->object);
+    }
+    __EXCEPT_PAGE_FAULT
+    {
+        ERR("Got page fault when releasing stub!\n");
+    }
+    __ENDTRY
 
     DEBUG_CLEAR_CRITSEC_NAME(&m->lock);
     DeleteCriticalSection(&m->lock);
@@ -284,10 +319,18 @@ ULONG stub_manager_int_release(struct stub_manager *This)
 /* gets the stub manager associated with an object - caller must have
  * a reference to the apartment while a reference to the stub manager is held.
  * it must also call release on the stub manager when it is no longer needed */
-struct stub_manager *get_stub_manager_from_object(APARTMENT *apt, void *object)
+struct stub_manager *get_stub_manager_from_object(APARTMENT *apt, IUnknown *obj, BOOL alloc)
 {
     struct stub_manager *result = NULL;
     struct list         *cursor;
+    IUnknown *object;
+    HRESULT hres;
+
+    hres = IUnknown_QueryInterface(obj, &IID_IUnknown, (void**)&object);
+    if (FAILED(hres)) {
+        ERR("QueryInterface(IID_IUnknown failed): %08x\n", hres);
+        return NULL;
+    }
 
     EnterCriticalSection(&apt->cs);
     LIST_FOR_EACH( cursor, &apt->stubmgrs )
@@ -303,37 +346,17 @@ struct stub_manager *get_stub_manager_from_object(APARTMENT *apt, void *object)
     }
     LeaveCriticalSection(&apt->cs);
 
-    if (result)
+    if (result) {
         TRACE("found %p for object %p\n", result, object);
-    else
+    }else if (alloc) {
+        TRACE("not found, creating new stub manager...\n");
+        result = new_stub_manager(apt, object);
+    }else {
         TRACE("not found for object %p\n", object);
-
-    return result;    
-}
-
-/* removes the apartment reference to an object, destroying it when no other
- * threads have a reference to it */
-void apartment_disconnectobject(struct apartment *apt, void *object)
-{
-    BOOL found = FALSE;
-    struct stub_manager *stubmgr;
-
-    EnterCriticalSection(&apt->cs);
-    LIST_FOR_EACH_ENTRY( stubmgr, &apt->stubmgrs, struct stub_manager, entry )
-    {
-        if (stubmgr->object == object)
-        {
-            found = TRUE;
-            stub_manager_int_release(stubmgr);
-            break;
-        }
     }
-    LeaveCriticalSection(&apt->cs);
 
-    if (found)
-        TRACE("disconnect object %p\n", object);
-    else
-        WARN("couldn't find object %p\n", object);
+    IUnknown_Release(object);
+    return result;    
 }
 
 /* gets the stub manager associated with an object id - caller must have
@@ -486,6 +509,7 @@ static HRESULT ipid_to_stub_manager(const IPID *ipid, APARTMENT **stub_apt, stru
  * release the references to all objects (except iface) if the function
  * returned success, otherwise no references are returned. */
 HRESULT ipid_get_dispatch_params(const IPID *ipid, APARTMENT **stub_apt,
+                                 struct stub_manager **manager,
                                  IRpcStubBuffer **stub, IRpcChannelBuffer **chan,
                                  IID *iid, IUnknown **iface)
 {
@@ -508,7 +532,10 @@ HRESULT ipid_get_dispatch_params(const IPID *ipid, APARTMENT **stub_apt,
         *iid = ifstub->iid;
         *iface = ifstub->iface;
 
-        stub_manager_int_release(stubmgr);
+        if (manager)
+            *manager = stubmgr;
+        else
+            stub_manager_int_release(stubmgr);
         return S_OK;
     }
     else
@@ -626,7 +653,8 @@ static HRESULT WINAPI RemUnknown_QueryInterface(IRemUnknown *iface, REFIID riid,
         return S_OK;
     }
 
-    FIXME("No interface for iid %s\n", debugstr_guid(riid));
+    if (!IsEqualIID(riid, &IID_IExternalConnection))
+        FIXME("No interface for iid %s\n", debugstr_guid(riid));
 
     *ppv = NULL;
     return E_NOINTERFACE;
index 9cae09e..4de57fd 100644 (file)
@@ -1472,6 +1472,7 @@ unsigned char * WINAPI WdtpInterfacePointer_UserUnmarshal(ULONG *pFlags, unsigne
     IStream *stm;
     DWORD size;
     void *ptr;
+    IUnknown *orig;
 
     TRACE("(%s, %p, %p, %s)\n", debugstr_user_flags(pFlags), pBuffer, ppunk, debugstr_guid(riid));
 
@@ -1499,11 +1500,14 @@ unsigned char * WINAPI WdtpInterfacePointer_UserUnmarshal(ULONG *pFlags, unsigne
     memcpy(ptr, pBuffer, size);
     GlobalUnlock(h);
 
+    orig = *ppunk;
     hr = CoUnmarshalInterface(stm, riid, (void**)ppunk);
     IStream_Release(stm);
 
     if(hr != S_OK) RaiseException(hr, 0, 0, NULL);
 
+    if(orig) IUnknown_Release(orig);
+
     return pBuffer + size;
 }
 
@@ -1828,7 +1832,10 @@ unsigned char * __RPC_USER STGMEDIUM_UserUnmarshal(ULONG *pFlags, unsigned char
             pBuffer = WdtpInterfacePointer_UserUnmarshal(pFlags, pBuffer, (IUnknown**)&pStgMedium->u.pstm, &IID_IStream);
         }
         else
+        {
+            if (pStgMedium->u.pstm) IStream_Release( pStgMedium->u.pstm );
             pStgMedium->u.pstm = NULL;
+        }
         break;
     case TYMED_ISTORAGE:
         TRACE("TYMED_ISTORAGE\n");
@@ -1837,7 +1844,10 @@ unsigned char * __RPC_USER STGMEDIUM_UserUnmarshal(ULONG *pFlags, unsigned char
             pBuffer = WdtpInterfacePointer_UserUnmarshal(pFlags, pBuffer, (IUnknown**)&pStgMedium->u.pstg, &IID_IStorage);
         }
         else
+        {
+            if (pStgMedium->u.pstg) IStorage_Release( pStgMedium->u.pstg );
             pStgMedium->u.pstg = NULL;
+        }
         break;
     case TYMED_GDI:
         TRACE("TYMED_GDI\n");
@@ -1866,9 +1876,10 @@ unsigned char * __RPC_USER STGMEDIUM_UserUnmarshal(ULONG *pFlags, unsigned char
         RaiseException(DV_E_TYMED, 0, 0, NULL);
     }
 
-    pStgMedium->pUnkForRelease = NULL;
     if (releaseunk)
         pBuffer = WdtpInterfacePointer_UserUnmarshal(pFlags, pBuffer, &pStgMedium->pUnkForRelease, &IID_IUnknown);
+    /* Unlike the IStream / IStorage ifaces, the existing pUnkForRelease
+       is left intact if a NULL ptr is unmarshalled - see the tests. */
 
     return pBuffer;
 }
@@ -2754,13 +2765,39 @@ HRESULT __RPC_STUB IDataObject_GetData_Stub(
     return IDataObject_GetData(This, pformatetcIn, pRemoteMedium);
 }
 
-HRESULT CALLBACK IDataObject_GetDataHere_Proxy(
-    IDataObject* This,
-    FORMATETC *pformatetc,
-    STGMEDIUM *pmedium)
+HRESULT CALLBACK IDataObject_GetDataHere_Proxy(IDataObject *iface, FORMATETC *fmt, STGMEDIUM *med)
 {
-    TRACE("(%p)->(%p, %p)\n", This, pformatetc, pmedium);
-    return IDataObject_RemoteGetDataHere_Proxy(This, pformatetc, pmedium);
+    IUnknown *release;
+    IStorage *stg = NULL;
+    HRESULT hr;
+
+    TRACE("(%p)->(%p, %p)\n", iface, fmt, med);
+
+    if ((med->tymed & (TYMED_HGLOBAL | TYMED_FILE | TYMED_ISTREAM | TYMED_ISTORAGE)) == 0)
+        return DV_E_TYMED;
+    if (med->tymed != fmt->tymed)
+        return DV_E_TYMED;
+
+    release = med->pUnkForRelease;
+    med->pUnkForRelease = NULL;
+
+    if (med->tymed == TYMED_ISTREAM || med->tymed == TYMED_ISTORAGE)
+    {
+        stg = med->u.pstg; /* This may actually be a stream, but that's ok */
+        if (stg) IStorage_AddRef( stg );
+    }
+
+    hr = IDataObject_RemoteGetDataHere_Proxy(iface, fmt, med);
+
+    med->pUnkForRelease = release;
+    if (stg)
+    {
+        if (med->u.pstg)
+            IStorage_Release( med->u.pstg );
+        med->u.pstg = stg;
+    }
+
+    return hr;
 }
 
 HRESULT __RPC_STUB IDataObject_GetDataHere_Stub(
index 35e3682..4b3642f 100644 (file)
@@ -144,7 +144,7 @@ reactos/dll/win32/ntprint             # Synced to WineStaging-1.7.47
 reactos/dll/win32/objsel              # Synced to WineStaging-1.7.47
 reactos/dll/win32/odbc32              # Synced to WineStaging-1.7.37. Depends on port of Linux ODBC.
 reactos/dll/win32/odbccp32            # Synced to WineStaging-1.7.47
-reactos/dll/win32/ole32               # Synced to WineStaging-1.7.47
+reactos/dll/win32/ole32               # Synced to WineStaging-1.7.55
 reactos/dll/win32/oleacc              # Synced to WineStaging-1.7.47
 reactos/dll/win32/oleaut32            # Synced to WineStaging-1.7.47
 reactos/dll/win32/olecli32            # Synced to WineStaging-1.7.47