1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_python.h>
26 #define WIN32_LEAN_AND_MEAN
29 #include <tools/pathutils.hxx>
31 #define MY_LENGTH(s) (sizeof (s) / sizeof *(s) - 1)
32 #define MY_STRING(s) (s), MY_LENGTH(s)
34 static wchar_t * encode(wchar_t * buffer
, wchar_t const * text
) {
41 } else if (c
== L
'"') {
42 // Double any preceding backslashes as required by Windows:
43 for (std::size_t i
= 0; i
< n
; ++i
) {
49 } else if (c
== L
'\\') {
57 // The command line will continue with a double quote, so double any
58 // preceding backslashes as required by Windows:
59 for (std::size_t i
= 0; i
< n
; ++i
) {
66 int wmain(int argc
, wchar_t ** argv
, wchar_t **) {
67 wchar_t path
[MAX_PATH
];
68 DWORD n
= GetModuleFileNameW(nullptr, path
, MAX_PATH
);
69 if (n
== 0 || n
>= MAX_PATH
) {
72 wchar_t * pathEnd
= tools::filename(path
);
74 n
= GetEnvironmentVariableW(L
"UNO_PATH", nullptr, 0);
76 if (GetLastError() != ERROR_ENVVAR_NOT_FOUND
||
77 !SetEnvironmentVariableW(L
"UNO_PATH", path
))
82 wchar_t bootstrap
[MY_LENGTH(L
"vnd.sun.star.pathname:") + MAX_PATH
] =
83 L
"vnd.sun.star.pathname:"; //TODO: overflow
84 wchar_t * bootstrapEnd
= tools::buildPath(
85 bootstrap
+ MY_LENGTH(L
"vnd.sun.star.pathname:"), path
, pathEnd
,
86 MY_STRING(L
"fundamental.ini"));
87 if (bootstrapEnd
== nullptr) {
90 wchar_t pythonpath2
[MAX_PATH
];
91 wchar_t * pythonpath2End
= tools::buildPath(
92 pythonpath2
, path
, pathEnd
,
93 MY_STRING(L
"\\python-core-" PYTHON_VERSION_STRING L
"\\lib"));
94 if (pythonpath2End
== nullptr) {
97 wchar_t pythonpath3
[MAX_PATH
];
98 wchar_t * pythonpath3End
= tools::buildPath(
99 pythonpath3
, path
, pathEnd
,
100 MY_STRING(L
"\\python-core-" PYTHON_VERSION_STRING L
"\\lib\\site-packages"));
101 if (pythonpath3End
== nullptr) {
104 wchar_t pythonhome
[MAX_PATH
];
105 wchar_t * pythonhomeEnd
= tools::buildPath(
106 pythonhome
, path
, pathEnd
, MY_STRING(L
"\\python-core-" PYTHON_VERSION_STRING
));
107 if (pythonhomeEnd
== nullptr) {
110 wchar_t pythonexe
[MAX_PATH
];
111 wchar_t * pythonexeEnd
= tools::buildPath(
112 pythonexe
, path
, pathEnd
,
113 MY_STRING(L
"\\python-core-" PYTHON_VERSION_STRING L
"\\bin\\python.exe"));
114 if (pythonexeEnd
== nullptr) {
117 std::size_t clSize
= MY_LENGTH(L
"\"") + 4 * (pythonexeEnd
- pythonexe
) +
118 MY_LENGTH(L
"\"\0"); //TODO: overflow
119 // 4 * len: each char preceded by backslash, each trailing backslash
121 for (int i
= 1; i
< argc
; ++i
) {
122 clSize
+= MY_LENGTH(L
" \"") + 4 * wcslen(argv
[i
]) + MY_LENGTH(L
"\"");
125 wchar_t * cl
= new wchar_t[clSize
];
126 wchar_t * cp
= encode(cl
, pythonhome
);
127 for (int i
= 1; i
< argc
; ++i
) {
129 cp
= encode(cp
, argv
[i
]);
132 n
= GetEnvironmentVariableW(L
"PATH", nullptr, 0);
135 if (GetLastError() != ERROR_ENVVAR_NOT_FOUND
) {
138 orig
= const_cast<wchar_t *>(L
"");
140 orig
= new wchar_t[n
];
141 if (GetEnvironmentVariableW(L
"PATH", orig
, n
) != n
- 1)
146 std::size_t len
= (pathEnd
- path
) + (n
== 0 ? 0 : MY_LENGTH(L
";") +
149 wchar_t * value
= new wchar_t[len
];
151 value
, len
, L
"%s%s%s", path
, n
== 0 ? L
"" : L
";", orig
);
152 if (!SetEnvironmentVariableW(L
"PATH", value
)) {
159 n
= GetEnvironmentVariableW(L
"PYTHONPATH", nullptr, 0);
161 if (GetLastError() != ERROR_ENVVAR_NOT_FOUND
) {
164 orig
= const_cast<wchar_t *>(L
"");
166 orig
= new wchar_t[n
];
167 if (GetEnvironmentVariableW(L
"PYTHONPATH", orig
, n
) != n
- 1)
172 len
= (pathEnd
- path
) + MY_LENGTH(L
";") + (pythonpath2End
- pythonpath2
) +
173 MY_LENGTH(L
";") + (pythonpath3End
- pythonpath3
) +
174 (n
== 0 ? 0 : MY_LENGTH(L
";") + (n
- 1)) + 1; //TODO: overflow
175 value
= new wchar_t[len
];
177 value
, len
, L
"%s;%s;%s%s%s", path
, pythonpath2
, pythonpath3
,
178 n
== 0 ? L
"" : L
";", orig
);
179 if (!SetEnvironmentVariableW(L
"PYTHONPATH", value
)) {
186 if (!SetEnvironmentVariableW(L
"PYTHONHOME", pythonhome
)) {
189 n
= GetEnvironmentVariableW(L
"URE_BOOTSTRAP", nullptr, 0);
191 if (GetLastError() != ERROR_ENVVAR_NOT_FOUND
||
192 !SetEnvironmentVariableW(L
"URE_BOOTSTRAP", bootstrap
))
197 STARTUPINFOW startinfo
;
198 ZeroMemory(&startinfo
, sizeof (STARTUPINFOW
));
199 startinfo
.cb
= sizeof (STARTUPINFOW
);
200 PROCESS_INFORMATION procinfo
;
202 pythonexe
, cl
, nullptr, nullptr, FALSE
, CREATE_UNICODE_ENVIRONMENT
, nullptr,
203 nullptr, &startinfo
, &procinfo
)) {
206 WaitForSingleObject(procinfo
.hProcess
,INFINITE
);
208 GetExitCodeProcess(procinfo
.hProcess
,&exitStatus
);
212 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */