enum object_state
{
object_state_not_running,
- object_state_running
+ object_state_running,
+ object_state_deferred_close
};
/****************************************************************************
/* IDataObject delegate */
IDataObject *pDataDelegate;
enum object_state object_state;
+ ULONG in_call;
/* connection cookie for the advise on the delegate OLE object */
DWORD dwAdvConn;
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.
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
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 );
/* 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 );
}
/************************************************************************
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;
}
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;
}
/************************************************************************
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)
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;
}
/************************************************************************
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(
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;
}
/************************************************************************
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);
IOleObject* iface)
{
DefaultHandler *This = impl_from_IOleObject(iface);
+ HRESULT hr;
+
TRACE("(%p)\n", iface);
if (!object_is_running(This))
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;
}
/************************************************************************
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;
}
/************************************************************************
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;
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);
}
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;
}
/************************************************************************
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))
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);
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;
}
/*********************************************************
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;
}
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;
}
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;
}
/************************************************************************
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))
{
DefaultHandler *This = impl_from_IRunnableObject(iface);
HRESULT hr;
+ IOleCacheControl *cache_ctrl;
FIXME("(%p): semi-stub\n", pbc);
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;
}
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
*
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);
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;
}
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))
{
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))
{
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;
}
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)
{
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;
This->pPSDelegate = NULL;
This->pDataDelegate = NULL;
This->object_state = object_state_not_running;
+ This->in_call = 0;
This->dwAdvConn = 0;
This->storage = NULL;
/* release delegates */
DefaultHandler_Stop(This);
- release_delegates(This);
HeapFree( GetProcessHeap(), 0, This->containerApp );
This->containerApp = NULL;