oleaut32/tests: Make sure return values are used (LLVM/Clang).
[wine] / dlls / ole32 / defaulthandler.c
index bc3b2f5..68d85ec 100644 (file)
@@ -16,7 +16,7 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
  * NOTES:
  *    The OLE2 default object handler supports a whole whack of
 #include "winbase.h"
 #include "winuser.h"
 #include "winerror.h"
-#include "wine/unicode.h"
 #include "ole2.h"
+
+#include "compobj_private.h"
+
+#include "wine/unicode.h"
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(ole);
 
+enum storage_state
+{
+    storage_state_uninitialised,
+    storage_state_initialised,
+    storage_state_loaded
+};
+
+enum object_state
+{
+    object_state_not_running,
+    object_state_running
+};
+
 /****************************************************************************
  * DefaultHandler
  *
  */
 struct DefaultHandler
 {
-  const IOleObjectVtbl*      lpVtbl;
-  const IUnknownVtbl*        lpvtblIUnknown;
-  const IDataObjectVtbl*     lpvtblIDataObject;
-  const IRunnableObjectVtbl* lpvtblIRunnableObject;
+  IOleObject        IOleObject_iface;
+  IUnknown          IUnknown_iface;
+  IDataObject       IDataObject_iface;
+  IRunnableObject   IRunnableObject_iface;
+  IAdviseSink       IAdviseSink_iface;
+  IPersistStorage   IPersistStorage_iface;
 
   /* Reference count of this object */
   LONG ref;
@@ -83,6 +101,8 @@ struct DefaultHandler
 
   /* IUnknown implementation of the datacache. */
   IUnknown* dataCache;
+  /* IPersistStorage implementation of the datacache. */
+  IPersistStorage* dataCache_PersistStg;
 
   /* Client site for the embedded object. */
   IOleClientSite* clientSite;
@@ -107,38 +127,61 @@ struct DefaultHandler
   IOleObject *pOleDelegate;
   /* IPersistStorage delegate */
   IPersistStorage *pPSDelegate;
+  /* IDataObject delegate */
+  IDataObject *pDataDelegate;
+  enum object_state object_state;
+
+  /* connection cookie for the advise on the delegate OLE object */
+  DWORD dwAdvConn;
+
+  /* storage passed to Load or InitNew */
+  IStorage *storage;
+  enum storage_state storage_state;
+
+  /* optional class factory for object */
+  IClassFactory *pCFObject;
+  /* TRUE if acting as an inproc server instead of an inproc handler */
+  BOOL inproc_server;
 };
 
 typedef struct DefaultHandler DefaultHandler;
 
-/*
- * Here, I define utility functions to help with the casting of the
- * "This" parameter.
- * There is a version to accommodate all of the VTables implemented
- * by this object.
- */
 static inline DefaultHandler *impl_from_IOleObject( IOleObject *iface )
 {
-    return (DefaultHandler *)((char*)iface - FIELD_OFFSET(DefaultHandler, lpVtbl));
+    return CONTAINING_RECORD(iface, DefaultHandler, IOleObject_iface);
 }
 
-static inline DefaultHandler *impl_from_NDIUnknown( IUnknown *iface )
+static inline DefaultHandler *impl_from_IUnknown( IUnknown *iface )
 {
-    return (DefaultHandler *)((char*)iface - FIELD_OFFSET(DefaultHandler, lpvtblIUnknown));
+    return CONTAINING_RECORD(iface, DefaultHandler, IUnknown_iface);
 }
 
 static inline DefaultHandler *impl_from_IDataObject( IDataObject *iface )
 {
-    return (DefaultHandler *)((char*)iface - FIELD_OFFSET(DefaultHandler, lpvtblIDataObject));
+    return CONTAINING_RECORD(iface, DefaultHandler, IDataObject_iface);
 }
 
 static inline DefaultHandler *impl_from_IRunnableObject( IRunnableObject *iface )
 {
-    return (DefaultHandler *)((char*)iface - FIELD_OFFSET(DefaultHandler, lpvtblIRunnableObject));
+    return CONTAINING_RECORD(iface, DefaultHandler, IRunnableObject_iface);
+}
+
+static inline DefaultHandler *impl_from_IAdviseSink( IAdviseSink *iface )
+{
+    return CONTAINING_RECORD(iface, DefaultHandler, IAdviseSink_iface);
+}
+
+static inline DefaultHandler *impl_from_IPersistStorage( IPersistStorage *iface )
+{
+    return CONTAINING_RECORD(iface, DefaultHandler, IPersistStorage_iface);
 }
 
 static void DefaultHandler_Destroy(DefaultHandler* This);
 
+static inline BOOL object_is_running(DefaultHandler *This)
+{
+    return IRunnableObject_IsRunning(&This->IRunnableObject_iface);
+}
 
 /*********************************************************
  * Method implementation for the  non delegating IUnknown
@@ -150,7 +193,7 @@ static void DefaultHandler_Destroy(DefaultHandler* This);
  *
  * See Windows documentation for more details on IUnknown methods.
  *
- * This version of QueryInterface will not delegate it's implementation
+ * This version of QueryInterface will not delegate its implementation
  * to the outer unknown.
  */
 static HRESULT WINAPI DefaultHandler_NDIUnknown_QueryInterface(
@@ -158,9 +201,8 @@ static HRESULT WINAPI DefaultHandler_NDIUnknown_QueryInterface(
             REFIID         riid,
             void**         ppvObject)
 {
-  DefaultHandler *This = impl_from_NDIUnknown(iface);
+  DefaultHandler *This = impl_from_IUnknown(iface);
 
-  /* Perform a sanity check on the parameters. */
   if (!ppvObject)
     return E_INVALIDARG;
 
@@ -169,18 +211,26 @@ static HRESULT WINAPI DefaultHandler_NDIUnknown_QueryInterface(
   if (IsEqualIID(&IID_IUnknown, riid))
     *ppvObject = iface;
   else if (IsEqualIID(&IID_IOleObject, riid))
-    *ppvObject = (IOleObject*)&This->lpVtbl;
+    *ppvObject = &This->IOleObject_iface;
   else if (IsEqualIID(&IID_IDataObject, riid))
-    *ppvObject = (IDataObject*)&This->lpvtblIDataObject;
+    *ppvObject = &This->IDataObject_iface;
   else if (IsEqualIID(&IID_IRunnableObject, riid))
-    *ppvObject = (IRunnableObject*)&This->lpvtblIRunnableObject;
-  else
+    *ppvObject = &This->IRunnableObject_iface;
+  else if (IsEqualIID(&IID_IPersist, riid) ||
+           IsEqualIID(&IID_IPersistStorage, riid))
+    *ppvObject = &This->IPersistStorage_iface;
+  else if (IsEqualIID(&IID_IViewObject, riid) ||
+           IsEqualIID(&IID_IViewObject2, riid) ||
+           IsEqualIID(&IID_IOleCache, riid) ||
+           IsEqualIID(&IID_IOleCache2, riid))
+  {
+    HRESULT hr = IUnknown_QueryInterface(This->dataCache, riid, ppvObject);
+    if (FAILED(hr)) FIXME("interface %s not implemented by data cache\n", debugstr_guid(riid));
+    return hr;
+  }
+  else if (This->inproc_server && This->pOleDelegate)
   {
-    /*
-     * Blind aggregate the data cache to "inherit" it's interfaces.
-     */
-    if (IUnknown_QueryInterface(This->dataCache, riid, ppvObject) == S_OK)
-       return S_OK;
+    return IUnknown_QueryInterface(This->pOleDelegate, riid, ppvObject);
   }
 
   /* Check that we obtained an interface. */
@@ -204,13 +254,13 @@ static HRESULT WINAPI DefaultHandler_NDIUnknown_QueryInterface(
  *
  * See Windows documentation for more details on IUnknown methods.
  *
- * This version of QueryInterface will not delegate it's implementation
+ * This version of QueryInterface will not delegate its implementation
  * to the outer unknown.
  */
 static ULONG WINAPI DefaultHandler_NDIUnknown_AddRef(
             IUnknown*      iface)
 {
-  DefaultHandler *This = impl_from_NDIUnknown(iface);
+  DefaultHandler *This = impl_from_IUnknown(iface);
   return InterlockedIncrement(&This->ref);
 }
 
@@ -219,16 +269,15 @@ static ULONG WINAPI DefaultHandler_NDIUnknown_AddRef(
  *
  * See Windows documentation for more details on IUnknown methods.
  *
- * This version of QueryInterface will not delegate it's implementation
+ * This version of QueryInterface will not delegate its implementation
  * to the outer unknown.
  */
 static ULONG WINAPI DefaultHandler_NDIUnknown_Release(
             IUnknown*      iface)
 {
-  DefaultHandler *This = impl_from_NDIUnknown(iface);
+  DefaultHandler *This = impl_from_IUnknown(iface);
   ULONG ref;
 
-  /* Decrease the reference count on this object. */
   ref = InterlockedDecrement(&This->ref);
 
   if (!ref) DefaultHandler_Destroy(This);
@@ -295,9 +344,13 @@ static HRESULT WINAPI DefaultHandler_SetClientSite(
            IOleClientSite*    pClientSite)
 {
   DefaultHandler *This = impl_from_IOleObject(iface);
+  HRESULT hr = S_OK;
 
   TRACE("(%p, %p)\n", iface, pClientSite);
 
+  if (object_is_running(This))
+    hr = IOleObject_SetClientSite(This->pOleDelegate, pClientSite);
+
   /*
    * Make sure we release the previous client site if there
    * was one.
@@ -310,7 +363,7 @@ static HRESULT WINAPI DefaultHandler_SetClientSite(
   if (This->clientSite)
     IOleClientSite_AddRef(This->clientSite);
 
-  return S_OK;
+  return hr;
 }
 
 /************************************************************************
@@ -327,7 +380,6 @@ static HRESULT WINAPI DefaultHandler_GetClientSite(
 {
   DefaultHandler *This = impl_from_IOleObject(iface);
 
-  /* Sanity check. */
   if (!ppClientSite)
     return E_POINTER;
 
@@ -359,13 +411,15 @@ static HRESULT WINAPI DefaultHandler_SetHostNames(
        debugstr_w(szContainerApp),
        debugstr_w(szContainerObj));
 
-  /* Be sure to cleanup before re-assinging the strings. */
+  if (object_is_running(This))
+    IOleObject_SetHostNames(This->pOleDelegate, szContainerApp, szContainerObj);
+
+  /* Be sure to cleanup before re-assigning the strings. */
   HeapFree( GetProcessHeap(), 0, This->containerApp );
   This->containerApp = NULL;
   HeapFree( GetProcessHeap(), 0, This->containerObj );
   This->containerObj = NULL;
 
-  /* Copy the string supplied. */
   if (szContainerApp)
   {
       if ((This->containerApp = HeapAlloc( GetProcessHeap(), 0,
@@ -382,6 +436,41 @@ static HRESULT WINAPI DefaultHandler_SetHostNames(
   return S_OK;
 }
 
+static void release_delegates(DefaultHandler *This)
+{
+    if (This->pDataDelegate)
+    {
+        IDataObject_Release(This->pDataDelegate);
+        This->pDataDelegate = NULL;
+    }
+    if (This->pPSDelegate)
+    {
+        IPersistStorage_Release(This->pPSDelegate);
+        This->pPSDelegate = NULL;
+    }
+    if (This->pOleDelegate)
+    {
+        IOleObject_Release(This->pOleDelegate);
+        This->pOleDelegate = NULL;
+    }
+}
+
+/* undoes the work done by DefaultHandler_Run */
+static void DefaultHandler_Stop(DefaultHandler *This)
+{
+  if (!object_is_running(This))
+    return;
+
+  IOleObject_Unadvise(This->pOleDelegate, This->dwAdvConn);
+
+  /* FIXME: call IOleCache_OnStop */
+
+  if (This->dataAdviseHolder)
+    DataAdviseHolder_OnDisconnect(This->dataAdviseHolder);
+
+  This->object_state = object_state_not_running;
+}
+
 /************************************************************************
  * DefaultHandler_Close (IOleObject)
  *
@@ -394,8 +483,20 @@ static HRESULT WINAPI DefaultHandler_Close(
            IOleObject*        iface,
            DWORD              dwSaveOption)
 {
-  TRACE("()\n");
-  return S_OK;
+  DefaultHandler *This = impl_from_IOleObject(iface);
+  HRESULT hr;
+
+  TRACE("(%d)\n", dwSaveOption);
+
+  if (!object_is_running(This))
+    return S_OK;
+
+  hr = IOleObject_Close(This->pOleDelegate, dwSaveOption);
+
+  DefaultHandler_Stop(This);
+  release_delegates(This);
+
+  return hr;
 }
 
 /************************************************************************
@@ -410,11 +511,16 @@ static HRESULT WINAPI DefaultHandler_SetMoniker(
            DWORD              dwWhichMoniker,
            IMoniker*          pmk)
 {
-  TRACE("(%p, %ld, %p)\n",
+  DefaultHandler *This = impl_from_IOleObject(iface);
+
+  TRACE("(%p, %d, %p)\n",
        iface,
        dwWhichMoniker,
        pmk);
 
+  if (object_is_running(This))
+    return IOleObject_SetMoniker(This->pOleDelegate, dwWhichMoniker, pmk);
+
   return S_OK;
 }
 
@@ -433,9 +539,14 @@ static HRESULT WINAPI DefaultHandler_GetMoniker(
 {
   DefaultHandler *This = impl_from_IOleObject(iface);
 
-  TRACE("(%p, %ld, %ld, %p)\n",
+  TRACE("(%p, %d, %d, %p)\n",
        iface, dwAssign, dwWhichMoniker, ppmk);
 
+  if (object_is_running(This))
+    return IOleObject_GetMoniker(This->pOleDelegate, dwAssign, dwWhichMoniker,
+                                 ppmk);
+
+  /* FIXME: dwWhichMoniker == OLEWHICHMK_CONTAINER only? */
   if (This->clientSite)
   {
     return IOleClientSite_GetMoniker(This->clientSite,
@@ -461,9 +572,14 @@ static HRESULT WINAPI DefaultHandler_InitFromData(
            BOOL               fCreation,
            DWORD              dwReserved)
 {
-  TRACE("(%p, %p, %d, %ld)\n",
+  DefaultHandler *This = impl_from_IOleObject(iface);
+
+  TRACE("(%p, %p, %d, %d)\n",
        iface, pDataObject, fCreation, dwReserved);
 
+  if (object_is_running(This))
+    return IOleObject_InitFromData(This->pOleDelegate, pDataObject, fCreation,
+                                  dwReserved);
   return OLE_E_NOTRUNNING;
 }
 
@@ -479,9 +595,15 @@ static HRESULT WINAPI DefaultHandler_GetClipboardData(
            DWORD              dwReserved,
            IDataObject**      ppDataObject)
 {
-  TRACE("(%p, %ld, %p)\n",
+  DefaultHandler *This = impl_from_IOleObject(iface);
+
+  TRACE("(%p, %d, %p)\n",
        iface, dwReserved, ppDataObject);
 
+  if (object_is_running(This))
+    return IOleObject_GetClipboardData(This->pOleDelegate, dwReserved,
+                                       ppDataObject);
+
   return OLE_E_NOTRUNNING;
 }
 
@@ -494,8 +616,17 @@ static HRESULT WINAPI DefaultHandler_DoVerb(
            HWND               hwndParent,
            LPCRECT            lprcPosRect)
 {
-  FIXME(": Stub\n");
-  return E_NOTIMPL;
+  DefaultHandler *This = impl_from_IOleObject(iface);
+  IRunnableObject *pRunnableObj = &This->IRunnableObject_iface;
+  HRESULT hr;
+
+  TRACE("(%d, %p, %p, %d, %p, %s)\n", iVerb, lpmsg, pActiveSite, lindex, hwndParent, wine_dbgstr_rect(lprcPosRect));
+
+  hr = IRunnableObject_Run(pRunnableObj, NULL);
+  if (FAILED(hr)) return hr;
+
+  return IOleObject_DoVerb(This->pOleDelegate, iVerb, lpmsg, pActiveSite,
+                           lindex, hwndParent, lprcPosRect);
 }
 
 /************************************************************************
@@ -511,17 +642,31 @@ static HRESULT WINAPI DefaultHandler_EnumVerbs(
            IEnumOLEVERB**     ppEnumOleVerb)
 {
   DefaultHandler *This = impl_from_IOleObject(iface);
+  HRESULT hr = OLE_S_USEREG;
 
   TRACE("(%p, %p)\n", iface, ppEnumOleVerb);
 
-  return OleRegEnumVerbs(&This->clsid, ppEnumOleVerb);
+  if (object_is_running(This))
+    hr = IOleObject_EnumVerbs(This->pOleDelegate, ppEnumOleVerb);
+
+  if (hr == OLE_S_USEREG)
+    return OleRegEnumVerbs(&This->clsid, ppEnumOleVerb);
+  else
+    return hr;
 }
 
 static HRESULT WINAPI DefaultHandler_Update(
            IOleObject*        iface)
 {
-  FIXME(": Stub\n");
-  return E_NOTIMPL;
+    DefaultHandler *This = impl_from_IOleObject(iface);
+    TRACE("(%p)\n", iface);
+
+    if (!object_is_running(This))
+    {
+        FIXME("Should run object\n");
+        return E_NOTIMPL;
+    }
+    return IOleObject_Update(This->pOleDelegate);
 }
 
 /************************************************************************
@@ -534,9 +679,13 @@ static HRESULT WINAPI DefaultHandler_Update(
 static HRESULT WINAPI DefaultHandler_IsUpToDate(
            IOleObject*        iface)
 {
-  TRACE("(%p)\n", iface);
+    DefaultHandler *This = impl_from_IOleObject(iface);
+    TRACE("(%p)\n", iface);
 
-  return OLE_E_NOTRUNNING;
+    if (object_is_running(This))
+        return IOleObject_IsUpToDate(This->pOleDelegate);
+
+    return OLE_E_NOTRUNNING;
 }
 
 /************************************************************************
@@ -554,11 +703,13 @@ static HRESULT WINAPI DefaultHandler_GetUserClassID(
 
   TRACE("(%p, %p)\n", iface, pClsid);
 
-  /* Sanity check. */
+  if (object_is_running(This))
+    return IOleObject_GetUserClassID(This->pOleDelegate, pClsid);
+
   if (!pClsid)
     return E_POINTER;
 
-  memcpy(pClsid, &This->clsid, sizeof(CLSID));
+  *pClsid = This->clsid;
 
   return S_OK;
 }
@@ -578,7 +729,9 @@ static HRESULT WINAPI DefaultHandler_GetUserType(
 {
   DefaultHandler *This = impl_from_IOleObject(iface);
 
-  TRACE("(%p, %ld, %p)\n", iface, dwFormOfType, pszUserType);
+  TRACE("(%p, %d, %p)\n", iface, dwFormOfType, pszUserType);
+  if (object_is_running(This))
+    return IOleObject_GetUserType(This->pOleDelegate, dwFormOfType, pszUserType);
 
   return OleRegGetUserType(&This->clsid, dwFormOfType, pszUserType);
 }
@@ -595,8 +748,14 @@ static HRESULT WINAPI DefaultHandler_SetExtent(
            DWORD              dwDrawAspect,
            SIZEL*             psizel)
 {
-  TRACE("(%p, %lx, (%ld x %ld))\n", iface,
+  DefaultHandler *This = impl_from_IOleObject(iface);
+
+  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);
+
   return OLE_E_NOTRUNNING;
 }
 
@@ -619,10 +778,12 @@ static HRESULT WINAPI DefaultHandler_GetExtent(
 
   DefaultHandler *This = impl_from_IOleObject(iface);
 
-  TRACE("(%p, %lx, %p)\n", iface, dwDrawAspect, psizel);
+  TRACE("(%p, %x, %p)\n", iface, dwDrawAspect, psizel);
 
-  hres = IUnknown_QueryInterface(This->dataCache, &IID_IViewObject2, (void**)&cacheView);
+  if (object_is_running(This))
+    return IOleObject_GetExtent(This->pOleDelegate, dwDrawAspect, psizel);
 
+  hres = IUnknown_QueryInterface(This->dataCache, &IID_IViewObject2, (void**)&cacheView);
   if (FAILED(hres))
     return E_UNEXPECTED;
 
@@ -631,7 +792,7 @@ static HRESULT WINAPI DefaultHandler_GetExtent(
    *
    * Here we would build a valid DVTARGETDEVICE structure
    * but, since we are calling into the data cache, we
-   * know it's implementation and we'll skip this
+   * know its implementation and we'll skip this
    * extra work until later.
    */
   targetDevice = NULL;
@@ -642,9 +803,6 @@ static HRESULT WINAPI DefaultHandler_GetExtent(
                                targetDevice,
                                psizel);
 
-  /*
-   * Cleanup
-   */
   IViewObject2_Release(cacheView);
 
   return hres;
@@ -694,7 +852,7 @@ static HRESULT WINAPI DefaultHandler_Unadvise(
 {
   DefaultHandler *This = impl_from_IOleObject(iface);
 
-  TRACE("(%p, %ld)\n", iface, dwConnection);
+  TRACE("(%p, %d)\n", iface, dwConnection);
 
   /*
    * If we don't have an advise holder yet, it means we don't have
@@ -723,17 +881,15 @@ static HRESULT WINAPI DefaultHandler_EnumAdvise(
 
   TRACE("(%p, %p)\n", iface, ppenumAdvise);
 
-  /* Sanity check */
   if (!ppenumAdvise)
     return E_POINTER;
 
   *ppenumAdvise = NULL;
 
   if (!This->oleAdviseHolder)
-    return IOleAdviseHolder_EnumAdvise(This->oleAdviseHolder,
-                                      ppenumAdvise);
+      return S_OK;
 
-  return S_OK;
+  return IOleAdviseHolder_EnumAdvise(This->oleAdviseHolder, ppenumAdvise);
 }
 
 /************************************************************************
@@ -752,18 +908,21 @@ static HRESULT WINAPI DefaultHandler_GetMiscStatus(
   HRESULT hres;
   DefaultHandler *This = impl_from_IOleObject(iface);
 
-  TRACE("(%p, %lx, %p)\n", iface, dwAspect, pdwStatus);
+  TRACE("(%p, %x, %p)\n", iface, dwAspect, pdwStatus);
+
+  if (object_is_running(This))
+    return IOleObject_GetMiscStatus(This->pOleDelegate, dwAspect, pdwStatus);
 
   hres = OleRegGetMiscStatus(&This->clsid, dwAspect, pdwStatus);
 
   if (FAILED(hres))
     *pdwStatus = 0;
 
-  return S_OK;
+  return hres;
 }
 
 /************************************************************************
- * DefaultHandler_SetExtent (IOleObject)
+ * DefaultHandler_SetColorScheme (IOleObject)
  *
  * This method is meaningless if the server is not running
  *
@@ -773,7 +932,13 @@ static HRESULT WINAPI DefaultHandler_SetColorScheme(
            IOleObject*           iface,
            struct tagLOGPALETTE* pLogpal)
 {
+  DefaultHandler *This = impl_from_IOleObject(iface);
+
   TRACE("(%p, %p))\n", iface, pLogpal);
+
+  if (object_is_running(This))
+    return IOleObject_SetColorScheme(This->pOleDelegate, pLogpal);
+
   return OLE_E_NOTRUNNING;
 }
 
@@ -855,6 +1020,9 @@ static HRESULT WINAPI DefaultHandler_GetData(
 
   IDataObject_Release(cacheDataObject);
 
+  if (FAILED(hres) && This->pDataDelegate)
+    hres = IDataObject_GetData(This->pDataDelegate, pformatetcIn, pmedium);
+
   return hres;
 }
 
@@ -898,6 +1066,9 @@ static HRESULT WINAPI DefaultHandler_QueryGetData(
 
   IDataObject_Release(cacheDataObject);
 
+  if (FAILED(hres) && This->pDataDelegate)
+    hres = IDataObject_QueryGetData(This->pDataDelegate, pformatetc);
+
   return hres;
 }
 
@@ -910,12 +1081,17 @@ static HRESULT WINAPI DefaultHandler_QueryGetData(
  */
 static HRESULT WINAPI DefaultHandler_GetCanonicalFormatEtc(
            IDataObject*     iface,
-           LPFORMATETC      pformatectIn,
+           LPFORMATETC      pformatetcIn,
            LPFORMATETC      pformatetcOut)
 {
-  FIXME("(%p, %p, %p)\n", iface, pformatectIn, pformatetcOut);
+  DefaultHandler *This = impl_from_IDataObject(iface);
 
-  return OLE_E_NOTRUNNING;
+  TRACE("(%p, %p, %p)\n", iface, pformatetcIn, pformatetcOut);
+
+  if (!This->pDataDelegate)
+    return OLE_E_NOTRUNNING;
+
+  return IDataObject_GetCanonicalFormatEtc(This->pDataDelegate, pformatetcIn, pformatetcOut);
 }
 
 /************************************************************************
@@ -932,11 +1108,10 @@ static HRESULT WINAPI DefaultHandler_SetData(
            STGMEDIUM*       pmedium,
            BOOL             fRelease)
 {
+  DefaultHandler *This = impl_from_IDataObject(iface);
   IDataObject* cacheDataObject = NULL;
   HRESULT      hres;
 
-  DefaultHandler *This = impl_from_IDataObject(iface);
-
   TRACE("(%p, %p, %p, %d)\n", iface, pformatetc, pmedium, fRelease);
 
   hres = IUnknown_QueryInterface(This->dataCache,
@@ -969,14 +1144,11 @@ static HRESULT WINAPI DefaultHandler_EnumFormatEtc(
            DWORD            dwDirection,
            IEnumFORMATETC** ppenumFormatEtc)
 {
-  HRESULT hres;
   DefaultHandler *This = impl_from_IDataObject(iface);
 
-  TRACE("(%p, %lx, %p)\n", iface, dwDirection, ppenumFormatEtc);
-
-  hres = OleRegEnumFormatEtc(&This->clsid, dwDirection, ppenumFormatEtc);
+  TRACE("(%p, %x, %p)\n", iface, dwDirection, ppenumFormatEtc);
 
-  return hres;
+  return OleRegEnumFormatEtc(&This->clsid, dwDirection, ppenumFormatEtc);
 }
 
 /************************************************************************
@@ -997,12 +1169,16 @@ static HRESULT WINAPI DefaultHandler_DAdvise(
   HRESULT hres = S_OK;
   DefaultHandler *This = impl_from_IDataObject(iface);
 
-  TRACE("(%p, %p, %ld, %p, %p)\n",
+  TRACE("(%p, %p, %d, %p, %p)\n",
        iface, pformatetc, advf, pAdvSink, pdwConnection);
 
   /* Make sure we have a data advise holder before we start. */
   if (!This->dataAdviseHolder)
+  {
     hres = CreateDataAdviseHolder(&This->dataAdviseHolder);
+    if (SUCCEEDED(hres) && This->pDataDelegate)
+      DataAdviseHolder_OnConnect(This->dataAdviseHolder, This->pDataDelegate);
+  }
 
   if (SUCCEEDED(hres))
     hres = IDataAdviseHolder_Advise(This->dataAdviseHolder,
@@ -1029,7 +1205,7 @@ static HRESULT WINAPI DefaultHandler_DUnadvise(
 {
   DefaultHandler *This = impl_from_IDataObject(iface);
 
-  TRACE("(%p, %ld)\n", iface, dwConnection);
+  TRACE("(%p, %d)\n", iface, dwConnection);
 
   /*
    * If we don't have a data advise holder yet, it means that
@@ -1058,7 +1234,6 @@ static HRESULT WINAPI DefaultHandler_EnumDAdvise(
 
   TRACE("(%p, %p)\n", iface, ppenumAdvise);
 
-  /* Sanity check */
   if (!ppenumAdvise)
     return E_POINTER;
 
@@ -1093,7 +1268,7 @@ static HRESULT WINAPI DefaultHandler_IRunnableObject_QueryInterface(
 }
 
 /************************************************************************
- * DefaultHandler_IRunnableObject_QueryInterface (IUnknown)
+ * DefaultHandler_IRunnableObject_AddRef (IUnknown)
  *
  * See Windows documentation for more details on IUnknown methods.
  */
@@ -1106,7 +1281,7 @@ static ULONG WINAPI DefaultHandler_IRunnableObject_AddRef(
 }
 
 /************************************************************************
- * DefaultHandler_IRunnableObject_QueryInterface (IUnknown)
+ * DefaultHandler_IRunnableObject_Release (IUnknown)
  *
  * See Windows documentation for more details on IUnknown methods.
  */
@@ -1141,34 +1316,58 @@ static HRESULT WINAPI DefaultHandler_Run(
   FIXME("(%p): semi-stub\n", pbc);
 
   /* already running? if so nothing to do */
-  if (This->pOleDelegate)
+  if (object_is_running(This))
     return S_OK;
 
-  hr = CoCreateInstance(&This->clsid, NULL, CLSCTX_LOCAL_SERVER, &IID_IOleObject, (void **)&This->pOleDelegate);
+  release_delegates(This);
+
+  hr = CoCreateInstance(&This->clsid, NULL, CLSCTX_LOCAL_SERVER,
+                        &IID_IOleObject, (void **)&This->pOleDelegate);
   if (FAILED(hr))
     return hr;
 
-  if (This->clientSite)
+  This->object_state = object_state_running;
+
+  hr = IOleObject_Advise(This->pOleDelegate, &This->IAdviseSink_iface, &This->dwAdvConn);
+
+  if (SUCCEEDED(hr) && This->clientSite)
     hr = IOleObject_SetClientSite(This->pOleDelegate, This->clientSite);
 
   if (SUCCEEDED(hr))
   {
-    IOleObject_QueryInterface(This->pOleDelegate, &IID_IPersistStorage, (void **)&This->pPSDelegate);
+    IOleObject_QueryInterface(This->pOleDelegate, &IID_IPersistStorage,
+                              (void **)&This->pPSDelegate);
     if (This->pPSDelegate)
-      hr = IPersistStorage_InitNew(This->pPSDelegate, NULL);
+    {
+      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 (SUCCEEDED(hr) && This->containerApp)
-    hr = IOleObject_SetHostNames(This->pOleDelegate, This->containerApp, This->containerObj);
+    hr = IOleObject_SetHostNames(This->pOleDelegate, This->containerApp,
+                                 This->containerObj);
 
   /* FIXME: do more stuff here:
    * - IOleObject_GetMiscStatus
-   * - IOleObject_Advise
    * - IOleObject_GetMoniker
-   * - advise data cache that we've connected somehow?
+   * - IOleCache_OnRun
    */
 
-  /* FIXME: if we failed, Close the object */
+  if (SUCCEEDED(hr))
+    hr = IOleObject_QueryInterface(This->pOleDelegate, &IID_IDataObject,
+                                   (void **)&This->pDataDelegate);
+
+  if (SUCCEEDED(hr) && This->dataAdviseHolder)
+    hr = DataAdviseHolder_OnConnect(This->dataAdviseHolder, This->pDataDelegate);
+
+  if (FAILED(hr))
+  {
+    DefaultHandler_Stop(This);
+    release_delegates(This);
+  }
 
   return hr;
 }
@@ -1185,7 +1384,7 @@ static BOOL    WINAPI DefaultHandler_IsRunning(
 
   TRACE("()\n");
 
-  if (This->pOleDelegate)
+  if (This->object_state == object_state_running)
     return TRUE;
   else
     return FALSE;
@@ -1218,6 +1417,397 @@ static HRESULT WINAPI DefaultHandler_SetContainedObject(
   return S_OK;
 }
 
+static HRESULT WINAPI DefaultHandler_IAdviseSink_QueryInterface(
+    IAdviseSink *iface,
+    REFIID riid,
+    void **ppvObject)
+{
+    if (IsEqualIID(riid, &IID_IUnknown) ||
+        IsEqualIID(riid, &IID_IAdviseSink))
+    {
+        *ppvObject = iface;
+        IAdviseSink_AddRef(iface);
+        return S_OK;
+    }
+
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI DefaultHandler_IAdviseSink_AddRef(
+    IAdviseSink *iface)
+{
+    DefaultHandler *This = impl_from_IAdviseSink(iface);
+
+    return IUnknown_AddRef(&This->IUnknown_iface);
+}
+
+static ULONG WINAPI DefaultHandler_IAdviseSink_Release(
+            IAdviseSink *iface)
+{
+    DefaultHandler *This = impl_from_IAdviseSink(iface);
+
+    return IUnknown_Release(&This->IUnknown_iface);
+}
+
+static void WINAPI DefaultHandler_IAdviseSink_OnDataChange(
+    IAdviseSink *iface,
+    FORMATETC *pFormatetc,
+    STGMEDIUM *pStgmed)
+{
+    FIXME(": stub\n");
+}
+
+static void WINAPI DefaultHandler_IAdviseSink_OnViewChange(
+    IAdviseSink *iface,
+    DWORD dwAspect,
+    LONG lindex)
+{
+    FIXME(": stub\n");
+}
+
+static void WINAPI DefaultHandler_IAdviseSink_OnRename(
+    IAdviseSink *iface,
+    IMoniker *pmk)
+{
+    DefaultHandler *This = impl_from_IAdviseSink(iface);
+
+    TRACE("(%p)\n", pmk);
+
+    if (This->oleAdviseHolder)
+        IOleAdviseHolder_SendOnRename(This->oleAdviseHolder, pmk);
+}
+
+static void WINAPI DefaultHandler_IAdviseSink_OnSave(
+    IAdviseSink *iface)
+{
+    DefaultHandler *This = impl_from_IAdviseSink(iface);
+
+    TRACE("()\n");
+
+    if (This->oleAdviseHolder)
+        IOleAdviseHolder_SendOnSave(This->oleAdviseHolder);
+}
+
+static void WINAPI DefaultHandler_IAdviseSink_OnClose(
+    IAdviseSink *iface)
+{
+    DefaultHandler *This = impl_from_IAdviseSink(iface);
+    
+    TRACE("()\n");
+
+    if (This->oleAdviseHolder)
+        IOleAdviseHolder_SendOnClose(This->oleAdviseHolder);
+
+    DefaultHandler_Stop(This);
+}
+
+
+/************************************************************************
+ * DefaultHandler_IPersistStorage_QueryInterface
+ *
+ */
+static HRESULT WINAPI DefaultHandler_IPersistStorage_QueryInterface(
+            IPersistStorage*     iface,
+            REFIID               riid,
+            void**               ppvObject)
+{
+  DefaultHandler *This = impl_from_IPersistStorage(iface);
+
+  return IUnknown_QueryInterface(This->outerUnknown, riid, ppvObject);
+}
+
+/************************************************************************
+ * DefaultHandler_IPersistStorage_AddRef
+ *
+ */
+static ULONG WINAPI DefaultHandler_IPersistStorage_AddRef(
+            IPersistStorage*     iface)
+{
+  DefaultHandler *This = impl_from_IPersistStorage(iface);
+
+  return IUnknown_AddRef(This->outerUnknown);
+}
+
+/************************************************************************
+ * DefaultHandler_IPersistStorage_Release
+ *
+ */
+static ULONG WINAPI DefaultHandler_IPersistStorage_Release(
+            IPersistStorage*     iface)
+{
+  DefaultHandler *This = impl_from_IPersistStorage(iface);
+
+  return IUnknown_Release(This->outerUnknown);
+}
+
+/************************************************************************
+ * DefaultHandler_IPersistStorage_GetClassID
+ *
+ */
+static HRESULT WINAPI DefaultHandler_IPersistStorage_GetClassID(
+            IPersistStorage*     iface,
+            CLSID*               clsid)
+{
+    DefaultHandler *This = impl_from_IPersistStorage(iface);
+    HRESULT hr;
+
+    TRACE("(%p)->(%p)\n", iface, clsid);
+
+    if(object_is_running(This))
+        hr = IPersistStorage_GetClassID(This->pPSDelegate, clsid);
+    else
+        hr = IPersistStorage_GetClassID(This->dataCache_PersistStg, clsid);
+
+    return hr;
+}
+
+/************************************************************************
+ * DefaultHandler_IPersistStorage_IsDirty
+ *
+ */
+static HRESULT WINAPI DefaultHandler_IPersistStorage_IsDirty(
+            IPersistStorage*     iface)
+{
+    DefaultHandler *This = impl_from_IPersistStorage(iface);
+    HRESULT hr;
+
+    TRACE("(%p)\n", iface);
+
+    hr = IPersistStorage_IsDirty(This->dataCache_PersistStg);
+    if(hr != S_FALSE) return hr;
+
+    if(object_is_running(This))
+        hr = IPersistStorage_IsDirty(This->pPSDelegate);
+
+    return hr;
+}
+
+/***********************************************************************
+ *   init_ole_stream
+ *
+ * Creates the '\1Ole' stream.
+ * The format of this stream is as follows:
+ *
+ * DWORD Version == 0x02000001
+ * DWORD Flags - low bit set indicates the object is a link otherwise it's embedded.
+ * DWORD LinkupdateOption - [MS-OLEDS describes this as an implementation specific hint
+ *                           supplied by the app that creates the data structure.  May be
+ *                           ignored on processing].
+ *
+ * DWORD Reserved == 0
+ * DWORD MonikerStreamSize - size of the rest of the data (ie CLSID + moniker stream data).
+ * CLSID clsid - class id of object capable of processing the moniker
+ * BYTE  data[] - moniker data for a link
+ */
+
+static const WCHAR OleStream[] = {1,'O','l','e',0};
+typedef struct
+{
+    DWORD version;
+    DWORD flags;
+    DWORD link_update_opt;
+    DWORD res;
+    DWORD moniker_size;
+} ole_stream_header_t;
+static const DWORD ole_stream_version = 0x02000001;
+
+static void init_ole_stream(IStorage *storage)
+{
+    HRESULT hr;
+    IStream *stream;
+
+    hr = IStorage_CreateStream(storage, OleStream, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stream);
+    if(SUCCEEDED(hr))
+    {
+        DWORD written;
+        ole_stream_header_t header;
+
+        header.version         = ole_stream_version;
+        header.flags           = 0;
+        header.link_update_opt = 0;
+        header.res             = 0;
+        header.moniker_size    = 0;
+
+        IStream_Write(stream, &header, sizeof(header), &written);
+        IStream_Release(stream);
+    }
+    return;
+}
+
+static HRESULT load_ole_stream(DefaultHandler *This, IStorage *storage)
+{
+    IStream *stream;
+    HRESULT hr;
+
+    hr = IStorage_OpenStream(storage, OleStream, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stream);
+
+    if(SUCCEEDED(hr))
+    {
+        DWORD read;
+        ole_stream_header_t header;
+
+        hr = IStream_Read(stream, &header, sizeof(header), &read);
+        if(hr == S_OK && read == sizeof(header) && header.version == ole_stream_version)
+        {
+            if(header.flags & 1)
+            {
+                /* FIXME: Read the moniker and deal with the link */
+                FIXME("Linked objects are not supported yet\n");
+            }
+        }
+        else
+        {
+            WARN("Incorrect OleStream header\n");
+            hr = DV_E_CLIPFORMAT;
+        }
+        IStream_Release(stream);
+    }
+    else
+    {
+        init_ole_stream(storage);
+        hr = S_OK;
+    }
+    return hr;
+}
+
+/************************************************************************
+ * DefaultHandler_IPersistStorage_InitNew
+ *
+ */
+static HRESULT WINAPI DefaultHandler_IPersistStorage_InitNew(
+           IPersistStorage*     iface,
+           IStorage*            pStg)
+{
+    DefaultHandler *This = impl_from_IPersistStorage(iface);
+    HRESULT hr;
+
+    TRACE("(%p)->(%p)\n", iface, pStg);
+    init_ole_stream(pStg);
+
+    hr = IPersistStorage_InitNew(This->dataCache_PersistStg, pStg);
+
+    if(SUCCEEDED(hr) && object_is_running(This))
+        hr = IPersistStorage_InitNew(This->pPSDelegate, pStg);
+
+    if(SUCCEEDED(hr))
+    {
+        IStorage_AddRef(pStg);
+        This->storage = pStg;
+        This->storage_state = storage_state_initialised;
+    }
+
+    return hr;
+}
+
+
+/************************************************************************
+ * DefaultHandler_IPersistStorage_Load
+ *
+ */
+static HRESULT WINAPI DefaultHandler_IPersistStorage_Load(
+           IPersistStorage*     iface,
+           IStorage*            pStg)
+{
+    DefaultHandler *This = impl_from_IPersistStorage(iface);
+    HRESULT hr;
+
+    TRACE("(%p)->(%p)\n", iface, pStg);
+
+    hr = load_ole_stream(This, pStg);
+
+    if(SUCCEEDED(hr))
+        hr = IPersistStorage_Load(This->dataCache_PersistStg, pStg);
+
+    if(SUCCEEDED(hr) && object_is_running(This))
+        hr = IPersistStorage_Load(This->pPSDelegate, pStg);
+
+    if(SUCCEEDED(hr))
+    {
+        IStorage_AddRef(pStg);
+        This->storage = pStg;
+        This->storage_state = storage_state_loaded;
+    }
+    return hr;
+}
+
+
+/************************************************************************
+ * DefaultHandler_IPersistStorage_Save
+ *
+ */
+static HRESULT WINAPI DefaultHandler_IPersistStorage_Save(
+           IPersistStorage*     iface,
+           IStorage*            pStgSave,
+           BOOL                 fSameAsLoad)
+{
+    DefaultHandler *This = impl_from_IPersistStorage(iface);
+    HRESULT hr;
+
+    TRACE("(%p)->(%p, %d)\n", iface, pStgSave, fSameAsLoad);
+
+    hr = IPersistStorage_Save(This->dataCache_PersistStg, pStgSave, fSameAsLoad);
+    if(SUCCEEDED(hr) && object_is_running(This))
+        hr = IPersistStorage_Save(This->pPSDelegate, pStgSave, fSameAsLoad);
+
+    return hr;
+}
+
+
+/************************************************************************
+ * DefaultHandler_IPersistStorage_SaveCompleted
+ *
+ */
+static HRESULT WINAPI DefaultHandler_IPersistStorage_SaveCompleted(
+           IPersistStorage*     iface,
+           IStorage*            pStgNew)
+{
+    DefaultHandler *This = impl_from_IPersistStorage(iface);
+    HRESULT hr;
+
+    TRACE("(%p)->(%p)\n", iface, pStgNew);
+
+    hr = IPersistStorage_SaveCompleted(This->dataCache_PersistStg, pStgNew);
+
+    if(SUCCEEDED(hr) && object_is_running(This))
+        hr = IPersistStorage_SaveCompleted(This->pPSDelegate, pStgNew);
+
+    if(pStgNew)
+    {
+        IStorage_AddRef(pStgNew);
+        if(This->storage) IStorage_Release(This->storage);
+        This->storage = pStgNew;
+        This->storage_state = storage_state_loaded;
+    }
+
+    return hr;
+}
+
+
+/************************************************************************
+ * DefaultHandler_IPersistStorage_HandsOffStorage
+ *
+ */
+static HRESULT WINAPI DefaultHandler_IPersistStorage_HandsOffStorage(
+            IPersistStorage*     iface)
+{
+    DefaultHandler *This = impl_from_IPersistStorage(iface);
+    HRESULT hr;
+
+    TRACE("(%p)\n", iface);
+
+    hr = IPersistStorage_HandsOffStorage(This->dataCache_PersistStg);
+
+    if(SUCCEEDED(hr) && object_is_running(This))
+        hr = IPersistStorage_HandsOffStorage(This->pPSDelegate);
+
+    if(This->storage) IStorage_Release(This->storage);
+    This->storage = NULL;
+    This->storage_state = storage_state_uninitialised;
+
+    return hr;
+}
+
+
 /*
  * Virtual function tables for the DefaultHandler class.
  */
@@ -1284,27 +1874,57 @@ static const IRunnableObjectVtbl DefaultHandler_IRunnableObject_VTable =
   DefaultHandler_SetContainedObject
 };
 
+static const IAdviseSinkVtbl DefaultHandler_IAdviseSink_VTable =
+{
+  DefaultHandler_IAdviseSink_QueryInterface,
+  DefaultHandler_IAdviseSink_AddRef,
+  DefaultHandler_IAdviseSink_Release,
+  DefaultHandler_IAdviseSink_OnDataChange,
+  DefaultHandler_IAdviseSink_OnViewChange,
+  DefaultHandler_IAdviseSink_OnRename,
+  DefaultHandler_IAdviseSink_OnSave,
+  DefaultHandler_IAdviseSink_OnClose
+};
+
+static const IPersistStorageVtbl DefaultHandler_IPersistStorage_VTable =
+{
+  DefaultHandler_IPersistStorage_QueryInterface,
+  DefaultHandler_IPersistStorage_AddRef,
+  DefaultHandler_IPersistStorage_Release,
+  DefaultHandler_IPersistStorage_GetClassID,
+  DefaultHandler_IPersistStorage_IsDirty,
+  DefaultHandler_IPersistStorage_InitNew,
+  DefaultHandler_IPersistStorage_Load,
+  DefaultHandler_IPersistStorage_Save,
+  DefaultHandler_IPersistStorage_SaveCompleted,
+  DefaultHandler_IPersistStorage_HandsOffStorage
+};
+
 /*********************************************************
  * Methods implementation for the DefaultHandler class.
  */
 static DefaultHandler* DefaultHandler_Construct(
   REFCLSID  clsid,
-  LPUNKNOWN pUnkOuter)
+  LPUNKNOWN pUnkOuter,
+  DWORD flags,
+  IClassFactory *pCF)
 {
   DefaultHandler* This = NULL;
+  HRESULT hr;
 
-  /*
-   * Allocate space for the object.
-   */
   This = HeapAlloc(GetProcessHeap(), 0, sizeof(DefaultHandler));
 
   if (!This)
     return This;
 
-  This->lpVtbl = &DefaultHandler_IOleObject_VTable;
-  This->lpvtblIUnknown = &DefaultHandler_NDIUnknown_VTable;
-  This->lpvtblIDataObject = &DefaultHandler_IDataObject_VTable;
-  This->lpvtblIRunnableObject = &DefaultHandler_IRunnableObject_VTable;
+  This->IOleObject_iface.lpVtbl = &DefaultHandler_IOleObject_VTable;
+  This->IUnknown_iface.lpVtbl = &DefaultHandler_NDIUnknown_VTable;
+  This->IDataObject_iface.lpVtbl = &DefaultHandler_IDataObject_VTable;
+  This->IRunnableObject_iface.lpVtbl = &DefaultHandler_IRunnableObject_VTable;
+  This->IAdviseSink_iface.lpVtbl = &DefaultHandler_IAdviseSink_VTable;
+  This->IPersistStorage_iface.lpVtbl = &DefaultHandler_IPersistStorage_VTable;
+
+  This->inproc_server = (flags & EMBDHLP_INPROC_SERVER) ? TRUE : FALSE;
 
   /*
    * Start with one reference count. The caller of this function
@@ -1315,11 +1935,11 @@ static DefaultHandler* DefaultHandler_Construct(
   /*
    * Initialize the outer unknown
    * We don't keep a reference on the outer unknown since, the way
-   * aggregation works, our lifetime is at least as large as it's
+   * aggregation works, our lifetime is at least as large as its
    * lifetime.
    */
   if (!pUnkOuter)
-    pUnkOuter = (IUnknown*)&This->lpvtblIUnknown;
+    pUnkOuter = &This->IUnknown_iface;
 
   This->outerUnknown = pUnkOuter;
 
@@ -1328,15 +1948,28 @@ static DefaultHandler* DefaultHandler_Construct(
    * We aggregate with the datacache. Make sure we pass our outer
    * unknown as the datacache's outer unknown.
    */
-  CreateDataCache(This->outerUnknown,
-                 clsid,
-                 &IID_IUnknown,
-                 (void**)&This->dataCache);
+  hr = CreateDataCache(This->outerUnknown,
+                       clsid,
+                       &IID_IUnknown,
+                       (void**)&This->dataCache);
+  if(SUCCEEDED(hr))
+  {
+    hr = IUnknown_QueryInterface(This->dataCache, &IID_IPersistStorage, (void**)&This->dataCache_PersistStg);
+    /* keeping a reference to This->dataCache_PersistStg causes us to keep a
+     * reference on the outer object */
+    if (SUCCEEDED(hr))
+        IUnknown_Release(This->outerUnknown);
+    else
+        IUnknown_Release(This->dataCache);
+  }
+  if(FAILED(hr))
+  {
+    ERR("Unexpected error creating data cache\n");
+    HeapFree(GetProcessHeap(), 0, This);
+    return NULL;
+  }
 
-  /*
-   * Initialize the other data members of the class.
-   */
-  memcpy(&This->clsid, clsid, sizeof(CLSID));
+  This->clsid = *clsid;
   This->clientSite = NULL;
   This->oleAdviseHolder = NULL;
   This->dataAdviseHolder = NULL;
@@ -1344,6 +1977,36 @@ static DefaultHandler* DefaultHandler_Construct(
   This->containerObj = NULL;
   This->pOleDelegate = NULL;
   This->pPSDelegate = NULL;
+  This->pDataDelegate = NULL;
+  This->object_state = object_state_not_running;
+
+  This->dwAdvConn = 0;
+  This->storage = NULL;
+  This->storage_state = storage_state_uninitialised;
+
+  if (This->inproc_server && !(flags & EMBDHLP_DELAYCREATE))
+  {
+    HRESULT hr;
+    This->pCFObject = NULL;
+    if (pCF)
+      hr = IClassFactory_CreateInstance(pCF, NULL, &IID_IOleObject, (void **)&This->pOleDelegate);
+    else
+      hr = CoCreateInstance(&This->clsid, NULL, CLSCTX_INPROC_SERVER,
+                            &IID_IOleObject, (void **)&This->pOleDelegate);
+    if (SUCCEEDED(hr))
+      hr = IOleObject_QueryInterface(This->pOleDelegate, &IID_IPersistStorage, (void **)&This->pPSDelegate);
+    if (SUCCEEDED(hr))
+      hr = IOleObject_QueryInterface(This->pOleDelegate, &IID_IDataObject, (void **)&This->pDataDelegate);
+    if (SUCCEEDED(hr))
+      This->object_state = object_state_running;
+    if (FAILED(hr))
+      WARN("object creation failed with error %08x\n", hr);
+  }
+  else
+  {
+    This->pCFObject = pCF;
+    if (pCF) IClassFactory_AddRef(pCF);
+  }
 
   return This;
 }
@@ -1351,66 +2014,82 @@ static DefaultHandler* DefaultHandler_Construct(
 static void DefaultHandler_Destroy(
   DefaultHandler* This)
 {
-  if (This->pOleDelegate)
-    IOleObject_Release(This->pOleDelegate);
-  if (This->pPSDelegate)
-    IPersistStorage_Release(This->pPSDelegate);
+  TRACE("(%p)\n", This);
+
+  /* AddRef/Release may be called on this object during destruction.
+   * Prevent the object being destroyed recursively by artificially raising
+   * the reference count. */
+  This->ref = 10000;
+
+  /* release delegates */
+  DefaultHandler_Stop(This);
+  release_delegates(This);
 
-  /* Free the strings idenfitying the object */
   HeapFree( GetProcessHeap(), 0, This->containerApp );
   This->containerApp = NULL;
   HeapFree( GetProcessHeap(), 0, This->containerObj );
   This->containerObj = NULL;
 
-  /* Release our reference to the data cache. */
   if (This->dataCache)
   {
+    /* to balance out the release of dataCache_PersistStg which will result
+     * in a reference being released from the outer unknown */
+    IUnknown_AddRef(This->outerUnknown);
+    IPersistStorage_Release(This->dataCache_PersistStg);
     IUnknown_Release(This->dataCache);
+    This->dataCache_PersistStg = NULL;
     This->dataCache = NULL;
   }
 
-  /* Same thing for the client site. */
   if (This->clientSite)
   {
     IOleClientSite_Release(This->clientSite);
     This->clientSite = NULL;
   }
 
-  /* And the advise holder. */
   if (This->oleAdviseHolder)
   {
     IOleAdviseHolder_Release(This->oleAdviseHolder);
     This->oleAdviseHolder = NULL;
   }
 
-  /* And the data advise holder. */
   if (This->dataAdviseHolder)
   {
     IDataAdviseHolder_Release(This->dataAdviseHolder);
     This->dataAdviseHolder = NULL;
   }
 
-  /* Free the actual default handler structure. */
+  if (This->storage)
+  {
+    IStorage_Release(This->storage);
+    This->storage = NULL;
+  }
+
+  if (This->pCFObject)
+  {
+    IClassFactory_Release(This->pCFObject);
+    This->pCFObject = NULL;
+  }
+
   HeapFree(GetProcessHeap(), 0, This);
 }
 
 /******************************************************************************
- * OleCreateDefaultHandler [OLE32.@]
+ * OleCreateEmbeddingHelper [OLE32.@]
  */
-HRESULT WINAPI OleCreateDefaultHandler(
+HRESULT WINAPI OleCreateEmbeddingHelper(
   REFCLSID  clsid,
   LPUNKNOWN pUnkOuter,
+  DWORD     flags,
+  IClassFactory *pCF,
   REFIID    riid,
   LPVOID*   ppvObj)
 {
   DefaultHandler* newHandler = NULL;
   HRESULT         hr         = S_OK;
 
-  TRACE("(%s, %p, %s, %p)\n", debugstr_guid(clsid), pUnkOuter, debugstr_guid(riid), ppvObj);
+  TRACE("(%s, %p, %08x, %p, %s, %p)\n", debugstr_guid(clsid), pUnkOuter, flags, pCF, debugstr_guid(riid), ppvObj);
 
-  /*
-   * Sanity check
-   */
   if (!ppvObj)
     return E_POINTER;
 
@@ -1428,7 +2107,7 @@ HRESULT WINAPI OleCreateDefaultHandler(
   /*
    * Try to construct a new instance of the class.
    */
-  newHandler = DefaultHandler_Construct(clsid, pUnkOuter);
+  newHandler = DefaultHandler_Construct(clsid, pUnkOuter, flags, pCF);
 
   if (!newHandler)
     return E_OUTOFMEMORY;
@@ -1436,13 +2115,104 @@ HRESULT WINAPI OleCreateDefaultHandler(
   /*
    * Make sure it supports the interface required by the caller.
    */
-  hr = IUnknown_QueryInterface((IUnknown*)&newHandler->lpvtblIUnknown, riid, ppvObj);
+  hr = IUnknown_QueryInterface(&newHandler->IUnknown_iface, riid, ppvObj);
 
   /*
    * Release the reference obtained in the constructor. If
    * the QueryInterface was unsuccessful, it will free the class.
    */
-  IUnknown_Release((IUnknown*)&newHandler->lpvtblIUnknown);
+  IUnknown_Release(&newHandler->IUnknown_iface);
 
   return hr;
 }
+
+
+/******************************************************************************
+ * OleCreateDefaultHandler [OLE32.@]
+ */
+HRESULT WINAPI OleCreateDefaultHandler(REFCLSID clsid, LPUNKNOWN pUnkOuter,
+                                       REFIID riid, LPVOID* ppvObj)
+{
+    TRACE("(%s, %p, %s, %p)\n", debugstr_guid(clsid), pUnkOuter,debugstr_guid(riid), ppvObj);
+    return OleCreateEmbeddingHelper(clsid, pUnkOuter, EMBDHLP_INPROC_HANDLER | EMBDHLP_CREATENOW,
+                                    NULL, riid, ppvObj);
+}
+
+typedef struct HandlerCF
+{
+    IClassFactory IClassFactory_iface;
+    LONG refs;
+    CLSID clsid;
+} HandlerCF;
+
+static inline HandlerCF *impl_from_IClassFactory(IClassFactory *iface)
+{
+    return CONTAINING_RECORD(iface, HandlerCF, IClassFactory_iface);
+}
+
+static HRESULT WINAPI
+HandlerCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid, LPVOID *ppv)
+{
+    *ppv = NULL;
+    if (IsEqualIID(riid,&IID_IUnknown) ||
+        IsEqualIID(riid,&IID_IClassFactory))
+    {
+        *ppv = iface;
+        IClassFactory_AddRef(iface);
+        return S_OK;
+    }
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI HandlerCF_AddRef(LPCLASSFACTORY iface)
+{
+    HandlerCF *This = impl_from_IClassFactory(iface);
+    return InterlockedIncrement(&This->refs);
+}
+
+static ULONG WINAPI HandlerCF_Release(LPCLASSFACTORY iface)
+{
+    HandlerCF *This = impl_from_IClassFactory(iface);
+    ULONG refs = InterlockedDecrement(&This->refs);
+    if (!refs)
+        HeapFree(GetProcessHeap(), 0, This);
+    return refs;
+}
+
+static HRESULT WINAPI
+HandlerCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pUnk,
+                         REFIID riid, LPVOID *ppv)
+{
+    HandlerCF *This = impl_from_IClassFactory(iface);
+    return OleCreateDefaultHandler(&This->clsid, pUnk, riid, ppv);
+}
+
+static HRESULT WINAPI HandlerCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
+{
+    FIXME("(%d), stub!\n",fLock);
+    return S_OK;
+}
+
+static const IClassFactoryVtbl HandlerClassFactoryVtbl = {
+    HandlerCF_QueryInterface,
+    HandlerCF_AddRef,
+    HandlerCF_Release,
+    HandlerCF_CreateInstance,
+    HandlerCF_LockServer
+};
+
+HRESULT HandlerCF_Create(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
+{
+    HRESULT hr;
+    HandlerCF *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
+    if (!This) return E_OUTOFMEMORY;
+    This->IClassFactory_iface.lpVtbl = &HandlerClassFactoryVtbl;
+    This->refs = 0;
+    This->clsid = *rclsid;
+
+    hr = IUnknown_QueryInterface((IUnknown *)&This->IClassFactory_iface, riid, ppv);
+    if (FAILED(hr))
+        HeapFree(GetProcessHeap(), 0, This);
+
+    return hr;
+}