blob: c3847104732b0d09ebf48336475d941b5686407c [file] [log] [blame]
/**************************************************************
*
* 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 <stdio.h>
#include <inprocembobj.h>
#ifdef __MINGW32__
#define INITGUID
#endif
#include <embservconst.h>
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