aboutsummaryrefslogtreecommitdiff
path: root/src/libs/dutil/WixToolset.DUtil/apputil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/dutil/WixToolset.DUtil/apputil.cpp')
-rw-r--r--src/libs/dutil/WixToolset.DUtil/apputil.cpp231
1 files changed, 227 insertions, 4 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/apputil.cpp b/src/libs/dutil/WixToolset.DUtil/apputil.cpp
index 589a09dd..7e0bbc7b 100644
--- a/src/libs/dutil/WixToolset.DUtil/apputil.cpp
+++ b/src/libs/dutil/WixToolset.DUtil/apputil.cpp
@@ -20,7 +20,18 @@ const DWORD PRIVATE_LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800;
20typedef BOOL(WINAPI *LPFN_SETDEFAULTDLLDIRECTORIES)(DWORD); 20typedef BOOL(WINAPI *LPFN_SETDEFAULTDLLDIRECTORIES)(DWORD);
21typedef BOOL(WINAPI *LPFN_SETDLLDIRECTORYW)(LPCWSTR); 21typedef BOOL(WINAPI *LPFN_SETDLLDIRECTORYW)(LPCWSTR);
22 22
23extern "C" void DAPI AppFreeCommandLineArgs( 23/********************************************************************
24EscapeCommandLineArgument - encodes wzArgument such that
25 ::CommandLineToArgv() will parse it back unaltered. If no escaping
26 was required, *psczEscaped is NULL.
27
28********************************************************************/
29static HRESULT EscapeCommandLineArgument(
30 __in_z LPCWSTR wzArgument,
31 __out_z LPWSTR* psczEscaped
32 );
33
34DAPI_(void) AppFreeCommandLineArgs(
24 __in LPWSTR* argv 35 __in LPWSTR* argv
25 ) 36 )
26{ 37{
@@ -34,7 +45,7 @@ AppInitialize - initializes the standard safety precautions for an
34 installation application. 45 installation application.
35 46
36********************************************************************/ 47********************************************************************/
37extern "C" void DAPI AppInitialize( 48DAPI_(void) AppInitialize(
38 __in_ecount(cSafelyLoadSystemDlls) LPCWSTR rgsczSafelyLoadSystemDlls[], 49 __in_ecount(cSafelyLoadSystemDlls) LPCWSTR rgsczSafelyLoadSystemDlls[],
39 __in DWORD cSafelyLoadSystemDlls 50 __in DWORD cSafelyLoadSystemDlls
40 ) 51 )
@@ -85,12 +96,12 @@ extern "C" void DAPI AppInitialize(
85 } 96 }
86} 97}
87 98
88extern "C" void DAPI AppInitializeUnsafe() 99DAPI_(void) AppInitializeUnsafe()
89{ 100{
90 ::HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0); 101 ::HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
91} 102}
92 103
93extern "C" DAPI_(HRESULT) AppParseCommandLine( 104DAPI_(HRESULT) AppParseCommandLine(
94 __in LPCWSTR wzCommandLine, 105 __in LPCWSTR wzCommandLine,
95 __in int* pArgc, 106 __in int* pArgc,
96 __in LPWSTR** pArgv 107 __in LPWSTR** pArgv
@@ -122,3 +133,215 @@ LExit:
122 133
123 return hr; 134 return hr;
124} 135}
136
137DAPI_(HRESULT) AppAppendCommandLineArgument(
138 __deref_inout_z LPWSTR* psczCommandLine,
139 __in_z LPCWSTR wzArgument
140 )
141{
142 HRESULT hr = S_OK;
143 LPWSTR sczQuotedArg = NULL;
144
145 hr = EscapeCommandLineArgument(wzArgument, &sczQuotedArg);
146 AppExitOnFailure(hr, "Failed to escape command line argument.");
147
148 // If there is already data in the command line,
149 // append a space before appending the argument.
150 if (*psczCommandLine && **psczCommandLine)
151 {
152 hr = StrAllocConcatSecure(psczCommandLine, L" ", 0);
153 AppExitOnFailure(hr, "Failed to append space to command line with existing data.");
154 }
155
156 hr = StrAllocConcatSecure(psczCommandLine, sczQuotedArg ? sczQuotedArg : wzArgument, 0);
157 AppExitOnFailure(hr, "Failed to copy command line argument.");
158
159LExit:
160 ReleaseStr(sczQuotedArg);
161
162 return hr;
163}
164
165DAPIV_(HRESULT) AppAppendCommandLineArgumentFormatted(
166 __deref_inout_z LPWSTR* psczCommandLine,
167 __in __format_string LPCWSTR wzFormat,
168 ...
169 )
170{
171 HRESULT hr = S_OK;
172 va_list args;
173
174 va_start(args, wzFormat);
175 hr = AppAppendCommandLineArgumentFormattedArgs(psczCommandLine, wzFormat, args);
176 va_end(args);
177
178 return hr;
179}
180
181DAPI_(HRESULT) AppAppendCommandLineArgumentFormattedArgs(
182 __deref_inout_z LPWSTR* psczCommandLine,
183 __in __format_string LPCWSTR wzFormat,
184 __in va_list args
185 )
186{
187 HRESULT hr = S_OK;
188 LPWSTR sczQuotedArg = NULL;
189
190 hr = AppEscapeCommandLineArgumentFormattedArgs(&sczQuotedArg, wzFormat, args);
191 AppExitOnFailure(hr, "Failed to escape command line argument.");
192
193 // If there is already data in the command line,
194 // append a space before appending the argument.
195 if (*psczCommandLine && **psczCommandLine)
196 {
197 hr = StrAllocConcatSecure(psczCommandLine, L" ", 0);
198 AppExitOnFailure(hr, "Failed to append space to command line with existing data.");
199 }
200
201 hr = StrAllocConcatSecure(psczCommandLine, sczQuotedArg, 0);
202 AppExitOnFailure(hr, "Failed to copy command line argument.");
203
204LExit:
205 ReleaseStr(sczQuotedArg);
206
207 return hr;
208}
209
210DAPIV_(HRESULT) AppEscapeCommandLineArgumentFormatted(
211 __deref_inout_z LPWSTR* psczEscapedArgument,
212 __in __format_string LPCWSTR wzFormat,
213 ...
214 )
215{
216 HRESULT hr = S_OK;
217 va_list args;
218
219 va_start(args, wzFormat);
220 hr = AppEscapeCommandLineArgumentFormattedArgs(psczEscapedArgument, wzFormat, args);
221 va_end(args);
222
223 return hr;
224}
225
226DAPI_(HRESULT) AppEscapeCommandLineArgumentFormattedArgs(
227 __deref_inout_z LPWSTR* psczEscapedArgument,
228 __in __format_string LPCWSTR wzFormat,
229 __in va_list args
230 )
231{
232 HRESULT hr = S_OK;
233 LPWSTR sczFormattedArg = NULL;
234 LPWSTR sczQuotedArg = NULL;
235
236 hr = StrAllocFormattedArgsSecure(&sczFormattedArg, wzFormat, args);
237 AppExitOnFailure(hr, "Failed to format command line argument.");
238
239 hr = EscapeCommandLineArgument(sczFormattedArg, &sczQuotedArg);
240 AppExitOnFailure(hr, "Failed to escape command line argument.");
241
242 if (sczQuotedArg)
243 {
244 *psczEscapedArgument = sczQuotedArg;
245 sczQuotedArg = NULL;
246 }
247 else
248 {
249 *psczEscapedArgument = sczFormattedArg;
250 sczFormattedArg = NULL;
251 }
252
253LExit:
254 ReleaseStr(sczFormattedArg);
255 ReleaseStr(sczQuotedArg);
256
257 return hr;
258}
259
260static HRESULT EscapeCommandLineArgument(
261 __in_z LPCWSTR wzArgument,
262 __out_z LPWSTR* psczEscaped
263 )
264{
265 HRESULT hr = S_OK;
266 BOOL fRequiresQuoting = FALSE;
267 SIZE_T cMaxEscapedSize = 0;
268
269 *psczEscaped = NULL;
270
271 // Loop through the argument determining if it needs to be quoted and what the maximum
272 // size would be if there are escape characters required.
273 for (LPCWSTR pwz = wzArgument; *pwz; ++pwz)
274 {
275 // Arguments with whitespace need quoting.
276 if (L' ' == *pwz || L'\t' == *pwz || L'\n' == *pwz || L'\v' == *pwz)
277 {
278 fRequiresQuoting = TRUE;
279 }
280 else if (L'"' == *pwz) // quotes need quoting and sometimes escaping.
281 {
282 fRequiresQuoting = TRUE;
283 ++cMaxEscapedSize;
284 }
285 else if (L'\\' == *pwz) // some backslashes need escaping, so we'll count them all to make sure there is room.
286 {
287 ++cMaxEscapedSize;
288 }
289
290 ++cMaxEscapedSize;
291 }
292
293 // If we found anything in the argument that requires our argument to be quoted
294 if (fRequiresQuoting)
295 {
296 hr = StrAlloc(psczEscaped, cMaxEscapedSize + 3); // plus three for the start and end quote plus null terminator.
297 AppExitOnFailure(hr, "Failed to allocate argument to be quoted.");
298
299 LPCWSTR pwz = wzArgument;
300 LPWSTR pwzQuoted = *psczEscaped;
301
302 *pwzQuoted = L'"';
303 ++pwzQuoted;
304 while (*pwz)
305 {
306 DWORD dwBackslashes = 0;
307 while (L'\\' == *pwz)
308 {
309 ++dwBackslashes;
310 ++pwz;
311 }
312
313 // Escape all backslashes at the end of the string.
314 if (!*pwz)
315 {
316 dwBackslashes *= 2;
317 }
318 else if (L'"' == *pwz) // escape all backslashes before the quote and escape the quote itself.
319 {
320 dwBackslashes = dwBackslashes * 2 + 1;
321 }
322 // the backslashes don't have to be escaped.
323
324 // Add the appropriate number of backslashes
325 for (DWORD i = 0; i < dwBackslashes; ++i)
326 {
327 *pwzQuoted = L'\\';
328 ++pwzQuoted;
329 }
330
331 // If there is a character, add it after all the escaped backslashes
332 if (*pwz)
333 {
334 *pwzQuoted = *pwz;
335 ++pwz;
336 ++pwzQuoted;
337 }
338 }
339
340 *pwzQuoted = L'"';
341 ++pwzQuoted;
342 *pwzQuoted = L'\0'; // ensure the arg is null terminated.
343 }
344
345LExit:
346 return hr;
347}