/**************************************************************
 * 
 * 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.
 * 
 *************************************************************/



// Use UNICODE Windows and C API.
#define _UNICODE
#define UNICODE

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <windows.h>
#include "uno/environment.hxx"
#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include <tchar.h>

#include "native_share.h"

#include "rtl/bootstrap.hxx"
#include "com/sun/star/uno/XComponentContext.hpp"
#include "cppuhelper/bootstrap.hxx"
#include <delayimp.h>
#include <stdio.h>

using namespace ::rtl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;

namespace cli_ure {
    WCHAR * resolveLink(WCHAR * path);
}

#define INSTALL_PATH L"Software\\OpenOffice.org\\UNO\\InstallPath"
#define BASIS_LINK L"\\basis-link"
#define URE_LINK L"\\ure-link"
#define URE_BIN L"\\bin"
#define UNO_PATH L"UNO_PATH"

namespace
{

 /*
 * Gets the installation path from the Windows Registry for the specified
 * registry key.
 *
 * @param hroot       open handle to predefined root registry key
 * @param subKeyName  name of the subkey to open
 *
 * @return the installation path or NULL, if no installation was found or
 *         if an error occured
 */
WCHAR* getPathFromRegistryKey( HKEY hroot, LPCWSTR subKeyName )
{
    HKEY hkey;
    DWORD type;
    TCHAR* data = NULL;
    DWORD size;

    /* open the specified registry key */
    if ( RegOpenKeyEx( hroot, subKeyName, 0, KEY_READ, &hkey ) != ERROR_SUCCESS )
    {
        return NULL;
    }

    /* find the type and size of the default value */
    if ( RegQueryValueEx( hkey, NULL, NULL, &type, NULL, &size) != ERROR_SUCCESS )
    {
        RegCloseKey( hkey );
        return NULL;
    }

    /* get memory to hold the default value */
    data = new WCHAR[size];

    /* read the default value */
    if ( RegQueryValueEx( hkey, NULL, NULL, &type, (LPBYTE) data, &size ) != ERROR_SUCCESS )
    {
        RegCloseKey( hkey );
        return NULL;
    }

    /* release registry key handle */
    RegCloseKey( hkey );

    return data;
}

/* If the path does not end with '\' the las segment will be removed.
    path: C:\a\b
    ->    C:\a
    @param io_path
        in/out parameter. The string is not reallocated. Simply a '\0'
        will be inserted to shorten the string.
*/
void oneDirUp(LPTSTR io_path)
{
    WCHAR * pEnd = io_path + lstrlen(io_path) - 1;
    while (pEnd > io_path //prevent crashing if provided string does not contain a backslash
        && *pEnd != L'\\')
        pEnd --;
    *pEnd = L'\0';
}


/* Returns the path to the program folder of the brand layer,
    for example c:/openoffice.org 3/program
   This path is either obtained from the environment variable UNO_PATH
   or the registry item
   "Software\\OpenOffice.org\\UNO\\InstallPath"
   either in HKEY_CURRENT_USER or HKEY_LOCAL_MACHINE
   The return value must be freed with delete[]
*/
WCHAR * getInstallPath()
{
    WCHAR * szInstallPath = NULL;

    DWORD  cChars = GetEnvironmentVariable(UNO_PATH, NULL, 0);
    if (cChars > 0)
    {	
        szInstallPath = new WCHAR[cChars];
        cChars = GetEnvironmentVariable(UNO_PATH, szInstallPath, cChars);
		//If PATH is not set then it is no error
		if (cChars == 0)
		{
			delete[] szInstallPath;
			return NULL;
		}
    }

    if (! szInstallPath)
    {
        szInstallPath = getPathFromRegistryKey( HKEY_CURRENT_USER, INSTALL_PATH );
        if ( szInstallPath == NULL )
        {
            /* read the key's default value from HKEY_LOCAL_MACHINE */
            szInstallPath = getPathFromRegistryKey( HKEY_LOCAL_MACHINE, INSTALL_PATH );
        }
    }
    return szInstallPath;
}

/* Returns the path to the URE/bin path, where cppuhelper lib resides.
    The returned string must be freed with delete[]
*/
WCHAR* getUnoPath()
{
    WCHAR * szLinkPath = NULL;
    WCHAR * szUrePath = NULL;
    WCHAR * szUreBin = NULL; //the return value

    WCHAR * szInstallPath = getInstallPath();
    if (szInstallPath)
    {
        //build the path tho the basis-link file
        oneDirUp(szInstallPath);
        int sizeLinkPath = lstrlen(szInstallPath) + lstrlen(INSTALL_PATH) + 1;
        if (sizeLinkPath < MAX_PATH)
            sizeLinkPath = MAX_PATH;
        szLinkPath = new WCHAR[sizeLinkPath];
        szLinkPath[0] = L'\0';
        lstrcat(szLinkPath, szInstallPath);
        lstrcat(szLinkPath, BASIS_LINK);
                
        //get the path to the actual Basis folder
        if (cli_ure::resolveLink(szLinkPath))
        {   
            //build the path to the ure-link file
            int sizeUrePath = lstrlen(szLinkPath) + lstrlen(URE_LINK) + 1;
            if (sizeUrePath < MAX_PATH)
                sizeUrePath = MAX_PATH;
            szUrePath = new WCHAR[sizeUrePath];
            szUrePath[0] = L'\0';
            lstrcat(szUrePath, szLinkPath);
            lstrcat(szUrePath, URE_LINK);

            //get the path to the actual Ure folder
            if (cli_ure::resolveLink(szUrePath))
            {
                //build the path to the URE/bin directory
        	    szUreBin = new WCHAR[lstrlen(szUrePath) + lstrlen(URE_BIN) + 1];
 	            szUreBin[0] = L'\0';
                lstrcat(szUreBin, szUrePath);
 	            lstrcat(szUreBin, URE_BIN);
            }     
        }
    }
#if OSL_DEBUG_LEVEL >=2
    if (szUreBin)
    {
        fwprintf(stdout,L"[cli_cppuhelper]: Path to URE libraries:\n %s \n", szUreBin);
    }
    else
    {
        fwprintf(stdout,L"[cli_cppuhelper]: Failed to determine location of URE.\n");
    }
#endif
    delete[] szInstallPath;
    delete[] szLinkPath;
    delete[] szUrePath;
    return szUreBin;
}


/*We extend the path to contain the Ure/bin folder,
  so that components can use osl_loadModule with arguments, such as
  "reg3.dll". That is, the arguments are only the library names.
*/
void extendPath(LPCWSTR szUreBinPath)
{
	if (!szUreBinPath)
		return;

    WCHAR * sEnvPath = NULL;
    DWORD  cChars = GetEnvironmentVariable(L"PATH", sEnvPath, 0);
    if (cChars > 0)
    {	
        sEnvPath = new WCHAR[cChars];
        cChars = GetEnvironmentVariable(L"PATH", sEnvPath, cChars);
		//If PATH is not set then it is no error
		if (cChars == 0 && GetLastError() != ERROR_ENVVAR_NOT_FOUND)
		{
			delete[] sEnvPath;
			return;
		}
    }
    //prepare the new PATH. Add the Ure/bin directory at the front.
    //note also adding ';'
    WCHAR * sNewPath = new WCHAR[lstrlen(sEnvPath) + lstrlen(szUreBinPath) + 2];
    sNewPath[0] = L'\0';
	lstrcat(sNewPath, szUreBinPath);
	if (lstrlen(sEnvPath))
	{
		lstrcat(sNewPath, L";");
		lstrcat(sNewPath, sEnvPath);
	}
    BOOL bSet = SetEnvironmentVariable(L"PATH", sNewPath);
    
    delete[] sEnvPath;
    delete[] sNewPath;
}


HMODULE loadFromPath(LPCWSTR sLibName)
{
	if (sLibName == NULL)
		return NULL;

	WCHAR * szUreBinPath =  getUnoPath();
	if (!szUreBinPath)
		return NULL;

    extendPath(szUreBinPath);

    WCHAR*  szFullPath = new WCHAR[lstrlen(sLibName) + lstrlen(szUreBinPath) + 2];
    szFullPath[0] = L'\0';
    lstrcat(szFullPath, szUreBinPath);
    lstrcat(szFullPath, L"\\");
    lstrcat(szFullPath, sLibName);
    HMODULE handle = LoadLibraryEx(szFullPath, NULL,
		LOAD_WITH_ALTERED_SEARCH_PATH);
	
    delete[] szFullPath;
    delete[] szUreBinPath;
	return handle;
}

/*Hook for delayed loading of libraries which this library is linked with.
    This is a failure hook. That is, it is only called when the loading of 
    a library failed. It will be called when loading of cppuhelper failed.
    Because we extend the PATH to the URE/bin folder while this function is
    executed (see extendPath), all other libraries are found.
*/
extern "C" FARPROC WINAPI delayLoadHook(
    unsigned        dliNotify,
    PDelayLoadInfo  pdli
    )
{
    if (dliNotify == dliFailLoadLib)
    {
        LPWSTR szLibName = NULL;
     	//Convert the ansi file name to wchar_t*
		int size = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pdli->szDll, -1, NULL, 0);
		if (size > 0)
		{
			szLibName = new WCHAR[size];
			if (! MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pdli->szDll, -1, szLibName, size))
			{
                return 0;
			}
		}
        HANDLE h = loadFromPath(szLibName);
        delete[] szLibName;
		return (FARPROC) h;
    }
    return 0;
}
}

ExternC
PfnDliHook   __pfnDliFailureHook2 = delayLoadHook;

namespace uno
{
namespace util
{

/** Bootstrapping native UNO.

    Bootstrapping requires the existence of many libraries which are contained
    in an URE installation. To find and load these libraries the Windows
    registry keys HKEY_CURRENT_USER\Software\OpenOffice.org\Layer\URE\1
    and HKEY_LOCAL_MACHINE\Software\OpenOffice.org\Layer\URE\1 are examined.
    These contain a named value UREINSTALLLOCATION which holds a path to the URE
	installation folder.
*/
public __sealed __gc class Bootstrap
{
    inline Bootstrap() {}
    
public:
    
    /** Bootstraps the initial component context from a native UNO installation.
        
        @see cppuhelper/bootstrap.hxx:defaultBootstrap_InitialComponentContext()
    */
    static ::unoidl::com::sun::star::uno::XComponentContext *
        defaultBootstrap_InitialComponentContext();
    
    /** Bootstraps the initial component context from a native UNO installation.
        
        @param ini_file
               a file URL of an ini file, e.g. uno.ini/unorc. (The ini file must
               reside next to the cppuhelper library)
        @param bootstrap_parameters
               bootstrap parameters (maybe null)
               
        @see cppuhelper/bootstrap.hxx:defaultBootstrap_InitialComponentContext()
    */
    static ::unoidl::com::sun::star::uno::XComponentContext *
        defaultBootstrap_InitialComponentContext(
            ::System::String * ini_file,
            ::System::Collections::IDictionaryEnumerator *
              bootstrap_parameters );

    /** Bootstraps the initial component context from a native UNO installation.

    @see cppuhelper/bootstrap.hxx:bootstrap()
     */
    static ::unoidl::com::sun::star::uno::XComponentContext *
    bootstrap();
};

//______________________________________________________________________________
::unoidl::com::sun::star::uno::XComponentContext *
Bootstrap::defaultBootstrap_InitialComponentContext(
    ::System::String * ini_file,
    ::System::Collections::IDictionaryEnumerator * bootstrap_parameters )
{
    if (0 != bootstrap_parameters)
    {
        bootstrap_parameters->Reset();
        while (bootstrap_parameters->MoveNext())
        {
            OUString key(
                String_to_ustring( __try_cast< ::System::String * >(
                                       bootstrap_parameters->get_Key() ) ) );
            OUString value(
                String_to_ustring( __try_cast< ::System::String * >(
                                       bootstrap_parameters->get_Value() ) ) );
            
            ::rtl::Bootstrap::set( key, value );
        }
    }
    
    // bootstrap native uno
    Reference< XComponentContext > xContext;
    if (0 == ini_file)
    {
        xContext = ::cppu::defaultBootstrap_InitialComponentContext();
    }
    else
    {
        xContext = ::cppu::defaultBootstrap_InitialComponentContext(
            String_to_ustring( __try_cast< ::System::String * >( ini_file ) ) );
    }
    
    return __try_cast< ::unoidl::com::sun::star::uno::XComponentContext * >(
        to_cli( xContext ) );
}

//______________________________________________________________________________
::unoidl::com::sun::star::uno::XComponentContext *
Bootstrap::defaultBootstrap_InitialComponentContext()
{
    return defaultBootstrap_InitialComponentContext( 0, 0 );
}

::unoidl::com::sun::star::uno::XComponentContext * Bootstrap::bootstrap()
{
    Reference<XComponentContext> xContext = ::cppu::bootstrap();
    return __try_cast< ::unoidl::com::sun::star::uno::XComponentContext * >(
        to_cli( xContext ) );
        
}

}
}
