blob: cfebc0aaafe039cc06f2ab3f9bc79c13e0dad03a [file] [log] [blame]
/**************************************************************
*
* 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// SOActiveX.cpp : Implementation of CSOActiveX
#pragma warning (disable:4505)
// permanently suppress "unreferenced local function has been removed" warning
#pragma warning (push,1)
#pragma warning (disable:4265)
#include "stdafx2.h"
#include "so_activex.h"
#include "SOActiveX.h"
#include "SOComWindowPeer.h"
#include "SODispatchInterceptor.h"
#include "SOActionsApproval.h"
#pragma warning (pop)
#define STAROFFICE_WINDOWCLASS "SOParentWindow"
/////////////////////////////////////////////////////////////////////////////
void OutputError_Impl( HWND hw, HRESULT ErrorCode )
{
void* sMessage;
FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
ErrorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &sMessage,
0,
NULL
);
::MessageBoxA( hw, (LPCTSTR)sMessage, NULL, MB_OK | MB_ICONINFORMATION );
LocalFree( sMessage );
}
HRESULT ExecuteFunc( IDispatch* idispUnoObject,
OLECHAR* sFuncName,
CComVariant* params,
unsigned int count,
CComVariant* pResult )
{
if( !idispUnoObject )
return E_FAIL;
DISPID id;
HRESULT hr = idispUnoObject->GetIDsOfNames( IID_NULL, &sFuncName, 1, LOCALE_USER_DEFAULT, &id);
if( !SUCCEEDED( hr ) ) return hr;
DISPPARAMS dispparams= { params, 0, count, 0};
// DEBUG
EXCEPINFO myInfo;
hr = idispUnoObject->Invoke( id, IID_NULL,LOCALE_USER_DEFAULT, DISPATCH_METHOD,
&dispparams, pResult, &myInfo, 0);
// for debugging purposes
// USES_CONVERSION;
// if ( !SUCCEEDED( hr ) )
// ::MessageBox( NULL, OLE2A( myInfo.bstrDescription ), OLE2A( myInfo.bstrSource ), MB_OK | MB_ICONINFORMATION );
return hr;
}
HRESULT GetIDispByFunc( IDispatch* idispUnoObject,
OLECHAR* 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 == NULL )
return E_FAIL;
pdispResult = CComPtr<IDispatch>( result.pdispVal );
return S_OK;
}
HRESULT PutPropertiesToIDisp( IDispatch* pdispObject,
OLECHAR** sMemberNames,
CComVariant* pVariant,
unsigned int count )
{
for( unsigned int ind = 0; ind < count; ind++ )
{
DISPID id;
HRESULT hr = pdispObject->GetIDsOfNames( IID_NULL, &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** sMemberNames,
CComVariant* pVariant,
unsigned int count )
{
for( unsigned int ind = 0; ind < count; ind++ )
{
DISPID id;
HRESULT hr = pdispObject->GetIDsOfNames( IID_NULL, &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 )
, mParentWin( NULL )
, mOffWin( NULL )
, mbViewOnly( TRUE )
, mpDispatchInterceptor( NULL )
, mnVersion( SO_NOT_DETECTED )
, mbReadyForActivation( FALSE )
, mbDrawLocked( FALSE )
{
CLSID clsFactory = {0x82154420,0x0FBF,0x11d4,{0x83, 0x13,0x00,0x50,0x04,0x52,0x6A,0xB4}};
HRESULT hr = CoCreateInstance( clsFactory, NULL, CLSCTX_ALL, __uuidof(IDispatch), (void**)&mpDispFactory);
if( !SUCCEEDED( hr ) )
OutputError_Impl( NULL, hr );
mPWinClass.style = CS_HREDRAW|CS_VREDRAW;
mPWinClass.lpfnWndProc = ::DefWindowProc;
mPWinClass.cbClsExtra = 0;
mPWinClass.cbWndExtra = 0;
mPWinClass.hInstance = (HINSTANCE) GetModuleHandle(NULL); //myInstance;
mPWinClass.hIcon = NULL;
mPWinClass.hCursor = NULL;
mPWinClass.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
mPWinClass.lpszMenuName = NULL;
mPWinClass.lpszClassName = STAROFFICE_WINDOWCLASS;
RegisterClass(&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 = NULL;
}
mpDispTempFile = CComPtr< IDispatch >();
mbReadyForActivation = FALSE;
if( mpInstanceLocker )
{
ExecuteFunc( mpInstanceLocker, L"dispose", NULL, 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 FAR* 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", NULL, 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", NULL, 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", NULL, 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", NULL, 0, &dummyResult );
}
}
return hr;
}
STDMETHODIMP CSOActiveX::InitNew ()
{
mnVersion = GetVersionConnected();
mbLoad = TRUE;
return S_OK;
}
STDMETHODIMP CSOActiveX::Load ( LPSTREAM /*pStm*/ )
{
mnVersion = GetVersionConnected();
mbLoad = TRUE;
// may be later?
// for now just ignore
return S_OK;
}
STDMETHODIMP CSOActiveX::Load( LPPROPERTYBAG pPropBag, LPERRORLOG /*pErrorLog*/ )
{
mnVersion = GetVersionConnected();
IPropertyBag2* pPropBag2;
HRESULT hr = pPropBag->QueryInterface( IID_IPropertyBag2, (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,
NULL,
aVal,
hvs );
//ATLASSERT( hr >= 0 );
if( !SUCCEEDED( hr ) )
{
delete[] hvs;
delete[] aVal;
delete[] aPropNames;
return hr;
}
USES_CONVERSION;
for( unsigned long ind = 0; ind < aNum; ind++ )
{
// all information from the 'object' tag is in strings
if( aVal[ind].vt == VT_BSTR && !strcmp( OLE2T( aPropNames[ind].pstrName ), "src" ) )
{
mCurFileUrl = wcsdup( aVal[ind].bstrVal );
}
else if( aVal[ind].vt == VT_BSTR
&& !strcmp( OLE2T( aPropNames[ind].pstrName ), "readonly" ) )
{
if( !strcmp( OLE2T( aVal[ind].bstrVal ), "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* sStructName, CComPtr<IDispatch>& pdispResult )
{
CComVariant aComStruct( sStructName );
return GetIDispByFunc( mpDispFactory, L"Bridge_GetStruct", &aComStruct, 1, pdispResult );
}
HRESULT CSOActiveX::GetUrlStruct( OLECHAR* sUrl, CComPtr<IDispatch>& pdispUrl )
{
HRESULT hr = GetUnoStruct( L"com.sun.star.util.URL", pdispUrl );
if( !SUCCEEDED( hr ) ) return hr;
OLECHAR* sURLMemberName = L"Complete";
DISPID nURLID;
hr = pdispUrl->GetIDsOfNames( IID_NULL, &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* sLMPropName = L"LayoutManager";
HRESULT hr = GetPropertiesFromIDisp( mpDispFrame, &sLMPropName, &pVarLayoutMgr, 1 );
if( pVarLayoutMgr.vt != VT_DISPATCH || pVarLayoutMgr.pdispVal == NULL )
return E_FAIL;
CComPtr<IDispatch> pdispLM( pVarLayoutMgr.pdispVal );
if( !SUCCEEDED( hr ) || !pdispLM )
return E_FAIL;
OLECHAR* 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* 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* 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", NULL, 0, pdispChildren );
if( !SUCCEEDED( hr ) ) return hr;
// insert new frame into desctop 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 FAR* 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( 1L );
SafeArrayPutElement( pInitVals, &nInitInd, &pStrArr );
// the third sequence element
nInitInd = 2;
CComPtr<IDispatch> pdispValueObj;
hr = GetIDispByFunc( mpDispFactory, L"Bridge_GetValueObject", NULL, 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* sUrl, OLECHAR* sArgName, BOOL sArgVal )
{
SAFEARRAY FAR* 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* 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* 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 FAR* pPropVals = SafeArrayCreateVector( VT_DISPATCH, 0, count );
for( long ix = 0; ix < (long)count; ix ++ )
{
CComPtr<IDispatch> pdispPropVal;
hr = GetUnoStruct( L"com.sun.star.beans.PropertyValue", pdispPropVal );
if( !SUCCEEDED( hr ) ) return hr;
OLECHAR* 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 FAR* pDataArray = SafeArrayCreateVector( VT_I1, 0, dwSize );
if ( pDataArray )
{
hr = SafeArrayLock( pDataArray );
if ( SUCCEEDED( hr ) )
{
for( DWORD ix = 0; ix < dwSize; ix++ )
((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;
CComVariant aBarName( L"MenuBarVisible" );
CComVariant aBarVis;
aBarVis.vt = VT_BOOL; aBarVis.boolVal = VARIANT_FALSE;
hr = CallDispatchMethod( L"slot:6661", &aBarName, &aBarVis, 1 );
// does not work for some documents, but it is no error
// if( !SUCCEEDED( hr ) ) return hr;
// try to get the model and set the presetation specific property, the setting will fail for other document formats
CComPtr<IDispatch> pdispController;
hr = GetIDispByFunc( mpDispFrame, L"getController", NULL, 0, pdispController );
if ( SUCCEEDED( hr ) && pdispController )
{
CComPtr<IDispatch> pdispModel;
hr = GetIDispByFunc( pdispController, L"getModel", NULL, 0, pdispModel );
if ( SUCCEEDED( hr ) && pdispModel )
{
CComPtr<IDispatch> pdispPres;
hr = GetIDispByFunc( pdispModel, L"getPresentation", NULL, 0, pdispPres );
if ( SUCCEEDED( hr ) && pdispPres )
{
// this is a presentation
// let the slide show be shown in the document window
OLECHAR* 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", NULL, 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 )
{
USES_CONVERSION;
if( !strcmp( OLE2T( aOfficeName.bstrVal ), "StarOffice" ) )
{
if( !strncmp( OLE2T( aOfficeVersion.bstrVal ), "6.1", 3 ) )
bResult = SO_61;
else if( !strncmp( OLE2T( aOfficeVersion.bstrVal ), "6.0", 3 ) )
bResult = SO_60;
else if( !strncmp( OLE2T( aOfficeVersion.bstrVal ), "5.2", 3 ) )
bResult = SO_52;
else
bResult = SO_UNKNOWN;
}
else // OpenOffice
{
if( !strncmp( OLE2T( aOfficeVersion.bstrVal ), "1.1", 3 ) )
bResult = OO_11;
else if( !strncmp( OLE2T( aOfficeVersion.bstrVal ), "1.0", 3 ) )
bResult = OO_10;
else
bResult = OO_UNKNOWN;
}
}
}
}
}
}
}
return bResult;
}
class LockingGuard
{
BOOL& mbLocked;
public:
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;
HRESULT hr = ExecuteFunc( mpDispFrame, L"close", &aPropVar, 1, &dummyResult );
(void)hr;
mpDispFrame = CComPtr<IDispatch>();
}
mParentWin = hwnd;
mOffWin = CreateWindow(
STAROFFICE_WINDOWCLASS,
"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,
NULL,
NULL,
NULL );
::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 )
{
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, (RECT*)di.prcBounds, (HBRUSH)COLOR_BACKGROUND );
return S_OK;
}
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,
(void**)&mWebBrowser2 );
// ATLASSERT( mWebBrowser2 );
if( mWebBrowser2 )
AtlAdvise( mWebBrowser2, GetUnknown(), DIID_DWebBrowserEvents2, &mCookie );
}
}
return hr;
}
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 );
}
// ---------------------------------------------------------------------------