bump product version to 6.3.0.0.beta1
[LibreOffice.git] / extensions / source / activex / SOActiveX.cxx
blobb1f4b9447260ff5c91311778bead3673b7be6af5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 // SOActiveX.cpp : Implementation of CSOActiveX
22 #include "StdAfx2.h"
23 #include "SOActiveX.h"
24 #include "SOComWindowPeer.h"
25 #include "SODispatchInterceptor.h"
26 #include "SOActionsApproval.h"
27 #include "com_uno_helper.h"
29 #if defined __clang__
30 #pragma clang diagnostic push
31 #pragma clang diagnostic ignored "-Wnon-virtual-dtor"
32 #endif
33 #include <so_activex.h>
34 #if defined __clang__
35 #pragma clang diagnostic pop
36 #endif
38 #define STAROFFICE_WINDOWCLASS L"SOParentWindow"
41 static void OutputError_Impl( HWND hw, HRESULT ErrorCode )
43 LPWSTR sMessage = nullptr;
44 FormatMessageW(
45 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
46 nullptr,
47 ErrorCode,
48 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
49 reinterpret_cast<LPWSTR>(&sMessage),
51 nullptr
53 MessageBoxW( hw, sMessage, nullptr, MB_OK | MB_ICONINFORMATION );
54 HeapFree( GetProcessHeap(), 0, sMessage );
57 HRESULT ExecuteFunc( IDispatch* idispUnoObject,
58 OLECHAR const * sFuncName,
59 CComVariant* params,
60 unsigned int count,
61 CComVariant* pResult )
63 if( !idispUnoObject )
64 return E_FAIL;
66 DISPID id;
67 HRESULT hr = idispUnoObject->GetIDsOfNames( IID_NULL, const_cast<OLECHAR **>(&sFuncName), 1, LOCALE_USER_DEFAULT, &id);
68 if( !SUCCEEDED( hr ) ) return hr;
70 DISPPARAMS dispparams= { params, nullptr, count, 0};
72 // DEBUG
73 EXCEPINFO myInfo;
74 hr = idispUnoObject->Invoke( id, IID_NULL,LOCALE_USER_DEFAULT, DISPATCH_METHOD,
75 &dispparams, pResult, &myInfo, nullptr);
77 // for debugging purposes
78 // USES_CONVERSION;
79 // if ( !SUCCEEDED( hr ) )
80 // ::MessageBox( NULL, OLE2A( myInfo.bstrDescription ), OLE2A( myInfo.bstrSource ), MB_OK | MB_ICONINFORMATION );
82 return hr;
85 static HRESULT GetIDispByFunc( IDispatch* idispUnoObject,
86 OLECHAR const * sFuncName,
87 CComVariant* params,
88 unsigned int count,
89 CComPtr<IDispatch>& pdispResult )
91 if( !idispUnoObject )
92 return E_FAIL;
94 CComVariant result;
95 HRESULT hr = ExecuteFunc( idispUnoObject, sFuncName, params, count, &result );
96 if( !SUCCEEDED( hr ) ) return hr;
98 if( result.vt != VT_DISPATCH || result.pdispVal == nullptr )
99 return E_FAIL;
101 pdispResult = CComPtr<IDispatch>( result.pdispVal );
103 return S_OK;
106 static HRESULT PutPropertiesToIDisp( IDispatch* pdispObject,
107 OLECHAR const ** sMemberNames,
108 CComVariant* pVariant,
109 unsigned int count )
111 for( unsigned int ind = 0; ind < count; ind++ )
113 DISPID id;
114 HRESULT hr = pdispObject->GetIDsOfNames( IID_NULL, const_cast<OLECHAR **>(&sMemberNames[ind]), 1, LOCALE_USER_DEFAULT, &id );
115 if( !SUCCEEDED( hr ) ) return hr;
117 hr = CComDispatchDriver::PutProperty( pdispObject, id, &pVariant[ind] );
118 if( !SUCCEEDED( hr ) ) return hr;
121 return S_OK;
124 HRESULT GetPropertiesFromIDisp( IDispatch* pdispObject,
125 OLECHAR const ** sMemberNames,
126 CComVariant* pVariant,
127 unsigned int count )
129 for( unsigned int ind = 0; ind < count; ind++ )
131 DISPID id;
132 HRESULT hr = pdispObject->GetIDsOfNames( IID_NULL, const_cast<OLECHAR **>(&sMemberNames[ind]), 1, LOCALE_USER_DEFAULT, &id );
133 if( !SUCCEEDED( hr ) ) return hr;
135 hr = CComDispatchDriver::GetProperty( pdispObject, id, &pVariant[ind] );
136 if( !SUCCEEDED( hr ) ) return hr;
139 return S_OK;
142 // CSOActiveX
144 CSOActiveX::CSOActiveX()
145 : mCookie(0)
146 , mCurFileUrl( L"private:factory/swriter" )
147 , mbLoad( FALSE )
148 , mbViewOnly( TRUE )
149 , mParentWin( nullptr )
150 , mOffWin( nullptr )
151 , mpDispatchInterceptor( nullptr )
152 , mnVersion( SO_NOT_DETECTED )
153 , mbReadyForActivation( FALSE )
154 , mbDrawLocked( FALSE )
156 CLSID const clsFactory = {0x82154420,0x0FBF,0x11d4,{0x83, 0x13,0x00,0x50,0x04,0x52,0x6A,0xB4}};
157 HRESULT hr = CoCreateInstance( clsFactory, nullptr, CLSCTX_ALL, __uuidof(IDispatch), reinterpret_cast<void**>(&mpDispFactory));
158 if( !SUCCEEDED( hr ) )
159 OutputError_Impl( nullptr, hr );
161 mPWinClass.style = CS_HREDRAW|CS_VREDRAW;
162 mPWinClass.lpfnWndProc = DefWindowProcW;
163 mPWinClass.cbClsExtra = 0;
164 mPWinClass.cbWndExtra = 0;
165 mPWinClass.hInstance = GetModuleHandleW(nullptr); //myInstance;
166 mPWinClass.hIcon = nullptr;
167 mPWinClass.hCursor = nullptr;
168 mPWinClass.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_BACKGROUND);
169 mPWinClass.lpszMenuName = nullptr;
170 mPWinClass.lpszClassName = STAROFFICE_WINDOWCLASS;
172 RegisterClassW(&mPWinClass);
175 CSOActiveX::~CSOActiveX()
177 Cleanup();
181 HRESULT CSOActiveX::Cleanup()
183 CComVariant dummyResult;
185 if( mpDispatchInterceptor )
187 if( mpDispFrame )
189 // remove dispatch interceptor
190 CComQIPtr< IDispatch, &IID_IDispatch > pIDispDispInter( mpDispatchInterceptor );
191 CComVariant aVariant( pIDispDispInter );
192 ExecuteFunc( mpDispFrame,
193 L"releaseDispatchProviderInterceptor",
194 &aVariant,
196 &dummyResult );
199 mpDispatchInterceptor->ClearParent();
200 mpDispatchInterceptor->Release();
201 mpDispatchInterceptor = nullptr;
204 mpDispTempFile = CComPtr< IDispatch >();
205 mbReadyForActivation = FALSE;
207 if( mpInstanceLocker )
209 ExecuteFunc( mpInstanceLocker, L"dispose", nullptr, 0, &dummyResult );
210 mpInstanceLocker = CComPtr< IDispatch >();
213 if( mpDispFrame )
215 BOOL bCloserActivated = FALSE;
217 CComPtr<IDispatch> pDispDocumentCloser;
218 CComVariant aDocCloser( L"com.sun.star.embed.DocumentCloser" );
219 HRESULT hr = GetIDispByFunc( mpDispFactory,
220 L"createInstance",
221 &aDocCloser,
223 pDispDocumentCloser );
224 if ( SUCCEEDED( hr ) && pDispDocumentCloser )
226 SAFEARRAY FAR* pInitFrame = SafeArrayCreateVector( VT_VARIANT, 0, 1 );
227 long nInitInd = 0;
228 CComVariant pFrameVariant( mpDispFrame );
229 SafeArrayPutElement( pInitFrame, &nInitInd, &pFrameVariant );
230 CComVariant aVarInitFrame;
231 aVarInitFrame.vt = VT_ARRAY | VT_VARIANT; aVarInitFrame.parray = pInitFrame;
232 hr = ExecuteFunc( pDispDocumentCloser, L"initialize", &aVarInitFrame, 1, &dummyResult );
233 if( SUCCEEDED( hr ) )
235 // the following call will let the closing happen
236 hr = ExecuteFunc( pDispDocumentCloser, L"dispose", nullptr, 0, &dummyResult );
237 bCloserActivated = SUCCEEDED( hr );
241 if ( !bCloserActivated )
243 CComVariant aPropVar;
244 aPropVar.vt = VT_BOOL; aPropVar.boolVal = VARIANT_TRUE;
245 if ( !SUCCEEDED( ExecuteFunc( mpDispFrame, L"close", &aPropVar, 1, &dummyResult ) ) )
246 ExecuteFunc( mpDispFrame, L"dispose", nullptr, 0, &dummyResult );
249 mpDispFrame = CComPtr< IDispatch >();
252 if( ::IsWindow( mOffWin ) )
253 ::DestroyWindow( mOffWin );
255 TerminateOffice();
257 return S_OK;
260 HRESULT CSOActiveX::TerminateOffice()
262 // create desktop
263 CComPtr<IDispatch> pdispDesktop;
264 CComVariant aDesktopServiceName( L"com.sun.star.frame.Desktop" );
266 HRESULT hr = GetIDispByFunc( mpDispFactory, L"createInstance", &aDesktopServiceName, 1, pdispDesktop );
267 if( !pdispDesktop || !SUCCEEDED( hr ) ) return hr;
269 // create tree of frames
270 CComPtr<IDispatch> pdispChildren;
271 hr = GetIDispByFunc( pdispDesktop, L"getFrames", nullptr, 0, pdispChildren );
272 if( !pdispChildren || !SUCCEEDED( hr ) ) return hr;
274 CComVariant aFrames;
275 CComVariant nFlag( 4 );
276 hr = ExecuteFunc( pdispChildren, L"queryFrames", &nFlag, 1, &aFrames );
277 if ( SUCCEEDED( hr ) )
279 if ( ( aFrames.vt == ( VT_ARRAY | VT_DISPATCH ) || aFrames.vt == ( VT_ARRAY | VT_VARIANT ) )
280 && ( !aFrames.parray || (aFrames.parray->cDims == 1 && aFrames.parray->rgsabound[0].cElements == 0) ) )
282 // there is no frames open
283 // TODO: check whether the frames are hidden if they are open?
284 CComVariant dummyResult;
285 hr = ExecuteFunc( pdispDesktop, L"terminate", nullptr, 0, &dummyResult );
289 return hr;
292 STDMETHODIMP CSOActiveX::InitNew ()
294 mnVersion = GetVersionConnected();
295 mbLoad = TRUE;
296 return S_OK;
299 STDMETHODIMP CSOActiveX::Load ( LPSTREAM /*pStm*/ )
301 mnVersion = GetVersionConnected();
302 mbLoad = TRUE;
304 // may be later?
305 // for now just ignore
307 return S_OK;
310 STDMETHODIMP CSOActiveX::Load( LPPROPERTYBAG pPropBag, LPERRORLOG /*pErrorLog*/ )
312 mnVersion = GetVersionConnected();
314 IPropertyBag2* pPropBag2;
315 HRESULT hr = pPropBag->QueryInterface( IID_IPropertyBag2, reinterpret_cast<void**>(&pPropBag2) );
316 //ATLASSERT( hr >= 0 );
318 if( !SUCCEEDED( hr ) )
319 return hr;
321 unsigned long aNum;
322 hr = pPropBag2->CountProperties( &aNum );
323 //ATLASSERT( hr >= 0 );
324 if( !SUCCEEDED( hr ) )
325 return hr;
327 PROPBAG2* aPropNames = new PROPBAG2[aNum];
328 unsigned long aReaded;
330 hr = pPropBag2->GetPropertyInfo( 0,
331 aNum,
332 aPropNames,
333 &aReaded );
334 //ATLASSERT( hr >= 0 );
335 if( !SUCCEEDED( hr ) )
337 delete[] aPropNames;
338 return hr;
341 CComVariant* aVal = new CComVariant[aNum];
342 HRESULT* hvs = new HRESULT[aNum];
343 hr = pPropBag2->Read( aNum,
344 aPropNames,
345 nullptr,
346 aVal,
347 hvs );
348 //ATLASSERT( hr >= 0 );
349 if( !SUCCEEDED( hr ) )
351 delete[] hvs;
352 delete[] aVal;
353 delete[] aPropNames;
354 return hr;
357 for( unsigned long ind = 0; ind < aNum; ind++ )
359 // all information from the 'object' tag is in strings
360 if (aVal[ind].vt == VT_BSTR && !wcscmp(aPropNames[ind].pstrName, L"src"))
362 mCurFileUrl = wcsdup( aVal[ind].bstrVal );
364 else if( aVal[ind].vt == VT_BSTR
365 && !wcscmp(aPropNames[ind].pstrName, L"readonly"))
367 if (!wcscmp(aVal[ind].bstrVal, L"true"))
369 // the default value
370 mbViewOnly = TRUE;
372 else
374 mbViewOnly = FALSE;
379 delete[] hvs;
380 delete[] aVal;
381 delete[] aPropNames;
383 if( !mpDispFactory )
384 return hr;
386 mbReadyForActivation = FALSE;
387 if (BSTR bStrUrl = SysAllocString(mCurFileUrl))
389 hr = CBindStatusCallback<CSOActiveX>::Download(
390 this, &CSOActiveX::CallbackCreateXInputStream, bStrUrl, m_spClientSite, FALSE);
391 SysFreeString(bStrUrl);
392 if (hr == MK_S_ASYNCHRONOUS)
393 hr = S_OK;
395 else
396 hr = E_OUTOFMEMORY;
398 if ( !SUCCEEDED( hr ) )
400 // trigger initialization without stream
401 mbLoad = TRUE;
403 Invalidate();
404 UpdateWindow();
407 return hr;
410 HRESULT CSOActiveX::GetUnoStruct( OLECHAR const * sStructName, CComPtr<IDispatch>& pdispResult )
412 CComVariant aComStruct( sStructName );
413 return GetIDispByFunc( mpDispFactory, L"Bridge_GetStruct", &aComStruct, 1, pdispResult );
416 HRESULT CSOActiveX::GetUrlStruct( OLECHAR const * sUrl, CComPtr<IDispatch>& pdispUrl )
418 HRESULT hr = GetUnoStruct( L"com.sun.star.util.URL", pdispUrl );
419 if( !SUCCEEDED( hr ) ) return hr;
421 OLECHAR const * sURLMemberName = L"Complete";
422 DISPID nURLID;
423 hr = pdispUrl->GetIDsOfNames( IID_NULL, const_cast<OLECHAR **>(&sURLMemberName), 1, LOCALE_USER_DEFAULT, &nURLID );
424 if( !SUCCEEDED( hr ) ) return hr;
425 CComVariant aComUrl( sUrl );
426 hr = CComDispatchDriver::PutProperty( pdispUrl, nURLID, &aComUrl );
427 if( !SUCCEEDED( hr ) ) return hr;
429 CComPtr<IDispatch> pdispTransformer;
430 CComVariant aServiceName( L"com.sun.star.util.URLTransformer" );
431 hr = GetIDispByFunc( mpDispFactory,
432 L"createInstance",
433 &aServiceName,
435 pdispTransformer );
436 if( !SUCCEEDED( hr ) ) return hr;
438 CComVariant dummyResult;
439 CComVariant aParam[2];
440 aParam[1].ppdispVal = &pdispUrl;
441 aParam[1].vt = VT_DISPATCH | VT_BYREF;
442 aParam[0] = CComVariant( L"file:///" );
444 hr = ExecuteFunc( pdispTransformer, L"parseSmart", aParam, 2, &dummyResult );
445 if( !SUCCEEDED( hr ) || dummyResult.vt != VT_BOOL || !dummyResult.boolVal ) return hr;
447 return S_OK;
450 HRESULT CSOActiveX::SetLayoutManagerProps()
452 if ( !mpDispFrame )
453 return E_FAIL;
455 CComVariant pVarLayoutMgr;
456 OLECHAR const * sLMPropName = L"LayoutManager";
457 HRESULT hr = GetPropertiesFromIDisp( mpDispFrame, &sLMPropName, &pVarLayoutMgr, 1 );
458 if( pVarLayoutMgr.vt != VT_DISPATCH || pVarLayoutMgr.pdispVal == nullptr )
459 return E_FAIL;
461 CComPtr<IDispatch> pdispLM( pVarLayoutMgr.pdispVal );
464 if( !SUCCEEDED( hr ) || !pdispLM )
465 return E_FAIL;
467 OLECHAR const * sATName = L"AutomaticToolbars";
468 CComVariant pATProp;
469 pATProp.vt = VT_BOOL; pATProp.boolVal = VARIANT_FALSE ;
470 hr = PutPropertiesToIDisp( pdispLM, &sATName, &pATProp, 1 );
472 return hr;
475 HRESULT CSOActiveX::CreateFrameOldWay( HWND hwnd, int width, int height )
477 if( !mpDispFactory )
478 return E_FAIL;
480 // create window handle holder
481 CComPtr< CComObject< SOComWindowPeer > > pPeerToSend = new CComObject<SOComWindowPeer>();
482 pPeerToSend->SetHWNDInternally( hwnd );
483 CComQIPtr< IDispatch, &IID_IDispatch > pIDispToSend( pPeerToSend );
485 // create rectangle structure
486 CComPtr<IDispatch> pdispRectangle;
487 HRESULT hr = GetUnoStruct( L"com.sun.star.awt.Rectangle", pdispRectangle );
488 if( !SUCCEEDED( hr ) ) return hr;
490 OLECHAR const * sRectMemberNames[4] = { L"X",
491 L"Y",
492 L"Width",
493 L"Height" };
494 CComVariant pRectVariant[4];
495 pRectVariant[0] = pRectVariant[1] = pRectVariant[2] = pRectVariant[3] = CComVariant( 0 );
497 hr = PutPropertiesToIDisp( pdispRectangle, sRectMemberNames, pRectVariant, 4 );
498 if( !SUCCEEDED( hr ) ) return hr;
500 // create WindowDescriptor structure
501 CComPtr<IDispatch> pdispWinDescr;
502 hr = GetUnoStruct( L"com.sun.star.awt.WindowDescriptor", pdispWinDescr );
503 if( !SUCCEEDED( hr ) ) return hr;
505 // fill in descriptor with info
506 OLECHAR const * sDescriptorMemberNames[6] = { L"Type",
507 L"WindowServiceName",
508 L"ParentIndex",
509 L"Parent",
510 L"Bounds",
511 L"WindowAttributes" };
512 CComVariant pDescriptorVar[6];
513 pDescriptorVar[0] = CComVariant( 0 );
514 pDescriptorVar[1] = CComVariant( L"workwindow" );
515 pDescriptorVar[2] = CComVariant( 1 );
516 pDescriptorVar[3] = CComVariant( pIDispToSend );
517 pDescriptorVar[4] = CComVariant( pdispRectangle );
518 pDescriptorVar[5] = CComVariant( 33 );
519 hr = PutPropertiesToIDisp( pdispWinDescr, sDescriptorMemberNames, pDescriptorVar, 6 );
520 if( !SUCCEEDED( hr ) ) return hr;
522 // create XToolkit instance
523 CComPtr<IDispatch> pdispToolkit;
524 CComVariant aServiceName( L"com.sun.star.awt.Toolkit" );
525 hr = GetIDispByFunc( mpDispFactory, L"createInstance", &aServiceName, 1, pdispToolkit );
526 if( !SUCCEEDED( hr ) ) return hr;
528 // create window with toolkit
529 CComVariant aWinDescr( pdispWinDescr );
530 hr = GetIDispByFunc( pdispToolkit, L"createWindow", &aWinDescr, 1, mpDispWin );
531 if( !SUCCEEDED( hr ) ) return hr;
533 // create frame
534 aServiceName = CComVariant( L"com.sun.star.frame.Task" );
535 hr = GetIDispByFunc( mpDispFactory, L"createInstance", &aServiceName, 1, mpDispFrame );
536 if( !SUCCEEDED( hr ) || !mpDispFrame )
538 // the interface com.sun.star.frame.Task is removed in 6.1
539 // but the interface com.sun.star.frame.Frame has some bugs in 6.0
540 aServiceName = CComVariant( L"com.sun.star.frame.Frame" );
541 hr = GetIDispByFunc( mpDispFactory, L"createInstance", &aServiceName, 1, mpDispFrame );
542 if( !SUCCEEDED( hr ) ) return hr;
545 // initialize frame
546 CComVariant dummyResult;
547 CComVariant aDispWin( mpDispWin );
548 hr = ExecuteFunc( mpDispFrame, L"initialize", &aDispWin, 1, &dummyResult );
549 if( !SUCCEEDED( hr ) ) return hr;
551 // set some properties to the layout manager, ignore errors for now
552 SetLayoutManagerProps();
554 // create desktop
555 CComPtr<IDispatch> pdispDesktop;
556 aServiceName = CComVariant( L"com.sun.star.frame.Desktop" );
557 hr = GetIDispByFunc( mpDispFactory, L"createInstance", &aServiceName, 1, pdispDesktop );
558 if( !SUCCEEDED( hr ) ) return hr;
560 // create tree of frames
561 CComPtr<IDispatch> pdispChildren;
562 hr = GetIDispByFunc( pdispDesktop, L"getFrames", nullptr, 0, pdispChildren );
563 if( !SUCCEEDED( hr ) ) return hr;
565 // insert new frame into desktop hierarchy
566 CComVariant aDispFrame( mpDispFrame );
567 hr = ExecuteFunc( pdispChildren, L"append", &aDispFrame, 1, &dummyResult );
568 if( !SUCCEEDED( hr ) ) return hr;
570 // initialize window
571 CComVariant aTransparent( long(0xFFFFFFFF) );
572 hr = ExecuteFunc( mpDispWin, L"setBackground", &aTransparent, 1, &dummyResult );
573 if( !SUCCEEDED( hr ) ) return hr;
575 CComVariant aTrue( TRUE );
576 hr = ExecuteFunc( mpDispWin, L"setVisible", &aTrue, 1, &dummyResult );
577 if( !SUCCEEDED( hr ) ) return hr;
579 CComVariant aPosArgs[5];
580 aPosArgs[4] = CComVariant( 0 );
581 aPosArgs[3] = CComVariant( 0 );
582 aPosArgs[2] = CComVariant( width );
583 aPosArgs[1] = CComVariant( height );
584 aPosArgs[0] = CComVariant( 12 );
585 hr = ExecuteFunc( mpDispWin, L"setPosSize", aPosArgs, 5, &dummyResult );
586 if( !SUCCEEDED( hr ) ) return hr;
588 // create frame locker if there is such service
589 aServiceName = CComVariant( L"com.sun.star.embed.InstanceLocker" );
590 hr = GetIDispByFunc( mpDispFactory, L"createInstance", &aServiceName, 1, mpInstanceLocker );
591 if( SUCCEEDED( hr ) && mpInstanceLocker )
593 SAFEARRAY FAR* pInitVals = SafeArrayCreateVector( VT_VARIANT, 0, 3 );
595 // the first sequence element
596 long nInitInd = 0;
597 CComVariant pFrameVariant( mpDispFrame );
598 SafeArrayPutElement( pInitVals, &nInitInd, &pFrameVariant );
600 // the second sequence element
601 nInitInd = 1;
602 CComVariant pStrArr( 1 );
603 SafeArrayPutElement( pInitVals, &nInitInd, &pStrArr );
605 // the third sequence element
606 nInitInd = 2;
607 CComPtr<IDispatch> pdispValueObj;
608 hr = GetIDispByFunc( mpDispFactory, L"Bridge_GetValueObject", nullptr, 0, pdispValueObj );
609 if( !SUCCEEDED( hr ) || !pdispValueObj ) return hr;
611 CComVariant aValueArgs[2];
612 aValueArgs[1] = CComVariant( L"com.sun.star.embed.XActionsApproval" );
613 CComPtr< CComObject< SOActionsApproval > > pApproval( new CComObject<SOActionsApproval>() );
614 aValueArgs[0] = CComVariant ( pApproval );
616 hr = ExecuteFunc( pdispValueObj, L"Set", aValueArgs, 2, &dummyResult );
617 if( !SUCCEEDED( hr ) ) return hr;
619 CComVariant aValueObj( pdispValueObj );
620 SafeArrayPutElement( pInitVals, &nInitInd, &aValueObj );
622 // execute initialize()
623 CComVariant aVarInitVals;
624 aVarInitVals.vt = VT_ARRAY | VT_VARIANT; aVarInitVals.parray = pInitVals;
625 hr = ExecuteFunc( mpInstanceLocker, L"initialize", &aVarInitVals, 1, &dummyResult );
626 if( !SUCCEEDED( hr ) ) return hr;
629 return S_OK;
632 HRESULT CSOActiveX::CallLoadComponentFromURL1PBool( OLECHAR const * sUrl, OLECHAR const * sArgName, BOOL sArgVal )
634 SAFEARRAY FAR* pPropVals = SafeArrayCreateVector( VT_DISPATCH, 0, 1 );
635 long ix = 0;
636 CComPtr<IDispatch> pdispPropVal;
637 HRESULT hr = GetUnoStruct( L"com.sun.star.beans.PropertyValue", pdispPropVal );
638 if( !SUCCEEDED( hr ) ) return hr;
640 OLECHAR const * sPropMemberNames[2] = { L"Name", L"Value" };
641 CComVariant pPropVar[2];
642 pPropVar[0] = CComVariant( sArgName );
643 pPropVar[1].vt = VT_BOOL; pPropVar[1].boolVal = sArgVal ? VARIANT_TRUE : VARIANT_FALSE ;
644 hr = PutPropertiesToIDisp( pdispPropVal, sPropMemberNames, pPropVar, 2 );
645 if( !SUCCEEDED( hr ) ) return hr;
647 SafeArrayPutElement( pPropVals, &ix, pdispPropVal );
649 CComVariant aDispArgs[4];
650 aDispArgs[3] = CComVariant( sUrl );
651 aDispArgs[2] = CComVariant( L"_self" );
652 aDispArgs[1] = CComVariant( 0 );
653 // aDispArgs[0] = CComVariant( pPropVals ); such constructor is not defined ??!
654 aDispArgs[0].vt = VT_ARRAY | VT_DISPATCH; aDispArgs[0].parray = pPropVals;
656 CComVariant dummyResult;
657 hr = ExecuteFunc( mpDispFrame, L"loadComponentFromURL", aDispArgs, 4, &dummyResult );
658 if( !SUCCEEDED( hr ) ) return hr;
660 return S_OK;
663 HRESULT CSOActiveX::CallDispatchMethod( OLECHAR const * sUrl,
664 CComVariant* aArgNames,
665 CComVariant* aArgVals,
666 unsigned int count )
668 CComPtr<IDispatch> pdispURL;
669 HRESULT hr = GetUrlStruct( sUrl, pdispURL );
670 if( !SUCCEEDED( hr ) ) return hr;
672 CComPtr<IDispatch> pdispXDispatch;
673 CComVariant aArgs[3];
674 aArgs[2] = CComVariant( pdispURL );
675 aArgs[1] = CComVariant( L"" );
676 aArgs[0] = CComVariant( int(0) );
677 hr = GetIDispByFunc( mpDispFrame,
678 L"queryDispatch",
679 aArgs,
681 pdispXDispatch );
682 if( !SUCCEEDED( hr ) ) return hr;
684 SAFEARRAY FAR* pPropVals = SafeArrayCreateVector( VT_DISPATCH, 0, count );
685 for( long ix = 0; ix < static_cast<long>(count); ix ++ )
687 CComPtr<IDispatch> pdispPropVal;
688 hr = GetUnoStruct( L"com.sun.star.beans.PropertyValue", pdispPropVal );
689 if( !SUCCEEDED( hr ) ) return hr;
691 OLECHAR const * sPropMemberNames[2] = { L"Name", L"Value" };
692 CComVariant pPropVar[2];
693 pPropVar[0] = aArgNames[ix];
694 pPropVar[1] = aArgVals[ix];
695 hr = PutPropertiesToIDisp( pdispPropVal, sPropMemberNames, pPropVar, 2 );
696 if( !SUCCEEDED( hr ) ) return hr;
698 SafeArrayPutElement( pPropVals, &ix, pdispPropVal );
701 CComVariant aDispArgs[2];
702 aDispArgs[1] = CComVariant( pdispURL );
703 // aDispArgs[0] = CComVariant( pPropVals ); such constructor is not defined ??!
704 aDispArgs[0].vt = VT_ARRAY | VT_DISPATCH; aDispArgs[0].parray = pPropVals;
706 CComVariant dummyResult;
707 hr = ExecuteFunc( pdispXDispatch, L"dispatch", aDispArgs, 2, &dummyResult );
708 if( !SUCCEEDED( hr ) ) return hr;
710 return S_OK;
713 void CSOActiveX::CallbackCreateXInputStream( CBindStatusCallback<CSOActiveX>* /*pbsc*/, BYTE* pBytes, DWORD dwSize )
715 if ( mbReadyForActivation )
716 return;
718 BOOL bSuccess = FALSE;
719 BOOL bFinishDownload = FALSE;
720 if ( !pBytes )
722 // means the download is finished, dwSize contains hresult
723 bFinishDownload = TRUE;
724 if ( SUCCEEDED( dwSize ) )
725 bSuccess = TRUE;
727 else
729 HRESULT hr = S_OK;
731 if ( !mpDispTempFile )
733 CComVariant aServiceName( L"com.sun.star.io.TempFile" );
734 hr = GetIDispByFunc( mpDispFactory,
735 L"createInstance",
736 &aServiceName,
738 mpDispTempFile );
741 if( SUCCEEDED( hr ) && mpDispTempFile )
743 SAFEARRAY FAR* pDataArray = SafeArrayCreateVector( VT_I1, 0, dwSize );
745 if ( pDataArray )
747 hr = SafeArrayLock( pDataArray );
748 if ( SUCCEEDED( hr ) )
750 for( DWORD ix = 0; ix < dwSize; ix++ )
751 static_cast<BYTE*>(pDataArray->pvData)[ix] = pBytes[ix];
752 hr = SafeArrayUnlock( pDataArray );
753 if ( SUCCEEDED( hr ) )
755 CComVariant aArgs[1];
756 aArgs[0].vt = VT_ARRAY | VT_I1; aArgs[0].parray = pDataArray;
757 CComVariant dummyResult;
758 hr = ExecuteFunc( mpDispTempFile, L"writeBytes", aArgs, 1, &dummyResult );
759 if( SUCCEEDED( hr ) )
760 bSuccess = TRUE;
767 if ( !bSuccess )
769 // the download failed, let StarOffice download
770 bFinishDownload = TRUE;
771 mpDispTempFile = CComPtr< IDispatch >();
774 if ( bFinishDownload )
776 // trigger the loading now
777 mbLoad = TRUE;
778 mbReadyForActivation = TRUE;
780 Invalidate();
781 UpdateWindow();
785 HRESULT CSOActiveX::LoadURLToFrame( )
787 CComVariant aArgNames[4] = { L"ReadOnly", L"ViewOnly", L"AsTemplate", L"InputStream" };
788 CComVariant aArgVals[4];
789 unsigned int nCount = 3; // the 4-th argument is used only if the stream can be retrieved
791 aArgVals[0].vt = VT_BOOL; aArgVals[0].boolVal = mbViewOnly ? VARIANT_TRUE : VARIANT_FALSE;
792 aArgVals[1].vt = VT_BOOL; aArgVals[1].boolVal = mbViewOnly ? VARIANT_TRUE : VARIANT_FALSE;
793 aArgVals[2].vt = VT_BOOL; aArgVals[2].boolVal = VARIANT_FALSE;
795 if ( mpDispTempFile )
797 aArgVals[3] = CComVariant( mpDispTempFile );
798 nCount = 4;
801 HRESULT hr = CallDispatchMethod( mCurFileUrl, aArgNames, aArgVals, nCount );
802 if( !SUCCEEDED( hr ) ) return hr;
804 CComVariant aBarName( L"MenuBarVisible" );
805 CComVariant aBarVis;
806 aBarVis.vt = VT_BOOL; aBarVis.boolVal = VARIANT_FALSE;
807 hr = CallDispatchMethod( L"slot:6661", &aBarName, &aBarVis, 1 );
808 // does not work for some documents, but it is no error
809 // if( !SUCCEEDED( hr ) ) return hr;
811 // try to get the model and set the presentation specific property, the setting will fail for other document formats
812 CComPtr<IDispatch> pdispController;
813 hr = GetIDispByFunc( mpDispFrame, L"getController", nullptr, 0, pdispController );
814 if ( SUCCEEDED( hr ) && pdispController )
816 CComPtr<IDispatch> pdispModel;
817 hr = GetIDispByFunc( pdispController, L"getModel", nullptr, 0, pdispModel );
818 if ( SUCCEEDED( hr ) && pdispModel )
820 CComPtr<IDispatch> pdispPres;
821 hr = GetIDispByFunc( pdispModel, L"getPresentation", nullptr, 0, pdispPres );
822 if ( SUCCEEDED( hr ) && pdispPres )
824 // this is a presentation
825 // let the slide show be shown in the document window
826 OLECHAR const * pPropName = L"IsFullScreen";
827 CComVariant pPresProp;
828 pPresProp.vt = VT_BOOL; pPresProp.boolVal = VARIANT_FALSE ;
829 hr = PutPropertiesToIDisp( pdispPres, &pPropName, &pPresProp, 1 );
831 // start the slide show
832 if ( SUCCEEDED( hr ) )
834 CComVariant dummyResult;
835 ExecuteFunc( pdispPres, L"Start", nullptr, 0, &dummyResult );
841 // create dispatch interceptor
842 mpDispatchInterceptor = new CComObject< SODispatchInterceptor >();
843 mpDispatchInterceptor->AddRef();
844 mpDispatchInterceptor->SetParent( this );
845 CComQIPtr< IDispatch, &IID_IDispatch > pIDispDispInter( mpDispatchInterceptor );
847 // register dispatch interceptor in the frame
848 CComVariant aDispVariant( pIDispDispInter );
849 CComVariant dummyResult;
850 hr = ExecuteFunc( mpDispFrame,
851 L"registerDispatchProviderInterceptor",
852 &aDispVariant,
854 &dummyResult );
856 if( !SUCCEEDED( hr ) ) return hr;
858 return S_OK;
861 SOVersion CSOActiveX::GetVersionConnected()
863 SOVersion bResult = SO_NOT_DETECTED;
864 if( mpDispFactory )
866 // create ConfigurationProvider instance
867 CComPtr<IDispatch> pdispConfProv;
868 CComVariant aServiceName( L"com.sun.star.configuration.ConfigurationProvider" );
869 HRESULT hr = GetIDispByFunc( mpDispFactory,
870 L"createInstance",
871 &aServiceName,
873 pdispConfProv );
875 if( SUCCEEDED( hr ) && pdispConfProv )
877 CComPtr<IDispatch> pdispConfAccess;
879 SAFEARRAY* pInitParams = SafeArrayCreateVector( VT_VARIANT, 0, 1 );
881 if( pInitParams )
883 long ix = 0;
884 CComVariant aConfPath( L"org.openoffice.Setup" );
885 SafeArrayPutElement( pInitParams, &ix, &aConfPath );
887 CComVariant aArgs[2];
888 aArgs[1] = CComVariant( L"com.sun.star.configuration.ConfigurationAccess" );
889 aArgs[0].vt = VT_ARRAY | VT_VARIANT; aArgs[0].parray = pInitParams;
891 hr = GetIDispByFunc( pdispConfProv,
892 L"createInstanceWithArguments",
893 aArgs,
895 pdispConfAccess );
897 if( SUCCEEDED( hr ) && pdispConfAccess )
899 CComVariant aOfficeName;
901 CComVariant aProductName( L"Product/ooName" );
902 hr = ExecuteFunc( pdispConfAccess,
903 L"getByHierarchicalName",
904 &aProductName,
906 &aOfficeName );
908 if( SUCCEEDED( hr ) && aOfficeName.vt == VT_BSTR )
910 CComVariant aOfficeVersion;
912 CComVariant aProductVersion( L"Product/ooSetupVersion" );
913 hr = ExecuteFunc( pdispConfAccess,
914 L"getByHierarchicalName",
915 &aProductVersion,
917 &aOfficeVersion );
919 if( SUCCEEDED( hr ) && aOfficeVersion.vt == VT_BSTR )
921 if (!wcscmp(aOfficeName.bstrVal, L"StarOffice"))
923 if (!wcsncmp(aOfficeVersion.bstrVal, L"6.1", 3))
924 bResult = SO_61;
925 else if (!wcsncmp(aOfficeVersion.bstrVal, L"6.0", 3))
926 bResult = SO_60;
927 else if (!wcsncmp(aOfficeVersion.bstrVal, L"5.2", 3))
928 bResult = SO_52;
929 else
930 bResult = SO_UNKNOWN;
932 else // OpenOffice
934 if (!wcsncmp(aOfficeVersion.bstrVal, L"1.1", 3))
935 bResult = OO_11;
936 else if (!wcsncmp(aOfficeVersion.bstrVal, L"1.0", 3))
937 bResult = OO_10;
938 else
939 bResult = OO_UNKNOWN;
948 return bResult;
951 class LockingGuard
953 BOOL& mbLocked;
954 public:
955 explicit LockingGuard( BOOL& bLocked )
956 : mbLocked( bLocked )
958 mbLocked = TRUE;
961 ~LockingGuard()
963 mbLocked = FALSE;
967 HRESULT CSOActiveX::OnDrawAdvanced( ATL_DRAWINFO& di )
969 // This method is called only in main thread, no need to lock it
971 // Get read of reentrance problems
972 if ( mbDrawLocked )
973 return S_OK;
974 LockingGuard aGuard( mbDrawLocked );
976 if( m_spInPlaceSite && mCurFileUrl && mbReadyForActivation )
978 HWND hwnd;
979 HRESULT hr = m_spInPlaceSite->GetWindow( &hwnd );
980 if( !SUCCEEDED( hr ) ) return hr;
982 if( mParentWin != hwnd || !mOffWin )
984 if( mpDispFrame )
986 CComVariant dummyResult;
987 CComVariant aPropVar;
988 aPropVar.vt = VT_BOOL; aPropVar.boolVal = VARIANT_FALSE;
989 (void) ExecuteFunc( mpDispFrame, L"close", &aPropVar, 1, &dummyResult );
990 mpDispFrame = CComPtr<IDispatch>();
993 mParentWin = hwnd;
994 mOffWin = CreateWindowW(
995 STAROFFICE_WINDOWCLASS,
996 L"OfficeContainer",
997 WS_CHILD | WS_CLIPCHILDREN | WS_BORDER,
998 di.prcBounds->left,
999 di.prcBounds->top,
1000 di.prcBounds->right - di.prcBounds->left,
1001 di.prcBounds->bottom - di.prcBounds->top,
1002 mParentWin,
1003 nullptr,
1004 nullptr,
1005 nullptr );
1007 ::ShowWindow( mOffWin, SW_SHOW );
1009 else
1011 RECT aRect;
1012 ::GetWindowRect( mOffWin, &aRect );
1014 if( aRect.left != di.prcBounds->left || aRect.top != di.prcBounds->top
1015 || aRect.right != di.prcBounds->right || aRect.bottom != di.prcBounds->bottom )
1017 // on this state the office window should exist already
1018 ::SetWindowPos( mOffWin,
1019 HWND_TOP,
1020 di.prcBounds->left,
1021 di.prcBounds->top,
1022 di.prcBounds->right - di.prcBounds->left,
1023 di.prcBounds->bottom - di.prcBounds->top,
1024 SWP_NOZORDER );
1026 CComVariant aPosArgs[5];
1027 aPosArgs[4] = CComVariant( 0 );
1028 aPosArgs[3] = CComVariant( 0 );
1029 aPosArgs[2] = CComVariant( int(di.prcBounds->right - di.prcBounds->left) );
1030 aPosArgs[1] = CComVariant( int(di.prcBounds->bottom - di.prcBounds->top) );
1031 aPosArgs[0] = CComVariant( 12 );
1032 CComVariant dummyResult;
1033 hr = ExecuteFunc( mpDispWin, L"setPosSize", aPosArgs, 5, &dummyResult );
1034 if( !SUCCEEDED( hr ) ) return hr;
1038 if (mnVersion == SO_NOT_DETECTED)
1040 OutputError_Impl( mOffWin, CS_E_INVALID_VERSION );
1041 return E_FAIL;
1044 if( ! mpDispFrame )
1046 hr = CreateFrameOldWay( mOffWin,
1047 di.prcBounds->right - di.prcBounds->left,
1048 di.prcBounds->bottom - di.prcBounds->top );
1050 if( !SUCCEEDED( hr ) )
1052 // if the frame can not be opened do not try any more
1053 mbReadyForActivation = FALSE;
1054 OutputError_Impl( mOffWin, STG_E_ABNORMALAPIEXIT );
1055 return hr;
1059 if( mbLoad )
1061 hr = LoadURLToFrame();
1062 mbLoad = FALSE;
1064 if( !SUCCEEDED( hr ) )
1066 // if the document can not be opened do not try any more
1067 mbReadyForActivation = FALSE;
1069 OutputError_Impl( mOffWin, STG_E_ABNORMALAPIEXIT );
1071 return hr;
1075 else
1077 // activate the fallback
1078 CComControl<CSOActiveX>::OnDrawAdvanced( di );
1081 return S_OK;
1084 HRESULT CSOActiveX::OnDraw( ATL_DRAWINFO& di )
1086 // fallback that is activated by the parent class
1087 if ( di.hdcDraw )
1088 FillRect( di.hdcDraw, reinterpret_cast<RECT const *>(di.prcBounds), reinterpret_cast<HBRUSH>(COLOR_BACKGROUND) );
1090 return S_OK;
1093 STDMETHODIMP CSOActiveX::SetClientSite( IOleClientSite* aClientSite )
1095 HRESULT hr = IOleObjectImpl<CSOActiveX>::SetClientSite( aClientSite );
1097 if( !aClientSite )
1099 //ATLASSERT( mWebBrowser2 );
1100 if( mWebBrowser2 )
1101 AtlUnadvise( mWebBrowser2, DIID_DWebBrowserEvents2, mCookie );
1102 return hr;
1105 CComPtr<IOleContainer> aContainer;
1106 m_spClientSite->GetContainer( &aContainer );
1107 // ATLASSERT( aContainer );
1109 if( SUCCEEDED( hr ) && aContainer )
1111 CComQIPtr<IServiceProvider, &IID_IServiceProvider> aServiceProvider( aContainer );
1112 //ATLASSERT( aServiceProvider );
1114 if( aServiceProvider )
1116 aServiceProvider->QueryService( SID_SInternetExplorer,
1117 IID_IWebBrowser,
1118 reinterpret_cast<void**>(&mWebBrowser2) );
1119 // ATLASSERT( mWebBrowser2 );
1120 if( mWebBrowser2 )
1121 AtlAdvise( mWebBrowser2, GetUnknown(), DIID_DWebBrowserEvents2, &mCookie );
1125 return hr;
1128 STDMETHODIMP CSOActiveX::Invoke(DISPID dispidMember,
1129 REFIID riid,
1130 LCID lcid,
1131 WORD wFlags,
1132 DISPPARAMS* pDispParams,
1133 VARIANT* pvarResult,
1134 EXCEPINFO* pExcepInfo,
1135 UINT* puArgErr)
1137 if (riid != IID_NULL)
1138 return DISP_E_UNKNOWNINTERFACE;
1140 if (!pDispParams)
1141 return DISP_E_PARAMNOTOPTIONAL;
1143 if ( dispidMember == DISPID_ONQUIT )
1144 Cleanup();
1146 IDispatchImpl<ISOActiveX, &IID_ISOActiveX,
1147 &LIBID_SO_ACTIVEXLib>::Invoke(
1148 dispidMember, riid, lcid, wFlags, pDispParams,
1149 pvarResult, pExcepInfo, puArgErr);
1151 return S_OK;
1154 HRESULT CSOActiveX::GetURL( const OLECHAR* url,
1155 const OLECHAR* target )
1157 CComVariant aEmpty1, aEmpty2, aEmpty3;
1158 CComVariant aUrl( url );
1159 CComVariant aTarget;
1160 if ( target )
1161 aTarget = CComVariant( target );
1163 return mWebBrowser2->Navigate2( &aUrl,
1164 &aEmpty1,
1165 &aTarget,
1166 &aEmpty2,
1167 &aEmpty3 );
1171 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */