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