/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   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 .
 */
 
#include <sal/types.h>
 
#include <stdio.h>
#include "inprocembobj.h"
#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 = nullptr;
static ULONG g_nObj = 0;
static ULONG g_nLock = 0;
 
 
namespace {
    void FillCharFromInt( int nValue, wchar_t* pBuf, int nLen )
    {
        int nInd = 0;
        while( nInd < nLen )
        {
            char nSign = ( nValue / ( 1 << ( ( nLen - nInd - 1 ) * 4 ) ) ) % 16;
            if ( nSign >= 0 && nSign <= 9 )
                pBuf[nInd] = nSign + L'0';
            else if ( nSign >= 10 && nSign <= 15 )
                pBuf[nInd] = nSign - 10 + L'a';
 
            nInd++;
        }
    }
 
    int GetStringFromClassID( const GUID& guid, wchar_t* pBuf, int nLen )
    {
        // is not allowed to insert
        if ( nLen < 38 )
            return 0;
 
        pBuf[0] = L'{';
        FillCharFromInt( guid.Data1, &pBuf[1], 8 );
        pBuf[9] = L'-';
        FillCharFromInt( guid.Data2, &pBuf[10], 4 );
        pBuf[14] = L'-';
        FillCharFromInt( guid.Data3, &pBuf[15], 4 );
        pBuf[19] = L'-';
 
        int nInd = 0;
        for ( nInd = 0; nInd < 2 ; nInd++ )
            FillCharFromInt( guid.Data4[nInd], &pBuf[20 + 2*nInd], 2 );
        pBuf[24] = L'-';
        for ( nInd = 2; nInd < 8 ; nInd++ )
            FillCharFromInt( guid.Data4[nInd], &pBuf[20 + 1 + 2*nInd], 2 );
        pBuf[37] = L'}';
 
        return 38;
    }
 
    HRESULT WriteLibraryToRegistry( const wchar_t* pLibrary, DWORD nLen )
    {
        HRESULT hRes = E_FAIL;
        if ( pLibrary && nLen )
        {
            HKEY hKey = nullptr;
 
            hRes = S_OK;
            for ( int nInd = 0; nInd < SUPPORTED_FACTORIES_NUM; nInd++ )
            {
                const wchar_t pSubKeyTemplate[] = L"Software\\Classes\\CLSID\\.....................................\\InprocHandler32";
                wchar_t pSubKey[SAL_N_ELEMENTS(pSubKeyTemplate)];
                wcsncpy(pSubKey, pSubKeyTemplate, SAL_N_ELEMENTS(pSubKeyTemplate));
 
                int nGuidLen = GetStringFromClassID( *guidList[nInd], &pSubKey[23], 38 );
 
                BOOL bLocalSuccess = FALSE;
                if ( nGuidLen == 38 )
                {
                    if ( ERROR_SUCCESS == RegOpenKeyW( HKEY_LOCAL_MACHINE, pSubKey, &hKey ) )
                    {
                        if ( ERROR_SUCCESS == RegSetValueExW( hKey, L"", 0, REG_SZ, reinterpret_cast<const BYTE*>(pLibrary), nLen*sizeof(wchar_t) ) )
                            bLocalSuccess = TRUE;
                    }
 
                    if ( hKey )
                    {
                        RegCloseKey( hKey );
                        hKey = nullptr;
                    }
                }
 
                if ( !bLocalSuccess )
                    hRes = E_FAIL;
            }
        }
 
        return hRes;
    }
};
 
 
// InprocEmbedProvider_Impl declaration
 
 
namespace inprocserv
{
 
class InprocEmbedProvider_Impl : public IClassFactory, public InprocCountedObject_Impl
{
public:
 
    explicit InprocEmbedProvider_Impl( const GUID& guid );
    virtual ~InprocEmbedProvider_Impl();
 
    /* IUnknown methods */
    STDMETHOD(QueryInterface)(REFIID riid, LPVOID FAR * ppvObj) override;
    STDMETHOD_(ULONG, AddRef)() override;
    STDMETHOD_(ULONG, Release)() override;
 
    /* IClassFactory methods */
    STDMETHOD(CreateInstance)(IUnknown FAR* punkOuter, REFIID riid, void FAR* FAR* ppv) override;
    STDMETHOD(LockServer)(int fLock) override;
 
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;
    }
 
    return TRUE;    // ok
}
 
 
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 );
            static_cast<LPUNKNOWN>(*ppv)->AddRef();
            return S_OK;
         }
 
    return E_FAIL;
}
 
 
STDAPI DllCanUnloadNow()
{
    if ( !g_nObj && !g_nLock )
        return S_OK;
 
    return S_FALSE;
}
 
 
STDAPI DllRegisterServer()
{
    HMODULE aCurModule = GetModuleHandleW( L"inprocserv.dll" );
    if( aCurModule )
    {
        wchar_t aLibPath[1024];
        DWORD nLen = GetModuleFileNameW( aCurModule, aLibPath, 1019 );
        if ( nLen && nLen < 1019 )
        {
            aLibPath[nLen++] = 0;
            return WriteLibraryToRegistry( aLibPath, nLen );
        }
    }
 
    return E_FAIL;
}
 
 
STDAPI DllUnregisterServer()
{
    return WriteLibraryToRegistry( L"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 = static_cast<IUnknown*>(this);
        return S_OK;
    }
    else if (IsEqualIID(riid, IID_IClassFactory))
    {
        AddRef();
        *ppv = static_cast<IClassFactory*>(this);
        return S_OK;
    }
 
    *ppv = nullptr;
    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 != nullptr )
        return CLASS_E_NOAGGREGATION;
 
    InprocEmbedDocument_Impl* pEmbedDocument = new InprocEmbedDocument_Impl( m_guid );
    pEmbedDocument->AddRef();
    HRESULT hr = pEmbedDocument->QueryInterface( riid, ppv );
    pEmbedDocument->Release();
 
    if ( !SUCCEEDED( hr ) )
        *ppv = nullptr;
 
    return hr;
}
 
 
STDMETHODIMP InprocEmbedProvider_Impl::LockServer( int fLock )
{
    if ( fLock )
        g_nLock++;
    else
        g_nLock--;
 
    return S_OK;
}
 
}; // namespace inprocserv
 
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

V560 A part of conditional expression is always true: nSign <= 15.