merged tag ooo/DEV300_m102
[LibreOffice.git] / pyuno / zipcore / python.cxx
blob14f629922a1d4d8a0274a7c1fd1d3afdbe6e8a3b
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
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.
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).
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.
26 ************************************************************************/
28 #include <cstddef>
29 #include <stdlib.h>
30 #include <wchar.h>
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
41 #include "tools/pathutils.hxx"
43 #include "pyversion.hxx"
45 #define MY_LENGTH(s) (sizeof (s) / sizeof *(s) - 1)
46 #define MY_STRING(s) (s), MY_LENGTH(s)
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'\\';
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;
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'\\';
76 *buffer++ = L'"';
77 return buffer;
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);
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))
97 exit(EXIT_FAILURE);
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))
109 exit(EXIT_FAILURE);
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);
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);
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);
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);
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);
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);
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);
169 if (tools::buildPath(path, path, pathEnd, MY_STRING(L"\\ure-link")) == NULL)
171 exit(EXIT_FAILURE);
173 pathEnd = tools::resolveLink(path);
174 if (pathEnd == NULL) {
175 exit(EXIT_FAILURE);
177 pathEnd = tools::buildPath(path, path, pathEnd, MY_STRING(L"\\bin"));
178 if (pathEnd == NULL) {
179 exit(EXIT_FAILURE);
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
193 wchar_t * cl = new wchar_t[clSize];
194 if (cl == NULL) {
195 exit(EXIT_FAILURE);
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
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);
218 orig = L"";
219 } else {
220 orig = new wchar_t[n];
221 if (orig == NULL ||
222 GetEnvironmentVariableW(L"PATH", orig, n) != n - 1)
224 exit(EXIT_FAILURE);
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);
234 if (n != 0) {
235 delete [] orig;
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);
243 orig = L"";
244 } else {
245 orig = new wchar_t[n];
246 if (orig == NULL ||
247 GetEnvironmentVariableW(L"PYTHONPATH", orig, n) != n - 1)
249 exit(EXIT_FAILURE);
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);
275 if (n != 0) {
276 delete [] orig;
278 delete [] value;
279 if (!SetEnvironmentVariableW(L"PYTHONHOME", pythonhome)) {
280 exit(EXIT_FAILURE);
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))
287 exit(EXIT_FAILURE);
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);
299 WaitForSingleObject(procinfo.hProcess,INFINITE);
300 DWORD exitStatus;
301 GetExitCodeProcess(procinfo.hProcess,&exitStatus);
302 exit(exitStatus);