1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #define WIN32_LEAN_AND_MEAN
11 #include <comphelper/windowsStart.hxx>
13 // Needed for CreateEnvironmentBlock
15 #pragma comment(lib, "userenv.lib")
18 * Get the length that the string will take and takes into account the
19 * additional length if the string needs to be quoted and if characters need to
22 static int ArgStrLen(const wchar_t *s
)
25 bool hasDoubleQuote
= wcschr(s
, L
'"') != nullptr;
26 // Only add doublequotes if the string contains a space or a tab
27 bool addDoubleQuotes
= wcspbrk(s
, L
" \t") != nullptr;
31 i
+= 2; // initial and final doublequote
47 // Escape the doublequote and all backslashes preceding the doublequote
62 * Copy string "s" to string "d", quoting the argument as appropriate and
63 * escaping doublequotes along with any backslashes that immediately precede
65 * The CRT parses this to retrieve the original argc/argv that we meant,
66 * see STDARGV.C in the MSVC CRT sources.
68 * @return the end of the string
70 static wchar_t* ArgToString(wchar_t *d
, const wchar_t *s
)
72 bool hasDoubleQuote
= wcschr(s
, L
'"') != nullptr;
73 // Only add doublequotes if the string contains a space or a tab
74 bool addDoubleQuotes
= wcspbrk(s
, L
" \t") != nullptr;
78 *d
= '"'; // initial doublequote
95 // Escape the doublequote and all backslashes preceding the doublequote
96 for (int i
= 0; i
<= backslashes
; ++i
)
119 *d
= '"'; // final doublequote
127 * Creates a command line from a list of arguments. The returned
128 * string is allocated with "malloc" and should be "free"d.
130 static wchar_t* MakeCommandLine(wchar_t **argv
)
135 // The + 1 of the last argument handles the allocation for null termination
136 for (i
= 0; argv
[i
]; ++i
)
137 len
+= ArgStrLen(argv
[i
]) + 1;
139 // Protect against callers that pass 0 arguments
143 wchar_t *s
= static_cast<wchar_t*>(malloc(len
* sizeof(wchar_t)));
148 for (i
= 0; argv
[i
]; ++i
)
150 c
= ArgToString(c
, argv
[i
]);
164 WinLaunchChild(const wchar_t *exePath
,
172 cl
= MakeCommandLine(argv
);
178 STARTUPINFOW si
{ .cb
= sizeof(si
), .lpDesktop
= const_cast<LPWSTR
>(L
"winsta0\\Default") };
179 PROCESS_INFORMATION pi
{};
181 if (userToken
== nullptr)
183 ok
= CreateProcessW(exePath
,
185 nullptr, // no special security attributes
186 nullptr, // no special thread attributes
187 FALSE
, // don't inherit filehandles
189 nullptr, // inherit my environment
190 nullptr, // use my current directory
196 // Create an environment block for the process we're about to start using
198 LPVOID environmentBlock
= nullptr;
199 if (!CreateEnvironmentBlock(&environmentBlock
, userToken
, TRUE
))
201 environmentBlock
= nullptr;
204 ok
= CreateProcessAsUserW(userToken
,
207 nullptr, // no special security attributes
208 nullptr, // no special thread attributes
209 FALSE
, // don't inherit filehandles
212 nullptr, // use my current directory
216 if (environmentBlock
)
218 DestroyEnvironmentBlock(environmentBlock
);
226 *hProcess
= pi
.hProcess
; // the caller now owns the HANDLE
230 CloseHandle(pi
.hProcess
);
232 CloseHandle(pi
.hThread
);
236 LPWSTR lpMsgBuf
= nullptr;
237 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
|
238 FORMAT_MESSAGE_FROM_SYSTEM
|
239 FORMAT_MESSAGE_IGNORE_INSERTS
,
242 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
243 reinterpret_cast<LPWSTR
>(&lpMsgBuf
),
246 wprintf(L
"Error restarting: %s\n", lpMsgBuf
? lpMsgBuf
: L
"(null)");
248 HeapFree(GetProcessHeap(), 0, lpMsgBuf
);