docthemes: Save themes def. to a file when added to ColorSets
[LibreOffice.git] / comphelper / source / windows / windows_process.cxx
blob12c14dff1ec397b11317a6867abdc2234b1a067d
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
6 #include <windows.h>
8 #include <cstring>
9 #include <wchar.h>
11 #include <comphelper/windowsStart.hxx>
13 // Needed for CreateEnvironmentBlock
14 #include <userenv.h>
15 #pragma comment(lib, "userenv.lib")
17 /**
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
20 * be escaped.
22 static int ArgStrLen(const wchar_t *s)
24 int i = wcslen(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;
29 if (addDoubleQuotes)
31 i += 2; // initial and final doublequote
34 if (hasDoubleQuote)
36 int backslashes = 0;
37 while (*s)
39 if (*s == '\\')
41 ++backslashes;
43 else
45 if (*s == '"')
47 // Escape the doublequote and all backslashes preceding the doublequote
48 i += backslashes + 1;
51 backslashes = 0;
54 ++s;
58 return i;
61 /**
62 * Copy string "s" to string "d", quoting the argument as appropriate and
63 * escaping doublequotes along with any backslashes that immediately precede
64 * doublequotes.
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;
76 if (addDoubleQuotes)
78 *d = '"'; // initial doublequote
79 ++d;
82 if (hasDoubleQuote)
84 int backslashes = 0;
85 while (*s)
87 if (*s == '\\')
89 ++backslashes;
91 else
93 if (*s == '"')
95 // Escape the doublequote and all backslashes preceding the doublequote
96 for (int i = 0; i <= backslashes; ++i)
98 *d = '\\';
99 ++d;
103 backslashes = 0;
106 *d = *s;
107 ++d;
108 ++s;
111 else
113 wcscpy(d, s);
114 d += wcslen(s);
117 if (addDoubleQuotes)
119 *d = '"'; // final doublequote
120 ++d;
123 return d;
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)
132 int i;
133 int len = 0;
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
140 if (len == 0)
141 len = 1;
143 wchar_t *s = static_cast<wchar_t*>(malloc(len * sizeof(wchar_t)));
144 if (!s)
145 return nullptr;
147 wchar_t *c = s;
148 for (i = 0; argv[i]; ++i)
150 c = ArgToString(c, argv[i]);
151 if (argv[i + 1])
153 *c = ' ';
154 ++c;
158 *c = '\0';
160 return s;
163 BOOL
164 WinLaunchChild(const wchar_t *exePath,
165 wchar_t **argv,
166 HANDLE userToken,
167 HANDLE *hProcess)
169 wchar_t *cl;
170 bool ok;
172 cl = MakeCommandLine(argv);
173 if (!cl)
175 return FALSE;
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
188 0, // creation flags
189 nullptr, // inherit my environment
190 nullptr, // use my current directory
191 &si,
192 &pi);
194 else
196 // Create an environment block for the process we're about to start using
197 // the user's token.
198 LPVOID environmentBlock = nullptr;
199 if (!CreateEnvironmentBlock(&environmentBlock, userToken, TRUE))
201 environmentBlock = nullptr;
204 ok = CreateProcessAsUserW(userToken,
205 exePath,
207 nullptr, // no special security attributes
208 nullptr, // no special thread attributes
209 FALSE, // don't inherit filehandles
210 0, // creation flags
211 environmentBlock,
212 nullptr, // use my current directory
213 &si,
214 &pi);
216 if (environmentBlock)
218 DestroyEnvironmentBlock(environmentBlock);
222 if (ok)
224 if (hProcess)
226 *hProcess = pi.hProcess; // the caller now owns the HANDLE
228 else
230 CloseHandle(pi.hProcess);
232 CloseHandle(pi.hThread);
234 else
236 LPWSTR lpMsgBuf = nullptr;
237 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
238 FORMAT_MESSAGE_FROM_SYSTEM |
239 FORMAT_MESSAGE_IGNORE_INSERTS,
240 nullptr,
241 GetLastError(),
242 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
243 reinterpret_cast<LPWSTR>(&lpMsgBuf),
245 nullptr);
246 wprintf(L"Error restarting: %s\n", lpMsgBuf ? lpMsgBuf : L"(null)");
247 if (lpMsgBuf)
248 HeapFree(GetProcessHeap(), 0, lpMsgBuf);
251 free(cl);
253 return ok;