1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 #if defined(_MSC_VER) && (_MSC_VER > 1310)
28 #pragma warning(disable : 4917 4555)
29 #endif
30 
31 #include "stdafx.h"
32 #include "servprov.hxx"
33 #include "embeddoc.hxx"
34 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
35 #include <cppuhelper/typeprovider.hxx>
36 #include <osl/mutex.hxx>
37 #include <osl/thread.h>
38 
39 using namespace com::sun::star;
40 
41 const GUID* guidList[ SUPPORTED_FACTORIES_NUM ] = {
42 	&OID_WriterTextServer,
43 	&OID_WriterOASISTextServer,
44 	&OID_CalcServer,
45 	&OID_CalcOASISServer,
46 	&OID_DrawingServer,
47 	&OID_DrawingOASISServer,
48 	&OID_PresentationServer,
49 	&OID_PresentationOASISServer,
50 	&OID_MathServer,
51 	&OID_MathOASISServer
52 };
53 
54 class CurThreadData
55 {
56 	public:
57 		CurThreadData();
58 		virtual ~CurThreadData();
59 
60 		sal_Bool SAL_CALL setData(void *pData);
61 
62 		void* SAL_CALL getData();
63 
64 	protected:
65 		oslThreadKey m_hKey;
66 };
67 
68 CurThreadData::CurThreadData()
69 {
70 	m_hKey = osl_createThreadKey( (oslThreadKeyCallbackFunction)NULL );
71 }
72 
73 CurThreadData::~CurThreadData()
74 {
75 	osl_destroyThreadKey(m_hKey);
76 }
77 
78 sal_Bool CurThreadData::setData(void *pData)
79 {
80 	OSL_ENSURE( m_hKey, "No thread key!\n" );
81 	return (osl_setThreadKeyData(m_hKey, pData));
82 }
83 
84 void *CurThreadData::getData()
85 {
86 	OSL_ENSURE( m_hKey, "No thread key!\n" );
87 	return (osl_getThreadKeyData(m_hKey));
88 }
89 
90 
91 // CoInitializeEx *
92 typedef DECLSPEC_IMPORT HRESULT (STDAPICALLTYPE *ptrCoInitEx)( LPVOID, DWORD);
93 // CoInitialize *
94 typedef DECLSPEC_IMPORT HRESULT (STDAPICALLTYPE *ptrCoInit)( LPVOID);
95 
96 void o2u_attachCurrentThread()
97 {
98     static CurThreadData oleThreadData;
99 
100     if ( oleThreadData.getData() != 0 )
101     {
102         HINSTANCE inst=	LoadLibrary( _T("ole32.dll"));
103         if( inst )
104         {
105             HRESULT hr;
106             ptrCoInitEx initFuncEx= (ptrCoInitEx)GetProcAddress( inst, _T("CoInitializeEx"));
107             if( initFuncEx)
108                 hr= initFuncEx( NULL, COINIT_MULTITHREADED);
109             else
110             {
111                 ptrCoInit initFunc= (ptrCoInit)GetProcAddress( inst,_T("CoInitialize"));
112                 if( initFunc)
113                     hr= initFunc( NULL);
114             }
115         }
116         oleThreadData.setData((void*)sal_True);
117     }
118 }
119 
120 
121 //===============================================================================
122 // EmbedServer_Impl
123 
124 EmbedServer_Impl::EmbedServer_Impl( const uno::Reference<lang::XMultiServiceFactory>& xFactory):
125 	m_xFactory( xFactory)
126 {
127 	for( int nInd = 0; nInd < SUPPORTED_FACTORIES_NUM; nInd++ )
128 	{
129 		m_pOLEFactories[nInd] = new EmbedProviderFactory_Impl( m_xFactory, guidList[nInd] );
130 		m_pOLEFactories[nInd]->registerClass();
131 	}
132 }
133 
134 EmbedServer_Impl::~EmbedServer_Impl()
135 {
136 	for( int nInd = 0; nInd < SUPPORTED_FACTORIES_NUM; nInd++ )
137 	{
138 		if ( m_pOLEFactories[nInd] )
139 			m_pOLEFactories[nInd]->deregisterClass();
140 	}
141 }
142 
143 // XInterface --------------------------------------------------
144 uno::Any SAL_CALL
145 EmbedServer_Impl::queryInterface(
146 	const uno::Type& aType )
147 	throw(
148 		uno::RuntimeException
149 	)
150 {
151 	uno::Any a=
152 		::cppu::queryInterface(
153 			aType, static_cast<lang::XTypeProvider*>(this));
154 	if( a == uno::Any())
155 		return OWeakObject::queryInterface( aType);
156 	else
157 		return a;
158 }
159 
160 void SAL_CALL EmbedServer_Impl::acquire(  ) throw(uno::RuntimeException)
161 {
162 	OWeakObject::acquire();
163 }
164 
165 void SAL_CALL EmbedServer_Impl::release(  ) throw (uno::RuntimeException)
166 {
167 	OWeakObject::release();
168 }
169 
170 
171 // XTypeProvider --------------------------------------------------
172 uno::Sequence< uno::Type > SAL_CALL
173 EmbedServer_Impl::getTypes( )
174 	throw(
175 		uno::RuntimeException
176 	)
177 {
178 	static ::cppu::OTypeCollection *pCollection = 0;
179 	if( ! pCollection )
180 	{
181 		::osl::MutexGuard guard( ::osl::Mutex::getGlobalMutex() );
182 		if( ! pCollection )
183 		{
184 			static ::cppu::OTypeCollection collection(
185 				getCppuType(
186 					reinterpret_cast<uno::Reference< uno::XWeak>*>(0)),
187 				getCppuType(
188 					reinterpret_cast<
189 					uno::Reference< lang::XTypeProvider>*>(0)));
190 			pCollection = &collection;
191 		}
192 	}
193 	return (*pCollection).getTypes();
194 }
195 
196 uno::Sequence< sal_Int8 > SAL_CALL EmbedServer_Impl::getImplementationId() throw(uno::RuntimeException)
197 {
198 	static ::cppu::OImplementationId *pId = 0;
199 	if( ! pId )
200 	{
201 		::osl::MutexGuard guard( ::osl::Mutex::getGlobalMutex() );
202 		if( ! pId )
203 		{
204 			static ::cppu::OImplementationId id( sal_False );
205 			pId = &id;
206 		}
207 	}
208 	return (*pId).getImplementationId();
209 }
210 
211 //===============================================================================
212 // EmbedProviderFactory_Impl
213 
214 EmbedProviderFactory_Impl::EmbedProviderFactory_Impl(const uno::Reference<lang::XMultiServiceFactory>& xFactory, const GUID* pGuid)
215 	: m_refCount( 0L )
216 	, m_xFactory( xFactory )
217 	, m_guid( *pGuid )
218 {
219 }
220 
221 EmbedProviderFactory_Impl::~EmbedProviderFactory_Impl()
222 {
223 }
224 
225 sal_Bool EmbedProviderFactory_Impl::registerClass()
226 {
227 	HRESULT hresult;
228 
229 	o2u_attachCurrentThread();
230 
231 	hresult = CoRegisterClassObject(
232 			m_guid,
233 			this,
234 			CLSCTX_LOCAL_SERVER,
235 			REGCLS_MULTIPLEUSE,
236 			&m_factoryHandle);
237 
238 	return (hresult == NOERROR);
239 }
240 
241 sal_Bool EmbedProviderFactory_Impl::deregisterClass()
242 {
243 	HRESULT hresult = CoRevokeClassObject( m_factoryHandle );
244 
245 	return (hresult == NOERROR);
246 }
247 
248 STDMETHODIMP EmbedProviderFactory_Impl::QueryInterface(REFIID riid, void FAR* FAR* ppv)
249 {
250     if(IsEqualIID(riid, IID_IUnknown))
251 	{
252 		AddRef();
253 		*ppv = (IUnknown*) (IClassFactory*) this;
254 		return NOERROR;
255     }
256     else if (IsEqualIID(riid, IID_IClassFactory))
257 	{
258 		AddRef();
259 		*ppv = (IClassFactory*) this;
260 		return NOERROR;
261 	}
262 
263     *ppv = NULL;
264     return ResultFromScode(E_NOINTERFACE);
265 }
266 
267 STDMETHODIMP_(ULONG) EmbedProviderFactory_Impl::AddRef()
268 {
269 	return osl_incrementInterlockedCount( &m_refCount);
270 }
271 
272 STDMETHODIMP_(ULONG) EmbedProviderFactory_Impl::Release()
273 {
274 	::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex());
275 	sal_Int32 nCount = --m_refCount;
276 	if ( nCount == 0 )
277 	{
278 		delete this;
279 	}
280 
281     return nCount;
282 }
283 
284 STDMETHODIMP EmbedProviderFactory_Impl::CreateInstance(IUnknown FAR* punkOuter,
285                                                        REFIID riid,
286                                                        void FAR* FAR* ppv)
287 {
288     punkOuter = NULL;
289 
290     IUnknown* pEmbedDocument = (IUnknown*)(IPersistStorage*)( new EmbedDocument_Impl( m_xFactory, &m_guid ) );
291 
292     return pEmbedDocument->QueryInterface( riid, ppv );
293 }
294 
295 STDMETHODIMP EmbedProviderFactory_Impl::LockServer( int /*fLock*/ )
296 {
297     return NOERROR;
298 }
299 
300 // Fix strange warnings about some
301 // ATL::CAxHostWindow::QueryInterface|AddRef|Releae functions.
302 // warning C4505: 'xxx' : unreferenced local function has been removed
303 #if defined(_MSC_VER)
304 #pragma warning(disable: 4505)
305 #endif
306