414 lines
12 KiB
C++
414 lines
12 KiB
C++
/* -*- 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 .
|
|
*/
|
|
|
|
// 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\\LibreOffice\\UNO\\InstallPath"
|
|
#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 occurred
|
|
*/
|
|
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 );
|
|
delete[] data;
|
|
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:/LibreOffice 3/program
|
|
This path is either obtained from the environment variable UNO_PATH
|
|
or the registry item
|
|
"Software\\LibreOffice\\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)
|
|
{
|
|
oneDirUp(szInstallPath);
|
|
|
|
//build the path to the ure-link file
|
|
szUrePath = new WCHAR[MAX_PATH];
|
|
szUrePath[0] = L'\0';
|
|
lstrcat(szUrePath, szInstallPath);
|
|
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))
|
|
{
|
|
delete[] szLibName;
|
|
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\LibreOffice\Layer\URE\1
|
|
and HKEY_LOCAL_MACHINE\Software\LibreOffice\Layer\URE\1 are examined.
|
|
These contain a named value UREINSTALLLOCATION which holds a path to the URE
|
|
installation folder.
|
|
*/
|
|
public ref class Bootstrap sealed
|
|
{
|
|
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 (nullptr != bootstrap_parameters)
|
|
{
|
|
bootstrap_parameters->Reset();
|
|
while (bootstrap_parameters->MoveNext())
|
|
{
|
|
OUString key(
|
|
String_to_ustring( safe_cast< ::System::String ^ >(
|
|
bootstrap_parameters->Key ) ) );
|
|
OUString value(
|
|
String_to_ustring( safe_cast< ::System::String ^ >(
|
|
bootstrap_parameters->Value ) ) );
|
|
|
|
::rtl::Bootstrap::set( key, value );
|
|
}
|
|
}
|
|
|
|
// bootstrap native uno
|
|
Reference< XComponentContext > xContext;
|
|
if (nullptr == ini_file)
|
|
{
|
|
xContext = ::cppu::defaultBootstrap_InitialComponentContext();
|
|
}
|
|
else
|
|
{
|
|
xContext = ::cppu::defaultBootstrap_InitialComponentContext(
|
|
String_to_ustring( safe_cast< ::System::String ^ >( ini_file ) ) );
|
|
}
|
|
|
|
return safe_cast< ::unoidl::com::sun::star::uno::XComponentContext ^ >(
|
|
to_cli( xContext ) );
|
|
}
|
|
|
|
|
|
::unoidl::com::sun::star::uno::XComponentContext ^
|
|
Bootstrap::defaultBootstrap_InitialComponentContext()
|
|
{
|
|
return defaultBootstrap_InitialComponentContext( nullptr, nullptr );
|
|
}
|
|
|
|
::unoidl::com::sun::star::uno::XComponentContext ^ Bootstrap::bootstrap()
|
|
{
|
|
Reference<XComponentContext> xContext = ::cppu::bootstrap();
|
|
return safe_cast< ::unoidl::com::sun::star::uno::XComponentContext ^ >(
|
|
to_cli( xContext ) );
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|