1*2722ceddSAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*2722ceddSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*2722ceddSAndrew Rist * or more contributor license agreements. See the NOTICE file 5*2722ceddSAndrew Rist * distributed with this work for additional information 6*2722ceddSAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*2722ceddSAndrew Rist * to you under the Apache License, Version 2.0 (the 8*2722ceddSAndrew Rist * "License"); you may not use this file except in compliance 9*2722ceddSAndrew Rist * with the License. You may obtain a copy of the License at 10*2722ceddSAndrew Rist * 11*2722ceddSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12*2722ceddSAndrew Rist * 13*2722ceddSAndrew Rist * Unless required by applicable law or agreed to in writing, 14*2722ceddSAndrew Rist * software distributed under the License is distributed on an 15*2722ceddSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*2722ceddSAndrew Rist * KIND, either express or implied. See the License for the 17*2722ceddSAndrew Rist * specific language governing permissions and limitations 18*2722ceddSAndrew Rist * under the License. 19*2722ceddSAndrew Rist * 20*2722ceddSAndrew Rist *************************************************************/ 21*2722ceddSAndrew Rist 22*2722ceddSAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir #include "precompiled_desktop.hxx" 25cdf0e10cSrcweir #include "sal/config.h" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include <cstddef> 28cdf0e10cSrcweir 29cdf0e10cSrcweir #define WIN32_LEAN_AND_MEAN 30cdf0e10cSrcweir #if defined _MSC_VER 31cdf0e10cSrcweir #pragma warning(push, 1) 32cdf0e10cSrcweir #endif 33cdf0e10cSrcweir #include <windows.h> 34cdf0e10cSrcweir #include <shlwapi.h> 35cdf0e10cSrcweir #if defined _MSC_VER 36cdf0e10cSrcweir #pragma warning(pop) 37cdf0e10cSrcweir #endif 38cdf0e10cSrcweir 39cdf0e10cSrcweir #include "tools/pathutils.hxx" 40cdf0e10cSrcweir 41cdf0e10cSrcweir #include "extendloaderenvironment.hxx" 42cdf0e10cSrcweir 43cdf0e10cSrcweir namespace { 44cdf0e10cSrcweir 45cdf0e10cSrcweir void fail() { 46cdf0e10cSrcweir LPWSTR buf = NULL; 47cdf0e10cSrcweir FormatMessageW( 48cdf0e10cSrcweir FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, 49cdf0e10cSrcweir GetLastError(), 0, reinterpret_cast< LPWSTR >(&buf), 0, NULL); 50cdf0e10cSrcweir MessageBoxW(NULL, buf, NULL, MB_OK | MB_ICONERROR); 51cdf0e10cSrcweir LocalFree(buf); 52cdf0e10cSrcweir TerminateProcess(GetCurrentProcess(), 255); 53cdf0e10cSrcweir } 54cdf0e10cSrcweir 55cdf0e10cSrcweir bool contains(WCHAR const * paths, WCHAR const * path, WCHAR const * pathEnd) { 56cdf0e10cSrcweir WCHAR const * q = path; 57cdf0e10cSrcweir for (WCHAR const * p = paths;; ++p) { 58cdf0e10cSrcweir WCHAR c = *p; 59cdf0e10cSrcweir switch (c) { 60cdf0e10cSrcweir case L'\0': 61cdf0e10cSrcweir return q == pathEnd; 62cdf0e10cSrcweir case L';': 63cdf0e10cSrcweir if (q == pathEnd) { 64cdf0e10cSrcweir return true; 65cdf0e10cSrcweir } 66cdf0e10cSrcweir q = path; 67cdf0e10cSrcweir break; 68cdf0e10cSrcweir default: 69cdf0e10cSrcweir if (q != NULL) { 70cdf0e10cSrcweir if (q != pathEnd && *q == c) { 71cdf0e10cSrcweir ++q; 72cdf0e10cSrcweir } else { 73cdf0e10cSrcweir q = NULL; 74cdf0e10cSrcweir } 75cdf0e10cSrcweir } 76cdf0e10cSrcweir break; 77cdf0e10cSrcweir } 78cdf0e10cSrcweir } 79cdf0e10cSrcweir } 80cdf0e10cSrcweir 81cdf0e10cSrcweir } 82cdf0e10cSrcweir 83cdf0e10cSrcweir namespace desktop_win32 { 84cdf0e10cSrcweir 85cdf0e10cSrcweir void extendLoaderEnvironment(WCHAR * binPath, WCHAR * iniDirectory) { 86cdf0e10cSrcweir if (!GetModuleFileNameW(NULL, iniDirectory, MAX_PATH)) { 87cdf0e10cSrcweir fail(); 88cdf0e10cSrcweir } 89cdf0e10cSrcweir WCHAR * iniDirEnd = tools::filename(iniDirectory); 90cdf0e10cSrcweir WCHAR name[MAX_PATH + MY_LENGTH(L".bin")]; 91cdf0e10cSrcweir // hopefully std::size_t is large enough to not overflow 92cdf0e10cSrcweir WCHAR * nameEnd = name; 93cdf0e10cSrcweir for (WCHAR * p = iniDirEnd; *p != L'\0'; ++p) { 94cdf0e10cSrcweir *nameEnd++ = *p; 95cdf0e10cSrcweir } 96cdf0e10cSrcweir if (!(nameEnd - name >= 4 && nameEnd[-4] == L'.' && 97cdf0e10cSrcweir (nameEnd[-3] == L'E' || nameEnd[-3] == L'e') && 98cdf0e10cSrcweir (nameEnd[-2] == L'X' || nameEnd[-2] == L'x') && 99cdf0e10cSrcweir (nameEnd[-1] == L'E' || nameEnd[-1] == L'e'))) 100cdf0e10cSrcweir { 101cdf0e10cSrcweir *nameEnd = L'.'; 102cdf0e10cSrcweir nameEnd += 4; 103cdf0e10cSrcweir } 104cdf0e10cSrcweir nameEnd[-3] = 'b'; 105cdf0e10cSrcweir nameEnd[-2] = 'i'; 106cdf0e10cSrcweir nameEnd[-1] = 'n'; 107cdf0e10cSrcweir tools::buildPath(binPath, iniDirectory, iniDirEnd, name, nameEnd - name); 108cdf0e10cSrcweir *iniDirEnd = L'\0'; 109cdf0e10cSrcweir WCHAR path[MAX_PATH]; 110cdf0e10cSrcweir WCHAR * pathEnd = tools::buildPath( 111cdf0e10cSrcweir path, iniDirectory, iniDirEnd, MY_STRING(L"..\\basis-link")); 112cdf0e10cSrcweir if (pathEnd == NULL) { 113cdf0e10cSrcweir fail(); 114cdf0e10cSrcweir } 115cdf0e10cSrcweir std::size_t const maxEnv = 32767; 116cdf0e10cSrcweir WCHAR pad[2 * MAX_PATH + maxEnv]; 117cdf0e10cSrcweir // hopefully std::size_t is large enough to not overflow 118cdf0e10cSrcweir WCHAR * padEnd = NULL; 119cdf0e10cSrcweir WCHAR env[maxEnv]; 120cdf0e10cSrcweir DWORD n = GetEnvironmentVariableW(L"PATH", env, maxEnv); 121cdf0e10cSrcweir if (n >= maxEnv || n == 0 && GetLastError() != ERROR_ENVVAR_NOT_FOUND) { 122cdf0e10cSrcweir fail(); 123cdf0e10cSrcweir } 124cdf0e10cSrcweir env[n] = L'\0'; 125cdf0e10cSrcweir bool exclude1; 126cdf0e10cSrcweir pathEnd = tools::resolveLink(path); 127cdf0e10cSrcweir if (pathEnd == NULL) { 128cdf0e10cSrcweir if (GetLastError() != ERROR_FILE_NOT_FOUND) { 129cdf0e10cSrcweir fail(); 130cdf0e10cSrcweir } 131cdf0e10cSrcweir // This path is only taken by testtool.exe in basis program directory; 132cdf0e10cSrcweir // its PATH needs to include the brand program directory: 133cdf0e10cSrcweir pathEnd = tools::buildPath( 134cdf0e10cSrcweir path, iniDirectory, iniDirEnd, MY_STRING(L"..")); 135cdf0e10cSrcweir if (pathEnd == NULL) { 136cdf0e10cSrcweir fail(); 137cdf0e10cSrcweir } 138cdf0e10cSrcweir padEnd = tools::buildPath( 139cdf0e10cSrcweir pad, path, pathEnd, MY_STRING(L"\\..\\program")); 140cdf0e10cSrcweir if (padEnd == NULL) { 141cdf0e10cSrcweir fail(); 142cdf0e10cSrcweir } 143cdf0e10cSrcweir exclude1 = contains(env, pad, padEnd); 144cdf0e10cSrcweir } else { 145cdf0e10cSrcweir exclude1 = true; 146cdf0e10cSrcweir } 147cdf0e10cSrcweir WCHAR * pad2 = exclude1 ? pad : padEnd + 1; 148cdf0e10cSrcweir pathEnd = tools::buildPath(path, path, pathEnd, MY_STRING(L"\\ure-link")); 149cdf0e10cSrcweir if (pathEnd == NULL) { 150cdf0e10cSrcweir fail(); 151cdf0e10cSrcweir } 152cdf0e10cSrcweir pathEnd = tools::resolveLink(path); 153cdf0e10cSrcweir if (pathEnd == NULL) { 154cdf0e10cSrcweir fail(); 155cdf0e10cSrcweir } 156cdf0e10cSrcweir padEnd = tools::buildPath(pad2, path, pathEnd, MY_STRING(L"\\bin")); 157cdf0e10cSrcweir if (padEnd == NULL) { 158cdf0e10cSrcweir fail(); 159cdf0e10cSrcweir } 160cdf0e10cSrcweir bool exclude2 = contains(env, pad2, padEnd); 161cdf0e10cSrcweir if (!(exclude1 && exclude2)) { 162cdf0e10cSrcweir if (!(exclude1 || exclude2)) { 163cdf0e10cSrcweir pad2[-1] = L';'; 164cdf0e10cSrcweir } 165cdf0e10cSrcweir WCHAR * p = exclude2 ? pad2 - 1 : padEnd; 166cdf0e10cSrcweir if (n != 0) { 167cdf0e10cSrcweir *p++ = L';'; 168cdf0e10cSrcweir } 169cdf0e10cSrcweir for (DWORD i = 0; i <= n; ++i) { 170cdf0e10cSrcweir *p++ = env[i]; 171cdf0e10cSrcweir } 172cdf0e10cSrcweir if (!SetEnvironmentVariableW(L"PATH", pad)) { 173cdf0e10cSrcweir fail(); 174cdf0e10cSrcweir } 175cdf0e10cSrcweir } 176cdf0e10cSrcweir } 177cdf0e10cSrcweir 178cdf0e10cSrcweir } 179