aboutsummaryrefslogtreecommitdiff
path: root/src/libs
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2021-08-03 18:06:54 -0500
committerSean Hall <r.sean.hall@gmail.com>2021-08-04 10:03:57 -0500
commitcdba28de1ee229369b254c62bc58cf2f001899a3 (patch)
tree4ae9a7aafd83ff311c5440df2c6d4a8693f8f23b /src/libs
parent75d645c6aec0df0e02bd3aaf2fe2571d83316d4c (diff)
downloadwix-cdba28de1ee229369b254c62bc58cf2f001899a3.tar.gz
wix-cdba28de1ee229369b254c62bc58cf2f001899a3.tar.bz2
wix-cdba28de1ee229369b254c62bc58cf2f001899a3.zip
Add argument and policy setting to set Burn's base working directory.
Fixes #5856
Diffstat (limited to 'src/libs')
-rw-r--r--src/libs/dutil/WixToolset.DUtil/apputil.cpp231
-rw-r--r--src/libs/dutil/WixToolset.DUtil/inc/apputil.h41
-rw-r--r--src/libs/dutil/WixToolset.DUtil/inc/pathutil.h10
-rw-r--r--src/libs/dutil/WixToolset.DUtil/pathutil.cpp102
-rw-r--r--src/libs/dutil/WixToolset.DUtil/precomp.h1
5 files changed, 268 insertions, 117 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}
diff --git a/src/libs/dutil/WixToolset.DUtil/inc/apputil.h b/src/libs/dutil/WixToolset.DUtil/inc/apputil.h
index 1a1e14f7..11280102 100644
--- a/src/libs/dutil/WixToolset.DUtil/inc/apputil.h
+++ b/src/libs/dutil/WixToolset.DUtil/inc/apputil.h
@@ -34,12 +34,51 @@ AppParseCommandLine - parses the command line using CommandLineToArgvW.
34 by calling AppFreeCommandLineArgs. 34 by calling AppFreeCommandLineArgs.
35 35
36********************************************************************/ 36********************************************************************/
37DAPI_(HRESULT) AppParseCommandLine( 37HRESULT DAPI AppParseCommandLine(
38 __in LPCWSTR wzCommandLine, 38 __in LPCWSTR wzCommandLine,
39 __in int* argc, 39 __in int* argc,
40 __in LPWSTR** pArgv 40 __in LPWSTR** pArgv
41 ); 41 );
42 42
43/*******************************************************************
44 AppAppendCommandLineArgument - appends a command line argument on to a
45 string such that ::CommandLineToArgv() will shred them correctly
46 (i.e. quote arguments with spaces in them).
47********************************************************************/
48HRESULT DAPI AppAppendCommandLineArgument(
49 __deref_inout_z LPWSTR* psczCommandLine,
50 __in_z LPCWSTR wzArgument
51 );
52
53HRESULT DAPIV AppAppendCommandLineArgumentFormatted(
54 __deref_inout_z LPWSTR* psczCommandLine,
55 __in __format_string LPCWSTR wzFormat,
56 ...
57 );
58
59HRESULT DAPI AppAppendCommandLineArgumentFormattedArgs(
60 __deref_inout_z LPWSTR* psczCommandLine,
61 __in __format_string LPCWSTR wzFormat,
62 __in va_list args
63 );
64
65/********************************************************************
66AppEscapeCommandLineArgumentFormatted - formats a string and then
67 escapes it such that ::CommandLineToArgv() will parse it back unaltered.
68
69********************************************************************/
70HRESULT DAPIV AppEscapeCommandLineArgumentFormatted(
71 __deref_inout_z LPWSTR* psczEscapedArgument,
72 __in __format_string LPCWSTR wzFormat,
73 ...
74 );
75
76HRESULT DAPI AppEscapeCommandLineArgumentFormattedArgs(
77 __deref_inout_z LPWSTR* psczEscapedArgument,
78 __in __format_string LPCWSTR wzFormat,
79 __in va_list args
80 );
81
43#ifdef __cplusplus 82#ifdef __cplusplus
44} 83}
45#endif 84#endif
diff --git a/src/libs/dutil/WixToolset.DUtil/inc/pathutil.h b/src/libs/dutil/WixToolset.DUtil/inc/pathutil.h
index 0ae9f437..00a468ce 100644
--- a/src/libs/dutil/WixToolset.DUtil/inc/pathutil.h
+++ b/src/libs/dutil/WixToolset.DUtil/inc/pathutil.h
@@ -14,16 +14,6 @@ typedef enum PATH_EXPAND
14 14
15 15
16/******************************************************************* 16/*******************************************************************
17 PathCommandLineAppend - appends a command line argument on to a
18 string such that ::CommandLineToArgv() will shred them correctly
19 (i.e. quote arguments with spaces in them).
20********************************************************************/
21DAPI_(HRESULT) PathCommandLineAppend(
22 __deref_inout_z LPWSTR* psczCommandLine,
23 __in_z LPCWSTR wzArgument
24 );
25
26/*******************************************************************
27 PathFile - returns a pointer to the file part of the path. 17 PathFile - returns a pointer to the file part of the path.
28********************************************************************/ 18********************************************************************/
29DAPI_(LPWSTR) PathFile( 19DAPI_(LPWSTR) PathFile(
diff --git a/src/libs/dutil/WixToolset.DUtil/pathutil.cpp b/src/libs/dutil/WixToolset.DUtil/pathutil.cpp
index 5fad519b..7bac8ac3 100644
--- a/src/libs/dutil/WixToolset.DUtil/pathutil.cpp
+++ b/src/libs/dutil/WixToolset.DUtil/pathutil.cpp
@@ -21,108 +21,6 @@
21#define PATH_GOOD_ENOUGH 64 21#define PATH_GOOD_ENOUGH 64
22 22
23 23
24DAPI_(HRESULT) PathCommandLineAppend(
25 __deref_inout_z LPWSTR* psczCommandLine,
26 __in_z LPCWSTR wzArgument
27 )
28{
29 HRESULT hr = S_OK;
30 LPWSTR sczQuotedArg = NULL;
31 BOOL fRequiresQuoting = FALSE;
32 DWORD dwMaxEscapedSize = 0;
33
34 // Loop through the argument determining if it needs to be quoted and what the maximum
35 // size would be if there are escape characters required.
36 for (LPCWSTR pwz = wzArgument; *pwz; ++pwz)
37 {
38 // Arguments with whitespace need quoting.
39 if (L' ' == *pwz || L'\t' == *pwz || L'\n' == *pwz || L'\v' == *pwz)
40 {
41 fRequiresQuoting = TRUE;
42 }
43 else if (L'"' == *pwz) // quotes need quoting and sometimes escaping.
44 {
45 fRequiresQuoting = TRUE;
46 ++dwMaxEscapedSize;
47 }
48 else if (L'\\' == *pwz) // some backslashes need escaping, so we'll count them all to make sure there is room.
49 {
50 ++dwMaxEscapedSize;
51 }
52
53 ++dwMaxEscapedSize;
54 }
55
56 // If we found anything in the argument that requires our argument to be quoted
57 if (fRequiresQuoting)
58 {
59 hr = StrAlloc(&sczQuotedArg, dwMaxEscapedSize + 3); // plus three for the start and end quote plus null terminator.
60 PathExitOnFailure(hr, "Failed to allocate argument to be quoted.");
61
62 LPCWSTR pwz = wzArgument;
63 LPWSTR pwzQuoted = sczQuotedArg;
64
65 *pwzQuoted = L'"';
66 ++pwzQuoted;
67 while (*pwz)
68 {
69 DWORD dwBackslashes = 0;
70 while (L'\\' == *pwz)
71 {
72 ++dwBackslashes;
73 ++pwz;
74 }
75
76 // Escape all backslashes at the end of the string.
77 if (!*pwz)
78 {
79 dwBackslashes *= 2;
80 }
81 else if (L'"' == *pwz) // escape all backslashes before the quote and escape the quote itself.
82 {
83 dwBackslashes = dwBackslashes * 2 + 1;
84 }
85 // the backslashes don't have to be escaped.
86
87 // Add the appropriate number of backslashes
88 for (DWORD i = 0; i < dwBackslashes; ++i)
89 {
90 *pwzQuoted = L'\\';
91 ++pwzQuoted;
92 }
93
94 // If there is a character, add it after all the escaped backslashes
95 if (*pwz)
96 {
97 *pwzQuoted = *pwz;
98 ++pwz;
99 ++pwzQuoted;
100 }
101 }
102
103 *pwzQuoted = L'"';
104 ++pwzQuoted;
105 *pwzQuoted = L'\0'; // ensure the arg is null terminated.
106 }
107
108 // If there is already data in the command line, append a space before appending the
109 // argument.
110 if (*psczCommandLine && **psczCommandLine)
111 {
112 hr = StrAllocConcat(psczCommandLine, L" ", 0);
113 PathExitOnFailure(hr, "Failed to append space to command line with existing data.");
114 }
115
116 hr = StrAllocConcat(psczCommandLine, sczQuotedArg ? sczQuotedArg : wzArgument, 0);
117 PathExitOnFailure(hr, "Failed to copy command line argument.");
118
119LExit:
120 ReleaseStr(sczQuotedArg);
121
122 return hr;
123}
124
125
126DAPI_(LPWSTR) PathFile( 24DAPI_(LPWSTR) PathFile(
127 __in_z LPCWSTR wzPath 25 __in_z LPCWSTR wzPath
128 ) 26 )
diff --git a/src/libs/dutil/WixToolset.DUtil/precomp.h b/src/libs/dutil/WixToolset.DUtil/precomp.h
index f8f3b944..46d29f21 100644
--- a/src/libs/dutil/WixToolset.DUtil/precomp.h
+++ b/src/libs/dutil/WixToolset.DUtil/precomp.h
@@ -45,6 +45,7 @@
45#include "dutil.h" 45#include "dutil.h"
46#include "verutil.h" 46#include "verutil.h"
47#include "aclutil.h" 47#include "aclutil.h"
48#include "apputil.h"
48#include "atomutil.h" 49#include "atomutil.h"
49#include "buffutil.h" 50#include "buffutil.h"
50#include "butil.h" 51#include "butil.h"