1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: python.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
35 #define WIN32_LEAN_AND_MEAN
37 #pragma warning(push, 1)
44 #include "tools/pathutils.hxx"
46 #include "pyversion.hxx"
48 #define MY_LENGTH(s) (sizeof (s) / sizeof *(s) - 1)
49 #define MY_STRING(s) (s), MY_LENGTH(s)
51 wchar_t * encode(wchar_t * buffer
, wchar_t const * text
) {
58 } else if (c
== L
'"') {
59 // Double any preceding backslashes as required by Windows:
60 for (std::size_t i
= 0; i
< n
; ++i
) {
66 } else if (c
== L
'\\') {
74 // The command line will continue with a double quote, so double any
75 // preceding backslashes as required by Windows:
76 for (std::size_t i
= 0; i
< n
; ++i
) {
84 int main(int argc
, char ** argv
, char **) {
86 int wmain(int argc
, wchar_t ** argv
, wchar_t **) {
88 wchar_t path
[MAX_PATH
];
89 DWORD n
= GetModuleFileNameW(NULL
, path
, MAX_PATH
);
90 if (n
== 0 || n
>= MAX_PATH
) {
93 wchar_t * pathEnd
= tools::filename(path
);
95 n
= GetEnvironmentVariableW(L
"UNO_PATH", NULL
, 0);
97 if (GetLastError() != ERROR_ENVVAR_NOT_FOUND
||
98 !SetEnvironmentVariableW(L
"UNO_PATH", path
))
103 wchar_t bootstrap
[MY_LENGTH(L
"vnd.sun.star.pathname:") + MAX_PATH
] =
104 L
"vnd.sun.star.pathname:"; //TODO: overflow
105 wchar_t * bootstrapEnd
= tools::buildPath(
106 bootstrap
+ MY_LENGTH(L
"vnd.sun.star.pathname:"), path
, pathEnd
,
107 MY_STRING(L
"fundamental.ini"));
108 if (bootstrapEnd
== NULL
||
109 (tools::buildPath(path
, path
, pathEnd
, MY_STRING(L
"..\\basis-link"))
114 pathEnd
= tools::resolveLink(path
);
115 wchar_t path1
[MAX_PATH
];
116 wchar_t * path1End
= tools::buildPath(
117 path1
, path
, pathEnd
, MY_STRING(L
"\\program"));
118 if (path1End
== NULL
) {
121 wchar_t pythonpath2
[MAX_PATH
];
122 wchar_t * pythonpath2End
= tools::buildPath(
123 pythonpath2
, path
, pathEnd
,
124 MY_STRING(L
"\\program\\python-core-" MY_PYVERSION L
"\\lib"));
125 if (pythonpath2End
== NULL
) {
128 wchar_t pythonpath3
[MAX_PATH
];
129 wchar_t * pythonpath3End
= tools::buildPath(
130 pythonpath3
, path
, pathEnd
,
132 L
"\\program\\python-core-" MY_PYVERSION L
"\\lib\\site-packages"));
133 if (pythonpath3End
== NULL
) {
137 wchar_t pythonpath4
[MAX_PATH
];
138 wchar_t * pythonpath4End
= tools::buildPath(
139 pythonpath4
, path
, pathEnd
,
140 MY_STRING(L
"\\program\\python-core-" MY_PYVERSION L
"\\lib\\lib-dynload"));
141 if (pythonpath4End
== NULL
) {
144 wchar_t pythonpath5
[MAX_PATH
];
145 wchar_t * pythonpath5End
= tools::buildPath(
146 pythonpath5
, path
, pathEnd
,
147 MY_STRING(L
"\\program\\python-core-" MY_PYVERSION L
"\\lib\\lib-dynload"));
148 if (pythonpath5End
== NULL
) {
152 wchar_t pythonhome
[MAX_PATH
];
153 wchar_t * pythonhomeEnd
= tools::buildPath(
154 pythonhome
, path
, pathEnd
,
155 MY_STRING(L
"\\program\\python-core-" MY_PYVERSION
));
156 if (pythonhomeEnd
== NULL
) {
159 wchar_t pythonexe
[MAX_PATH
];
160 wchar_t * pythonexeEnd
= tools::buildPath(
161 pythonexe
, path
, pathEnd
,
164 L
"\\program\\python-core-" MY_PYVERSION L
"\\bin\\python.bin"));
167 L
"\\program\\python-core-" MY_PYVERSION L
"\\bin\\python.exe"));
169 if (pythonexeEnd
== NULL
) {
172 if (tools::buildPath(path
, path
, pathEnd
, MY_STRING(L
"\\ure-link")) == NULL
)
176 pathEnd
= tools::resolveLink(path
);
177 if (pathEnd
== NULL
) {
180 pathEnd
= tools::buildPath(path
, path
, pathEnd
, MY_STRING(L
"\\bin"));
181 if (pathEnd
== NULL
) {
184 std::size_t clSize
= MY_LENGTH(L
"\"") + 4 * (pythonexeEnd
- pythonexe
) +
185 MY_LENGTH(L
"\"\0"); //TODO: overflow
186 // 4 * len: each char preceded by backslash, each trailing backslash
188 for (int i
= 1; i
< argc
; ++i
) {
190 clSize
+= MY_LENGTH(L
" \"") + 4 * strlen(argv
[i
]) +
192 clSize
+= MY_LENGTH(L
" \"") + 4 * wcslen(argv
[i
]) +
194 MY_LENGTH(L
"\""); //TODO: overflow
196 wchar_t * cl
= new wchar_t[clSize
];
200 wchar_t * cp
= encode(cl
, pythonhome
);
201 for (int i
= 1; i
< argc
; ++i
) {
204 int nNeededWStrBuffSize
= MultiByteToWideChar(CP_ACP
, 0, argv
[i
], -1, NULL
, 0);
205 WCHAR
*buff
= new WCHAR
[nNeededWStrBuffSize
+1];
206 MultiByteToWideChar(CP_ACP
, 0, argv
[i
], -1, buff
, nNeededWStrBuffSize
);
207 buff
[nNeededWStrBuffSize
] = 0;
208 cp
= encode(cp
, buff
);
211 cp
= encode(cp
, argv
[i
]);
215 n
= GetEnvironmentVariableW(L
"PATH", NULL
, 0);
218 if (GetLastError() != ERROR_ENVVAR_NOT_FOUND
) {
223 orig
= new wchar_t[n
];
225 GetEnvironmentVariableW(L
"PATH", orig
, n
) != n
- 1)
230 wchar_t * value
= new wchar_t[
231 (pathEnd
- path
) + MY_LENGTH(L
";") + (path1End
- path1
) +
232 (n
== 0 ? 0 : MY_LENGTH(L
";") + (n
- 1)) + 1]; //TODO: overflow
233 wsprintfW(value
, L
"%s;%s%s%s", path
, path1
, n
== 0 ? L
"" : L
";", orig
);
234 if (!SetEnvironmentVariableW(L
"PATH", value
)) {
241 n
= GetEnvironmentVariableW(L
"PYTHONPATH", NULL
, 0);
243 if (GetLastError() != ERROR_ENVVAR_NOT_FOUND
) {
248 orig
= new wchar_t[n
];
250 GetEnvironmentVariableW(L
"PYTHONPATH", orig
, n
) != n
- 1)
257 (path1End
- path1
) + MY_LENGTH(L
";") + (pythonpath2End
- pythonpath2
) +
258 MY_LENGTH(L
";") + (pythonpath4End
- pythonpath4
) +
259 MY_LENGTH(L
";") + (pythonpath5End
- pythonpath5
) +
260 MY_LENGTH(L
";") + (pythonpath3End
- pythonpath3
) +
261 (n
== 0 ? 0 : MY_LENGTH(L
";") + (n
- 1)) + 1]; //TODO: overflow
263 value
, L
"%s;%s;%s;%s;%s%s%s", path1
, pythonpath2
, pythonpath4
,
264 pythonpath5
, pythonpath3
,
265 n
== 0 ? L
"" : L
";", orig
);
268 (path1End
- path1
) + MY_LENGTH(L
";") + (pythonpath2End
- pythonpath2
) +
269 MY_LENGTH(L
";") + (pythonpath3End
- pythonpath3
) +
270 (n
== 0 ? 0 : MY_LENGTH(L
";") + (n
- 1)) + 1]; //TODO: overflow
272 value
, L
"%s;%s;%s%s%s", path1
, pythonpath2
, pythonpath3
,
273 n
== 0 ? L
"" : L
";", orig
);
275 if (!SetEnvironmentVariableW(L
"PYTHONPATH", value
)) {
282 if (!SetEnvironmentVariableW(L
"PYTHONHOME", pythonhome
)) {
285 n
= GetEnvironmentVariableW(L
"URE_BOOTSTRAP", NULL
, 0);
287 if (GetLastError() != ERROR_ENVVAR_NOT_FOUND
||
288 !SetEnvironmentVariableW(L
"URE_BOOTSTRAP", bootstrap
))
293 STARTUPINFOW startinfo
;
294 ZeroMemory(&startinfo
, sizeof (STARTUPINFOW
));
295 startinfo
.cb
= sizeof (STARTUPINFOW
);
296 PROCESS_INFORMATION procinfo
;
298 pythonexe
, cl
, NULL
, NULL
, FALSE
, CREATE_UNICODE_ENVIRONMENT
, NULL
,
299 NULL
, &startinfo
, &procinfo
)) {
302 WaitForSingleObject(procinfo
.hProcess
,INFINITE
);
304 GetExitCodeProcess(procinfo
.hProcess
,&exitStatus
);