embeddedobj/source/inc/oleembobj.hxx      |   14 
 embeddedobj/source/msole/olecomponent.cxx |  531 ++++++++++++++++++------------
 embeddedobj/source/msole/olecomponent.hxx |   12 
 embeddedobj/source/msole/oleembed.cxx     |   21 -
 embeddedobj/source/msole/olevisual.cxx    |    7 
 5 files changed, 357 insertions(+), 228 deletions(-)

New commits:
commit e2bfc34d146806a8f96be0cd2323d716f12cba4e
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Wed Mar 6 15:36:55 2024 +0600
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Mon Mar 11 04:39:58 2024 +0100

    Reimplement OleComponentNative_Impl to use IGlobalInterfaceTable
    
    ... to make sure that object methods are called in correct apartment
    
    The user-visible problem was, that running a Java code that connects
    to LibreOffice, and opening a document with an embedded OLE object
    (it was Word object in a specific case, which needs activation at
    opening stage, because these objects have OLEMISC_RECOMPOSEONRESIZE
    flag), using loadComponentFromURL with "OnMainThread" set to true,
    then closing the document, resulted in a hang after several hundreds
    iterations. This was caused by Word process, that was started in
    background to serve the COM calls, wasn't closed properly, and kept
    all the objects in memory, until OOM.
    
    The reason why it wasn't closed was failed call to IOleObject::Close
    in OleComponent::CloseObject, which returned RPC_E_WRONG_THREAD,
    because the activation of the OLE object happened in the main thread
    (because of "OnMainThread"), which is STA, but closing happened in
    the handler thread (belonging to MTA).
    
    Similar problems previously were addressed in commits
    2dc3a6c273cb82506842864481d78df7294debbf (framework: allow loading a
    component on the main thread, 2018-12-20),
    6002014ce0a5c9cea22c14b2437b7a508b2c72cb (framework: allow loading a
    component on the main thread, using XDesktop, 2021-04-28),
    d5cd62164d32273a25913c93aa04be9f7f3a4073 (embeddedobj: handle getting
    the visible area on a thread, 2021-05-07).
    These changes tried different workarounds for the same problem, when
    a COM object instantiated in one apartment is later manipulated from
    another, which fails. First two handled the case when the document
    is loaded from a non-UI thread, and then manipulated with the UI; to
    handle that, they introduced flags that delegated opening the file
    to the main (UI) thread. The last change tried to handle the reverse
    problem of the OLE object instantiated in the main thread was saved
    in a handler thread, which again failed; the workaround was, again,
    to try to delegate the second attempt to the main thread.
    
    But basically all methods can fail in such circumstations, as shown
    in this problem's case. The "OnMainThread" flag must be passed to
    fileopen functions explicitly. Also, the workarounds only work by
    passing everything to STA, and don't target a case when the calls
    must be passed from STA to MTA.
    
    Since Windows 2000, there is IGlobalInterfaceTable, which goal is
    to solve this problem. It allows to use an intermediate object,
    which can transparently delegate all calls to the correct thread.
    
    This change re-implements how OLE objects are referenced from
    OleComponentNative_Impl, using the said IGlobalInterfaceTable.
    This should hopefully obsolete the previous workarounds, which
    nevertheless are kept for now.
    
    Change-Id: Ia1c590e547ed24a2c7389283aed6cc3d8ea024b0
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164457
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/embeddedobj/source/inc/oleembobj.hxx 
b/embeddedobj/source/inc/oleembobj.hxx
index a59a33551f06..274ecfaf8847 100644
--- a/embeddedobj/source/inc/oleembobj.hxx
+++ b/embeddedobj/source/inc/oleembobj.hxx
@@ -453,4 +453,18 @@ public:
     css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() 
override;
 };
 
+class ClearedMutexArea
+{
+public:
+    ClearedMutexArea(osl::ResettableMutexGuard& guard)
+        : m_guard(guard)
+    {
+        m_guard.clear();
+    }
+    ~ClearedMutexArea() { m_guard.reset(); }
+
+private:
+    osl::ResettableMutexGuard& m_guard;
+};
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/embeddedobj/source/msole/olecomponent.cxx 
b/embeddedobj/source/msole/olecomponent.cxx
index 2bc0263343e9..98ab58c8c622 100644
--- a/embeddedobj/source/msole/olecomponent.cxx
+++ b/embeddedobj/source/msole/olecomponent.cxx
@@ -43,6 +43,7 @@
 #include <o3tl/char16_t2wchar_t.hxx>
 #include <o3tl/unit_conversion.hxx>
 #include <systools/win32/comtools.hxx>
+#include <vcl/svapp.hxx>
 #include <vcl/threadex.hxx>
 
 #include "graphconvert.hxx"
@@ -60,23 +61,81 @@ using namespace ::comphelper;
 #define     MAX_ENUM_ELE     20
 #define     FORMATS_NUM      3
 
-typedef std::vector< FORMATETC* > FormatEtcList;
-
 FORMATETC const pFormatTemplates[FORMATS_NUM] = {
                     { CF_ENHMETAFILE, nullptr, 0, -1, TYMED_ENHMF },
                     { CF_METAFILEPICT, nullptr, 0, -1, TYMED_MFPICT },
                     { CF_BITMAP, nullptr, 0, -1, TYMED_GDI } };
 
 
-struct OleComponentNative_Impl {
+// We have at least one single-threaded apartment (STA) in the process (the 
VCL Main thread, which
+// is the GUI thread), and a multithreaded apartment (MTA) for most of other 
threads. OLE objects
+// may be created in either: in interactive mode, this typically happens in 
the STA; when serving
+// external requests, this may be either in STA (when explicit "OnMainThread" 
argument is passed to
+// loadComponentFromURL, and the instantiation of the object happens during 
the load), or in MTA
+// (the thread actually serving the incoming calls).
+//
+// The objects typically can only be used in the appartment where they were 
instantiated. This means
+// that e.g. a call to IOleObject::Close will fail, if it is performed in a 
different thread, when
+// it was started in the main thread. And vice versa, opening a document in a 
handler thread, then
+// trying to interact with the OLE object in GUI would fail.
+//
+// To handle this, several workarounds were implemented in the past; the 
mentioned "OnMainThread"
+// argument is one of these, allowing open document requests be processed not 
in the handler threads
+// that receired the request, but in the main thread which will then be used 
for interaction. Also
+// OleComponent::GetExtent was changed to check if the first call to 
IDataObject::GetData failed
+// with RPC_E_WRONG_THREAD, and then retry in the main thread.
+//
+// But ultimately every call to the OLE object needs such checks. E.g., 
failing to close the object
+// keeps the server running, effectively leaking resources, until it 
crashes/freezes after multiple
+// iterations.
+//
+// Currently, OleComponentNative_Impl is implemented using 
IGlobalInterfaceTable, which allows to
+// register an object in process-global instance of the table from the thread 
that instantiated the
+// object, and obtain a "cookie" (a number); and then use that cookie from any 
thread to access that
+// object. The global table will do its magic to provide either the original 
object (when it is
+// requested from the same apartment as used for its registration), or a 
"proxy", which will marshal
+// all calls to the proper thread, transparently for the caller. This 
implementation should obsolete
+// the previous workarounds (in theory).
+//
+// m_pGlobalTable is the reference to the global table.
+// The storage object gets registered in the global table immediately when 
it's created.
+// But the OLE object itself can't be registered immediately, before it is 
run: an attempt to call
+// RegisterInterfaceInGlobal with such a newly created OLE object fails with 
CO_E_OBJNOTCONNECTED.
+// Thus, the initial reference to the OLE object (which at this stage seems to 
be apartment-neutral)
+// is stored to m_pObj. Only when it is run, it is registered in the global 
table.
+//
+// Indeed, the implicit change of the thread is a blocking operation, which 
opens a wonderful new
+// opportunities for shiny deadlocks. Thus, precautions are needed to avoid 
them.
+//
+// When the OLE object is accessed by m_pObj (should be only in initialization 
code!), no measures
+// are taken to change locking. But when it is accessed by getObj() - which 
may return the proxy -
+// the calls are guarded by a SolarMutexReleaser, to allow the other thread do 
its job.
+//
+// There are at least two other mutexes in play here. One is in 
OleEmbeddedObject, that holds the
+// OleComponent. The calls to OleComponent's methods are also wrapped there 
into unlock/lock pairs
+// (see OleEmbeddedObject::changeState). The other is in OleComponent itself. 
For now, I see no
+// deadlocks caused by that mutex, so no unlock/lock is introduced for that. 
It may turn out to be
+// required eventually.
+class OleComponentNative_Impl
+{
+public:
     sal::systools::COMReference< IUnknown > m_pObj;
-    sal::systools::COMReference< IOleObject > m_pOleObject;
-    sal::systools::COMReference< IViewObject2 > m_pViewObject2;
-    sal::systools::COMReference< IStorage > m_pIStorage;
-    FormatEtcList m_aFormatsList;
     uno::Sequence< datatransfer::DataFlavor > m_aSupportedGraphFormats;
 
+    // The getters may return a proxy, that redirects the calls to another 
thread.
+    // Thus, calls to methods of returned objects must be inside solar mutex 
releaser.
+    auto getStorage() const { return getInterface<IStorage>(m_nStorage); }
+    auto getObj() const { return m_nOleObject ? 
getInterface<IUnknown>(m_nOleObject) : m_pObj; }
+    template <typename T>
+    auto get() const { return 
getObj().QueryInterface<T>(sal::systools::COM_QUERY); }
+
+    void registerStorage(IStorage* pStorage) { registerInterface(pStorage, 
m_nStorage); }
+    void registerObj() { registerInterface(m_pObj.get(), m_nOleObject); }
+
+    bool IsStorageRegistered() const { return m_nStorage != 0; }
+
     OleComponentNative_Impl()
+        : m_pGlobalTable(CLSID_StdGlobalInterfaceTable, nullptr, 
CLSCTX_INPROC_SERVER)
     {
         // TODO: Extend format list
         m_aSupportedGraphFormats = {
@@ -108,6 +167,14 @@ struct OleComponentNative_Impl {
         };
     }
 
+    ~OleComponentNative_Impl()
+    {
+        if (m_nOleObject)
+            m_pGlobalTable->RevokeInterfaceFromGlobal(m_nOleObject);
+        if (m_nStorage)
+            m_pGlobalTable->RevokeInterfaceFromGlobal(m_nStorage);
+    }
+
     bool ConvertDataForFlavor( const STGMEDIUM& aMedium,
                                     const datatransfer::DataFlavor& aFlavor,
                                     uno::Any& aResult );
@@ -115,8 +182,39 @@ struct OleComponentNative_Impl {
     bool GraphicalFlavor( const datatransfer::DataFlavor& aFlavor );
 
     uno::Sequence< datatransfer::DataFlavor > GetFlavorsForAspects( sal_uInt32 
nSupportedAspects );
+
+    sal::systools::COMReference<IStorage> CreateNewStorage(const OUString& 
url);
+
+private:
+    sal::systools::COMReference<IGlobalInterfaceTable> m_pGlobalTable;
+    DWORD m_nStorage = 0;
+    DWORD m_nOleObject = 0;
+
+    template <typename T> sal::systools::COMReference<T> getInterface(DWORD 
cookie) const
+    {
+        sal::systools::COMReference<T> result;
+        HRESULT hr = m_pGlobalTable->GetInterfaceFromGlobal(cookie, 
IID_PPV_ARGS(&result));
+        SAL_WARN_IF(FAILED(hr), "embeddedobj.ole",
+                    "GetInterfaceFromGlobal failed: is cookie " << cookie << " 
not registered?");
+        return result;
+    }
+
+    template <typename T> void registerInterface(T* pInterface, DWORD& cookie)
+    {
+        assert(cookie == 0); // do not set again
+        HRESULT hr = m_pGlobalTable->RegisterInterfaceInGlobal(pInterface, 
__uuidof(T), &cookie);
+        SAL_WARN_IF(FAILED(hr), "embeddedobj.ole", "RegisterInterfaceInGlobal 
failed");
+    }
 };
 
+namespace
+{
+struct SafeSolarMutexReleaser
+{
+    SolarMutexGuard guard; // To make sure we actually hold it prior to release
+    SolarMutexReleaser releaser;
+};
+}
 
 static DWORD GetAspectFromFlavor( const datatransfer::DataFlavor& aFlavor )
 {
@@ -148,23 +246,6 @@ static OUString GetFlavorSuffixFromAspect( DWORD nAsp )
 }
 
 
-static HRESULT OpenIStorageFromURL_Impl( const OUString& aURL, IStorage** 
ppIStorage )
-{
-    OSL_ENSURE( ppIStorage, "The pointer must not be empty!" );
-
-    OUString aFilePath;
-    if ( !ppIStorage || ::osl::FileBase::getSystemPathFromFileURL( aURL, 
aFilePath ) != ::osl::FileBase::E_None )
-        throw uno::RuntimeException(); // TODO: something dangerous happened
-
-    return StgOpenStorage( o3tl::toW(aFilePath.getStr()),
-                             nullptr,
-                             STGM_READWRITE | STGM_TRANSACTED, // | 
STGM_DELETEONRELEASE,
-                             nullptr,
-                             0,
-                             ppIStorage );
-}
-
-
 bool OleComponentNative_Impl::ConvertDataForFlavor( const STGMEDIUM& aMedium,
                                                         const 
datatransfer::DataFlavor& aFlavor,
                                                         uno::Any& aResult )
@@ -321,12 +402,10 @@ OleComponent::OleComponent( const uno::Reference< 
uno::XComponentContext >& xCon
 : m_pInterfaceContainer( nullptr )
 , m_bDisposed( false )
 , m_bModified( false )
-, m_pNativeImpl( new OleComponentNative_Impl() )
+, m_pNativeImpl( std::make_unique<OleComponentNative_Impl>() )
 , m_pUnoOleObject( pUnoOleObject )
 , m_pOleWrapClientSite( nullptr )
 , m_pImplAdviseSink( nullptr )
-, m_nOLEMiscFlags( 0 )
-, m_nAdvConn( 0 )
 , m_xContext( xContext )
 , m_bOleInitialized( false )
 , m_bWorkaroundActive( false )
@@ -364,14 +443,6 @@ OleComponent::~OleComponent()
             Dispose();
         } catch( const uno::Exception& ) {}
     }
-
-    for (auto const& format : m_pNativeImpl->m_aFormatsList)
-    {
-        delete format;
-    }
-    m_pNativeImpl->m_aFormatsList.clear();
-
-    delete m_pNativeImpl;
 }
 
 void OleComponent::Dispose()
@@ -429,30 +500,37 @@ void OleComponent::disconnectEmbeddedObject()
 }
 
 
-void OleComponent::CreateNewIStorage_Impl()
+OUString OleComponent::getTempURL() const
 {
-    // TODO: in future a global memory could be used instead of file.
-
-    // write the stream to the temporary file
-    OUString aTempURL;
-
     OSL_ENSURE( m_pUnoOleObject, "Unexpected object absence!" );
     if ( m_pUnoOleObject )
-        aTempURL = m_pUnoOleObject->CreateTempURLEmpty_Impl();
+        return m_pUnoOleObject->CreateTempURLEmpty_Impl();
     else
-        aTempURL = GetNewTempFileURL_Impl( m_xContext );
+        return GetNewTempFileURL_Impl(m_xContext);
+}
 
-    if ( !aTempURL.getLength() )
+
+sal::systools::COMReference<IStorage> 
OleComponentNative_Impl::CreateNewStorage(const OUString& url)
+{
+    if (IsStorageRegistered())
+        throw io::IOException(); // TODO:the object is already initialized
+    // TODO: in future a global memory could be used instead of file.
+
+    // write the stream to the temporary file
+    if (url.isEmpty())
         throw uno::RuntimeException(); // TODO
 
     // open an IStorage based on the temporary file
     OUString aTempFilePath;
-    if ( ::osl::FileBase::getSystemPathFromFileURL( aTempURL, aTempFilePath ) 
!= ::osl::FileBase::E_None )
+    if (osl::FileBase::getSystemPathFromFileURL(url, aTempFilePath) != 
osl::FileBase::E_None)
         throw uno::RuntimeException(); // TODO: something dangerous happened
 
-    HRESULT hr = StgCreateDocfile( o3tl::toW(aTempFilePath.getStr()), 
STGM_CREATE | STGM_READWRITE | STGM_TRANSACTED | STGM_DELETEONRELEASE, 0, 
&m_pNativeImpl->m_pIStorage );
-    if ( FAILED( hr ) || !m_pNativeImpl->m_pIStorage )
+    sal::systools::COMReference<IStorage> pStorage;
+    HRESULT hr = StgCreateDocfile( o3tl::toW(aTempFilePath.getStr()), 
STGM_CREATE | STGM_READWRITE | STGM_TRANSACTED | STGM_DELETEONRELEASE, 0, 
&pStorage );
+    if (FAILED(hr) || !pStorage)
         throw io::IOException(); // TODO: transport error code?
+    registerStorage(pStorage);
+    return pStorage;
 }
 
 
@@ -482,16 +560,19 @@ uno::Sequence< datatransfer::DataFlavor > 
OleComponentNative_Impl::GetFlavorsFor
 
 void OleComponent::RetrieveObjectDataFlavors_Impl()
 {
-    if ( !m_pNativeImpl->m_pOleObject )
+    if (!m_pNativeImpl->m_pObj)
         throw embed::WrongStateException(); // TODO: the object is in wrong 
state
 
     if ( !m_aDataFlavors.getLength() )
     {
-        sal::systools::COMReference< IDataObject > 
pDataObject(m_pNativeImpl->m_pObj, sal::systools::COM_QUERY);
-        if ( pDataObject )
+        if (auto pDataObject = m_pNativeImpl->get<IDataObject>())
         {
+            HRESULT hr;
             sal::systools::COMReference< IEnumFORMATETC > pFormatEnum;
-            HRESULT hr = pDataObject->EnumFormatEtc( DATADIR_GET, &pFormatEnum 
);
+            {
+                SafeSolarMutexReleaser releaser;
+                hr = pDataObject->EnumFormatEtc(DATADIR_GET, &pFormatEnum);
+            }
             if ( SUCCEEDED( hr ) && pFormatEnum )
             {
                 FORMATETC pElem[ MAX_ENUM_ELE ];
@@ -531,19 +612,20 @@ void OleComponent::RetrieveObjectDataFlavors_Impl()
 }
 
 
-bool OleComponent::InitializeObject_Impl()
+void OleComponent::InitializeObject_Impl()
 // There will be no static objects!
 {
     if ( !m_pNativeImpl->m_pObj )
-        return false;
+        throw embed::WrongStateException();
 
     // the linked object will be detected here
     OSL_ENSURE( m_pUnoOleObject, "Unexpected object absence!" );
     if ( m_pUnoOleObject )
         m_pUnoOleObject->SetObjectIsLink_Impl( 
m_pNativeImpl->m_pObj.QueryInterface<IOleLink>(sal::systools::COM_QUERY).is() );
 
-    if ( !m_pNativeImpl->m_pViewObject2.set(m_pNativeImpl->m_pObj, 
sal::systools::COM_QUERY) )
-        return false;
+    auto 
pViewObject2(m_pNativeImpl->m_pObj.QueryInterface<IViewObject2>(sal::systools::COM_QUERY));
+    if (!pViewObject2)
+        throw uno::RuntimeException(); // TODO
 
     // remove all the caches
     if ( sal::systools::COMReference< IOleCache > pIOleCache{ 
m_pNativeImpl->m_pObj, sal::systools::COM_QUERY } )
@@ -566,23 +648,24 @@ bool OleComponent::InitializeObject_Impl()
         hr2 = pIOleCache->Cache( &aFormat, ADVFCACHE_ONSAVE, &nConn );
     }
 
-    if ( !m_pNativeImpl->m_pOleObject.set(m_pNativeImpl->m_pObj, 
sal::systools::COM_QUERY) )
-        return false; // Static objects are not supported, they should be 
inserted as graphics
+    auto 
pOleObject(m_pNativeImpl->m_pObj.QueryInterface<IOleObject>(sal::systools::COM_QUERY));
+    if (!pOleObject)
+        throw uno::RuntimeException(); // Static objects are not supported, 
they should be inserted as graphics
 
-    m_pNativeImpl->m_pOleObject->GetMiscStatus( DVASPECT_CONTENT, 
reinterpret_cast<DWORD*>(&m_nOLEMiscFlags) );
+    DWORD nOLEMiscFlags(0);
+    pOleObject->GetMiscStatus(DVASPECT_CONTENT, 
reinterpret_cast<DWORD*>(&nOLEMiscFlags));
     // TODO: use other misc flags also
     // the object should have drawable aspect even in case it supports only 
iconic representation
-    // if ( m_nOLEMiscFlags & OLEMISC_ONLYICONIC )
+    // if ( nOLEMiscFlags & OLEMISC_ONLYICONIC )
 
-    m_pNativeImpl->m_pOleObject->SetClientSite( m_pOleWrapClientSite );
+    pOleObject->SetClientSite(m_pOleWrapClientSite);
 
     // the only need in this registration is workaround for close notification
-    m_pNativeImpl->m_pOleObject->Advise( m_pImplAdviseSink, 
reinterpret_cast<DWORD*>(&m_nAdvConn) );
-    m_pNativeImpl->m_pViewObject2->SetAdvise( DVASPECT_CONTENT, 0, 
m_pImplAdviseSink );
+    DWORD nAdvConn(0);
+    pOleObject->Advise(m_pImplAdviseSink, reinterpret_cast<DWORD*>(&nAdvConn));
+    pViewObject2->SetAdvise(DVASPECT_CONTENT, 0, m_pImplAdviseSink);
 
-    OleSetContainedObject( m_pNativeImpl->m_pOleObject, TRUE );
-
-    return true;
+    OleSetContainedObject(pOleObject, TRUE);
 }
 
 namespace
@@ -617,62 +700,62 @@ void OleComponent::LoadEmbeddedObject( const OUString& 
aTempURL )
     if ( !aTempURL.getLength() )
         throw lang::IllegalArgumentException(); // TODO
 
-    if ( m_pNativeImpl->m_pIStorage )
+    if (m_pNativeImpl->IsStorageRegistered())
         throw io::IOException(); // TODO the object is already initialized or 
wrong initialization is done
 
     // open an IStorage based on the temporary file
-    HRESULT hr = OpenIStorageFromURL_Impl( aTempURL, 
&m_pNativeImpl->m_pIStorage );
+    OUString aFilePath;
+    if (osl::FileBase::getSystemPathFromFileURL(aTempURL, aFilePath) != 
::osl::FileBase::E_None)
+        throw uno::RuntimeException(); // TODO: something dangerous happened
 
-    if ( FAILED( hr ) || !m_pNativeImpl->m_pIStorage )
+    sal::systools::COMReference<IStorage> pStorage;
+    HRESULT hr = StgOpenStorage(o3tl::toW(aFilePath.getStr()), nullptr,
+                                STGM_READWRITE | STGM_TRANSACTED, // | 
STGM_DELETEONRELEASE,
+                                nullptr, 0, &pStorage);
+    if (FAILED(hr) || !pStorage)
         throw io::IOException(); // TODO: transport error code?
 
-    hr = OleLoadSeh(m_pNativeImpl->m_pIStorage, &m_pNativeImpl->m_pObj);
-    if ( FAILED( hr ) || !m_pNativeImpl->m_pObj )
-    {
+    m_pNativeImpl->registerStorage(pStorage);
+
+    hr = OleLoadSeh(pStorage, &m_pNativeImpl->m_pObj);
+    if (FAILED(hr))
         throw uno::RuntimeException();
-    }
 
-    if ( !InitializeObject_Impl() )
-        throw uno::RuntimeException(); // TODO
+    InitializeObject_Impl();
 }
 
 
 void OleComponent::CreateObjectFromClipboard()
 {
-    if ( m_pNativeImpl->m_pIStorage )
-        throw io::IOException(); // TODO:the object is already initialized
-
-    CreateNewIStorage_Impl();
-    if ( !m_pNativeImpl->m_pIStorage )
+    auto pStorage(m_pNativeImpl->CreateNewStorage(getTempURL()));
+    if (!pStorage)
         throw uno::RuntimeException(); // TODO
 
     IDataObject * pDO = nullptr;
     HRESULT hr = OleGetClipboard( &pDO );
-    if( SUCCEEDED( hr ) && pDO )
+    if (FAILED(hr))
+        throw uno::RuntimeException();
+
+    hr = OleQueryCreateFromData(pDO);
+    if (S_OK == hr)
     {
-        hr = OleQueryCreateFromData( pDO );
-        if( S_OK == GetScode( hr ) )
-        {
-            hr = OleCreateFromData( pDO,
-                                    IID_IUnknown,
-                                    OLERENDER_DRAW, // OLERENDER_FORMAT
-                                    nullptr,        // &aFormat,
-                                    nullptr,
-                                    m_pNativeImpl->m_pIStorage,
-                                    
reinterpret_cast<void**>(&m_pNativeImpl->m_pObj) );
-        }
-        else
-        {
-            // Static objects are not supported
-            pDO->Release();
-        }
+        hr = OleCreateFromData( pDO,
+                                IID_IUnknown,
+                                OLERENDER_DRAW, // OLERENDER_FORMAT
+                                nullptr,        // &aFormat,
+                                nullptr,
+                                pStorage,
+                                IID_PPV_ARGS_Helper(&m_pNativeImpl->m_pObj) );
+        if (FAILED(hr))
+            throw uno::RuntimeException();
+    }
+    else
+    {
+        // Static objects are not supported
+        pDO->Release();
     }
 
-    if ( FAILED( hr ) || !m_pNativeImpl->m_pObj )
-        throw uno::RuntimeException();
-
-    if ( !InitializeObject_Impl() )
-        throw uno::RuntimeException(); // TODO
+    InitializeObject_Impl();
 }
 
 
@@ -683,11 +766,8 @@ void OleComponent::CreateNewEmbeddedObject( const 
uno::Sequence< sal_Int8 >& aSe
     if ( !GetClassIDFromSequence_Impl( aSeqCLSID, aClsID ) )
         throw lang::IllegalArgumentException(); // TODO
 
-    if ( m_pNativeImpl->m_pIStorage )
-        throw io::IOException(); // TODO:the object is already initialized
-
-    CreateNewIStorage_Impl();
-    if ( !m_pNativeImpl->m_pIStorage )
+    auto pStorage(m_pNativeImpl->CreateNewStorage(getTempURL()));
+    if (!pStorage)
         throw uno::RuntimeException(); // TODO
 
     // FORMATETC aFormat = { CF_METAFILEPICT, NULL, nAspect, -1, TYMED_MFPICT 
}; // for OLE..._DRAW should be NULL
@@ -697,14 +777,12 @@ void OleComponent::CreateNewEmbeddedObject( const 
uno::Sequence< sal_Int8 >& aSe
                             OLERENDER_DRAW, // OLERENDER_FORMAT
                             nullptr,        // &aFormat,
                             nullptr,
-                            m_pNativeImpl->m_pIStorage,
-                            reinterpret_cast<void**>(&m_pNativeImpl->m_pObj) );
-
-    if ( FAILED( hr ) || !m_pNativeImpl->m_pObj )
+                            pStorage,
+                            IID_PPV_ARGS_Helper(&m_pNativeImpl->m_pObj) );
+    if (FAILED(hr))
         throw uno::RuntimeException(); // TODO
 
-    if ( !InitializeObject_Impl() )
-        throw uno::RuntimeException(); // TODO
+    InitializeObject_Impl();
 
     // TODO: getExtent???
 }
@@ -723,11 +801,8 @@ void OleComponent::CreateObjectFromData( const 
uno::Reference< datatransfer::XTr
 
 void OleComponent::CreateObjectFromFile( const OUString& aFileURL )
 {
-    if ( m_pNativeImpl->m_pIStorage )
-        throw io::IOException(); // TODO:the object is already initialized
-
-    CreateNewIStorage_Impl();
-    if ( !m_pNativeImpl->m_pIStorage )
+    auto pStorage(m_pNativeImpl->CreateNewStorage(getTempURL()));
+    if (!pStorage)
         throw uno::RuntimeException(); // TODO:
 
     OUString aFilePath;
@@ -740,24 +815,19 @@ void OleComponent::CreateObjectFromFile( const OUString& 
aFileURL )
                                     OLERENDER_DRAW, // OLERENDER_FORMAT
                                     nullptr,
                                     nullptr,
-                                    m_pNativeImpl->m_pIStorage,
-                                    
reinterpret_cast<void**>(&m_pNativeImpl->m_pObj) );
-
-    if ( FAILED( hr ) || !m_pNativeImpl->m_pObj )
+                                    pStorage,
+                                    
IID_PPV_ARGS_Helper(&m_pNativeImpl->m_pObj) );
+    if (FAILED(hr))
         throw uno::RuntimeException(); // TODO
 
-    if ( !InitializeObject_Impl() )
-        throw uno::RuntimeException(); // TODO
+    InitializeObject_Impl();
 }
 
 
 void OleComponent::CreateLinkFromFile( const OUString& aFileURL )
 {
-    if ( m_pNativeImpl->m_pIStorage )
-        throw io::IOException(); // TODO:the object is already initialized
-
-    CreateNewIStorage_Impl();
-    if ( !m_pNativeImpl->m_pIStorage )
+    auto pStorage(m_pNativeImpl->CreateNewStorage(getTempURL()));
+    if (!pStorage)
         throw uno::RuntimeException(); // TODO:
 
     OUString aFilePath;
@@ -769,31 +839,33 @@ void OleComponent::CreateLinkFromFile( const OUString& 
aFileURL )
                                         OLERENDER_DRAW, // OLERENDER_FORMAT
                                         nullptr,
                                         nullptr,
-                                        m_pNativeImpl->m_pIStorage,
-                                        
reinterpret_cast<void**>(&m_pNativeImpl->m_pObj) );
-
-    if ( FAILED( hr ) || !m_pNativeImpl->m_pObj )
+                                        pStorage,
+                                        
IID_PPV_ARGS_Helper(&m_pNativeImpl->m_pObj) );
+    if (FAILED(hr))
         throw uno::RuntimeException(); // TODO
 
-    if ( !InitializeObject_Impl() )
-        throw uno::RuntimeException(); // TODO
+    InitializeObject_Impl();
 }
 
 
 void OleComponent::InitEmbeddedCopyOfLink( rtl::Reference<OleComponent> const 
& pOleLinkComponent )
 {
-    if ( !pOleLinkComponent || !pOleLinkComponent->m_pNativeImpl->m_pObj )
+    if (!pOleLinkComponent)
         throw lang::IllegalArgumentException(); // TODO
 
-    if ( m_pNativeImpl->m_pIStorage )
-        throw io::IOException(); // TODO:the object is already initialized
+    auto pOleLinkComponentObj(pOleLinkComponent->m_pNativeImpl->getObj());
+    if (!pOleLinkComponentObj)
+        throw lang::IllegalArgumentException();
+
+    // the object must be already disconnected from the temporary URL
+    auto pStorage(m_pNativeImpl->CreateNewStorage(getTempURL()));
 
-    sal::systools::COMReference< IDataObject > 
pDataObject(pOleLinkComponent->m_pNativeImpl->m_pObj, sal::systools::COM_QUERY);
+    SafeSolarMutexReleaser releaser;
+
+    auto 
pDataObject(pOleLinkComponentObj.QueryInterface<IDataObject>(sal::systools::COM_QUERY));
     if ( pDataObject && SUCCEEDED( OleQueryCreateFromData( pDataObject ) ) )
     {
-        // the object must be already disconnected from the temporary URL
-        CreateNewIStorage_Impl();
-        if ( !m_pNativeImpl->m_pIStorage )
+        if (!pStorage)
             throw uno::RuntimeException(); // TODO:
 
         OleCreateFromData( pDataObject,
@@ -801,13 +873,13 @@ void OleComponent::InitEmbeddedCopyOfLink( 
rtl::Reference<OleComponent> const &
                                 OLERENDER_DRAW,
                                 nullptr,
                                 nullptr,
-                                m_pNativeImpl->m_pIStorage,
-                                
reinterpret_cast<void**>(&m_pNativeImpl->m_pObj) );
+                                pStorage,
+                                IID_PPV_ARGS_Helper(&m_pNativeImpl->m_pObj) );
     }
 
     if ( !m_pNativeImpl->m_pObj )
     {
-        sal::systools::COMReference< IOleLink > 
pOleLink(m_pNativeImpl->m_pObj, sal::systools::COM_QUERY);
+        auto 
pOleLink(pOleLinkComponentObj.QueryInterface<IOleLink>(sal::systools::COM_QUERY));
         if ( !pOleLink )
             throw io::IOException(); // TODO: the object doesn't support 
IOleLink
 
@@ -839,8 +911,8 @@ void OleComponent::InitEmbeddedCopyOfLink( 
rtl::Reference<OleComponent> const &
                                         OLERENDER_DRAW, // OLERENDER_FORMAT
                                         nullptr,
                                         nullptr,
-                                        m_pNativeImpl->m_pIStorage,
-                                        
reinterpret_cast<void**>(&m_pNativeImpl->m_pObj) );
+                                        pStorage,
+                                        
IID_PPV_ARGS_Helper(&m_pNativeImpl->m_pObj) );
             }
         }
 
@@ -852,33 +924,29 @@ void OleComponent::InitEmbeddedCopyOfLink( 
rtl::Reference<OleComponent> const &
             if ( SUCCEEDED( hr ) && pBindCtx )
             {
                 sal::systools::COMReference< IStorage > pObjectStorage;
-                hr = pMoniker->BindToStorage( pBindCtx, nullptr, IID_IStorage, 
reinterpret_cast<void**>(&pObjectStorage) );
+                hr = pMoniker->BindToStorage(pBindCtx, nullptr, 
IID_PPV_ARGS(&pObjectStorage));
                 if ( SUCCEEDED( hr ) && pObjectStorage )
                 {
-                    hr = pObjectStorage->CopyTo( 0, nullptr, nullptr, 
m_pNativeImpl->m_pIStorage );
+                    hr = pObjectStorage->CopyTo(0, nullptr, nullptr, pStorage);
                     if ( SUCCEEDED( hr ) )
-                        hr = OleLoadSeh(m_pNativeImpl->m_pIStorage, 
&m_pNativeImpl->m_pObj);
+                        hr = OleLoadSeh(pStorage, &m_pNativeImpl->m_pObj);
                 }
             }
         }
     }
 
-    // If object could not be created the only way is to use graphical 
representation
-    if ( !m_pNativeImpl->m_pObj )
-        throw uno::RuntimeException(); // TODO
-
-    if ( !InitializeObject_Impl() )
-        throw uno::RuntimeException(); // TODO
+    InitializeObject_Impl();
 }
 
 
 void OleComponent::RunObject()
 {
-    OSL_ENSURE( m_pNativeImpl->m_pOleObject, "The pointer can not be set to 
NULL here!" );
-    if ( !m_pNativeImpl->m_pOleObject )
+    auto pOleObject(m_pNativeImpl->get<IOleObject>());
+    OSL_ENSURE(pOleObject, "The pointer can not be set to NULL here!");
+    if (!pOleObject)
         throw embed::WrongStateException(); // TODO: the object is in wrong 
state
 
-    if ( !OleIsRunning( m_pNativeImpl->m_pOleObject ) )
+    if (!OleIsRunning(pOleObject))
     {
         HRESULT hr = OleRun( m_pNativeImpl->m_pObj );
 
@@ -908,6 +976,9 @@ void OleComponent::RunObject()
             else
                 throw io::IOException(error, getXWeak());
         }
+        // Only now, when the object is activated, it can be registered in the 
global table;
+        // before this point, RegisterInterfaceInGlobal would return 
CO_E_OBJNOTCONNECTED
+        m_pNativeImpl->registerObj();
     }
 }
 
@@ -933,20 +1004,31 @@ awt::Size OleComponent::CalculateWithFactor( const 
awt::Size& aSize,
 
 void OleComponent::CloseObject()
 {
-    if ( m_pNativeImpl->m_pOleObject && OleIsRunning( 
m_pNativeImpl->m_pOleObject ) )
-        m_pNativeImpl->m_pOleObject->Close( OLECLOSE_NOSAVE ); // must be 
saved before
+    auto pOleObject(m_pNativeImpl->get<IOleObject>());
+    if (pOleObject && OleIsRunning(pOleObject))
+    {
+        SafeSolarMutexReleaser releaser;
+        HRESULT hr = pOleObject->Close(OLECLOSE_NOSAVE); // must be saved 
before
+        SAL_WARN_IF(FAILED(hr), "embeddedobj.ole", "IOleObject::Close failed");
+    }
 }
 
 
 uno::Sequence< embed::VerbDescriptor > OleComponent::GetVerbList()
 {
-    if ( !m_pNativeImpl->m_pOleObject )
+    auto pOleObject(m_pNativeImpl->get<IOleObject>());
+    if (!pOleObject)
         throw embed::WrongStateException(); // TODO: the object is in wrong 
state
 
     if( !m_aVerbList.getLength() )
     {
         sal::systools::COMReference< IEnumOLEVERB > pEnum;
-        if( SUCCEEDED( m_pNativeImpl->m_pOleObject->EnumVerbs( &pEnum ) ) )
+        HRESULT hr;
+        {
+            SafeSolarMutexReleaser releaser;
+            hr = pOleObject->EnumVerbs(&pEnum);
+        }
+        if (SUCCEEDED(hr))
         {
             OLEVERB     szEle[ MAX_ENUM_ELE ];
             ULONG       nNum = 0;
@@ -954,7 +1036,7 @@ uno::Sequence< embed::VerbDescriptor > 
OleComponent::GetVerbList()
 
             do
             {
-                HRESULT hr = pEnum->Next( MAX_ENUM_ELE, szEle, &nNum );
+                hr = pEnum->Next(MAX_ENUM_ELE, szEle, &nNum);
                 if( hr == S_OK || hr == S_FALSE )
                 {
                     m_aVerbList.realloc( nSeqSize += nNum );
@@ -980,16 +1062,17 @@ uno::Sequence< embed::VerbDescriptor > 
OleComponent::GetVerbList()
 
 void OleComponent::ExecuteVerb( sal_Int32 nVerbID )
 {
-    if ( !m_pNativeImpl->m_pOleObject )
+    RunObject();
+
+    auto pOleObject(m_pNativeImpl->get<IOleObject>());
+    if (!pOleObject)
         throw embed::WrongStateException(); // TODO
 
-    HRESULT hr = OleRun( m_pNativeImpl->m_pOleObject );
-    if ( FAILED( hr ) )
-        throw io::IOException(); // TODO: a specific exception that transport 
error code can be thrown here
+    SafeSolarMutexReleaser releaser;
 
     // TODO: probably extents should be set here and stored in aRect
     // TODO: probably the parent window also should be set
-    hr = m_pNativeImpl->m_pOleObject->DoVerb( nVerbID, nullptr, 
m_pOleWrapClientSite, 0, nullptr, nullptr );
+    HRESULT hr = pOleObject->DoVerb(nVerbID, nullptr, m_pOleWrapClientSite, 0, 
nullptr, nullptr);
 
     if ( FAILED( hr ) )
         throw io::IOException(); // TODO
@@ -998,22 +1081,29 @@ void OleComponent::ExecuteVerb( sal_Int32 nVerbID )
 
 void OleComponent::SetHostName( const OUString& aEmbDocName )
 {
-    if ( !m_pNativeImpl->m_pOleObject )
+    auto pOleObject(m_pNativeImpl->get<IOleObject>());
+    if (!pOleObject)
         throw embed::WrongStateException(); // TODO: the object is in wrong 
state
 
-    m_pNativeImpl->m_pOleObject->SetHostNames( L"app name", o3tl::toW( 
aEmbDocName.getStr() ) );
+    SafeSolarMutexReleaser releaser;
+    pOleObject->SetHostNames(L"app name", o3tl::toW(aEmbDocName.getStr()));
 }
 
 
 void OleComponent::SetExtent( const awt::Size& aVisAreaSize, sal_Int64 nAspect 
)
 {
-    if ( !m_pNativeImpl->m_pOleObject )
+    auto pOleObject(m_pNativeImpl->get<IOleObject>());
+    if (!pOleObject)
         throw embed::WrongStateException(); // TODO: the object is in wrong 
state
 
     DWORD nMSAspect = static_cast<DWORD>(nAspect); // first 32 bits are for MS 
aspects
 
     SIZEL aSize = { aVisAreaSize.Width, aVisAreaSize.Height };
-    HRESULT hr = m_pNativeImpl->m_pOleObject->SetExtent( nMSAspect, &aSize );
+    HRESULT hr;
+    {
+        SafeSolarMutexReleaser releaser;
+        hr = pOleObject->SetExtent(nMSAspect, &aSize);
+    }
 
     if ( FAILED( hr ) )
     {
@@ -1029,7 +1119,7 @@ void OleComponent::SetExtent( const awt::Size& 
aVisAreaSize, sal_Int64 nAspect )
 
 awt::Size OleComponent::GetExtent( sal_Int64 nAspect )
 {
-    if ( !m_pNativeImpl->m_pOleObject )
+    if (!m_pNativeImpl->m_pObj)
         throw embed::WrongStateException(); // TODO: the object is in wrong 
state
 
     DWORD nMSAspect = static_cast<DWORD>(nAspect); // first 32 bits are for MS 
aspects
@@ -1039,14 +1129,17 @@ awt::Size OleComponent::GetExtent( sal_Int64 nAspect )
     if ( nMSAspect == DVASPECT_CONTENT )
     {
         // Try to get the size from the replacement image first
-        sal::systools::COMReference< IDataObject > 
pDataObject(m_pNativeImpl->m_pObj, sal::systools::COM_QUERY);
-        if ( pDataObject )
+        if (auto pDataObject = m_pNativeImpl->get<IDataObject>())
         {
             STGMEDIUM aMedium;
             FORMATETC aFormat = pFormatTemplates[1]; // use windows metafile 
format
             aFormat.dwAspect = nMSAspect;
 
-            HRESULT hr = pDataObject->GetData( &aFormat, &aMedium );
+            HRESULT hr;
+            {
+                SafeSolarMutexReleaser releaser;
+                hr = pDataObject->GetData(&aFormat, &aMedium);
+            }
 
             if (hr == RPC_E_WRONG_THREAD)
             {
@@ -1122,13 +1215,18 @@ awt::Size OleComponent::GetExtent( sal_Int64 nAspect )
 
 awt::Size OleComponent::GetCachedExtent( sal_Int64 nAspect )
 {
-    if (!m_pNativeImpl->m_pViewObject2)
+    auto pViewObject2(m_pNativeImpl->get<IViewObject2>());
+    if (!pViewObject2)
         throw embed::WrongStateException(); // TODO: the object is in wrong 
state
 
     DWORD nMSAspect = static_cast<DWORD>(nAspect); // first 32 bits are for MS 
aspects
     SIZEL aSize;
 
-    HRESULT hr = m_pNativeImpl->m_pViewObject2->GetExtent( nMSAspect, -1, 
nullptr, &aSize );
+    HRESULT hr;
+    {
+        SafeSolarMutexReleaser releaser;
+        hr = pViewObject2->GetExtent(nMSAspect, -1, nullptr, &aSize);
+    }
 
     if ( FAILED( hr ) )
     {
@@ -1149,12 +1247,17 @@ awt::Size OleComponent::GetCachedExtent( sal_Int64 
nAspect )
 
 awt::Size OleComponent::GetRecommendedExtent( sal_Int64 nAspect )
 {
-    if ( !m_pNativeImpl->m_pOleObject )
+    auto pOleObject(m_pNativeImpl->get<IOleObject>());
+    if (!pOleObject)
         throw embed::WrongStateException(); // TODO: the object is in wrong 
state
 
     DWORD nMSAspect = static_cast<DWORD>(nAspect); // first 32 bits are for MS 
aspects
     SIZEL aSize;
-    HRESULT hr = m_pNativeImpl->m_pOleObject->GetExtent( nMSAspect, &aSize );
+    HRESULT hr;
+    {
+        SafeSolarMutexReleaser releaser;
+        hr = pOleObject->GetExtent(nMSAspect, &aSize);
+    }
     if ( FAILED( hr ) )
     {
         SAL_WARN("embeddedobj.ole", " OleComponent::GetRecommendedExtent: 
GetExtent() failed");
@@ -1167,22 +1270,31 @@ awt::Size OleComponent::GetRecommendedExtent( sal_Int64 
nAspect )
 
 sal_Int64 OleComponent::GetMiscStatus( sal_Int64 nAspect )
 {
-    if ( !m_pNativeImpl->m_pOleObject )
+    auto pOleObject(m_pNativeImpl->get<IOleObject>());
+    if (!pOleObject)
         throw embed::WrongStateException(); // TODO: the object is in wrong 
state
 
-    DWORD nResult;
-    m_pNativeImpl->m_pOleObject->GetMiscStatus( static_cast<DWORD>(nAspect), 
&nResult );
+    DWORD nResult = 0;
+    {
+        SafeSolarMutexReleaser releaser;
+        pOleObject->GetMiscStatus(static_cast<DWORD>(nAspect), &nResult);
+    }
     return static_cast<sal_Int64>(nResult); // first 32 bits are for MS flags
 }
 
 
 uno::Sequence< sal_Int8 > OleComponent::GetCLSID()
 {
-    if ( !m_pNativeImpl->m_pOleObject )
+    auto pOleObject(m_pNativeImpl->get<IOleObject>());
+    if (!pOleObject)
         throw embed::WrongStateException(); // TODO: the object is in wrong 
state
 
     GUID aCLSID;
-    HRESULT hr = m_pNativeImpl->m_pOleObject->GetUserClassID( &aCLSID );
+    HRESULT hr;
+    {
+        SafeSolarMutexReleaser releaser;
+        hr = pOleObject->GetUserClassID(&aCLSID);
+    }
     if ( FAILED( hr ) )
         throw io::IOException(); // TODO:
 
@@ -1196,16 +1308,14 @@ uno::Sequence< sal_Int8 > OleComponent::GetCLSID()
 
 bool OleComponent::IsDirty()
 {
-    if ( !m_pNativeImpl->m_pOleObject )
-        throw embed::WrongStateException(); // TODO: the object is in wrong 
state
-
     if ( IsWorkaroundActive() )
         return true;
 
-    sal::systools::COMReference< IPersistStorage > 
pPersistStorage(m_pNativeImpl->m_pObj, sal::systools::COM_QUERY);
+    auto pPersistStorage(m_pNativeImpl->get<IPersistStorage>());
     if ( !pPersistStorage )
         throw io::IOException(); // TODO
 
+    SafeSolarMutexReleaser releaser;
     HRESULT hr = pPersistStorage->IsDirty();
     return ( hr != S_FALSE );
 }
@@ -1213,41 +1323,45 @@ bool OleComponent::IsDirty()
 
 void OleComponent::StoreOwnTmpIfNecessary()
 {
-    if ( !m_pNativeImpl->m_pOleObject )
+    auto pOleObject(m_pNativeImpl->get<IOleObject>());
+    if (!pOleObject)
         throw embed::WrongStateException(); // TODO: the object is in wrong 
state
 
-    sal::systools::COMReference< IPersistStorage > 
pPersistStorage(m_pNativeImpl->m_pObj, sal::systools::COM_QUERY);
+    auto pPersistStorage(m_pNativeImpl->get<IPersistStorage>());
     if ( !pPersistStorage )
         throw io::IOException(); // TODO
 
+    SafeSolarMutexReleaser releaser;
+
     if ( m_bWorkaroundActive || pPersistStorage->IsDirty() != S_FALSE )
     {
-        HRESULT hr = OleSave( pPersistStorage, m_pNativeImpl->m_pIStorage, 
TRUE );
+        auto pStorage(m_pNativeImpl->getStorage());
+        HRESULT hr = OleSave(pPersistStorage, pStorage, TRUE);
         if ( FAILED( hr ) )
         {
             // Till now was required only for AcrobatReader7.0.8
             GUID aCLSID;
-            hr = m_pNativeImpl->m_pOleObject->GetUserClassID( &aCLSID );
+            hr = pOleObject->GetUserClassID(&aCLSID);
             if ( FAILED( hr ) )
             {
                 SAL_WARN("embeddedobj.ole", 
"OleComponent::StoreOwnTmpIfNecessary: GetUserClassID() failed");
                 throw io::IOException(); // TODO
             }
 
-            hr = WriteClassStg( m_pNativeImpl->m_pIStorage, aCLSID );
+            hr = WriteClassStg(pStorage, aCLSID);
             if ( FAILED( hr ) )
                 throw io::IOException(); // TODO
 
             // the result of the following call is not checked because some 
objects, for example AcrobatReader7.0.8
             // return error even in case the saving was done correctly
-            hr = pPersistStorage->Save( m_pNativeImpl->m_pIStorage, TRUE );
+            hr = pPersistStorage->Save(pStorage, TRUE);
 
             // another workaround for AcrobatReader7.0.8 object, this object 
might think that it is not changed
             // when it has been created from file, although it must be saved
             m_bWorkaroundActive = true;
         }
 
-        hr = m_pNativeImpl->m_pIStorage->Commit( STGC_DEFAULT );
+        hr = pStorage->Commit(STGC_DEFAULT);
         if ( FAILED( hr ) )
             throw io::IOException(); // TODO
 
@@ -1439,7 +1553,7 @@ uno::Any SAL_CALL OleComponent::getTransferData( const 
datatransfer::DataFlavor&
     if ( m_bDisposed )
         throw lang::DisposedException(); // TODO
 
-    if ( !m_pNativeImpl->m_pOleObject )
+    if (!m_pNativeImpl->m_pObj)
         throw embed::WrongStateException(); // TODO: the object is in wrong 
state
 
     uno::Any aResult;
@@ -1450,7 +1564,7 @@ uno::Any SAL_CALL OleComponent::getTransferData( const 
datatransfer::DataFlavor&
         DWORD nRequestedAspect = GetAspectFromFlavor( aFlavor );
         // if own icon is set and icon aspect is requested the own icon can be 
returned directly
 
-        sal::systools::COMReference< IDataObject > 
pDataObject(m_pNativeImpl->m_pObj, sal::systools::COM_QUERY);
+        auto pDataObject(m_pNativeImpl->get<IDataObject>());
         if ( !pDataObject )
             throw io::IOException(); // TODO: transport error code
 
@@ -1477,7 +1591,11 @@ uno::Any SAL_CALL OleComponent::getTransferData( const 
datatransfer::DataFlavor&
                 FORMATETC aFormat = pFormatTemplates[nInd];
                 aFormat.dwAspect = nRequestedAspect;
 
-                HRESULT hr = pDataObject->GetData( &aFormat, &aMedium );
+                HRESULT hr;
+                {
+                    SafeSolarMutexReleaser releaser;
+                    hr = pDataObject->GetData(&aFormat, &aMedium);
+                }
                 if ( SUCCEEDED( hr ) )
                 {
                     bSupportedFlavor = m_pNativeImpl->ConvertDataForFlavor( 
aMedium, aFlavor, aResult );
@@ -1536,9 +1654,6 @@ uno::Sequence< datatransfer::DataFlavor > SAL_CALL 
OleComponent::getTransferData
     if ( m_bDisposed )
         throw lang::DisposedException(); // TODO
 
-    if ( !m_pNativeImpl->m_pOleObject )
-        throw embed::WrongStateException(); // TODO: the object is in wrong 
state
-
     RetrieveObjectDataFlavors_Impl();
 
     return m_aDataFlavors;
@@ -1551,13 +1666,7 @@ sal_Bool SAL_CALL OleComponent::isDataFlavorSupported( 
const datatransfer::DataF
     if ( m_bDisposed )
         throw lang::DisposedException(); // TODO
 
-    if ( !m_pNativeImpl->m_pOleObject )
-        throw embed::WrongStateException(); // TODO: the object is in wrong 
state
-
-    if ( !m_aDataFlavors.getLength() )
-    {
-        RetrieveObjectDataFlavors_Impl();
-    }
+    RetrieveObjectDataFlavors_Impl();
 
     for (auto const& supportedFormat : m_aDataFlavors)
         if ( supportedFormat.MimeType.equals( aFlavor.MimeType ) && 
supportedFormat.DataType == aFlavor.DataType )
@@ -1607,7 +1716,7 @@ sal_Int64 SAL_CALL OleComponent::getSomething( const 
css::uno::Sequence< sal_Int
     {
         uno::Sequence < sal_Int8 > aCLSID = GetCLSID();
         if ( MimeConfigurationHelper::ClassIDsEqual( aIdentifier, aCLSID ) )
-            return 
comphelper::getSomething_cast(static_cast<IUnknown*>(m_pNativeImpl->m_pObj));
+            return comphelper::getSomething_cast(m_pNativeImpl->m_pObj.get());
 
         // compatibility hack for old versions: CLSID was used in wrong order 
(SvGlobalName order)
         sal_Int32 nLength = aIdentifier.getLength();
@@ -1624,7 +1733,7 @@ sal_Int64 SAL_CALL OleComponent::getSomething( const 
css::uno::Sequence< sal_Int
                  aIdentifier[2] == aCLSID[1] &&
                  aIdentifier[1] == aCLSID[2] &&
                  aIdentifier[0] == aCLSID[3] )
-                return 
reinterpret_cast<sal_Int64>(static_cast<IUnknown*>(m_pNativeImpl->m_pObj));
+                return 
comphelper::getSomething_cast(m_pNativeImpl->m_pObj.get());
         }
     }
     catch ( const uno::Exception& )
diff --git a/embeddedobj/source/msole/olecomponent.hxx 
b/embeddedobj/source/msole/olecomponent.hxx
index 5a96b64fcbfc..e08d5a69b2f4 100644
--- a/embeddedobj/source/msole/olecomponent.hxx
+++ b/embeddedobj/source/msole/olecomponent.hxx
@@ -41,7 +41,7 @@ namespace comphelper {
 class OleWrapperClientSite;
 class OleWrapperAdviseSink;
 class OleEmbeddedObject;
-struct OleComponentNative_Impl;
+class OleComponentNative_Impl;
 
 class OleComponent : public ::cppu::WeakImplHelper< css::util::XCloseable, 
css::lang::XComponent,
                                                     css::lang::XUnoTunnel, 
css::util::XModifiable,
@@ -52,15 +52,12 @@ class OleComponent : public ::cppu::WeakImplHelper< 
css::util::XCloseable, css::
 
     bool m_bDisposed;
     bool m_bModified;
-    OleComponentNative_Impl* m_pNativeImpl;
+    std::unique_ptr<OleComponentNative_Impl> m_pNativeImpl;
 
     OleEmbeddedObject* m_pUnoOleObject;
     OleWrapperClientSite* m_pOleWrapClientSite;
     OleWrapperAdviseSink* m_pImplAdviseSink;
 
-    sal_Int32 m_nOLEMiscFlags;
-    sal_Int32 m_nAdvConn;
-
     css::uno::Sequence< css::embed::VerbDescriptor > m_aVerbList;
     css::uno::Sequence< css::datatransfer::DataFlavor > m_aDataFlavors;
 
@@ -72,9 +69,10 @@ class OleComponent : public ::cppu::WeakImplHelper< 
css::util::XCloseable, css::
     // such objects report the dirty state wrongly sometimes and do not allow 
to store them any time
     bool m_bWorkaroundActive;
 
-    bool InitializeObject_Impl();
+    void InitializeObject_Impl();
+
+    OUString getTempURL() const;
 
-    void CreateNewIStorage_Impl();
     void RetrieveObjectDataFlavors_Impl();
     void Dispose();
 
diff --git a/embeddedobj/source/msole/oleembed.cxx 
b/embeddedobj/source/msole/oleembed.cxx
index 69b3ca8d239e..bd424e4c0afb 100644
--- a/embeddedobj/source/msole/oleembed.cxx
+++ b/embeddedobj/source/msole/oleembed.cxx
@@ -498,12 +498,12 @@ void SAL_CALL OleEmbeddedObject::changeState( sal_Int32 
nNewState )
                 // the loaded state must be set before, because of 
notifications!
                 m_nObjectState = nNewState;
 
+                aGuard.clear();
                 {
                     VerbExecutionControllerGuard aVerbGuard( 
m_aVerbExecutionController );
                     m_pOleComponent->CloseObject();
                 }
 
-                aGuard.clear();
                 StateChangeNotification_Impl( false, nOldState, m_nObjectState 
);
                 aGuard.reset();
             }
@@ -866,9 +866,11 @@ void SAL_CALL OleEmbeddedObject::doVerb( sal_Int32 nVerbID 
)
             // ==== the STAMPIT related solution =============================
             m_aVerbExecutionController.StartControlExecution();
 
-
-            m_pOleComponent->ExecuteVerb( nVerbID );
-            m_pOleComponent->SetHostName( m_aContainerName );
+            {
+                ClearedMutexArea clearedMutex(aGuard);
+                m_pOleComponent->ExecuteVerb(nVerbID);
+                m_pOleComponent->SetHostName(m_aContainerName);
+            }
 
             // ==== the STAMPIT related solution =============================
             bool bModifiedOnExecution = 
m_aVerbExecutionController.EndControlExecution_WasModified();
@@ -975,7 +977,7 @@ uno::Sequence< embed::VerbDescriptor > SAL_CALL 
OleEmbeddedObject::getSupportedV
     }
     // end wrapping related part ====================
 
-    ::osl::MutexGuard aGuard( m_aMutex );
+    osl::ClearableMutexGuard aGuard(m_aMutex);
     if ( m_bDisposed )
         throw lang::DisposedException(); // TODO
 
@@ -992,6 +994,7 @@ uno::Sequence< embed::VerbDescriptor > SAL_CALL 
OleEmbeddedObject::getSupportedV
         //  throw embed::NeedsRunningStateException(); // TODO:
         // }
 
+        aGuard.clear();
         return m_pOleComponent->GetVerbList();
     }
     else
@@ -1131,7 +1134,7 @@ sal_Int64 SAL_CALL OleEmbeddedObject::getStatus( sal_Int64
     }
     // end wrapping related part ====================
 
-    ::osl::MutexGuard aGuard( m_aMutex );
+    osl::ResettableMutexGuard aGuard(m_aMutex);
     if ( m_bDisposed )
         throw lang::DisposedException(); // TODO
 
@@ -1146,8 +1149,10 @@ sal_Int64 SAL_CALL OleEmbeddedObject::getStatus( 
sal_Int64
         nResult = m_nStatus;
     else if ( m_pOleComponent )
     {
-
-        m_nStatus = m_pOleComponent->GetMiscStatus( nAspect );
+        {
+            ClearedMutexArea clearedMutex(aGuard);
+            m_nStatus = m_pOleComponent->GetMiscStatus(nAspect);
+        }
         m_nStatusAspect = nAspect;
         m_bGotStatus = true;
         nResult = m_nStatus;
diff --git a/embeddedobj/source/msole/olevisual.cxx 
b/embeddedobj/source/msole/olevisual.cxx
index 7d8de650db3e..bcbacffe5d64 100644
--- a/embeddedobj/source/msole/olevisual.cxx
+++ b/embeddedobj/source/msole/olevisual.cxx
@@ -325,7 +325,7 @@ embed::VisualRepresentation SAL_CALL 
OleEmbeddedObject::getPreferredVisualRepres
     }
     // end wrapping related part ====================
 
-    ::osl::MutexGuard aGuard( m_aMutex );
+    osl::ResettableMutexGuard aGuard(m_aMutex);
     if ( m_bDisposed )
         throw lang::DisposedException(); // TODO
 
@@ -364,7 +364,10 @@ embed::VisualRepresentation SAL_CALL 
OleEmbeddedObject::getPreferredVisualRepres
                     cppu::UnoType<uno::Sequence< sal_Int8 >>::get() );
 
             embed::VisualRepresentation aVisualRepr;
-            aVisualRepr.Data = m_pOleComponent->getTransferData( aDataFlavor );
+            {
+                ClearedMutexArea clearedMutex(aGuard);
+                aVisualRepr.Data = 
m_pOleComponent->getTransferData(aDataFlavor);
+            }
             aVisualRepr.Flavor = aDataFlavor;
 
             uno::Sequence< sal_Int8 > aVisReplSeq;

Reply via email to