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