1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "embeddoc.hxx"
25 #include <osl/diagnose.h>
26 #include <com/sun/star/frame/XController.hpp>
27 #include <com/sun/star/beans/PropertyValue.hpp>
28 
29 
30 using namespace ::com::sun::star;
31 
32 
33 extern ::rtl::OUString	getFilterNameFromGUID_Impl( GUID* );
34 
35 //-------------------------------------------------------------------------------
36 // IOleObject
37 
38 
SetClientSite(IOleClientSite * pSite)39 STDMETHODIMP EmbedDocument_Impl::SetClientSite( IOleClientSite* pSite )
40 {
41 	m_pClientSite = pSite;
42 	return S_OK;
43 }
44 
GetClientSite(IOleClientSite ** pSite)45 STDMETHODIMP EmbedDocument_Impl::GetClientSite( IOleClientSite** pSite )
46 {
47 	*pSite = m_pClientSite;
48 	return S_OK;
49 }
50 
SetHostNames(LPCOLESTR szContainerApp,LPCOLESTR szContainerObj)51 STDMETHODIMP EmbedDocument_Impl::SetHostNames( LPCOLESTR szContainerApp, LPCOLESTR szContainerObj )
52 {
53 	// the code should be ignored for links
54 	if ( !m_aFileName.getLength() )
55 	{
56 		m_pDocHolder->setTitle(
57 			rtl::OUString(
58 				(sal_Unicode*)szContainerObj));
59 		m_pDocHolder->setContainerName(
60 			rtl::OUString(
61 				(sal_Unicode*)szContainerApp));
62 	}
63 
64 	return S_OK;
65 }
66 
Close(DWORD dwSaveOption)67 STDMETHODIMP EmbedDocument_Impl::Close( DWORD dwSaveOption )
68 {
69     HRESULT hr = S_OK;
70 
71     if ( m_pDocHolder->HasFrame() )
72     {
73         if ( dwSaveOption == 2 && m_aFileName.getLength() )
74         {
75             // ask the user about saving
76             if ( m_pDocHolder->ExecuteSuspendCloseFrame() )
77             {
78                 m_pDocHolder->CloseDocument();
79                 return S_OK;
80             }
81             else
82                 return OLE_E_PROMPTSAVECANCELLED;
83         }
84 
85         if ( dwSaveOption != 1 )
86             hr = SaveObject(); // ADVF_DATAONSTOP);
87 
88 	    m_pDocHolder->CloseFrame();
89         OLENotifyDeactivation();
90     }
91 
92 	m_pDocHolder->FreeOffice();
93 	m_pDocHolder->CloseDocument();
94 
95 	OLENotifyClosing();
96 
97 	return hr;
98 }
99 
100 
OLENotifyClosing()101 HRESULT EmbedDocument_Impl::OLENotifyClosing()
102 {
103 	HRESULT hr = S_OK;
104 
105 	AdviseSinkHashMap aAHM(m_aAdviseHashMap);
106 
107 	for ( AdviseSinkHashMapIterator iAdvise = aAHM.begin();
108 		  iAdvise != aAHM.end(); iAdvise++ )
109 	{
110 		if ( iAdvise->second )
111 			iAdvise->second->OnClose();
112 	}
113 
114 	return hr;
115 
116 }
117 
SetMoniker(DWORD,IMoniker *)118 STDMETHODIMP EmbedDocument_Impl::SetMoniker( DWORD /*dwWhichMoniker*/, IMoniker * /*pmk*/ )
119 {
120     return E_NOTIMPL;
121 }
122 
GetMoniker(DWORD,DWORD,IMoniker **)123 STDMETHODIMP EmbedDocument_Impl::GetMoniker( DWORD /*dwAssign*/, DWORD /*dwWhichMoniker*/, IMoniker ** /*ppmk*/ )
124 {
125     return E_NOTIMPL;
126 }
127 
InitFromData(IDataObject *,BOOL,DWORD)128 STDMETHODIMP EmbedDocument_Impl::InitFromData( IDataObject * /*pDataObject*/, BOOL /*fCreation*/, DWORD /*dwReserved*/ )
129 {
130     return E_NOTIMPL;
131 }
132 
GetClipboardData(DWORD,IDataObject **)133 STDMETHODIMP EmbedDocument_Impl::GetClipboardData( DWORD /*dwReserved*/, IDataObject ** /*ppDataObject*/ )
134 {
135     return E_NOTIMPL;
136 }
137 
138 /**
139  *  Well, this is a not so very inefficient way to deliver
140  *
141  */
142 
DoVerb(LONG iVerb,LPMSG,IOleClientSite * pActiveSite,LONG,HWND,LPCRECT)143 STDMETHODIMP EmbedDocument_Impl::DoVerb(
144 	LONG iVerb,
145 	LPMSG,
146 	IOleClientSite *pActiveSite,
147 	LONG,
148 	HWND,
149 	LPCRECT )
150 {
151 	// no locking is used since the OLE must use the same thread always
152 	if ( m_bIsInVerbHandling )
153         return OLEOBJ_S_CANNOT_DOVERB_NOW;
154 
155     // an object can not handle any Verbs in Hands off mode
156     if ( m_pMasterStorage == NULL || m_pOwnStream == NULL )
157         return OLE_E_CANT_BINDTOSOURCE;
158 
159 
160 	BooleanGuard_Impl aGuard( m_bIsInVerbHandling );
161 
162 	if ( iVerb == OLEIVERB_PRIMARY )
163 	{
164 		if ( m_aFileName.getLength() )
165 		{
166 			// that should be a link
167 			iVerb = OLEIVERB_OPEN;
168 		}
169 		else
170 			iVerb = OLEIVERB_SHOW;
171 	}
172 
173 	try
174 	{
175 		switch(iVerb) {
176 			case OLEIVERB_DISCARDUNDOSTATE:
177 				// free any undostate?
178 				break;
179 			case OLEIVERB_INPLACEACTIVATE:
180 				OSL_ENSURE(m_pDocHolder,"no document for inplace activation");
181 
182 				return m_pDocHolder->InPlaceActivate(pActiveSite,FALSE);
183 				break;
184 			case OLEIVERB_UIACTIVATE:
185 				OSL_ENSURE(m_pDocHolder,"no document for	 inplace activation");
186 
187 				return m_pDocHolder->InPlaceActivate(pActiveSite,TRUE);
188 				break;
189 			case OLEIVERB_PRIMARY:
190 			case OLEIVERB_SHOW:
191 				OSL_ENSURE(m_pDocHolder,"no document for inplace activation");
192 
193 				if(m_pDocHolder->isActive())
194 					return NOERROR; //Already active
195 
196 				if(SUCCEEDED(
197 					m_pDocHolder->InPlaceActivate(
198 						pActiveSite,TRUE)))
199 					return NOERROR;
200 
201 				// intended fall trough
202 			case OLEIVERB_OPEN:
203 				OSL_ENSURE(m_pDocHolder,"no document to open");
204 
205 				// the commented code could be usefull in case
206 				// outer window would be resized depending from inner one
207 				// RECTL aEmbArea;
208 				// m_pDocHolder->GetVisArea( &aEmbArea );
209 				// m_pDocHolder->show();
210 				// m_pDocHolder->SetVisArea( &aEmbArea );
211 
212 				if(m_pDocHolder->isActive())
213 				{
214 					m_pDocHolder->InPlaceDeactivate();
215 					m_pDocHolder->DisableInplaceActivation(true);
216 				}
217 
218 				SIZEL aEmbSize;
219 				m_pDocHolder->GetExtent( &aEmbSize );
220 				m_pDocHolder->show();
221 				m_pDocHolder->resizeWin( aEmbSize );
222 
223 				if ( m_pClientSite )
224 					m_pClientSite->OnShowWindow( TRUE );
225 
226 				notify();
227 				break;
228 			case OLEIVERB_HIDE:
229 				OSL_ENSURE(m_pDocHolder,"no document to hide");
230 
231 				if(m_pDocHolder->isActive())
232 					m_pDocHolder->InPlaceDeactivate();
233 				else {
234 					m_pDocHolder->hide();
235 
236 					if( m_pClientSite )
237 						m_pClientSite->OnShowWindow(FALSE);
238 				}
239 				break;
240 			default:
241 				break;
242 		}
243 	}
244 	catch( uno::Exception& )
245 	{
246 		return OLEOBJ_S_CANNOT_DOVERB_NOW;
247 	}
248 
249 	return NOERROR;
250 }
251 
252 
253 
EnumVerbs(IEnumOLEVERB **)254 STDMETHODIMP EmbedDocument_Impl::EnumVerbs( IEnumOLEVERB ** /*ppEnumOleVerb*/ )
255 {
256     return OLE_S_USEREG;
257 }
258 
Update()259 STDMETHODIMP EmbedDocument_Impl::Update()
260 {
261     return S_OK;
262 //    HRESULT hr = CACHE_E_NOCACHE_UPDATED;
263 //    return hr;
264 }
265 
IsUpToDate()266 STDMETHODIMP EmbedDocument_Impl::IsUpToDate()
267 {
268     return S_OK;
269 }
270 
GetUserClassID(CLSID * pClsid)271 STDMETHODIMP EmbedDocument_Impl::GetUserClassID( CLSID *pClsid )
272 {
273     return GetClassID( pClsid );
274 }
275 
GetUserType(DWORD,LPOLESTR *)276 STDMETHODIMP EmbedDocument_Impl::GetUserType( DWORD /*dwFormOfTypeUe*/, LPOLESTR * /*pszUserType*/ )
277 {
278     return OLE_S_USEREG;
279 }
280 
SetExtent(DWORD,SIZEL * psizel)281 STDMETHODIMP EmbedDocument_Impl::SetExtent( DWORD /*dwDrawAspect*/, SIZEL *psizel )
282 {
283     if ( !psizel )
284         return E_FAIL;
285 
286     m_pDocHolder->SetExtent( psizel );
287 
288     return S_OK;
289 }
290 
GetExtent(DWORD,SIZEL * psizel)291 STDMETHODIMP EmbedDocument_Impl::GetExtent( DWORD /*dwDrawAspect*/, SIZEL * psizel )
292 {
293     if ( !psizel )
294         return E_INVALIDARG;
295 
296     if ( FAILED( m_pDocHolder->GetExtent( psizel ) ) )
297     {
298         // return default values
299         psizel->cx = 500;
300         psizel->cy = 500;
301     }
302 
303     return S_OK;
304 }
305 
Advise(IAdviseSink * pAdvSink,DWORD * pdwConnection)306 STDMETHODIMP EmbedDocument_Impl::Advise( IAdviseSink *pAdvSink, DWORD *pdwConnection )
307 {
308     if ( m_nAdviseNum == 0xFFFFFFFF )
309         return E_OUTOFMEMORY;
310 
311     pAdvSink->AddRef();
312     m_aAdviseHashMap.insert( ::std::pair< DWORD, IAdviseSink* >( m_nAdviseNum, pAdvSink ) );
313     *pdwConnection = m_nAdviseNum++;
314 
315     return S_OK;
316 }
317 
Unadvise(DWORD dwConnection)318 STDMETHODIMP EmbedDocument_Impl::Unadvise( DWORD dwConnection )
319 {
320 	AdviseSinkHashMapIterator iAdvise = m_aAdviseHashMap.find( dwConnection );
321 	if ( iAdvise != m_aAdviseHashMap.end() )
322 	{
323 		iAdvise->second->Release();
324 		m_aAdviseHashMap.erase( iAdvise );
325 	}
326 	else
327 		return OLE_E_NOCONNECTION;
328 
329 	return S_OK;
330 }
331 
EnumAdvise(IEnumSTATDATA **)332 STDMETHODIMP EmbedDocument_Impl::EnumAdvise( IEnumSTATDATA ** /*ppenumAdvise*/ )
333 {
334 	return E_NOTIMPL;
335 }
336 
GetMiscStatus(DWORD,DWORD *)337 STDMETHODIMP EmbedDocument_Impl::GetMiscStatus( DWORD /*dwAspect*/, DWORD * /*pdwStatus*/ )
338 {
339 	return OLE_S_USEREG;
340 }
341 
SetColorScheme(LOGPALETTE *)342 STDMETHODIMP EmbedDocument_Impl::SetColorScheme( LOGPALETTE * /*pLogpal*/ )
343 {
344 	return E_NOTIMPL;
345 }
346 
347 //-------------------------------------------------------------------------------
348 // IDispatch
349 
GetTypeInfoCount(unsigned int FAR * pctinfo)350 STDMETHODIMP EmbedDocument_Impl::GetTypeInfoCount( unsigned int FAR*  pctinfo )
351 {
352 	if ( m_pDocHolder->GetIDispatch() )
353 		return m_pDocHolder->GetIDispatch()->GetTypeInfoCount( pctinfo );
354 
355 	return E_NOTIMPL;
356 }
357 
GetTypeInfo(unsigned int iTInfo,LCID lcid,ITypeInfo FAR * FAR * ppTInfo)358 STDMETHODIMP EmbedDocument_Impl::GetTypeInfo( unsigned int iTInfo, LCID lcid, ITypeInfo FAR* FAR* ppTInfo )
359 {
360 	if ( m_pDocHolder->GetIDispatch() )
361 		return m_pDocHolder->GetIDispatch()->GetTypeInfo( iTInfo, lcid, ppTInfo );
362 
363 	return DISP_E_BADINDEX; // the only error that can be returned
364 }
365 
GetIDsOfNames(REFIID riid,OLECHAR FAR * FAR * rgszNames,unsigned int cNames,LCID lcid,DISPID FAR * rgDispId)366 STDMETHODIMP EmbedDocument_Impl::GetIDsOfNames( REFIID riid,
367 												OLECHAR FAR* FAR* rgszNames,
368 												unsigned int cNames,
369 												LCID lcid,
370 												DISPID FAR* rgDispId )
371 {
372 	if ( m_pDocHolder->GetIDispatch() )
373 		return m_pDocHolder->GetIDispatch()->GetIDsOfNames( riid, rgszNames, cNames, lcid, rgDispId );
374 
375 	for ( unsigned int ind = 0; ind < cNames; ind++ )
376 		rgDispId[ind] = DISPID_UNKNOWN;
377 
378 	return DISP_E_UNKNOWNNAME;
379 }
380 
Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS FAR * pDispParams,VARIANT FAR * pVarResult,EXCEPINFO FAR * pExcepInfo,unsigned int FAR * puArgErr)381 STDMETHODIMP EmbedDocument_Impl::Invoke( DISPID dispIdMember,
382 										 REFIID riid,
383 										 LCID lcid,
384 										 WORD wFlags,
385 										 DISPPARAMS FAR* pDispParams,
386 										 VARIANT FAR* pVarResult,
387 										 EXCEPINFO FAR* pExcepInfo,
388 										 unsigned int FAR* puArgErr )
389 {
390 	if ( m_pDocHolder->GetIDispatch() )
391 		return m_pDocHolder->GetIDispatch()->Invoke( dispIdMember,
392 													 riid,
393 													 lcid,
394 													 wFlags,
395 													 pDispParams,
396 													 pVarResult,
397 													 pExcepInfo,
398 													 puArgErr );
399 
400 	return DISP_E_MEMBERNOTFOUND;
401 }
402 
403 //-------------------------------------------------------------------------------
404 // IExternalConnection
405 
AddConnection(DWORD,DWORD)406 DWORD STDMETHODCALLTYPE EmbedDocument_Impl::AddConnection( DWORD , DWORD )
407 {
408     return AddRef();
409 }
410 
ReleaseConnection(DWORD,DWORD,BOOL)411 DWORD STDMETHODCALLTYPE EmbedDocument_Impl::ReleaseConnection( DWORD , DWORD , BOOL )
412 {
413     return Release();
414 }
415 
416 // C++ - methods
417 
SaveObject()418 HRESULT EmbedDocument_Impl::SaveObject()
419 {
420 	HRESULT hr = S_OK;
421 
422 	if(m_pClientSite) {
423 		hr = m_pClientSite->SaveObject();
424 
425 		for ( AdviseSinkHashMapIterator iAdvise =
426 				  m_aAdviseHashMap.begin();
427 			  iAdvise != m_aAdviseHashMap.end();
428 			  iAdvise++ )
429 			if ( iAdvise->second )
430 				iAdvise->second->OnSave( );
431 	}
432 	else if ( m_aFileName.getLength() && IsDirty() == S_OK )
433 	{
434 		::rtl::OUString aPreservFileName = m_aFileName;
435 
436 		// in case of links the containers does not provide client site sometimes
437 		hr = Save( (LPCOLESTR)NULL, FALSE ); // triggers saving to the link location
438 		SaveCompleted( (LPCOLESTR)aPreservFileName.getStr() );
439 	}
440 
441     notify( false );
442 
443 	return hr;
444 }
445 
446 
ShowObject()447 HRESULT EmbedDocument_Impl::ShowObject()
448 {
449 	HRESULT hr = S_OK;
450 
451 	if(m_pClientSite)
452 		hr = m_pClientSite->ShowObject();
453 
454 	return hr;
455 }
456 
457 
notify(bool bDataChanged)458 void EmbedDocument_Impl::notify( bool bDataChanged )
459 {
460 	for ( AdviseSinkHashMapIterator iAdvise =
461 			  m_aAdviseHashMap.begin();
462 		  iAdvise != m_aAdviseHashMap.end();
463 		  iAdvise++ )
464 		if ( iAdvise->second )
465 			iAdvise->second->OnViewChange( DVASPECT_CONTENT, -1 );
466 
467     if ( m_pDAdviseHolder && bDataChanged )
468 		m_pDAdviseHolder->SendOnDataChange( (IDataObject*)this, 0, 0 );
469 }
470 
Deactivate()471 void EmbedDocument_Impl::Deactivate()
472 {
473     HRESULT hr = S_OK;
474 
475     if ( m_pDocHolder->HasFrame() )
476     {
477 	    hr = SaveObject();
478 	    m_pDocHolder->CloseFrame();
479 	    OLENotifyDeactivation();
480     }
481 }
482 
OLENotifyDeactivation()483 HRESULT EmbedDocument_Impl::OLENotifyDeactivation()
484 {
485 	HRESULT hr = S_OK;
486 
487 	if ( m_pClientSite )
488 		hr = m_pClientSite->OnShowWindow( FALSE );
489 
490 	return hr;
491 
492 }
493 
494 // Fix strange warnings about some
495 // ATL::CAxHostWindow::QueryInterface|AddRef|Releae functions.
496 // warning C4505: 'xxx' : unreferenced local function has been removed
497 #if defined(_MSC_VER)
498 #pragma warning(disable: 4505)
499 #endif
500 
501