1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include <cstddef> 29 #include <stdlib.h> 30 #include <wchar.h> 31 32 #define WIN32_LEAN_AND_MEAN 33 #if defined _MSC_VER 34 #pragma warning(push, 1) 35 #endif 36 #include <windows.h> 37 #if defined _MSC_VER 38 #pragma warning(pop) 39 #endif 40 41 #include "tools/pathutils.hxx" 42 43 #include "pyversion.hxx" 44 45 #define MY_LENGTH(s) (sizeof (s) / sizeof *(s) - 1) 46 #define MY_STRING(s) (s), MY_LENGTH(s) 47 48 wchar_t * encode(wchar_t * buffer, wchar_t const * text) { 49 *buffer++ = L'"'; 50 std::size_t n = 0; 51 for (;;) { 52 wchar_t c = *text++; 53 if (c == L'\0') { 54 break; 55 } else if (c == L'"') { 56 // Double any preceding backslashes as required by Windows: 57 for (std::size_t i = 0; i < n; ++i) { 58 *buffer++ = L'\\'; 59 } 60 *buffer++ = L'\\'; 61 *buffer++ = L'"'; 62 n = 0; 63 } else if (c == L'\\') { 64 *buffer++ = L'\\'; 65 ++n; 66 } else { 67 *buffer++ = c; 68 n = 0; 69 } 70 } 71 // The command line will continue with a double quote, so double any 72 // preceding backslashes as required by Windows: 73 for (std::size_t i = 0; i < n; ++i) { 74 *buffer++ = L'\\'; 75 } 76 *buffer++ = L'"'; 77 return buffer; 78 } 79 80 #ifdef __MINGW32__ 81 int main(int argc, char ** argv, char **) { 82 #else 83 int wmain(int argc, wchar_t ** argv, wchar_t **) { 84 #endif 85 wchar_t path[MAX_PATH]; 86 DWORD n = GetModuleFileNameW(NULL, path, MAX_PATH); 87 if (n == 0 || n >= MAX_PATH) { 88 exit(EXIT_FAILURE); 89 } 90 wchar_t * pathEnd = tools::filename(path); 91 *pathEnd = L'\0'; 92 n = GetEnvironmentVariableW(L"UNO_PATH", NULL, 0); 93 if (n == 0) { 94 if (GetLastError() != ERROR_ENVVAR_NOT_FOUND || 95 !SetEnvironmentVariableW(L"UNO_PATH", path)) 96 { 97 exit(EXIT_FAILURE); 98 } 99 } 100 wchar_t bootstrap[MY_LENGTH(L"vnd.sun.star.pathname:") + MAX_PATH] = 101 L"vnd.sun.star.pathname:"; //TODO: overflow 102 wchar_t * bootstrapEnd = tools::buildPath( 103 bootstrap + MY_LENGTH(L"vnd.sun.star.pathname:"), path, pathEnd, 104 MY_STRING(L"fundamental.ini")); 105 if (bootstrapEnd == NULL || 106 (tools::buildPath(path, path, pathEnd, MY_STRING(L"..\\basis-link")) 107 == NULL)) 108 { 109 exit(EXIT_FAILURE); 110 } 111 pathEnd = tools::resolveLink(path); 112 wchar_t path1[MAX_PATH]; 113 wchar_t * path1End = tools::buildPath( 114 path1, path, pathEnd, MY_STRING(L"\\program")); 115 if (path1End == NULL) { 116 exit(EXIT_FAILURE); 117 } 118 wchar_t pythonpath2[MAX_PATH]; 119 wchar_t * pythonpath2End = tools::buildPath( 120 pythonpath2, path, pathEnd, 121 MY_STRING(L"\\program\\python-core-" MY_PYVERSION L"\\lib")); 122 if (pythonpath2End == NULL) { 123 exit(EXIT_FAILURE); 124 } 125 wchar_t pythonpath3[MAX_PATH]; 126 wchar_t * pythonpath3End = tools::buildPath( 127 pythonpath3, path, pathEnd, 128 MY_STRING( 129 L"\\program\\python-core-" MY_PYVERSION L"\\lib\\site-packages")); 130 if (pythonpath3End == NULL) { 131 exit(EXIT_FAILURE); 132 } 133 #ifdef __MINGW32__ 134 wchar_t pythonpath4[MAX_PATH]; 135 wchar_t * pythonpath4End = tools::buildPath( 136 pythonpath4, path, pathEnd, 137 MY_STRING(L"\\program\\python-core-" MY_PYVERSION L"\\lib\\lib-dynload")); 138 if (pythonpath4End == NULL) { 139 exit(EXIT_FAILURE); 140 } 141 wchar_t pythonpath5[MAX_PATH]; 142 wchar_t * pythonpath5End = tools::buildPath( 143 pythonpath5, path, pathEnd, 144 MY_STRING(L"\\program\\python-core-" MY_PYVERSION L"\\lib\\lib-dynload")); 145 if (pythonpath5End == NULL) { 146 exit(EXIT_FAILURE); 147 } 148 #endif 149 wchar_t pythonhome[MAX_PATH]; 150 wchar_t * pythonhomeEnd = tools::buildPath( 151 pythonhome, path, pathEnd, 152 MY_STRING(L"\\program\\python-core-" MY_PYVERSION)); 153 if (pythonhomeEnd == NULL) { 154 exit(EXIT_FAILURE); 155 } 156 wchar_t pythonexe[MAX_PATH]; 157 wchar_t * pythonexeEnd = tools::buildPath( 158 pythonexe, path, pathEnd, 159 #ifdef __MINGW32__ 160 MY_STRING( 161 L"\\program\\python-core-" MY_PYVERSION L"\\bin\\python.bin")); 162 #else 163 MY_STRING( 164 L"\\program\\python-core-" MY_PYVERSION L"\\bin\\python.exe")); 165 #endif 166 if (pythonexeEnd == NULL) { 167 exit(EXIT_FAILURE); 168 } 169 if (tools::buildPath(path, path, pathEnd, MY_STRING(L"\\ure-link")) == NULL) 170 { 171 exit(EXIT_FAILURE); 172 } 173 pathEnd = tools::resolveLink(path); 174 if (pathEnd == NULL) { 175 exit(EXIT_FAILURE); 176 } 177 pathEnd = tools::buildPath(path, path, pathEnd, MY_STRING(L"\\bin")); 178 if (pathEnd == NULL) { 179 exit(EXIT_FAILURE); 180 } 181 std::size_t clSize = MY_LENGTH(L"\"") + 4 * (pythonexeEnd - pythonexe) + 182 MY_LENGTH(L"\"\0"); //TODO: overflow 183 // 4 * len: each char preceded by backslash, each trailing backslash 184 // doubled 185 for (int i = 1; i < argc; ++i) { 186 #ifdef __MINGW32__ 187 clSize += MY_LENGTH(L" \"") + 4 * strlen(argv[i]) + 188 #else 189 clSize += MY_LENGTH(L" \"") + 4 * wcslen(argv[i]) + 190 #endif 191 MY_LENGTH(L"\""); //TODO: overflow 192 } 193 wchar_t * cl = new wchar_t[clSize]; 194 if (cl == NULL) { 195 exit(EXIT_FAILURE); 196 } 197 wchar_t * cp = encode(cl, pythonhome); 198 for (int i = 1; i < argc; ++i) { 199 *cp++ = L' '; 200 #ifdef __MINGW32__ 201 int nNeededWStrBuffSize = MultiByteToWideChar(CP_ACP, 0, argv[i], -1, NULL, 0); 202 WCHAR *buff = new WCHAR[nNeededWStrBuffSize+1]; 203 MultiByteToWideChar(CP_ACP, 0, argv[i], -1, buff, nNeededWStrBuffSize); 204 buff[nNeededWStrBuffSize] = 0; 205 cp = encode(cp, buff); 206 delete [] buff; 207 #else 208 cp = encode(cp, argv[i]); 209 #endif 210 } 211 *cp = L'\0'; 212 n = GetEnvironmentVariableW(L"PATH", NULL, 0); 213 wchar_t * orig; 214 if (n == 0) { 215 if (GetLastError() != ERROR_ENVVAR_NOT_FOUND) { 216 exit(EXIT_FAILURE); 217 } 218 orig = L""; 219 } else { 220 orig = new wchar_t[n]; 221 if (orig == NULL || 222 GetEnvironmentVariableW(L"PATH", orig, n) != n - 1) 223 { 224 exit(EXIT_FAILURE); 225 } 226 } 227 wchar_t * value = new wchar_t[ 228 (pathEnd - path) + MY_LENGTH(L";") + (path1End - path1) + 229 (n == 0 ? 0 : MY_LENGTH(L";") + (n - 1)) + 1]; //TODO: overflow 230 wsprintfW(value, L"%s;%s%s%s", path, path1, n == 0 ? L"" : L";", orig); 231 if (!SetEnvironmentVariableW(L"PATH", value)) { 232 exit(EXIT_FAILURE); 233 } 234 if (n != 0) { 235 delete [] orig; 236 } 237 delete [] value; 238 n = GetEnvironmentVariableW(L"PYTHONPATH", NULL, 0); 239 if (n == 0) { 240 if (GetLastError() != ERROR_ENVVAR_NOT_FOUND) { 241 exit(EXIT_FAILURE); 242 } 243 orig = L""; 244 } else { 245 orig = new wchar_t[n]; 246 if (orig == NULL || 247 GetEnvironmentVariableW(L"PYTHONPATH", orig, n) != n - 1) 248 { 249 exit(EXIT_FAILURE); 250 } 251 } 252 #ifdef __MINGW32__ 253 value = new wchar_t[ 254 (path1End - path1) + MY_LENGTH(L";") + (pythonpath2End - pythonpath2) + 255 MY_LENGTH(L";") + (pythonpath4End - pythonpath4) + 256 MY_LENGTH(L";") + (pythonpath5End - pythonpath5) + 257 MY_LENGTH(L";") + (pythonpath3End - pythonpath3) + 258 (n == 0 ? 0 : MY_LENGTH(L";") + (n - 1)) + 1]; //TODO: overflow 259 wsprintfW( 260 value, L"%s;%s;%s;%s;%s%s%s", path1, pythonpath2, pythonpath4, 261 pythonpath5, pythonpath3, 262 n == 0 ? L"" : L";", orig); 263 #else 264 value = new wchar_t[ 265 (path1End - path1) + MY_LENGTH(L";") + (pythonpath2End - pythonpath2) + 266 MY_LENGTH(L";") + (pythonpath3End - pythonpath3) + 267 (n == 0 ? 0 : MY_LENGTH(L";") + (n - 1)) + 1]; //TODO: overflow 268 wsprintfW( 269 value, L"%s;%s;%s%s%s", path1, pythonpath2, pythonpath3, 270 n == 0 ? L"" : L";", orig); 271 #endif 272 if (!SetEnvironmentVariableW(L"PYTHONPATH", value)) { 273 exit(EXIT_FAILURE); 274 } 275 if (n != 0) { 276 delete [] orig; 277 } 278 delete [] value; 279 if (!SetEnvironmentVariableW(L"PYTHONHOME", pythonhome)) { 280 exit(EXIT_FAILURE); 281 } 282 n = GetEnvironmentVariableW(L"URE_BOOTSTRAP", NULL, 0); 283 if (n == 0) { 284 if (GetLastError() != ERROR_ENVVAR_NOT_FOUND || 285 !SetEnvironmentVariableW(L"URE_BOOTSTRAP", bootstrap)) 286 { 287 exit(EXIT_FAILURE); 288 } 289 } 290 STARTUPINFOW startinfo; 291 ZeroMemory(&startinfo, sizeof (STARTUPINFOW)); 292 startinfo.cb = sizeof (STARTUPINFOW); 293 PROCESS_INFORMATION procinfo; 294 if (!CreateProcessW( 295 pythonexe, cl, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, NULL, 296 NULL, &startinfo, &procinfo)) { 297 exit(EXIT_FAILURE); 298 } 299 WaitForSingleObject(procinfo.hProcess,INFINITE); 300 DWORD exitStatus; 301 GetExitCodeProcess(procinfo.hProcess,&exitStatus); 302 exit(exitStatus); 303 } 304