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 
28 #include <stdio.h>
29 #include <inprocembobj.h>
30 #ifdef __MINGW32__
31 #define INITGUID
32 #endif
33 #include <embservconst.h>
34 
35 static const GUID* guidList[ SUPPORTED_FACTORIES_NUM ] = {
36 	&OID_WriterTextServer,
37 	&OID_WriterOASISTextServer,
38 	&OID_CalcServer,
39 	&OID_CalcOASISServer,
40 	&OID_DrawingServer,
41 	&OID_DrawingOASISServer,
42 	&OID_PresentationServer,
43 	&OID_PresentationOASISServer,
44 	&OID_MathServer,
45 	&OID_MathOASISServer
46 };
47 
48 static HINSTANCE g_hInstance = NULL;
49 static ULONG g_nObj = 0;
50 static ULONG g_nLock = 0;
51 
52 
53 namespace {
54     void FillCharFromInt( int nValue, char* pBuf, int nLen )
55     {
56         int nInd = 0;
57         while( nInd < nLen )
58         {
59             char nSign = ( nValue / ( 1 << ( ( nLen - nInd ) * 4 ) ) ) % 16;
60             if ( nSign >= 0 && nSign <= 9 )
61                 pBuf[nInd] = nSign + '0';
62             else if ( nSign >= 10 && nSign <= 15 )
63                 pBuf[nInd] = nSign - 10 + 'a';
64 
65             nInd++;
66         }
67     }
68 
69     int GetStringFromClassID( const GUID& guid, char* pBuf, int nLen )
70     {
71         // is not allowed to insert
72         if ( nLen < 38 )
73             return 0;
74 
75         pBuf[0] = '{';
76         FillCharFromInt( guid.Data1, &pBuf[1], 8 );
77         pBuf[9] = '-';
78         FillCharFromInt( guid.Data2, &pBuf[10], 4 );
79         pBuf[14] = '-';
80         FillCharFromInt( guid.Data3, &pBuf[15], 4 );
81         pBuf[19] = '-';
82 
83         int nInd = 0;
84         for ( nInd = 0; nInd < 2 ; nInd++ )
85             FillCharFromInt( guid.Data4[nInd], &pBuf[20 + 2*nInd], 2 );
86         pBuf[24] = '-';
87         for ( nInd = 2; nInd < 8 ; nInd++ )
88             FillCharFromInt( guid.Data4[nInd], &pBuf[20 + 1 + 2*nInd], 2 );
89         pBuf[37] = '}';
90 
91         return 38;
92 	}
93 
94     HRESULT WriteLibraryToRegistry( char* pLibrary, DWORD nLen )
95     {
96         HRESULT hRes = E_FAIL;
97         if ( pLibrary && nLen )
98         {
99             HKEY hKey = NULL;
100 
101             hRes = S_OK;
102             for ( int nInd = 0; nInd < SUPPORTED_FACTORIES_NUM; nInd++ )
103             {
104                 char* pSubKey = "Software\\Classes\\CLSID\\.....................................\\InprocHandler32";
105 
106                 int nGuidLen = GetStringFromClassID( *guidList[nInd], &pSubKey[23], 38 );
107 
108                 BOOL bLocalSuccess = FALSE;
109                 if ( nGuidLen && nGuidLen == 38 )
110                 {
111                     if ( ERROR_SUCCESS == RegOpenKey( HKEY_LOCAL_MACHINE, pSubKey, &hKey ) )
112                     {
113                         if ( ERROR_SUCCESS == RegSetValueEx( hKey, "", 0, REG_SZ, (const BYTE*)pLibrary, nLen ) )
114                             bLocalSuccess = TRUE;
115                     }
116 
117                     if ( hKey )
118                     {
119                         RegCloseKey( hKey );
120                         hKey = NULL;
121                     }
122                 }
123 
124                 if ( !bLocalSuccess )
125                     hRes = E_FAIL;
126             }
127         }
128 
129         return hRes;
130     }
131 };
132 
133 // ===========================
134 // InprocEmbedProvider_Impl declaration
135 // ===========================
136 
137 namespace inprocserv
138 {
139 
140 class InprocEmbedProvider_Impl : public IClassFactory, public InprocCountedObject_Impl
141 {
142 public:
143 
144 	InprocEmbedProvider_Impl( const GUID& guid );
145 	virtual ~InprocEmbedProvider_Impl();
146 
147 	/* IUnknown methods */
148 	STDMETHOD(QueryInterface)(REFIID riid, LPVOID FAR * ppvObj);
149 	STDMETHOD_(ULONG, AddRef)();
150 	STDMETHOD_(ULONG, Release)();
151 
152 	/* IClassFactory methods */
153 	STDMETHOD(CreateInstance)(IUnknown FAR* punkOuter, REFIID riid, void FAR* FAR* ppv);
154 	STDMETHOD(LockServer)(int fLock);
155 
156 protected:
157 
158 	ULONG               m_refCount;
159 	GUID				m_guid;
160 };
161 }; // namespace inprocserv
162 
163 
164 // ===========================
165 // Entry points
166 // ===========================
167 
168 // -------------------------------------------------------------------------------
169 extern "C" BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/ )
170 {
171     if (dwReason == DLL_PROCESS_ATTACH)
172     {
173         g_hInstance = hInstance;
174     }
175     else if (dwReason == DLL_PROCESS_DETACH)
176     {
177     }
178 
179     return TRUE;    // ok
180 }
181 
182 // -------------------------------------------------------------------------------
183 extern "C" STDAPI DllGetClassObject( REFCLSID rclsid, REFIID riid, LPVOID* ppv )
184 {
185 	for( int nInd = 0; nInd < SUPPORTED_FACTORIES_NUM; nInd++ )
186 		 if ( *guidList[nInd] == rclsid )
187          {
188             if ( !IsEqualIID( riid, IID_IUnknown ) && !IsEqualIID( riid, IID_IClassFactory ) )
189                 return E_NOINTERFACE;
190 
191             *ppv = new inprocserv::InprocEmbedProvider_Impl( rclsid );
192             if ( *ppv == NULL )
193                 return E_OUTOFMEMORY;
194 
195             ((LPUNKNOWN)*ppv)->AddRef();
196             return S_OK;
197          }
198 
199     return E_FAIL;
200 }
201 
202 // -------------------------------------------------------------------------------
203 extern "C" STDAPI DllCanUnloadNow()
204 {
205     if ( !g_nObj && !g_nLock )
206         return S_OK;
207 
208     return S_FALSE;
209 }
210 
211 // -------------------------------------------------------------------------------
212 STDAPI DllRegisterServer( void )
213 {
214 	char aLibPath[1024];
215 	HMODULE aCurModule = GetModuleHandleA( "inprocserv.dll" );
216 	if( aCurModule )
217     {
218         DWORD nLen = GetModuleFileNameA( aCurModule, aLibPath, 1019 );
219         if ( nLen && nLen < 1019 )
220         {
221             aLibPath[nLen++] = 0;
222             return WriteLibraryToRegistry( aLibPath, nLen );
223         }
224     }
225 
226     return E_FAIL;
227 }
228 
229 // -------------------------------------------------------------------------------
230 STDAPI DllUnregisterServer( void )
231 {
232     return WriteLibraryToRegistry( "ole32.dll", 10 );
233 }
234 
235 // ===========================
236 // End of entry points
237 // ===========================
238 
239 namespace inprocserv
240 {
241 
242 // ===========================
243 // InprocCountedObject_Impl implementation
244 // ===========================
245 
246 // -------------------------------------------------------------------------------
247 InprocCountedObject_Impl::InprocCountedObject_Impl()
248 {
249     g_nObj++;
250 }
251 
252 // -------------------------------------------------------------------------------
253 InprocCountedObject_Impl::~InprocCountedObject_Impl()
254 {
255     g_nObj--;
256 }
257 
258 // ===========================
259 // InprocEmbedProvider_Impl implementation
260 // ===========================
261 
262 // -------------------------------------------------------------------------------
263 InprocEmbedProvider_Impl::InprocEmbedProvider_Impl( const GUID& guid )
264 : m_refCount( 0 )
265 , m_guid( guid )
266 {
267 }
268 
269 // -------------------------------------------------------------------------------
270 InprocEmbedProvider_Impl::~InprocEmbedProvider_Impl()
271 {
272 }
273 
274 // IUnknown
275 // -------------------------------------------------------------------------------
276 STDMETHODIMP InprocEmbedProvider_Impl::QueryInterface( REFIID riid, void FAR* FAR* ppv )
277 {
278     if(IsEqualIID(riid, IID_IUnknown))
279 	{
280 		AddRef();
281 		*ppv = (IUnknown*) this;
282 		return S_OK;
283     }
284     else if (IsEqualIID(riid, IID_IClassFactory))
285 	{
286 		AddRef();
287 		*ppv = (IClassFactory*) this;
288 		return S_OK;
289 	}
290 
291     *ppv = NULL;
292     return E_NOINTERFACE;
293 }
294 
295 // -------------------------------------------------------------------------------
296 STDMETHODIMP_(ULONG) InprocEmbedProvider_Impl::AddRef()
297 {
298 	return ++m_refCount;
299 }
300 
301 // -------------------------------------------------------------------------------
302 STDMETHODIMP_(ULONG) InprocEmbedProvider_Impl::Release()
303 {
304 	sal_Int32 nCount = --m_refCount;
305 	if ( nCount == 0 )
306 		delete this;
307     return nCount;
308 }
309 
310 // -------------------------------------------------------------------------------
311 STDMETHODIMP InprocEmbedProvider_Impl::CreateInstance(IUnknown FAR* punkOuter,
312                                                        REFIID riid,
313                                                        void FAR* FAR* ppv)
314 {
315     // TODO/LATER: should the aggregation be supported?
316     // if ( punkOuter != NULL && riid != IID_IUnknown )
317     //     return E_NOINTERFACE;
318     if ( punkOuter != NULL )
319         return CLASS_E_NOAGGREGATION;
320 
321     InprocEmbedDocument_Impl* pEmbedDocument = new InprocEmbedDocument_Impl( m_guid );
322     if ( !pEmbedDocument )
323         return E_OUTOFMEMORY;
324 
325     pEmbedDocument->AddRef();
326     HRESULT hr = pEmbedDocument->Init();
327     if ( SUCCEEDED( hr ) )
328         hr = pEmbedDocument->QueryInterface( riid, ppv );
329 	pEmbedDocument->Release();
330 
331 	if ( !SUCCEEDED( hr ) )
332         *ppv = NULL;
333 
334     return hr;
335 }
336 
337 // -------------------------------------------------------------------------------
338 STDMETHODIMP InprocEmbedProvider_Impl::LockServer( int fLock )
339 {
340     if ( fLock )
341         g_nLock++;
342     else
343         g_nLock--;
344 
345     return S_OK;
346 }
347 
348 }; // namespace inprocserv
349 
350