[Libreoffice-commits] core.git: cli_ure/source

Mike Kaganski mike.kaganski at collabora.com
Mon Apr 9 07:07:06 UTC 2018


 cli_ure/source/native/native_bootstrap.cxx |  160 +++++++++++++++++++++++++++++
 1 file changed, 160 insertions(+)

New commits:
commit b9d709e84728270acb00c3952551f5c608260e62
Author: Mike Kaganski <mike.kaganski at collabora.com>
Date:   Sun Apr 8 00:47:18 2018 +0100

    tdf#94265: use install directory on delay load failure
    
    This partially reverts commit 827430c8c0417396b3c1d2a049ccddb818c89646
    
    Change-Id: Ia5d609040a3b355659e780e0606ce4bff0d22509
    Reviewed-on: https://gerrit.libreoffice.org/52572
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Stephan Bergmann <sbergman at redhat.com>

diff --git a/cli_ure/source/native/native_bootstrap.cxx b/cli_ure/source/native/native_bootstrap.cxx
index 0ec2375a1c78..f26a634c2aa1 100644
--- a/cli_ure/source/native/native_bootstrap.cxx
+++ b/cli_ure/source/native/native_bootstrap.cxx
@@ -22,7 +22,167 @@
 #include "rtl/bootstrap.hxx"
 #include "com/sun/star/uno/XComponentContext.hpp"
 #include "cppuhelper/bootstrap.hxx"
+#include <memory>
 #include <stdio.h>
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <delayimp.h>
+
+#define INSTALL_PATH L"Software\\LibreOffice\\UNO\\InstallPath"
+#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 nullptr, if no installation was found or
+           if an error occurred
+*/
+WCHAR* getPathFromRegistryKey( HKEY hroot, LPCWSTR subKeyName )
+{
+    // open the specified registry key
+    HKEY hkey;
+    if ( RegOpenKeyExW( hroot, subKeyName, 0, KEY_READ, &hkey ) != ERROR_SUCCESS )
+        return nullptr;
+
+    struct CloseKeyGuard {
+        HKEY m_hkey;
+        ~CloseKeyGuard() { RegCloseKey( m_hkey ); }
+    } aCloseKeyGuard{hkey};
+
+    // find the type and size of the default value
+    DWORD type;
+    DWORD size;
+    if ( RegQueryValueExW( hkey, nullptr, nullptr, &type, nullptr, &size ) != ERROR_SUCCESS )
+        return nullptr;
+
+    // get memory to hold the default value
+    std::unique_ptr<WCHAR[]> data(new WCHAR[size]);
+
+    // read the default value
+    if ( RegQueryValueExW( hkey, nullptr, nullptr, &type, reinterpret_cast<LPBYTE>(data.get()), &size ) != ERROR_SUCCESS )
+        return nullptr;
+
+    return data.release();
+}
+
+/* Returns the path to the program folder of the brand layer,
+   for example C:/Program Files/LibreOffice/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()
+{
+    std::unique_ptr<WCHAR[]> szInstallPath;
+
+    DWORD cChars = GetEnvironmentVariableW(UNO_PATH, nullptr, 0);
+    if (cChars > 0)
+    {
+        szInstallPath.reset(new WCHAR[cChars]);
+        cChars = GetEnvironmentVariableW(UNO_PATH, szInstallPath.get(), cChars);
+        // If PATH is not set then it is no error
+        if (cChars == 0)
+            return nullptr;
+    }
+
+    if (! szInstallPath)
+    {
+        szInstallPath.reset(getPathFromRegistryKey( HKEY_CURRENT_USER, INSTALL_PATH ));
+        if (! szInstallPath)
+        {
+            // read the key's default value from HKEY_LOCAL_MACHINE
+            szInstallPath.reset(getPathFromRegistryKey( HKEY_LOCAL_MACHINE, INSTALL_PATH ));
+        }
+    }
+    return szInstallPath.release();
+}
+
+/* We extend the path to contain the install 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 szPath)
+{
+    if (!szPath)
+        return;
+
+    std::unique_ptr<WCHAR[]> sEnvPath;
+    DWORD cChars = GetEnvironmentVariableW(L"PATH", nullptr, 0);
+    if (cChars > 0)
+    {
+        sEnvPath.reset(new WCHAR[cChars]);
+        cChars = GetEnvironmentVariableW(L"PATH", sEnvPath.get(), cChars);
+        // If PATH is not set then it is no error
+        if (cChars == 0 && GetLastError() != ERROR_ENVVAR_NOT_FOUND)
+            return;
+    }
+    // Prepare the new PATH. Add the directory at the front.
+    // Note also adding ';'
+    std::unique_ptr<WCHAR[]> sNewPath(new WCHAR[lstrlenW(sEnvPath.get()) + lstrlenW(szPath) + 2]);
+    lstrcpyW(sNewPath.get(), szPath);
+    if (lstrlenW(sEnvPath.get()))
+    {
+        lstrcatW(sNewPath.get(), L";");
+        lstrcatW(sNewPath.get(), sEnvPath.get());
+    }
+    SetEnvironmentVariableW(L"PATH", sNewPath.get());
+}
+
+HMODULE loadFromPath(LPCSTR sLibName)
+{
+    if (!sLibName)
+        return nullptr;
+
+    // Convert the ansi file name to wchar_t*
+    int size = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, sLibName, -1, nullptr, 0);
+    if (size == 0)
+        return nullptr;
+    std::unique_ptr<WCHAR[]> wsLibName(new WCHAR[size]);
+    if (!MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, sLibName, -1, wsLibName.get(), size))
+        return nullptr;
+
+    std::unique_ptr<WCHAR[]> szPath(getInstallPath());
+    if (!szPath)
+        return nullptr;
+
+    extendPath(szPath.get());
+
+    std::unique_ptr<WCHAR[]> szFullPath(new WCHAR[lstrlenW(wsLibName.get()) + lstrlenW(szPath.get()) + 2]);
+    lstrcpyW(szFullPath.get(), szPath.get());
+    lstrcatW(szFullPath.get(), L"\\");
+    lstrcatW(szFullPath.get(), wsLibName.get());
+    HMODULE handle = LoadLibraryW(szFullPath.get());
+    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 install folder while this function is
+   executed (see extendPath), all other libraries are found.
+*/
+extern "C" FARPROC WINAPI delayLoadHook(
+    unsigned int   dliNotify,
+    PDelayLoadInfo pdli
+    )
+{
+    if (dliNotify == dliFailLoadLib)
+    {
+        HANDLE h = loadFromPath(pdli->szDll);
+        return reinterpret_cast<FARPROC>(h);
+    }
+    return nullptr;
+}
+}
+
+ExternC
+const PfnDliHook __pfnDliFailureHook2 = delayLoadHook;
 
 using namespace ::com::sun::star;
 using namespace ::com::sun::star::uno;


More information about the Libreoffice-commits mailing list