/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ #include #include #ifdef __MINGW32__ #define INITGUID #endif #include static const GUID* guidList[ SUPPORTED_FACTORIES_NUM ] = { &OID_WriterTextServer, &OID_WriterOASISTextServer, &OID_CalcServer, &OID_CalcOASISServer, &OID_DrawingServer, &OID_DrawingOASISServer, &OID_PresentationServer, &OID_PresentationOASISServer, &OID_MathServer, &OID_MathOASISServer }; static HINSTANCE g_hInstance = NULL; static ULONG g_nObj = 0; static ULONG g_nLock = 0; namespace { void FillCharFromInt( int nValue, char* pBuf, int nLen ) { int nInd = 0; while( nInd < nLen ) { char nSign = ( nValue / ( 1 << ( ( nLen - nInd ) * 4 ) ) ) % 16; if ( nSign >= 0 && nSign <= 9 ) pBuf[nInd] = nSign + '0'; else if ( nSign >= 10 && nSign <= 15 ) pBuf[nInd] = nSign - 10 + 'a'; nInd++; } } int GetStringFromClassID( const GUID& guid, char* pBuf, int nLen ) { // is not allowed to insert if ( nLen < 38 ) return 0; pBuf[0] = '{'; FillCharFromInt( guid.Data1, &pBuf[1], 8 ); pBuf[9] = '-'; FillCharFromInt( guid.Data2, &pBuf[10], 4 ); pBuf[14] = '-'; FillCharFromInt( guid.Data3, &pBuf[15], 4 ); pBuf[19] = '-'; int nInd = 0; for ( nInd = 0; nInd < 2 ; nInd++ ) FillCharFromInt( guid.Data4[nInd], &pBuf[20 + 2*nInd], 2 ); pBuf[24] = '-'; for ( nInd = 2; nInd < 8 ; nInd++ ) FillCharFromInt( guid.Data4[nInd], &pBuf[20 + 1 + 2*nInd], 2 ); pBuf[37] = '}'; return 38; } HRESULT WriteLibraryToRegistry( char* pLibrary, DWORD nLen ) { HRESULT hRes = E_FAIL; if ( pLibrary && nLen ) { HKEY hKey = NULL; hRes = S_OK; for ( int nInd = 0; nInd < SUPPORTED_FACTORIES_NUM; nInd++ ) { char* pSubKey = "Software\\Classes\\CLSID\\.....................................\\InprocHandler32"; int nGuidLen = GetStringFromClassID( *guidList[nInd], &pSubKey[23], 38 ); BOOL bLocalSuccess = FALSE; if ( nGuidLen && nGuidLen == 38 ) { if ( ERROR_SUCCESS == RegOpenKey( HKEY_LOCAL_MACHINE, pSubKey, &hKey ) ) { if ( ERROR_SUCCESS == RegSetValueEx( hKey, "", 0, REG_SZ, (const BYTE*)pLibrary, nLen ) ) bLocalSuccess = TRUE; } if ( hKey ) { RegCloseKey( hKey ); hKey = NULL; } } if ( !bLocalSuccess ) hRes = E_FAIL; } } return hRes; } }; // =========================== // InprocEmbedProvider_Impl declaration // =========================== namespace inprocserv { class InprocEmbedProvider_Impl : public IClassFactory, public InprocCountedObject_Impl { public: InprocEmbedProvider_Impl( const GUID& guid ); virtual ~InprocEmbedProvider_Impl(); /* IUnknown methods */ STDMETHOD(QueryInterface)(REFIID riid, LPVOID FAR * ppvObj); STDMETHOD_(ULONG, AddRef)(); STDMETHOD_(ULONG, Release)(); /* IClassFactory methods */ STDMETHOD(CreateInstance)(IUnknown FAR* punkOuter, REFIID riid, void FAR* FAR* ppv); STDMETHOD(LockServer)(int fLock); protected: ULONG m_refCount; GUID m_guid; }; }; // namespace inprocserv // =========================== // Entry points // =========================== // ------------------------------------------------------------------------------- extern "C" BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/ ) { if (dwReason == DLL_PROCESS_ATTACH) { g_hInstance = hInstance; } else if (dwReason == DLL_PROCESS_DETACH) { } return TRUE; // ok } // ------------------------------------------------------------------------------- extern "C" STDAPI DllGetClassObject( REFCLSID rclsid, REFIID riid, LPVOID* ppv ) { for( int nInd = 0; nInd < SUPPORTED_FACTORIES_NUM; nInd++ ) if ( *guidList[nInd] == rclsid ) { if ( !IsEqualIID( riid, IID_IUnknown ) && !IsEqualIID( riid, IID_IClassFactory ) ) return E_NOINTERFACE; *ppv = new inprocserv::InprocEmbedProvider_Impl( rclsid ); if ( *ppv == NULL ) return E_OUTOFMEMORY; ((LPUNKNOWN)*ppv)->AddRef(); return S_OK; } return E_FAIL; } // ------------------------------------------------------------------------------- extern "C" STDAPI DllCanUnloadNow() { if ( !g_nObj && !g_nLock ) return S_OK; return S_FALSE; } // ------------------------------------------------------------------------------- STDAPI DllRegisterServer( void ) { char aLibPath[1024]; HMODULE aCurModule = GetModuleHandleA( "inprocserv.dll" ); if( aCurModule ) { DWORD nLen = GetModuleFileNameA( aCurModule, aLibPath, 1019 ); if ( nLen && nLen < 1019 ) { aLibPath[nLen++] = 0; return WriteLibraryToRegistry( aLibPath, nLen ); } } return E_FAIL; } // ------------------------------------------------------------------------------- STDAPI DllUnregisterServer( void ) { return WriteLibraryToRegistry( "ole32.dll", 10 ); } // =========================== // End of entry points // =========================== namespace inprocserv { // =========================== // InprocCountedObject_Impl implementation // =========================== // ------------------------------------------------------------------------------- InprocCountedObject_Impl::InprocCountedObject_Impl() { g_nObj++; } // ------------------------------------------------------------------------------- InprocCountedObject_Impl::~InprocCountedObject_Impl() { g_nObj--; } // =========================== // InprocEmbedProvider_Impl implementation // =========================== // ------------------------------------------------------------------------------- InprocEmbedProvider_Impl::InprocEmbedProvider_Impl( const GUID& guid ) : m_refCount( 0 ) , m_guid( guid ) { } // ------------------------------------------------------------------------------- InprocEmbedProvider_Impl::~InprocEmbedProvider_Impl() { } // IUnknown // ------------------------------------------------------------------------------- STDMETHODIMP InprocEmbedProvider_Impl::QueryInterface( REFIID riid, void FAR* FAR* ppv ) { if(IsEqualIID(riid, IID_IUnknown)) { AddRef(); *ppv = (IUnknown*) this; return S_OK; } else if (IsEqualIID(riid, IID_IClassFactory)) { AddRef(); *ppv = (IClassFactory*) this; return S_OK; } *ppv = NULL; return E_NOINTERFACE; } // ------------------------------------------------------------------------------- STDMETHODIMP_(ULONG) InprocEmbedProvider_Impl::AddRef() { return ++m_refCount; } // ------------------------------------------------------------------------------- STDMETHODIMP_(ULONG) InprocEmbedProvider_Impl::Release() { sal_Int32 nCount = --m_refCount; if ( nCount == 0 ) delete this; return nCount; } // ------------------------------------------------------------------------------- STDMETHODIMP InprocEmbedProvider_Impl::CreateInstance(IUnknown FAR* punkOuter, REFIID riid, void FAR* FAR* ppv) { // TODO/LATER: should the aggregation be supported? // if ( punkOuter != NULL && riid != IID_IUnknown ) // return E_NOINTERFACE; if ( punkOuter != NULL ) return CLASS_E_NOAGGREGATION; InprocEmbedDocument_Impl* pEmbedDocument = new InprocEmbedDocument_Impl( m_guid ); if ( !pEmbedDocument ) return E_OUTOFMEMORY; pEmbedDocument->AddRef(); HRESULT hr = pEmbedDocument->Init(); if ( SUCCEEDED( hr ) ) hr = pEmbedDocument->QueryInterface( riid, ppv ); pEmbedDocument->Release(); if ( !SUCCEEDED( hr ) ) *ppv = NULL; return hr; } // ------------------------------------------------------------------------------- STDMETHODIMP InprocEmbedProvider_Impl::LockServer( int fLock ) { if ( fLock ) g_nLock++; else g_nLock--; return S_OK; } }; // namespace inprocserv