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.
133 MakeCommandLine(int argc
, wchar_t **argv
)
138 // The + 1 of the last argument handles the allocation for null termination
139 for (i
= 0; i
< argc
&& argv
[i
]; ++i
)
140 len
+= ArgStrLen(argv
[i
]) + 1;
142 // Protect against callers that pass 0 arguments
146 wchar_t *s
= static_cast<wchar_t*>(malloc(len
* sizeof(wchar_t)));
151 for (i
= 0; i
< argc
&& argv
[i
]; ++i
)
153 c
= ArgToString(c
, argv
[i
]);
167 WinLaunchChild(const wchar_t *exePath
,
176 cl
= MakeCommandLine(argc
, argv
);
183 std::memset(&si
, 0, sizeof si
);
184 si
.cb
= sizeof(STARTUPINFOW
);
185 si
.lpDesktop
= const_cast<LPWSTR
>(L
"winsta0\\Default");
186 PROCESS_INFORMATION pi
;
187 std::memset(&pi
, 0, sizeof pi
);
189 if (userToken
== nullptr)
191 ok
= CreateProcessW(exePath
,
193 nullptr, // no special security attributes
194 nullptr, // no special thread attributes
195 FALSE
, // don't inherit filehandles
197 nullptr, // inherit my environment
198 nullptr, // use my current directory
204 // Create an environment block for the process we're about to start using
206 LPVOID environmentBlock
= nullptr;
207 if (!CreateEnvironmentBlock(&environmentBlock
, userToken
, TRUE
))
209 environmentBlock
= nullptr;
212 ok
= CreateProcessAsUserW(userToken
,
215 nullptr, // no special security attributes
216 nullptr, // no special thread attributes
217 FALSE
, // don't inherit filehandles
220 nullptr, // use my current directory
224 if (environmentBlock
)
226 DestroyEnvironmentBlock(environmentBlock
);
234 *hProcess
= pi
.hProcess
; // the caller now owns the HANDLE
238 CloseHandle(pi
.hProcess
);
240 CloseHandle(pi
.hThread
);
244 LPVOID lpMsgBuf
= nullptr;
245 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
|
246 FORMAT_MESSAGE_FROM_SYSTEM
|
247 FORMAT_MESSAGE_IGNORE_INSERTS
,
250 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
251 reinterpret_cast<LPWSTR
>(&lpMsgBuf
),
254 wprintf(L
"Error restarting: %s\n", lpMsgBuf
? lpMsgBuf
: L
"(null)");
256 HeapFree(GetProcessHeap(), 0, lpMsgBuf
);