diff --git a/reactos/dll/win32/ole32/compobj.c b/reactos/dll/win32/ole32/compobj.c index 89a6a47b410..40ceb77c502 100644 --- a/reactos/dll/win32/ole32/compobj.c +++ b/reactos/dll/win32/ole32/compobj.c @@ -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; - return return_multi_qi(pUnk, cmq, pResults); + 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; + + /* + * 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); diff --git a/reactos/dll/win32/ole32/compobj_private.h b/reactos/dll/win32/ole32/compobj_private.h index 5dc8eb8e5aa..64f3cf6c0ea 100644 --- a/reactos/dll/win32/ole32/compobj_private.h +++ b/reactos/dll/win32/ole32/compobj_private.h @@ -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); diff --git a/reactos/dll/win32/ole32/datacache.c b/reactos/dll/win32/ole32/datacache.c index 48b173fccaa..2da1b6fed2b 100644 --- a/reactos/dll/win32/ole32/datacache.c +++ b/reactos/dll/win32/ole32/datacache.c @@ -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)) { diff --git a/reactos/dll/win32/ole32/defaulthandler.c b/reactos/dll/win32/ole32/defaulthandler.c index e54bb25cedf..4e5bb211108 100644 --- a/reactos/dll/win32/ole32/defaulthandler.c +++ b/reactos/dll/win32/ole32/defaulthandler.c @@ -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; diff --git a/reactos/dll/win32/ole32/filemoniker.c b/reactos/dll/win32/ole32/filemoniker.c index 757df82bbbb..aa77662439a 100644 --- a/reactos/dll/win32/ole32/filemoniker.c +++ b/reactos/dll/win32/ole32/filemoniker.c @@ -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); diff --git a/reactos/dll/win32/ole32/marshal.c b/reactos/dll/win32/ole32/marshal.c index 3de95d73a06..fee74ef765e 100644 --- a/reactos/dll/win32/ole32/marshal.c +++ b/reactos/dll/win32/ole32/marshal.c @@ -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; - 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; + 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 (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"); diff --git a/reactos/dll/win32/ole32/ole2.c b/reactos/dll/win32/ole32/ole2.c index 354d4bdeeee..0c843febfe5 100644 --- a/reactos/dll/win32/ole32/ole2.c +++ b/reactos/dll/win32/ole32/ole2.c @@ -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; diff --git a/reactos/dll/win32/ole32/ole2impl.c b/reactos/dll/win32/ole32/ole2impl.c index 12d3c0174af..10b7d5bb45b 100644 --- a/reactos/dll/win32/ole32/ole2impl.c +++ b/reactos/dll/win32/ole32/ole2impl.c @@ -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.@] * diff --git a/reactos/dll/win32/ole32/ole2stubs.c b/reactos/dll/win32/ole32/ole2stubs.c index 47b5f7ea5e0..2d5cbed89fb 100644 --- a/reactos/dll/win32/ole32/ole2stubs.c +++ b/reactos/dll/win32/ole32/ole2stubs.c @@ -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) diff --git a/reactos/dll/win32/ole32/ole32.spec b/reactos/dll/win32/ole32/ole32.spec index 9dc51fbc3ff..baa220991b9 100644 --- a/reactos/dll/win32/ole32/ole32.spec +++ b/reactos/dll/win32/ole32/ole32.spec @@ -218,8 +218,8 @@ @ 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) diff --git a/reactos/dll/win32/ole32/ole32_main.c b/reactos/dll/win32/ole32/ole32_main.c index edfceacc849..cf21eef56b1 100644 --- a/reactos/dll/win32/ole32/ole32_main.c +++ b/reactos/dll/win32/ole32/ole32_main.c @@ -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; +} diff --git a/reactos/dll/win32/ole32/rpc.c b/reactos/dll/win32/ole32/rpc.c index 45ee59e2ebe..750955bfd72 100644 --- a/reactos/dll/win32/ole32/rpc.c +++ b/reactos/dll/win32/ole32/rpc.c @@ -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, ¶ms->stub, ¶ms->chan, + hr = ipid_get_dispatch_params(&ipid, &apt, &stub_manager, ¶ms->stub, ¶ms->chan, ¶ms->iid, ¶ms->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); } diff --git a/reactos/dll/win32/ole32/storage32.c b/reactos/dll/win32/ole32/storage32.c index 9b2f0cd7e9b..a151f709ef3 100644 --- a/reactos/dll/win32/ole32/storage32.c +++ b/reactos/dll/win32/ole32/storage32.c @@ -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, ¤tSearchNode); 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, ¤tEntry); + 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 ); diff --git a/reactos/dll/win32/ole32/stubmanager.c b/reactos/dll/win32/ole32/stubmanager.c index 9d96899cbaa..07d5d655aa3 100644 --- a/reactos/dll/win32/ole32/stubmanager.c +++ b/reactos/dll/win32/ole32/stubmanager.c @@ -25,6 +25,8 @@ #include "precomp.h" +#include + 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; diff --git a/reactos/dll/win32/ole32/usrmarshal.c b/reactos/dll/win32/ole32/usrmarshal.c index 9cae09e21ca..4de57fd8184 100644 --- a/reactos/dll/win32/ole32/usrmarshal.c +++ b/reactos/dll/win32/ole32/usrmarshal.c @@ -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( diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index 35e3682c102..4b3642f6d1e 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -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