Skip to content

Commit 5916e76

Browse files
committed
Properly handle launching script executable (not DLL)
1 parent e621dd4 commit 5916e76

File tree

4 files changed

+49
-41
lines changed

4 files changed

+49
-41
lines changed

src/pymanager/_launch.cpp

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -34,49 +34,48 @@ dup_handle(HANDLE input, HANDLE *output)
3434

3535

3636
int
37-
launch(const wchar_t *executable, const wchar_t *insert_args, int skip_argc, DWORD *exitCode)
38-
{
37+
launch(
38+
const wchar_t *executable,
39+
const wchar_t *origCmdLine,
40+
const wchar_t *insert_args,
41+
int skip_argc,
42+
DWORD *exitCode
43+
) {
3944
HANDLE job;
4045
JOBOBJECT_EXTENDED_LIMIT_INFORMATION info;
4146
DWORD info_len;
4247
STARTUPINFOW si;
4348
PROCESS_INFORMATION pi;
4449
int lastError = 0;
45-
const wchar_t *arg_space = L" ";
46-
LPCWSTR origCmdLine = GetCommandLineW();
4750
const wchar_t *cmdLine = NULL;
4851

49-
if (insert_args == NULL) {
50-
insert_args = L"";
52+
if (origCmdLine[0] == L'"') {
53+
cmdLine = wcschr(origCmdLine + 1, L'"');
54+
} else {
55+
cmdLine = wcschr(origCmdLine, L' ');
5156
}
5257

53-
size_t n = wcslen(executable) + wcslen(origCmdLine) + wcslen(insert_args) + 5;
58+
size_t n = wcslen(executable) + wcslen(origCmdLine) + wcslen(insert_args) + 6;
5459
wchar_t *newCmdLine = (wchar_t *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, n * sizeof(wchar_t));
5560
if (!newCmdLine) {
5661
lastError = GetLastError();
5762
goto exit;
5863
}
5964

60-
if (origCmdLine[0] == L'"') {
61-
cmdLine = wcschr(origCmdLine + 1, L'"');
62-
} else {
63-
cmdLine = wcschr(origCmdLine, L' ');
64-
}
65-
65+
// Skip any requested args, deliberately leaving any trailing spaces
66+
// (we'll skip one later one and add our own space, and preserve multiple)
6667
while (skip_argc-- > 0) {
6768
wchar_t c;
6869
while (*++cmdLine && *cmdLine == L' ') { }
6970
while (*++cmdLine && *cmdLine != L' ') { }
7071
}
7172

72-
if (!insert_args || !*insert_args) {
73-
arg_space = L"";
74-
}
75-
if (cmdLine && *cmdLine) {
76-
swprintf_s(newCmdLine, n + 1, L"\"%s\"%s%s %s", executable, arg_space, insert_args, cmdLine + 1);
77-
} else {
78-
swprintf_s(newCmdLine, n + 1, L"\"%s\"%s%s", executable, arg_space, insert_args);
79-
}
73+
swprintf_s(newCmdLine, n, L"\"%s\"%s%s%s%s",
74+
executable,
75+
(insert_args && *insert_args) ? L" ": L"",
76+
(insert_args && *insert_args) ? insert_args : L"",
77+
(cmdLine && *cmdLine) ? L" " : L"",
78+
(cmdLine && *cmdLine) ? cmdLine + 1 : L"");
8079

8180
#if defined(_WINDOWS)
8281
/*

src/pymanager/_launch.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,7 @@
1-
int launch(const wchar_t *executable, const wchar_t *insert_args, int skip_argc, DWORD *exitCode);
1+
int launch(
2+
const wchar_t *executable,
3+
const wchar_t *origCmdLine,
4+
const wchar_t *insert_args,
5+
int skip_argc,
6+
DWORD *exitCode
7+
);

src/pymanager/launcher.cpp

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ get_executable(wchar_t *executable, unsigned int bufferSize)
143143

144144

145145
int
146-
insert_script(int *argc, wchar_t ***argv)
146+
get_script(wchar_t **result_path)
147147
{
148148
HANDLE ph = GetProcessHeap();
149149
wchar_t *path = NULL;
@@ -194,22 +194,9 @@ insert_script(int *argc, wchar_t ***argv)
194194
}
195195
FindClose(fh);
196196

197-
// Create a new argv that will be used to launch the script.
198-
wchar_t **argv2 = (wchar_t **)HeapAlloc(ph, HEAP_ZERO_MEMORY, sizeof(wchar_t *) * (*argc + 1));
199-
if (!argv2) {
200-
HeapFree(ph, 0, path);
201-
return HRESULT_FROM_WIN32(GetLastError());
202-
}
203-
204197
// Deliberately letting our memory leak - it'll be cleaned up when the
205198
// process ends, and this is not a loop.
206-
argv2[0] = (*argv)[0];
207-
argv2[1] = path;
208-
for (int i = 1; i < (*argc); ++i) {
209-
argv2[i + 1] = (*argv)[i];
210-
}
211-
*argv = argv2;
212-
*argc += 1;
199+
*result_path = path;
213200
return 0;
214201
}
215202

@@ -280,21 +267,36 @@ wmain(int argc, wchar_t **argv)
280267
{
281268
int exit_code;
282269
wchar_t executable[MAXLEN];
270+
wchar_t *script;
283271

284272
int err = get_executable(executable, MAXLEN);
285273
if (err) {
286274
return print_error(err, L"Failed to get target path");
287275
}
288276

289-
err = insert_script(&argc, &argv);
277+
err = get_script(&script);
290278
if (err) {
291-
return print_error(err, L"Failed to insert script path");
279+
return print_error(err, L"Failed to get script path");
292280
}
293281

294282
void *main_func = NULL;
295283
err = try_load_python3_dll(executable, MAXLEN, (void **)&main_func);
296284
switch (err) {
297285
case 0:
286+
if (script) {
287+
wchar_t **argv2 = (wchar_t **)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
288+
(argc + 1) * sizeof(wchar_t *));
289+
if (!argv2) {
290+
return HRESULT_FROM_WIN32(GetLastError());
291+
}
292+
argv2[0] = argv[0];
293+
argv2[1] = script;
294+
for (int i = 1; i < argc; ++i) {
295+
argv2[i + 1] = argv[i];
296+
}
297+
argv = argv2;
298+
argc += 1;
299+
}
298300
err = launch_by_dll(main_func, executable, argc, argv, &exit_code);
299301
if (!err) {
300302
return exit_code;
@@ -324,7 +326,8 @@ wmain(int argc, wchar_t **argv)
324326
break;
325327
}
326328

327-
err = launch(executable, NULL, 0, (DWORD *)&exit_code);
329+
err = launch(executable, GetCommandLineW(), script, 0, (DWORD *)&exit_code);
330+
328331
if (!err) {
329332
return exit_code;
330333
}

src/pymanager/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,7 @@ wmain(int argc, wchar_t **argv)
630630
}
631631
#endif
632632

633-
err = launch(executable.c_str(), args.c_str(), skip_argc, &exitCode);
633+
err = launch(executable.c_str(), GetCommandLineW(), args.c_str(), skip_argc, &exitCode);
634634

635635
// TODO: Consider sharing print_error() with launcher.cpp
636636
// This will ensure error messages are aligned whether we're launching

0 commit comments

Comments
 (0)