diff options
Diffstat (limited to 'extensions/source/activex/SOActiveX.cxx')
-rw-r--r-- | extensions/source/activex/SOActiveX.cxx | 1162 |
1 files changed, 1162 insertions, 0 deletions
diff --git a/extensions/source/activex/SOActiveX.cxx b/extensions/source/activex/SOActiveX.cxx new file mode 100644 index 000000000..88b3ad769 --- /dev/null +++ b/extensions/source/activex/SOActiveX.cxx @@ -0,0 +1,1162 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +// SOActiveX.cpp : Implementation of CSOActiveX + +#include "StdAfx2.h" +#include "SOActiveX.h" +#include "SOComWindowPeer.h" +#include "SODispatchInterceptor.h" +#include "SOActionsApproval.h" +#include "com_uno_helper.h" + +#if defined __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnon-virtual-dtor" +#endif +#include <so_activex.h> +#if defined __clang__ +#pragma clang diagnostic pop +#endif + +#define STAROFFICE_WINDOWCLASS L"SOParentWindow" + + +static void OutputError_Impl( HWND hw, HRESULT ErrorCode ) +{ + LPWSTR sMessage = nullptr; + FormatMessageW( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, + ErrorCode, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + reinterpret_cast<LPWSTR>(&sMessage), + 0, + nullptr + ); + MessageBoxW( hw, sMessage, nullptr, MB_OK | MB_ICONINFORMATION ); + HeapFree( GetProcessHeap(), 0, sMessage ); +} + +HRESULT ExecuteFunc( IDispatch* idispUnoObject, + OLECHAR const * sFuncName, + CComVariant* params, + unsigned int count, + CComVariant* pResult ) +{ + if( !idispUnoObject ) + return E_FAIL; + + DISPID id; + HRESULT hr = idispUnoObject->GetIDsOfNames( IID_NULL, const_cast<OLECHAR **>(&sFuncName), 1, LOCALE_USER_DEFAULT, &id); + if( !SUCCEEDED( hr ) ) return hr; + + DISPPARAMS dispparams= { params, nullptr, count, 0}; + + // DEBUG + EXCEPINFO myInfo; + hr = idispUnoObject->Invoke( id, IID_NULL,LOCALE_USER_DEFAULT, DISPATCH_METHOD, + &dispparams, pResult, &myInfo, nullptr); + + // for debugging purposes + // USES_CONVERSION; + // if ( !SUCCEEDED( hr ) ) + // ::MessageBox( NULL, OLE2A( myInfo.bstrDescription ), OLE2A( myInfo.bstrSource ), MB_OK | MB_ICONINFORMATION ); + + return hr; +} + +static HRESULT GetIDispByFunc( IDispatch* idispUnoObject, + OLECHAR const * sFuncName, + CComVariant* params, + unsigned int count, + CComPtr<IDispatch>& pdispResult ) +{ + if( !idispUnoObject ) + return E_FAIL; + + CComVariant result; + HRESULT hr = ExecuteFunc( idispUnoObject, sFuncName, params, count, &result ); + if( !SUCCEEDED( hr ) ) return hr; + + if( result.vt != VT_DISPATCH || result.pdispVal == nullptr ) + return E_FAIL; + + pdispResult = CComPtr<IDispatch>( result.pdispVal ); + + return S_OK; +} + +static HRESULT PutPropertiesToIDisp( IDispatch* pdispObject, + OLECHAR const ** sMemberNames, + CComVariant* pVariant, + unsigned int count ) +{ + for( unsigned int ind = 0; ind < count; ind++ ) + { + DISPID id; + HRESULT hr = pdispObject->GetIDsOfNames( IID_NULL, const_cast<OLECHAR **>(&sMemberNames[ind]), 1, LOCALE_USER_DEFAULT, &id ); + if( !SUCCEEDED( hr ) ) return hr; + + hr = CComDispatchDriver::PutProperty( pdispObject, id, &pVariant[ind] ); + if( !SUCCEEDED( hr ) ) return hr; + } + + return S_OK; +} + +HRESULT GetPropertiesFromIDisp( IDispatch* pdispObject, + OLECHAR const ** sMemberNames, + CComVariant* pVariant, + unsigned int count ) +{ + for( unsigned int ind = 0; ind < count; ind++ ) + { + DISPID id; + HRESULT hr = pdispObject->GetIDsOfNames( IID_NULL, const_cast<OLECHAR **>(&sMemberNames[ind]), 1, LOCALE_USER_DEFAULT, &id ); + if( !SUCCEEDED( hr ) ) return hr; + + hr = CComDispatchDriver::GetProperty( pdispObject, id, &pVariant[ind] ); + if( !SUCCEEDED( hr ) ) return hr; + } + + return S_OK; +} + +// CSOActiveX + +CSOActiveX::CSOActiveX() +: mCookie(0) +, mCurFileUrl( L"private:factory/swriter" ) +, mbLoad( FALSE ) +, mbViewOnly( TRUE ) +, mParentWin( nullptr ) +, mOffWin( nullptr ) +, mpDispatchInterceptor( nullptr ) +, mnVersion( SO_NOT_DETECTED ) +, mbReadyForActivation( FALSE ) +, mbDrawLocked( false ) +{ + CLSID const clsFactory = {0x82154420,0x0FBF,0x11d4,{0x83, 0x13,0x00,0x50,0x04,0x52,0x6A,0xB4}}; + HRESULT hr = CoCreateInstance( clsFactory, nullptr, CLSCTX_ALL, __uuidof(IDispatch), reinterpret_cast<void**>(&mpDispFactory)); + if( !SUCCEEDED( hr ) ) + OutputError_Impl( nullptr, hr ); + + mPWinClass.style = CS_HREDRAW|CS_VREDRAW; + mPWinClass.lpfnWndProc = DefWindowProcW; + mPWinClass.cbClsExtra = 0; + mPWinClass.cbWndExtra = 0; + mPWinClass.hInstance = GetModuleHandleW(nullptr); //myInstance; + mPWinClass.hIcon = nullptr; + mPWinClass.hCursor = nullptr; + mPWinClass.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_BACKGROUND); + mPWinClass.lpszMenuName = nullptr; + mPWinClass.lpszClassName = STAROFFICE_WINDOWCLASS; + + RegisterClassW(&mPWinClass); +} + +CSOActiveX::~CSOActiveX() +{ + Cleanup(); + +} + +HRESULT CSOActiveX::Cleanup() +{ + CComVariant dummyResult; + + if( mpDispatchInterceptor ) + { + if( mpDispFrame ) + { + // remove dispatch interceptor + CComQIPtr< IDispatch, &IID_IDispatch > pIDispDispInter( mpDispatchInterceptor ); + CComVariant aVariant( pIDispDispInter ); + ExecuteFunc( mpDispFrame, + L"releaseDispatchProviderInterceptor", + &aVariant, + 1, + &dummyResult ); + } + + mpDispatchInterceptor->ClearParent(); + mpDispatchInterceptor->Release(); + mpDispatchInterceptor = nullptr; + } + + mpDispTempFile = CComPtr< IDispatch >(); + mbReadyForActivation = FALSE; + + if( mpInstanceLocker ) + { + ExecuteFunc( mpInstanceLocker, L"dispose", nullptr, 0, &dummyResult ); + mpInstanceLocker = CComPtr< IDispatch >(); + } + + if( mpDispFrame ) + { + bool bCloserActivated = false; + + CComPtr<IDispatch> pDispDocumentCloser; + CComVariant aDocCloser( L"com.sun.star.embed.DocumentCloser" ); + HRESULT hr = GetIDispByFunc( mpDispFactory, + L"createInstance", + &aDocCloser, + 1, + pDispDocumentCloser ); + if ( SUCCEEDED( hr ) && pDispDocumentCloser ) + { + SAFEARRAY* pInitFrame = SafeArrayCreateVector(VT_VARIANT, 0, 1); + LONG nInitInd = 0; + CComVariant pFrameVariant( mpDispFrame ); + SafeArrayPutElement( pInitFrame, &nInitInd, &pFrameVariant ); + CComVariant aVarInitFrame; + aVarInitFrame.vt = VT_ARRAY | VT_VARIANT; aVarInitFrame.parray = pInitFrame; + hr = ExecuteFunc( pDispDocumentCloser, L"initialize", &aVarInitFrame, 1, &dummyResult ); + if( SUCCEEDED( hr ) ) + { + // the following call will let the closing happen + hr = ExecuteFunc( pDispDocumentCloser, L"dispose", nullptr, 0, &dummyResult ); + bCloserActivated = SUCCEEDED( hr ); + } + } + + if ( !bCloserActivated ) + { + CComVariant aPropVar; + aPropVar.vt = VT_BOOL; aPropVar.boolVal = VARIANT_TRUE; + if ( !SUCCEEDED( ExecuteFunc( mpDispFrame, L"close", &aPropVar, 1, &dummyResult ) ) ) + ExecuteFunc( mpDispFrame, L"dispose", nullptr, 0, &dummyResult ); + } + + mpDispFrame = CComPtr< IDispatch >(); + } + + if( ::IsWindow( mOffWin ) ) + ::DestroyWindow( mOffWin ); + + TerminateOffice(); + + return S_OK; +} + +HRESULT CSOActiveX::TerminateOffice() +{ + // create desktop + CComPtr<IDispatch> pdispDesktop; + CComVariant aDesktopServiceName( L"com.sun.star.frame.Desktop" ); + + HRESULT hr = GetIDispByFunc( mpDispFactory, L"createInstance", &aDesktopServiceName, 1, pdispDesktop ); + if( !pdispDesktop || !SUCCEEDED( hr ) ) return hr; + + // create tree of frames + CComPtr<IDispatch> pdispChildren; + hr = GetIDispByFunc( pdispDesktop, L"getFrames", nullptr, 0, pdispChildren ); + if( !pdispChildren || !SUCCEEDED( hr ) ) return hr; + + CComVariant aFrames; + CComVariant nFlag( 4 ); + hr = ExecuteFunc( pdispChildren, L"queryFrames", &nFlag, 1, &aFrames ); + if ( SUCCEEDED( hr ) ) + { + if ( ( aFrames.vt == ( VT_ARRAY | VT_DISPATCH ) || aFrames.vt == ( VT_ARRAY | VT_VARIANT ) ) + && ( !aFrames.parray || (aFrames.parray->cDims == 1 && aFrames.parray->rgsabound[0].cElements == 0) ) ) + { + // there is no frames open + // TODO: check whether the frames are hidden if they are open? + CComVariant dummyResult; + hr = ExecuteFunc( pdispDesktop, L"terminate", nullptr, 0, &dummyResult ); + } + } + + return hr; +} + +COM_DECLSPEC_NOTHROW STDMETHODIMP CSOActiveX::InitNew () +{ + mnVersion = GetVersionConnected(); + mbLoad = TRUE; + return S_OK; +} + +COM_DECLSPEC_NOTHROW STDMETHODIMP CSOActiveX::Load ( LPSTREAM /*pStm*/ ) +{ + mnVersion = GetVersionConnected(); + mbLoad = TRUE; + + // may be later? + // for now just ignore + + return S_OK; +} + +COM_DECLSPEC_NOTHROW STDMETHODIMP CSOActiveX::Load( LPPROPERTYBAG pPropBag, LPERRORLOG /*pErrorLog*/ ) +{ + mnVersion = GetVersionConnected(); + + IPropertyBag2* pPropBag2; + HRESULT hr = pPropBag->QueryInterface( IID_IPropertyBag2, reinterpret_cast<void**>(&pPropBag2) ); + //ATLASSERT( hr >= 0 ); + + if( !SUCCEEDED( hr ) ) + return hr; + + unsigned long aNum; + hr = pPropBag2->CountProperties( &aNum ); + //ATLASSERT( hr >= 0 ); + if( !SUCCEEDED( hr ) ) + return hr; + + PROPBAG2* aPropNames = new PROPBAG2[aNum]; + unsigned long aReaded; + + hr = pPropBag2->GetPropertyInfo( 0, + aNum, + aPropNames, + &aReaded ); + //ATLASSERT( hr >= 0 ); + if( !SUCCEEDED( hr ) ) + { + delete[] aPropNames; + return hr; + } + + CComVariant* aVal = new CComVariant[aNum]; + HRESULT* hvs = new HRESULT[aNum]; + hr = pPropBag2->Read( aNum, + aPropNames, + nullptr, + aVal, + hvs ); + //ATLASSERT( hr >= 0 ); + if( !SUCCEEDED( hr ) ) + { + delete[] hvs; + delete[] aVal; + delete[] aPropNames; + return hr; + } + + for( unsigned long ind = 0; ind < aNum; ind++ ) + { + // all information from the 'object' tag is in strings + if (aVal[ind].vt == VT_BSTR && !wcscmp(aPropNames[ind].pstrName, L"src")) + { + mCurFileUrl.AssignBSTR(aVal[ind].bstrVal); + } + else if( aVal[ind].vt == VT_BSTR + && !wcscmp(aPropNames[ind].pstrName, L"readonly")) + { + if (!wcscmp(aVal[ind].bstrVal, L"true")) + { + // the default value + mbViewOnly = TRUE; + } + else + { + mbViewOnly = FALSE; + } + } + } + + delete[] hvs; + delete[] aVal; + delete[] aPropNames; + + if( !mpDispFactory ) + return hr; + + mbReadyForActivation = FALSE; + hr = CBindStatusCallback<CSOActiveX>::Download( + this, &CSOActiveX::CallbackCreateXInputStream, mCurFileUrl, m_spClientSite, FALSE); + if (hr == MK_S_ASYNCHRONOUS) + hr = S_OK; + + if ( !SUCCEEDED( hr ) ) + { + // trigger initialization without stream + mbLoad = TRUE; + + Invalidate(); + UpdateWindow(); + } + + return hr; +} + +HRESULT CSOActiveX::GetUnoStruct( OLECHAR const * sStructName, CComPtr<IDispatch>& pdispResult ) +{ + CComVariant aComStruct( sStructName ); + return GetIDispByFunc( mpDispFactory, L"Bridge_GetStruct", &aComStruct, 1, pdispResult ); +} + +HRESULT CSOActiveX::GetUrlStruct( OLECHAR const * sUrl, CComPtr<IDispatch>& pdispUrl ) +{ + HRESULT hr = GetUnoStruct( L"com.sun.star.util.URL", pdispUrl ); + if( !SUCCEEDED( hr ) ) return hr; + + OLECHAR const * sURLMemberName = L"Complete"; + DISPID nURLID; + hr = pdispUrl->GetIDsOfNames( IID_NULL, const_cast<OLECHAR **>(&sURLMemberName), 1, LOCALE_USER_DEFAULT, &nURLID ); + if( !SUCCEEDED( hr ) ) return hr; + CComVariant aComUrl( sUrl ); + hr = CComDispatchDriver::PutProperty( pdispUrl, nURLID, &aComUrl ); + if( !SUCCEEDED( hr ) ) return hr; + + CComPtr<IDispatch> pdispTransformer; + CComVariant aServiceName( L"com.sun.star.util.URLTransformer" ); + hr = GetIDispByFunc( mpDispFactory, + L"createInstance", + &aServiceName, + 1, + pdispTransformer ); + if( !SUCCEEDED( hr ) ) return hr; + + CComVariant dummyResult; + CComVariant aParam[2]; + aParam[1].ppdispVal = &pdispUrl; + aParam[1].vt = VT_DISPATCH | VT_BYREF; + aParam[0] = CComVariant( L"file:///" ); + + hr = ExecuteFunc( pdispTransformer, L"parseSmart", aParam, 2, &dummyResult ); + if( !SUCCEEDED( hr ) || dummyResult.vt != VT_BOOL || !dummyResult.boolVal ) return hr; + + return S_OK; +} + +HRESULT CSOActiveX::SetLayoutManagerProps() +{ + if ( !mpDispFrame ) + return E_FAIL; + + CComVariant pVarLayoutMgr; + OLECHAR const * sLMPropName = L"LayoutManager"; + HRESULT hr = GetPropertiesFromIDisp( mpDispFrame, &sLMPropName, &pVarLayoutMgr, 1 ); + if( pVarLayoutMgr.vt != VT_DISPATCH || pVarLayoutMgr.pdispVal == nullptr ) + return E_FAIL; + + CComPtr<IDispatch> pdispLM( pVarLayoutMgr.pdispVal ); + + + if( !SUCCEEDED( hr ) || !pdispLM ) + return E_FAIL; + + OLECHAR const * sATName = L"AutomaticToolbars"; + CComVariant pATProp; + pATProp.vt = VT_BOOL; pATProp.boolVal = VARIANT_FALSE ; + hr = PutPropertiesToIDisp( pdispLM, &sATName, &pATProp, 1 ); + + return hr; +} + +HRESULT CSOActiveX::CreateFrameOldWay( HWND hwnd, int width, int height ) +{ + if( !mpDispFactory ) + return E_FAIL; + + // create window handle holder + CComPtr< CComObject< SOComWindowPeer > > pPeerToSend = new CComObject<SOComWindowPeer>(); + pPeerToSend->SetHWNDInternally( hwnd ); + CComQIPtr< IDispatch, &IID_IDispatch > pIDispToSend( pPeerToSend ); + + // create rectangle structure + CComPtr<IDispatch> pdispRectangle; + HRESULT hr = GetUnoStruct( L"com.sun.star.awt.Rectangle", pdispRectangle ); + if( !SUCCEEDED( hr ) ) return hr; + + OLECHAR const * sRectMemberNames[4] = { L"X", + L"Y", + L"Width", + L"Height" }; + CComVariant pRectVariant[4]; + pRectVariant[0] = pRectVariant[1] = pRectVariant[2] = pRectVariant[3] = CComVariant( 0 ); + + hr = PutPropertiesToIDisp( pdispRectangle, sRectMemberNames, pRectVariant, 4 ); + if( !SUCCEEDED( hr ) ) return hr; + + // create WindowDescriptor structure + CComPtr<IDispatch> pdispWinDescr; + hr = GetUnoStruct( L"com.sun.star.awt.WindowDescriptor", pdispWinDescr ); + if( !SUCCEEDED( hr ) ) return hr; + + // fill in descriptor with info + OLECHAR const * sDescriptorMemberNames[6] = { L"Type", + L"WindowServiceName", + L"ParentIndex", + L"Parent", + L"Bounds", + L"WindowAttributes" }; + CComVariant pDescriptorVar[6]; + pDescriptorVar[0] = CComVariant( 0 ); + pDescriptorVar[1] = CComVariant( L"workwindow" ); + pDescriptorVar[2] = CComVariant( 1 ); + pDescriptorVar[3] = CComVariant( pIDispToSend ); + pDescriptorVar[4] = CComVariant( pdispRectangle ); + pDescriptorVar[5] = CComVariant( 33 ); + hr = PutPropertiesToIDisp( pdispWinDescr, sDescriptorMemberNames, pDescriptorVar, 6 ); + if( !SUCCEEDED( hr ) ) return hr; + + // create XToolkit instance + CComPtr<IDispatch> pdispToolkit; + CComVariant aServiceName( L"com.sun.star.awt.Toolkit" ); + hr = GetIDispByFunc( mpDispFactory, L"createInstance", &aServiceName, 1, pdispToolkit ); + if( !SUCCEEDED( hr ) ) return hr; + + // create window with toolkit + CComVariant aWinDescr( pdispWinDescr ); + hr = GetIDispByFunc( pdispToolkit, L"createWindow", &aWinDescr, 1, mpDispWin ); + if( !SUCCEEDED( hr ) ) return hr; + + // create frame + aServiceName = CComVariant( L"com.sun.star.frame.Task" ); + hr = GetIDispByFunc( mpDispFactory, L"createInstance", &aServiceName, 1, mpDispFrame ); + if( !SUCCEEDED( hr ) || !mpDispFrame ) + { + // the interface com.sun.star.frame.Task is removed in 6.1 + // but the interface com.sun.star.frame.Frame has some bugs in 6.0 + aServiceName = CComVariant( L"com.sun.star.frame.Frame" ); + hr = GetIDispByFunc( mpDispFactory, L"createInstance", &aServiceName, 1, mpDispFrame ); + if( !SUCCEEDED( hr ) ) return hr; + } + + // initialize frame + CComVariant dummyResult; + CComVariant aDispWin( mpDispWin ); + hr = ExecuteFunc( mpDispFrame, L"initialize", &aDispWin, 1, &dummyResult ); + if( !SUCCEEDED( hr ) ) return hr; + + // set some properties to the layout manager, ignore errors for now + SetLayoutManagerProps(); + + // create desktop + CComPtr<IDispatch> pdispDesktop; + aServiceName = CComVariant( L"com.sun.star.frame.Desktop" ); + hr = GetIDispByFunc( mpDispFactory, L"createInstance", &aServiceName, 1, pdispDesktop ); + if( !SUCCEEDED( hr ) ) return hr; + + // create tree of frames + CComPtr<IDispatch> pdispChildren; + hr = GetIDispByFunc( pdispDesktop, L"getFrames", nullptr, 0, pdispChildren ); + if( !SUCCEEDED( hr ) ) return hr; + + // insert new frame into desktop hierarchy + CComVariant aDispFrame( mpDispFrame ); + hr = ExecuteFunc( pdispChildren, L"append", &aDispFrame, 1, &dummyResult ); + if( !SUCCEEDED( hr ) ) return hr; + + // initialize window + CComVariant aTransparent( long(0xFFFFFFFF) ); + hr = ExecuteFunc( mpDispWin, L"setBackground", &aTransparent, 1, &dummyResult ); + if( !SUCCEEDED( hr ) ) return hr; + + CComVariant aTrue( TRUE ); + hr = ExecuteFunc( mpDispWin, L"setVisible", &aTrue, 1, &dummyResult ); + if( !SUCCEEDED( hr ) ) return hr; + + CComVariant aPosArgs[5]; + aPosArgs[4] = CComVariant( 0 ); + aPosArgs[3] = CComVariant( 0 ); + aPosArgs[2] = CComVariant( width ); + aPosArgs[1] = CComVariant( height ); + aPosArgs[0] = CComVariant( 12 ); + hr = ExecuteFunc( mpDispWin, L"setPosSize", aPosArgs, 5, &dummyResult ); + if( !SUCCEEDED( hr ) ) return hr; + + // create frame locker if there is such service + aServiceName = CComVariant( L"com.sun.star.embed.InstanceLocker" ); + hr = GetIDispByFunc( mpDispFactory, L"createInstance", &aServiceName, 1, mpInstanceLocker ); + if( SUCCEEDED( hr ) && mpInstanceLocker ) + { + SAFEARRAY* pInitVals = SafeArrayCreateVector(VT_VARIANT, 0, 3); + + // the first sequence element + LONG nInitInd = 0; + CComVariant pFrameVariant( mpDispFrame ); + SafeArrayPutElement( pInitVals, &nInitInd, &pFrameVariant ); + + // the second sequence element + nInitInd = 1; + CComVariant pStrArr( 1 ); + SafeArrayPutElement( pInitVals, &nInitInd, &pStrArr ); + + // the third sequence element + nInitInd = 2; + CComPtr<IDispatch> pdispValueObj; + hr = GetIDispByFunc( mpDispFactory, L"Bridge_GetValueObject", nullptr, 0, pdispValueObj ); + if( !SUCCEEDED( hr ) || !pdispValueObj ) return hr; + + CComVariant aValueArgs[2]; + aValueArgs[1] = CComVariant( L"com.sun.star.embed.XActionsApproval" ); + CComPtr< CComObject< SOActionsApproval > > pApproval( new CComObject<SOActionsApproval>() ); + aValueArgs[0] = CComVariant ( pApproval ); + + hr = ExecuteFunc( pdispValueObj, L"Set", aValueArgs, 2, &dummyResult ); + if( !SUCCEEDED( hr ) ) return hr; + + CComVariant aValueObj( pdispValueObj ); + SafeArrayPutElement( pInitVals, &nInitInd, &aValueObj ); + + // execute initialize() + CComVariant aVarInitVals; + aVarInitVals.vt = VT_ARRAY | VT_VARIANT; aVarInitVals.parray = pInitVals; + hr = ExecuteFunc( mpInstanceLocker, L"initialize", &aVarInitVals, 1, &dummyResult ); + if( !SUCCEEDED( hr ) ) return hr; + } + + return S_OK; +} + +HRESULT CSOActiveX::CallLoadComponentFromURL1PBool( OLECHAR const * sUrl, OLECHAR const * sArgName, BOOL sArgVal ) +{ + SAFEARRAY* pPropVals = SafeArrayCreateVector(VT_DISPATCH, 0, 1); + LONG ix = 0; + CComPtr<IDispatch> pdispPropVal; + HRESULT hr = GetUnoStruct( L"com.sun.star.beans.PropertyValue", pdispPropVal ); + if( !SUCCEEDED( hr ) ) return hr; + + OLECHAR const * sPropMemberNames[2] = { L"Name", L"Value" }; + CComVariant pPropVar[2]; + pPropVar[0] = CComVariant( sArgName ); + pPropVar[1].vt = VT_BOOL; pPropVar[1].boolVal = sArgVal ? VARIANT_TRUE : VARIANT_FALSE ; + hr = PutPropertiesToIDisp( pdispPropVal, sPropMemberNames, pPropVar, 2 ); + if( !SUCCEEDED( hr ) ) return hr; + + SafeArrayPutElement( pPropVals, &ix, pdispPropVal ); + + CComVariant aDispArgs[4]; + aDispArgs[3] = CComVariant( sUrl ); + aDispArgs[2] = CComVariant( L"_self" ); + aDispArgs[1] = CComVariant( 0 ); + // aDispArgs[0] = CComVariant( pPropVals ); such constructor is not defined ??! + aDispArgs[0].vt = VT_ARRAY | VT_DISPATCH; aDispArgs[0].parray = pPropVals; + + CComVariant dummyResult; + hr = ExecuteFunc( mpDispFrame, L"loadComponentFromURL", aDispArgs, 4, &dummyResult ); + if( !SUCCEEDED( hr ) ) return hr; + + return S_OK; +} + +HRESULT CSOActiveX::CallDispatchMethod( OLECHAR const * sUrl, + CComVariant* aArgNames, + CComVariant* aArgVals, + unsigned int count ) +{ + CComPtr<IDispatch> pdispURL; + HRESULT hr = GetUrlStruct( sUrl, pdispURL ); + if( !SUCCEEDED( hr ) ) return hr; + + CComPtr<IDispatch> pdispXDispatch; + CComVariant aArgs[3]; + aArgs[2] = CComVariant( pdispURL ); + aArgs[1] = CComVariant( L"" ); + aArgs[0] = CComVariant( int(0) ); + hr = GetIDispByFunc( mpDispFrame, + L"queryDispatch", + aArgs, + 3, + pdispXDispatch ); + if( !SUCCEEDED( hr ) ) return hr; + + SAFEARRAY* pPropVals = SafeArrayCreateVector(VT_DISPATCH, 0, count); + for( LONG ix = 0; ix < static_cast<LONG>(count); ix ++ ) + { + CComPtr<IDispatch> pdispPropVal; + hr = GetUnoStruct( L"com.sun.star.beans.PropertyValue", pdispPropVal ); + if( !SUCCEEDED( hr ) ) return hr; + + OLECHAR const * sPropMemberNames[2] = { L"Name", L"Value" }; + CComVariant pPropVar[2]; + pPropVar[0] = aArgNames[ix]; + pPropVar[1] = aArgVals[ix]; + hr = PutPropertiesToIDisp( pdispPropVal, sPropMemberNames, pPropVar, 2 ); + if( !SUCCEEDED( hr ) ) return hr; + + SafeArrayPutElement( pPropVals, &ix, pdispPropVal ); + } + + CComVariant aDispArgs[2]; + aDispArgs[1] = CComVariant( pdispURL ); + // aDispArgs[0] = CComVariant( pPropVals ); such constructor is not defined ??! + aDispArgs[0].vt = VT_ARRAY | VT_DISPATCH; aDispArgs[0].parray = pPropVals; + + CComVariant dummyResult; + hr = ExecuteFunc( pdispXDispatch, L"dispatch", aDispArgs, 2, &dummyResult ); + if( !SUCCEEDED( hr ) ) return hr; + + return S_OK; +} + +void CSOActiveX::CallbackCreateXInputStream( CBindStatusCallback<CSOActiveX>* /*pbsc*/, BYTE* pBytes, DWORD dwSize ) +{ + if ( mbReadyForActivation ) + return; + + bool bSuccess = false; + bool bFinishDownload = false; + if ( !pBytes ) + { + // means the download is finished, dwSize contains hresult + bFinishDownload = true; + if ( SUCCEEDED( dwSize ) ) + bSuccess = true; + } + else + { + HRESULT hr = S_OK; + + if ( !mpDispTempFile ) + { + CComVariant aServiceName( L"com.sun.star.io.TempFile" ); + hr = GetIDispByFunc( mpDispFactory, + L"createInstance", + &aServiceName, + 1, + mpDispTempFile ); + } + + if( SUCCEEDED( hr ) && mpDispTempFile ) + { + SAFEARRAY* pDataArray = SafeArrayCreateVector(VT_I1, 0, dwSize); + + if ( pDataArray ) + { + hr = SafeArrayLock( pDataArray ); + if ( SUCCEEDED( hr ) ) + { + for( DWORD ix = 0; ix < dwSize; ix++ ) + static_cast<BYTE*>(pDataArray->pvData)[ix] = pBytes[ix]; + hr = SafeArrayUnlock( pDataArray ); + if ( SUCCEEDED( hr ) ) + { + CComVariant aArgs[1]; + aArgs[0].vt = VT_ARRAY | VT_I1; aArgs[0].parray = pDataArray; + CComVariant dummyResult; + hr = ExecuteFunc( mpDispTempFile, L"writeBytes", aArgs, 1, &dummyResult ); + if( SUCCEEDED( hr ) ) + bSuccess = true; + } + } + } + } + } + + if ( !bSuccess ) + { + // the download failed, let StarOffice download + bFinishDownload = true; + mpDispTempFile = CComPtr< IDispatch >(); + } + + if ( bFinishDownload ) + { + // trigger the loading now + mbLoad = TRUE; + mbReadyForActivation = TRUE; + + Invalidate(); + UpdateWindow(); + } +} + +HRESULT CSOActiveX::LoadURLToFrame( ) +{ + CComVariant aArgNames[4] = { L"ReadOnly", L"ViewOnly", L"AsTemplate", L"InputStream" }; + CComVariant aArgVals[4]; + unsigned int nCount = 3; // the 4-th argument is used only if the stream can be retrieved + + aArgVals[0].vt = VT_BOOL; aArgVals[0].boolVal = mbViewOnly ? VARIANT_TRUE : VARIANT_FALSE; + aArgVals[1].vt = VT_BOOL; aArgVals[1].boolVal = mbViewOnly ? VARIANT_TRUE : VARIANT_FALSE; + aArgVals[2].vt = VT_BOOL; aArgVals[2].boolVal = VARIANT_FALSE; + + if ( mpDispTempFile ) + { + aArgVals[3] = CComVariant( mpDispTempFile ); + nCount = 4; + } + + HRESULT hr = CallDispatchMethod( mCurFileUrl, aArgNames, aArgVals, nCount ); + if( !SUCCEEDED( hr ) ) return hr; + + // try to get the model and set the presentation specific property, the setting will fail for other document formats + CComPtr<IDispatch> pdispController; + hr = GetIDispByFunc( mpDispFrame, L"getController", nullptr, 0, pdispController ); + if ( SUCCEEDED( hr ) && pdispController ) + { + CComPtr<IDispatch> pdispModel; + hr = GetIDispByFunc( pdispController, L"getModel", nullptr, 0, pdispModel ); + if ( SUCCEEDED( hr ) && pdispModel ) + { + CComPtr<IDispatch> pdispPres; + hr = GetIDispByFunc( pdispModel, L"getPresentation", nullptr, 0, pdispPres ); + if ( SUCCEEDED( hr ) && pdispPres ) + { + // this is a presentation + // let the slide show be shown in the document window + OLECHAR const * pPropName = L"IsFullScreen"; + CComVariant pPresProp; + pPresProp.vt = VT_BOOL; pPresProp.boolVal = VARIANT_FALSE ; + hr = PutPropertiesToIDisp( pdispPres, &pPropName, &pPresProp, 1 ); + + // start the slide show + if ( SUCCEEDED( hr ) ) + { + CComVariant dummyResult; + ExecuteFunc( pdispPres, L"Start", nullptr, 0, &dummyResult ); + } + } + } + } + + // create dispatch interceptor + mpDispatchInterceptor = new CComObject< SODispatchInterceptor >(); + mpDispatchInterceptor->AddRef(); + mpDispatchInterceptor->SetParent( this ); + CComQIPtr< IDispatch, &IID_IDispatch > pIDispDispInter( mpDispatchInterceptor ); + + // register dispatch interceptor in the frame + CComVariant aDispVariant( pIDispDispInter ); + CComVariant dummyResult; + hr = ExecuteFunc( mpDispFrame, + L"registerDispatchProviderInterceptor", + &aDispVariant, + 1, + &dummyResult ); + + if( !SUCCEEDED( hr ) ) return hr; + + return S_OK; +} + +SOVersion CSOActiveX::GetVersionConnected() +{ + SOVersion bResult = SO_NOT_DETECTED; + if( mpDispFactory ) + { + // create ConfigurationProvider instance + CComPtr<IDispatch> pdispConfProv; + CComVariant aServiceName( L"com.sun.star.configuration.ConfigurationProvider" ); + HRESULT hr = GetIDispByFunc( mpDispFactory, + L"createInstance", + &aServiceName, + 1, + pdispConfProv ); + + if( SUCCEEDED( hr ) && pdispConfProv ) + { + CComPtr<IDispatch> pdispConfAccess; + + SAFEARRAY* pInitParams = SafeArrayCreateVector( VT_VARIANT, 0, 1 ); + + if( pInitParams ) + { + LONG ix = 0; + CComVariant aConfPath( L"org.openoffice.Setup" ); + SafeArrayPutElement( pInitParams, &ix, &aConfPath ); + + CComVariant aArgs[2]; + aArgs[1] = CComVariant( L"com.sun.star.configuration.ConfigurationAccess" ); + aArgs[0].vt = VT_ARRAY | VT_VARIANT; aArgs[0].parray = pInitParams; + + hr = GetIDispByFunc( pdispConfProv, + L"createInstanceWithArguments", + aArgs, + 2, + pdispConfAccess ); + + if( SUCCEEDED( hr ) && pdispConfAccess ) + { + CComVariant aOfficeName; + + CComVariant aProductName( L"Product/ooName" ); + hr = ExecuteFunc( pdispConfAccess, + L"getByHierarchicalName", + &aProductName, + 1, + &aOfficeName ); + + if( SUCCEEDED( hr ) && aOfficeName.vt == VT_BSTR ) + { + CComVariant aOfficeVersion; + + CComVariant aProductVersion( L"Product/ooSetupVersion" ); + hr = ExecuteFunc( pdispConfAccess, + L"getByHierarchicalName", + &aProductVersion, + 1, + &aOfficeVersion ); + + if( SUCCEEDED( hr ) && aOfficeVersion.vt == VT_BSTR ) + { + if (!wcscmp(aOfficeName.bstrVal, L"StarOffice")) + { + if (!wcsncmp(aOfficeVersion.bstrVal, L"6.1", 3)) + bResult = SO_61; + else if (!wcsncmp(aOfficeVersion.bstrVal, L"6.0", 3)) + bResult = SO_60; + else if (!wcsncmp(aOfficeVersion.bstrVal, L"5.2", 3)) + bResult = SO_52; + else + bResult = SO_UNKNOWN; + } + else // OpenOffice + { + if (!wcsncmp(aOfficeVersion.bstrVal, L"1.1", 3)) + bResult = OO_11; + else if (!wcsncmp(aOfficeVersion.bstrVal, L"1.0", 3)) + bResult = OO_10; + else + bResult = OO_UNKNOWN; + } + } + } + } + } + } + } + + return bResult; +} + +namespace { + +class LockingGuard +{ + bool& mbLocked; +public: + explicit LockingGuard( bool& bLocked ) + : mbLocked( bLocked ) + { + mbLocked = true; + } + + ~LockingGuard() + { + mbLocked = false; + } +}; + +} + +HRESULT CSOActiveX::OnDrawAdvanced( ATL_DRAWINFO& di ) +{ + // This method is called only in main thread, no need to lock it + + // Get read of reentrance problems + if ( mbDrawLocked ) + return S_OK; + LockingGuard aGuard( mbDrawLocked ); + + if( m_spInPlaceSite && mCurFileUrl && mbReadyForActivation ) + { + HWND hwnd; + HRESULT hr = m_spInPlaceSite->GetWindow( &hwnd ); + if( !SUCCEEDED( hr ) ) return hr; + + if( mParentWin != hwnd || !mOffWin ) + { + if( mpDispFrame ) + { + CComVariant dummyResult; + CComVariant aPropVar; + aPropVar.vt = VT_BOOL; aPropVar.boolVal = VARIANT_FALSE; + (void) ExecuteFunc( mpDispFrame, L"close", &aPropVar, 1, &dummyResult ); + mpDispFrame = CComPtr<IDispatch>(); + } + + mParentWin = hwnd; + mOffWin = CreateWindowW( + STAROFFICE_WINDOWCLASS, + L"OfficeContainer", + WS_CHILD | WS_CLIPCHILDREN | WS_BORDER, + di.prcBounds->left, + di.prcBounds->top, + di.prcBounds->right - di.prcBounds->left, + di.prcBounds->bottom - di.prcBounds->top, + mParentWin, + nullptr, + nullptr, + nullptr ); + + ::ShowWindow( mOffWin, SW_SHOW ); + } + else + { + RECT aRect; + ::GetWindowRect( mOffWin, &aRect ); + + if( aRect.left != di.prcBounds->left || aRect.top != di.prcBounds->top + || aRect.right != di.prcBounds->right || aRect.bottom != di.prcBounds->bottom ) + { + // on this state the office window should exist already + ::SetWindowPos( mOffWin, + HWND_TOP, + di.prcBounds->left, + di.prcBounds->top, + di.prcBounds->right - di.prcBounds->left, + di.prcBounds->bottom - di.prcBounds->top, + SWP_NOZORDER ); + + CComVariant aPosArgs[5]; + aPosArgs[4] = CComVariant( 0 ); + aPosArgs[3] = CComVariant( 0 ); + aPosArgs[2] = CComVariant( int(di.prcBounds->right - di.prcBounds->left) ); + aPosArgs[1] = CComVariant( int(di.prcBounds->bottom - di.prcBounds->top) ); + aPosArgs[0] = CComVariant( 12 ); + CComVariant dummyResult; + hr = ExecuteFunc( mpDispWin, L"setPosSize", aPosArgs, 5, &dummyResult ); + if( !SUCCEEDED( hr ) ) return hr; + } + } + + if (mnVersion == SO_NOT_DETECTED) + { + OutputError_Impl( mOffWin, CS_E_INVALID_VERSION ); + return E_FAIL; + } + + if( ! mpDispFrame ) + { + hr = CreateFrameOldWay( mOffWin, + di.prcBounds->right - di.prcBounds->left, + di.prcBounds->bottom - di.prcBounds->top ); + + if( !SUCCEEDED( hr ) ) + { + // if the frame can not be opened do not try any more + mbReadyForActivation = FALSE; + OutputError_Impl( mOffWin, STG_E_ABNORMALAPIEXIT ); + return hr; + } + } + + if( mbLoad ) + { + hr = LoadURLToFrame(); + mbLoad = FALSE; + + if( !SUCCEEDED( hr ) ) + { + // if the document can not be opened do not try any more + mbReadyForActivation = FALSE; + + OutputError_Impl( mOffWin, STG_E_ABNORMALAPIEXIT ); + + return hr; + } + } + } + else + { + // activate the fallback + CComControl<CSOActiveX>::OnDrawAdvanced( di ); + } + + return S_OK; +} + +HRESULT CSOActiveX::OnDraw( ATL_DRAWINFO& di ) +{ + // fallback that is activated by the parent class + if ( di.hdcDraw ) + FillRect( di.hdcDraw, reinterpret_cast<RECT const *>(di.prcBounds), reinterpret_cast<HBRUSH>(COLOR_BACKGROUND) ); + + return S_OK; +} + +COM_DECLSPEC_NOTHROW STDMETHODIMP CSOActiveX::SetClientSite( IOleClientSite* aClientSite ) +{ + HRESULT hr = IOleObjectImpl<CSOActiveX>::SetClientSite( aClientSite ); + + if( !aClientSite ) + { + //ATLASSERT( mWebBrowser2 ); + if( mWebBrowser2 ) + AtlUnadvise( mWebBrowser2, DIID_DWebBrowserEvents2, mCookie ); + return hr; + } + + CComPtr<IOleContainer> aContainer; + m_spClientSite->GetContainer( &aContainer ); +// ATLASSERT( aContainer ); + + if( SUCCEEDED( hr ) && aContainer ) + { + CComQIPtr<IServiceProvider, &IID_IServiceProvider> aServiceProvider( aContainer ); + //ATLASSERT( aServiceProvider ); + + if( aServiceProvider ) + { + aServiceProvider->QueryService( SID_SInternetExplorer, + IID_IWebBrowser, + reinterpret_cast<void**>(&mWebBrowser2) ); +// ATLASSERT( mWebBrowser2 ); + if( mWebBrowser2 ) + AtlAdvise( mWebBrowser2, GetUnknown(), DIID_DWebBrowserEvents2, &mCookie ); + } + } + + return hr; +} + +COM_DECLSPEC_NOTHROW STDMETHODIMP CSOActiveX::Invoke(DISPID dispidMember, + REFIID riid, + LCID lcid, + WORD wFlags, + DISPPARAMS* pDispParams, + VARIANT* pvarResult, + EXCEPINFO* pExcepInfo, + UINT* puArgErr) +{ + if (riid != IID_NULL) + return DISP_E_UNKNOWNINTERFACE; + + if (!pDispParams) + return DISP_E_PARAMNOTOPTIONAL; + + if ( dispidMember == DISPID_ONQUIT ) + Cleanup(); + + IDispatchImpl<ISOActiveX, &IID_ISOActiveX, + &LIBID_SO_ACTIVEXLib>::Invoke( + dispidMember, riid, lcid, wFlags, pDispParams, + pvarResult, pExcepInfo, puArgErr); + + return S_OK; +} + +HRESULT CSOActiveX::GetURL( const OLECHAR* url, + const OLECHAR* target ) +{ + CComVariant aEmpty1, aEmpty2, aEmpty3; + CComVariant aUrl( url ); + CComVariant aTarget; + if ( target ) + aTarget = CComVariant( target ); + + return mWebBrowser2->Navigate2( &aUrl, + &aEmpty1, + &aTarget, + &aEmpty2, + &aEmpty3 ); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |