diff options
author | Sean Hall <r.sean.hall@gmail.com> | 2021-08-03 18:06:54 -0500 |
---|---|---|
committer | Sean Hall <r.sean.hall@gmail.com> | 2021-08-04 10:03:57 -0500 |
commit | cdba28de1ee229369b254c62bc58cf2f001899a3 (patch) | |
tree | 4ae9a7aafd83ff311c5440df2c6d4a8693f8f23b /src | |
parent | 75d645c6aec0df0e02bd3aaf2fe2571d83316d4c (diff) | |
download | wix-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')
-rw-r--r-- | src/burn/engine/cache.cpp | 65 | ||||
-rw-r--r-- | src/burn/engine/core.cpp | 151 | ||||
-rw-r--r-- | src/burn/engine/core.h | 7 | ||||
-rw-r--r-- | src/burn/engine/elevation.cpp | 14 | ||||
-rw-r--r-- | src/burn/engine/engine.cpp | 1 | ||||
-rw-r--r-- | src/burn/engine/exeengine.cpp | 9 | ||||
-rw-r--r-- | src/burn/engine/package.h | 1 | ||||
-rw-r--r-- | src/burn/engine/plan.cpp | 2 | ||||
-rw-r--r-- | src/burn/engine/plan.h | 1 | ||||
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/apputil.cpp | 231 | ||||
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/inc/apputil.h | 41 | ||||
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/inc/pathutil.h | 10 | ||||
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/pathutil.cpp | 102 | ||||
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/precomp.h | 1 |
14 files changed, 503 insertions, 133 deletions
diff --git a/src/burn/engine/cache.cpp b/src/burn/engine/cache.cpp index 54328091..0c5266a0 100644 --- a/src/burn/engine/cache.cpp +++ b/src/burn/engine/cache.cpp | |||
@@ -14,6 +14,10 @@ static HRESULT CacheVerifyPayloadSignature( | |||
14 | __in_z LPCWSTR wzUnverifiedPayloadPath, | 14 | __in_z LPCWSTR wzUnverifiedPayloadPath, |
15 | __in HANDLE hFile | 15 | __in HANDLE hFile |
16 | ); | 16 | ); |
17 | static HRESULT CalculateBaseWorkingFolder( | ||
18 | __in BURN_ENGINE_COMMAND* pInternalCommand, | ||
19 | __inout_z LPWSTR* psczBaseWorkingFolder | ||
20 | ); | ||
17 | static HRESULT CalculateWorkingFolder( | 21 | static HRESULT CalculateWorkingFolder( |
18 | __in BURN_CACHE* pCache, | 22 | __in BURN_CACHE* pCache, |
19 | __in BURN_ENGINE_COMMAND* pInternalCommand | 23 | __in BURN_ENGINE_COMMAND* pInternalCommand |
@@ -1337,28 +1341,71 @@ extern "C" void CacheUninitialize( | |||
1337 | 1341 | ||
1338 | // Internal functions. | 1342 | // Internal functions. |
1339 | 1343 | ||
1340 | static HRESULT CalculateWorkingFolder( | 1344 | static HRESULT CalculateBaseWorkingFolder( |
1341 | __in BURN_CACHE* pCache, | 1345 | __in BURN_ENGINE_COMMAND* pInternalCommand, |
1342 | __in BURN_ENGINE_COMMAND* pInternalCommand | 1346 | __inout_z LPWSTR* psczBaseWorkingFolder |
1343 | ) | 1347 | ) |
1344 | { | 1348 | { |
1345 | HRESULT hr = S_OK; | 1349 | HRESULT hr = S_OK; |
1346 | RPC_STATUS rs = RPC_S_OK; | ||
1347 | LPWSTR sczTempPath = NULL; | ||
1348 | UUID guid = {}; | ||
1349 | WCHAR wzGuid[39]; | ||
1350 | 1350 | ||
1351 | ReleaseNullStr(*psczBaseWorkingFolder); | ||
1352 | |||
1353 | // The value from the command line takes precedence. | ||
1354 | if (pInternalCommand->sczWorkingDirectory) | ||
1355 | { | ||
1356 | hr = PathExpand(psczBaseWorkingFolder, pInternalCommand->sczWorkingDirectory, PATH_EXPAND_FULLPATH); | ||
1357 | ExitOnFailure(hr, "Failed to expand engine working directory from command-line: '%ls'", pInternalCommand->sczWorkingDirectory); | ||
1358 | |||
1359 | ExitFunction(); | ||
1360 | } | ||
1361 | |||
1362 | // The base working folder can be specified through policy, | ||
1363 | // but only use it if elevated because it should be secured against non-admin users. | ||
1351 | if (pInternalCommand->fInitiallyElevated) | 1364 | if (pInternalCommand->fInitiallyElevated) |
1352 | { | 1365 | { |
1353 | hr = PathGetSystemTempPath(&sczTempPath); | 1366 | hr = PolcReadString(POLICY_BURN_REGISTRY_PATH, L"EngineWorkingDirectory", NULL, psczBaseWorkingFolder); |
1367 | ExitOnFailure(hr, "Failed to read EngineWorkingDirectory policy directory."); | ||
1368 | |||
1369 | if (*psczBaseWorkingFolder) | ||
1370 | { | ||
1371 | // PolcReadString is supposed to automatically expand REG_EXPAND_SZ values. | ||
1372 | ExitFunction(); | ||
1373 | } | ||
1374 | } | ||
1375 | |||
1376 | // Default to the temp path specified in environment variables, but need to use system temp path for security reasons if running elevated. | ||
1377 | if (pInternalCommand->fInitiallyElevated) | ||
1378 | { | ||
1379 | hr = PathGetSystemTempPath(psczBaseWorkingFolder); | ||
1354 | ExitOnFailure(hr, "Failed to get system temp folder path for working folder."); | 1380 | ExitOnFailure(hr, "Failed to get system temp folder path for working folder."); |
1355 | } | 1381 | } |
1356 | else | 1382 | else |
1357 | { | 1383 | { |
1358 | hr = PathGetTempPath(&sczTempPath); | 1384 | hr = PathGetTempPath(psczBaseWorkingFolder); |
1359 | ExitOnFailure(hr, "Failed to get temp folder path for working folder."); | 1385 | ExitOnFailure(hr, "Failed to get temp folder path for working folder."); |
1360 | } | 1386 | } |
1361 | 1387 | ||
1388 | LExit: | ||
1389 | return hr; | ||
1390 | } | ||
1391 | |||
1392 | static HRESULT CalculateWorkingFolder( | ||
1393 | __in BURN_CACHE* pCache, | ||
1394 | __in BURN_ENGINE_COMMAND* pInternalCommand | ||
1395 | ) | ||
1396 | { | ||
1397 | HRESULT hr = S_OK; | ||
1398 | RPC_STATUS rs = RPC_S_OK; | ||
1399 | LPWSTR sczTempPath = NULL; | ||
1400 | UUID guid = {}; | ||
1401 | WCHAR wzGuid[39]; | ||
1402 | |||
1403 | hr = CalculateBaseWorkingFolder(pInternalCommand, &sczTempPath); | ||
1404 | ExitOnFailure(hr, "Failed to get base engine working directory."); | ||
1405 | |||
1406 | hr = PathBackslashTerminate(&sczTempPath); | ||
1407 | ExitOnFailure(hr, "Failed to backslashify base engine working directory."); | ||
1408 | |||
1362 | rs = ::UuidCreate(&guid); | 1409 | rs = ::UuidCreate(&guid); |
1363 | hr = HRESULT_FROM_RPC(rs); | 1410 | hr = HRESULT_FROM_RPC(rs); |
1364 | ExitOnFailure(hr, "Failed to create working folder guid."); | 1411 | ExitOnFailure(hr, "Failed to create working folder guid."); |
diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp index 3e45cdfc..e8c51187 100644 --- a/src/burn/engine/core.cpp +++ b/src/burn/engine/core.cpp | |||
@@ -22,6 +22,23 @@ static HRESULT CoreRecreateCommandLine( | |||
22 | __in BOOTSTRAPPER_RELATION_TYPE relationType, | 22 | __in BOOTSTRAPPER_RELATION_TYPE relationType, |
23 | __in BOOL fPassthrough | 23 | __in BOOL fPassthrough |
24 | ); | 24 | ); |
25 | static HRESULT AppendEscapedArgumentToCommandLine( | ||
26 | __in_z LPCWSTR wzEscapedArgument, | ||
27 | __deref_inout_z LPWSTR* psczCommandLine, | ||
28 | __deref_inout_z_opt LPWSTR* psczObfuscatedCommandLine | ||
29 | ); | ||
30 | static HRESULT EscapeAndAppendArgumentToCommandLineFormatted( | ||
31 | __deref_inout_z LPWSTR* psczCommandLine, | ||
32 | __deref_inout_z_opt LPWSTR* psczObfuscatedCommandLine, | ||
33 | __in __format_string LPCWSTR wzFormat, | ||
34 | ... | ||
35 | ); | ||
36 | static HRESULT EscapeAndAppendArgumentToCommandLineFormattedArgs( | ||
37 | __deref_inout_z LPWSTR* psczCommandLine, | ||
38 | __deref_inout_z_opt LPWSTR* psczObfuscatedCommandLine, | ||
39 | __in __format_string LPCWSTR wzFormat, | ||
40 | __in va_list args | ||
41 | ); | ||
25 | static HRESULT AppendLayoutToCommandLine( | 42 | static HRESULT AppendLayoutToCommandLine( |
26 | __in BOOTSTRAPPER_ACTION action, | 43 | __in BOOTSTRAPPER_ACTION action, |
27 | __in_z LPCWSTR wzLayoutDirectory, | 44 | __in_z LPCWSTR wzLayoutDirectory, |
@@ -207,11 +224,12 @@ extern "C" HRESULT CoreInitializeConstants( | |||
207 | for (DWORD i = 0; i < pEngineState->packages.cPackages; ++i) | 224 | for (DWORD i = 0; i < pEngineState->packages.cPackages; ++i) |
208 | { | 225 | { |
209 | BURN_PACKAGE* pPackage = pEngineState->packages.rgPackages + i; | 226 | BURN_PACKAGE* pPackage = pEngineState->packages.rgPackages + i; |
210 | 227 | ||
211 | if (BURN_PACKAGE_TYPE_EXE == pPackage->type && BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol) // TODO: Don't assume exePackages with burn protocol are bundles. | 228 | if (BURN_PACKAGE_TYPE_EXE == pPackage->type && BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol) // TODO: Don't assume exePackages with burn protocol are bundles. |
212 | { | 229 | { |
213 | // Pass along any ancestors and ourself to prevent infinite loops. | 230 | // Pass along any ancestors and ourself to prevent infinite loops. |
214 | pPackage->Exe.wzAncestors = pRegistration->sczBundlePackageAncestors; | 231 | pPackage->Exe.wzAncestors = pRegistration->sczBundlePackageAncestors; |
232 | pPackage->Exe.wzEngineWorkingDirectory = pInternalCommand->sczWorkingDirectory; | ||
215 | } | 233 | } |
216 | } | 234 | } |
217 | 235 | ||
@@ -1001,6 +1019,9 @@ static HRESULT CoreRecreateCommandLine( | |||
1001 | ExitOnFailure(hr, "Failed to append ancestors to command-line."); | 1019 | ExitOnFailure(hr, "Failed to append ancestors to command-line."); |
1002 | } | 1020 | } |
1003 | 1021 | ||
1022 | hr = CoreAppendEngineWorkingDirectoryToCommandLine(pInternalCommand->sczWorkingDirectory, psczCommandLine, NULL); | ||
1023 | ExitOnFailure(hr, "Failed to append the custom working directory to command-line."); | ||
1024 | |||
1004 | if (wzRelationTypeCommandLine) | 1025 | if (wzRelationTypeCommandLine) |
1005 | { | 1026 | { |
1006 | hr = StrAllocConcatFormatted(psczCommandLine, L" /%ls", wzRelationTypeCommandLine); | 1027 | hr = StrAllocConcatFormatted(psczCommandLine, L" /%ls", wzRelationTypeCommandLine); |
@@ -1060,7 +1081,7 @@ extern "C" HRESULT CoreCreateCleanRoomCommandLine( | |||
1060 | hr = StrAllocConcatFormatted(psczCommandLine, L" /%ls", wzLogParameter); | 1081 | hr = StrAllocConcatFormatted(psczCommandLine, L" /%ls", wzLogParameter); |
1061 | ExitOnFailure(hr, "Failed to append logging switch."); | 1082 | ExitOnFailure(hr, "Failed to append logging switch."); |
1062 | 1083 | ||
1063 | hr = PathCommandLineAppend(psczCommandLine, pInternalCommand->sczLogFile); | 1084 | hr = AppAppendCommandLineArgument(psczCommandLine, pInternalCommand->sczLogFile); |
1064 | ExitOnFailure(hr, "Failed to append custom log path."); | 1085 | ExitOnFailure(hr, "Failed to append custom log path."); |
1065 | } | 1086 | } |
1066 | 1087 | ||
@@ -1091,7 +1112,7 @@ extern "C" HRESULT CoreCreateCleanRoomCommandLine( | |||
1091 | hr = StrAllocConcat(psczCommandLine, L" /originalsource", 0); | 1112 | hr = StrAllocConcat(psczCommandLine, L" /originalsource", 0); |
1092 | ExitOnFailure(hr, "Failed to append /originalsource."); | 1113 | ExitOnFailure(hr, "Failed to append /originalsource."); |
1093 | 1114 | ||
1094 | hr = PathCommandLineAppend(psczCommandLine, pInternalCommand->sczOriginalSource); | 1115 | hr = AppAppendCommandLineArgument(psczCommandLine, pInternalCommand->sczOriginalSource); |
1095 | ExitOnFailure(hr, "Failed to append original source."); | 1116 | ExitOnFailure(hr, "Failed to append original source."); |
1096 | } | 1117 | } |
1097 | 1118 | ||
@@ -1256,6 +1277,28 @@ LExit: | |||
1256 | return hr; | 1277 | return hr; |
1257 | } | 1278 | } |
1258 | 1279 | ||
1280 | extern "C" HRESULT CoreAppendEngineWorkingDirectoryToCommandLine( | ||
1281 | __in_z_opt LPCWSTR wzEngineWorkingDirectory, | ||
1282 | __deref_inout_z LPWSTR* psczCommandLine, | ||
1283 | __deref_inout_z_opt LPWSTR* psczObfuscatedCommandLine | ||
1284 | ) | ||
1285 | { | ||
1286 | HRESULT hr = S_OK; | ||
1287 | LPWSTR sczArgument = NULL; | ||
1288 | |||
1289 | if (wzEngineWorkingDirectory) | ||
1290 | { | ||
1291 | hr = EscapeAndAppendArgumentToCommandLineFormatted(psczCommandLine, psczObfuscatedCommandLine, L"-%ls=%ls", BURN_COMMANDLINE_SWITCH_WORKING_DIRECTORY, wzEngineWorkingDirectory); | ||
1292 | ExitOnFailure(hr, "Failed to append the custom working directory to the command line."); | ||
1293 | } | ||
1294 | |||
1295 | LExit: | ||
1296 | ReleaseStr(sczArgument); | ||
1297 | |||
1298 | return hr; | ||
1299 | } | ||
1300 | |||
1301 | |||
1259 | extern "C" void CoreCleanup( | 1302 | extern "C" void CoreCleanup( |
1260 | __in BURN_ENGINE_STATE* pEngineState | 1303 | __in BURN_ENGINE_STATE* pEngineState |
1261 | ) | 1304 | ) |
@@ -1678,6 +1721,27 @@ extern "C" HRESULT CoreParseCommandLine( | |||
1678 | ExitOnFailure(hr, "Failed to allocate the list of ancestors."); | 1721 | ExitOnFailure(hr, "Failed to allocate the list of ancestors."); |
1679 | } | 1722 | } |
1680 | } | 1723 | } |
1724 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], lstrlenW(BURN_COMMANDLINE_SWITCH_WORKING_DIRECTORY), BURN_COMMANDLINE_SWITCH_WORKING_DIRECTORY, lstrlenW(BURN_COMMANDLINE_SWITCH_WORKING_DIRECTORY))) | ||
1725 | { | ||
1726 | // Get a pointer to the next character after the switch. | ||
1727 | LPCWSTR wzParam = &argv[i][1 + lstrlenW(BURN_COMMANDLINE_SWITCH_WORKING_DIRECTORY)]; | ||
1728 | if (L'=' != wzParam[0]) | ||
1729 | { | ||
1730 | fInvalidCommandLine = TRUE; | ||
1731 | TraceLog(E_INVALIDARG, "Invalid switch: %ls", argv[i]); | ||
1732 | } | ||
1733 | else if (L'\0' == wzParam[1]) | ||
1734 | { | ||
1735 | // Need to grab the current directory here since this is passed on to other processes. | ||
1736 | hr = DirGetCurrent(&pInternalCommand->sczWorkingDirectory); | ||
1737 | ExitOnFailure(hr, "Failed to get current directory for custom working directory."); | ||
1738 | } | ||
1739 | else | ||
1740 | { | ||
1741 | hr = StrAllocString(&pInternalCommand->sczWorkingDirectory, wzParam + 1, 0); | ||
1742 | ExitOnFailure(hr, "Failed to allocate the custom working directory."); | ||
1743 | } | ||
1744 | } | ||
1681 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], lstrlenW(BURN_COMMANDLINE_SWITCH_FILEHANDLE_ATTACHED), BURN_COMMANDLINE_SWITCH_FILEHANDLE_ATTACHED, lstrlenW(BURN_COMMANDLINE_SWITCH_FILEHANDLE_ATTACHED))) | 1745 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], lstrlenW(BURN_COMMANDLINE_SWITCH_FILEHANDLE_ATTACHED), BURN_COMMANDLINE_SWITCH_FILEHANDLE_ATTACHED, lstrlenW(BURN_COMMANDLINE_SWITCH_FILEHANDLE_ATTACHED))) |
1682 | { | 1746 | { |
1683 | LPCWSTR wzParam = &argv[i][2 + lstrlenW(BURN_COMMANDLINE_SWITCH_FILEHANDLE_ATTACHED)]; | 1747 | LPCWSTR wzParam = &argv[i][2 + lstrlenW(BURN_COMMANDLINE_SWITCH_FILEHANDLE_ATTACHED)]; |
@@ -1807,6 +1871,79 @@ LExit: | |||
1807 | 1871 | ||
1808 | // internal helper functions | 1872 | // internal helper functions |
1809 | 1873 | ||
1874 | static HRESULT AppendEscapedArgumentToCommandLine( | ||
1875 | __in_z LPCWSTR wzEscapedArgument, | ||
1876 | __deref_inout_z LPWSTR* psczCommandLine, | ||
1877 | __deref_inout_z_opt LPWSTR* psczObfuscatedCommandLine | ||
1878 | ) | ||
1879 | { | ||
1880 | HRESULT hr = S_OK; | ||
1881 | |||
1882 | // If there is already data in the command line, | ||
1883 | // append a space before appending the argument. | ||
1884 | if (*psczCommandLine && **psczCommandLine) | ||
1885 | { | ||
1886 | hr = StrAllocConcatSecure(psczCommandLine, L" ", 0); | ||
1887 | ExitOnFailure(hr, "Failed to append space to command line with existing data."); | ||
1888 | } | ||
1889 | |||
1890 | hr = StrAllocConcatSecure(psczCommandLine, wzEscapedArgument, 0); | ||
1891 | ExitOnFailure(hr, "Failed to append escaped command line argument."); | ||
1892 | |||
1893 | if (psczObfuscatedCommandLine) | ||
1894 | { | ||
1895 | if (*psczObfuscatedCommandLine && **psczObfuscatedCommandLine) | ||
1896 | { | ||
1897 | hr = StrAllocConcat(psczObfuscatedCommandLine, L" ", 0); | ||
1898 | ExitOnFailure(hr, "Failed to append space to obfuscated command line with existing data."); | ||
1899 | } | ||
1900 | |||
1901 | hr = StrAllocConcat(psczObfuscatedCommandLine, wzEscapedArgument, 0); | ||
1902 | ExitOnFailure(hr, "Failed to append escaped argument to obfuscated command line."); | ||
1903 | } | ||
1904 | |||
1905 | LExit: | ||
1906 | return hr; | ||
1907 | } | ||
1908 | |||
1909 | static HRESULT EscapeAndAppendArgumentToCommandLineFormatted( | ||
1910 | __deref_inout_z LPWSTR* psczCommandLine, | ||
1911 | __deref_inout_z_opt LPWSTR* psczObfuscatedCommandLine, | ||
1912 | __in __format_string LPCWSTR wzFormat, | ||
1913 | ... | ||
1914 | ) | ||
1915 | { | ||
1916 | HRESULT hr = S_OK; | ||
1917 | va_list args; | ||
1918 | |||
1919 | va_start(args, wzFormat); | ||
1920 | hr = EscapeAndAppendArgumentToCommandLineFormattedArgs(psczCommandLine, psczObfuscatedCommandLine, wzFormat, args); | ||
1921 | va_end(args); | ||
1922 | |||
1923 | return hr; | ||
1924 | } | ||
1925 | |||
1926 | static HRESULT EscapeAndAppendArgumentToCommandLineFormattedArgs( | ||
1927 | __deref_inout_z LPWSTR* psczCommandLine, | ||
1928 | __deref_inout_z_opt LPWSTR* psczObfuscatedCommandLine, | ||
1929 | __in __format_string LPCWSTR wzFormat, | ||
1930 | __in va_list args | ||
1931 | ) | ||
1932 | { | ||
1933 | HRESULT hr = S_OK; | ||
1934 | LPWSTR sczArgument = NULL; | ||
1935 | |||
1936 | hr = AppEscapeCommandLineArgumentFormattedArgs(&sczArgument, wzFormat, args); | ||
1937 | ExitOnFailure(hr, "Failed to escape the argument for the command line."); | ||
1938 | |||
1939 | hr = AppendEscapedArgumentToCommandLine(sczArgument, psczCommandLine, psczObfuscatedCommandLine); | ||
1940 | |||
1941 | LExit: | ||
1942 | ReleaseStr(sczArgument); | ||
1943 | |||
1944 | return hr; | ||
1945 | } | ||
1946 | |||
1810 | static HRESULT AppendLayoutToCommandLine( | 1947 | static HRESULT AppendLayoutToCommandLine( |
1811 | __in BOOTSTRAPPER_ACTION action, | 1948 | __in BOOTSTRAPPER_ACTION action, |
1812 | __in_z LPCWSTR wzLayoutDirectory, | 1949 | __in_z LPCWSTR wzLayoutDirectory, |
@@ -1822,7 +1959,7 @@ static HRESULT AppendLayoutToCommandLine( | |||
1822 | 1959 | ||
1823 | if (wzLayoutDirectory) | 1960 | if (wzLayoutDirectory) |
1824 | { | 1961 | { |
1825 | hr = PathCommandLineAppend(psczCommandLine, wzLayoutDirectory); | 1962 | hr = AppAppendCommandLineArgument(psczCommandLine, wzLayoutDirectory); |
1826 | ExitOnFailure(hr, "Failed to append layout directory."); | 1963 | ExitOnFailure(hr, "Failed to append layout directory."); |
1827 | } | 1964 | } |
1828 | } | 1965 | } |
@@ -1883,16 +2020,16 @@ static HRESULT GetSanitizedCommandLine( | |||
1883 | } | 2020 | } |
1884 | 2021 | ||
1885 | // Remember command-line switch to pass off to BA. | 2022 | // Remember command-line switch to pass off to BA. |
1886 | PathCommandLineAppend(&pCommand->wzCommandLine, argv[i]); | 2023 | AppAppendCommandLineArgument(&pCommand->wzCommandLine, argv[i]); |
1887 | } | 2024 | } |
1888 | 2025 | ||
1889 | if (fHidden) | 2026 | if (fHidden) |
1890 | { | 2027 | { |
1891 | PathCommandLineAppend(psczSanitizedCommandLine, sczSanitizedArgument); | 2028 | AppAppendCommandLineArgument(psczSanitizedCommandLine, sczSanitizedArgument); |
1892 | } | 2029 | } |
1893 | else | 2030 | else |
1894 | { | 2031 | { |
1895 | PathCommandLineAppend(psczSanitizedCommandLine, argv[i]); | 2032 | AppAppendCommandLineArgument(psczSanitizedCommandLine, argv[i]); |
1896 | } | 2033 | } |
1897 | } | 2034 | } |
1898 | 2035 | ||
diff --git a/src/burn/engine/core.h b/src/burn/engine/core.h index f3328738..5361a5c0 100644 --- a/src/burn/engine/core.h +++ b/src/burn/engine/core.h | |||
@@ -14,6 +14,7 @@ const LPCWSTR BURN_POLICY_REGISTRY_PATH = L"WiX\\Burn"; | |||
14 | const LPCWSTR BURN_COMMANDLINE_SWITCH_PARENT = L"parent"; | 14 | const LPCWSTR BURN_COMMANDLINE_SWITCH_PARENT = L"parent"; |
15 | const LPCWSTR BURN_COMMANDLINE_SWITCH_PARENT_NONE = L"parent:none"; | 15 | const LPCWSTR BURN_COMMANDLINE_SWITCH_PARENT_NONE = L"parent:none"; |
16 | const LPCWSTR BURN_COMMANDLINE_SWITCH_CLEAN_ROOM = L"burn.clean.room"; | 16 | const LPCWSTR BURN_COMMANDLINE_SWITCH_CLEAN_ROOM = L"burn.clean.room"; |
17 | const LPCWSTR BURN_COMMANDLINE_SWITCH_WORKING_DIRECTORY = L"burn.working.directory"; | ||
17 | const LPCWSTR BURN_COMMANDLINE_SWITCH_ELEVATED = L"burn.elevated"; | 18 | const LPCWSTR BURN_COMMANDLINE_SWITCH_ELEVATED = L"burn.elevated"; |
18 | const LPCWSTR BURN_COMMANDLINE_SWITCH_EMBEDDED = L"burn.embedded"; | 19 | const LPCWSTR BURN_COMMANDLINE_SWITCH_EMBEDDED = L"burn.embedded"; |
19 | const LPCWSTR BURN_COMMANDLINE_SWITCH_RUNONCE = L"burn.runonce"; | 20 | const LPCWSTR BURN_COMMANDLINE_SWITCH_RUNONCE = L"burn.runonce"; |
@@ -99,6 +100,7 @@ typedef struct _BURN_ENGINE_COMMAND | |||
99 | 100 | ||
100 | LPWSTR sczSourceProcessPath; | 101 | LPWSTR sczSourceProcessPath; |
101 | LPWSTR sczOriginalSource; | 102 | LPWSTR sczOriginalSource; |
103 | LPWSTR sczWorkingDirectory; | ||
102 | 104 | ||
103 | DWORD dwLoggingAttributes; | 105 | DWORD dwLoggingAttributes; |
104 | LPWSTR sczLogFile; | 106 | LPWSTR sczLogFile; |
@@ -254,6 +256,11 @@ HRESULT CoreAppendSplashScreenWindowToCommandLine( | |||
254 | __in_opt HWND hwndSplashScreen, | 256 | __in_opt HWND hwndSplashScreen, |
255 | __deref_inout_z LPWSTR* psczCommandLine | 257 | __deref_inout_z LPWSTR* psczCommandLine |
256 | ); | 258 | ); |
259 | HRESULT CoreAppendEngineWorkingDirectoryToCommandLine( | ||
260 | __in_z_opt LPCWSTR wzEngineWorkingDirectory, | ||
261 | __deref_inout_z LPWSTR* psczCommandLine, | ||
262 | __deref_inout_z_opt LPWSTR* psczObfuscatedCommandLine | ||
263 | ); | ||
257 | void CoreCleanup( | 264 | void CoreCleanup( |
258 | __in BURN_ENGINE_STATE* pEngineState | 265 | __in BURN_ENGINE_STATE* pEngineState |
259 | ); | 266 | ); |
diff --git a/src/burn/engine/elevation.cpp b/src/burn/engine/elevation.cpp index c229fa58..0e1cf0b7 100644 --- a/src/burn/engine/elevation.cpp +++ b/src/burn/engine/elevation.cpp | |||
@@ -852,6 +852,9 @@ extern "C" HRESULT ElevationExecuteExePackage( | |||
852 | hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.sczAncestors); | 852 | hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.sczAncestors); |
853 | ExitOnFailure(hr, "Failed to write the list of ancestors to the message buffer."); | 853 | ExitOnFailure(hr, "Failed to write the list of ancestors to the message buffer."); |
854 | 854 | ||
855 | hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.sczEngineWorkingDirectory); | ||
856 | ExitOnFailure(hr, "Failed to write the custom working directory to the message buffer."); | ||
857 | |||
855 | hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData); | 858 | hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData); |
856 | ExitOnFailure(hr, "Failed to write variables."); | 859 | ExitOnFailure(hr, "Failed to write variables."); |
857 | 860 | ||
@@ -2476,6 +2479,7 @@ static HRESULT OnExecuteExePackage( | |||
2476 | BURN_EXECUTE_ACTION executeAction = { }; | 2479 | BURN_EXECUTE_ACTION executeAction = { }; |
2477 | LPWSTR sczIgnoreDependencies = NULL; | 2480 | LPWSTR sczIgnoreDependencies = NULL; |
2478 | LPWSTR sczAncestors = NULL; | 2481 | LPWSTR sczAncestors = NULL; |
2482 | LPWSTR sczEngineWorkingDirectory = NULL; | ||
2479 | BOOTSTRAPPER_APPLY_RESTART exeRestart = BOOTSTRAPPER_APPLY_RESTART_NONE; | 2483 | BOOTSTRAPPER_APPLY_RESTART exeRestart = BOOTSTRAPPER_APPLY_RESTART_NONE; |
2480 | 2484 | ||
2481 | executeAction.type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE; | 2485 | executeAction.type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE; |
@@ -2496,6 +2500,9 @@ static HRESULT OnExecuteExePackage( | |||
2496 | hr = BuffReadString(pbData, cbData, &iData, &sczAncestors); | 2500 | hr = BuffReadString(pbData, cbData, &iData, &sczAncestors); |
2497 | ExitOnFailure(hr, "Failed to read the list of ancestors."); | 2501 | ExitOnFailure(hr, "Failed to read the list of ancestors."); |
2498 | 2502 | ||
2503 | hr = BuffReadString(pbData, cbData, &iData, &sczEngineWorkingDirectory); | ||
2504 | ExitOnFailure(hr, "Failed to read the custom working directory."); | ||
2505 | |||
2499 | hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData); | 2506 | hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData); |
2500 | ExitOnFailure(hr, "Failed to read variables."); | 2507 | ExitOnFailure(hr, "Failed to read variables."); |
2501 | 2508 | ||
@@ -2520,11 +2527,18 @@ static HRESULT OnExecuteExePackage( | |||
2520 | ExitOnFailure(hr, "Failed to allocate the list of ancestors."); | 2527 | ExitOnFailure(hr, "Failed to allocate the list of ancestors."); |
2521 | } | 2528 | } |
2522 | 2529 | ||
2530 | if (sczEngineWorkingDirectory && *sczEngineWorkingDirectory) | ||
2531 | { | ||
2532 | hr = StrAllocString(&executeAction.exePackage.sczEngineWorkingDirectory, sczEngineWorkingDirectory, 0); | ||
2533 | ExitOnFailure(hr, "Failed to allocate the custom working directory."); | ||
2534 | } | ||
2535 | |||
2523 | // Execute EXE package. | 2536 | // Execute EXE package. |
2524 | hr = ExeEngineExecutePackage(&executeAction, pCache, pVariables, static_cast<BOOL>(dwRollback), GenericExecuteMessageHandler, hPipe, &exeRestart); | 2537 | hr = ExeEngineExecutePackage(&executeAction, pCache, pVariables, static_cast<BOOL>(dwRollback), GenericExecuteMessageHandler, hPipe, &exeRestart); |
2525 | ExitOnFailure(hr, "Failed to execute EXE package."); | 2538 | ExitOnFailure(hr, "Failed to execute EXE package."); |
2526 | 2539 | ||
2527 | LExit: | 2540 | LExit: |
2541 | ReleaseStr(sczEngineWorkingDirectory); | ||
2528 | ReleaseStr(sczAncestors); | 2542 | ReleaseStr(sczAncestors); |
2529 | ReleaseStr(sczIgnoreDependencies); | 2543 | ReleaseStr(sczIgnoreDependencies); |
2530 | ReleaseStr(sczPackage); | 2544 | ReleaseStr(sczPackage); |
diff --git a/src/burn/engine/engine.cpp b/src/burn/engine/engine.cpp index 0ce2de6d..d5dc0545 100644 --- a/src/burn/engine/engine.cpp +++ b/src/burn/engine/engine.cpp | |||
@@ -401,6 +401,7 @@ static void UninitializeEngineState( | |||
401 | ReleaseStr(pEngineState->internalCommand.sczLogFile); | 401 | ReleaseStr(pEngineState->internalCommand.sczLogFile); |
402 | ReleaseStr(pEngineState->internalCommand.sczOriginalSource); | 402 | ReleaseStr(pEngineState->internalCommand.sczOriginalSource); |
403 | ReleaseStr(pEngineState->internalCommand.sczSourceProcessPath); | 403 | ReleaseStr(pEngineState->internalCommand.sczSourceProcessPath); |
404 | ReleaseStr(pEngineState->internalCommand.sczWorkingDirectory); | ||
404 | 405 | ||
405 | ReleaseStr(pEngineState->log.sczExtension); | 406 | ReleaseStr(pEngineState->log.sczExtension); |
406 | ReleaseStr(pEngineState->log.sczPrefix); | 407 | ReleaseStr(pEngineState->log.sczPrefix); |
diff --git a/src/burn/engine/exeengine.cpp b/src/burn/engine/exeengine.cpp index 9eea4960..67da3bdd 100644 --- a/src/burn/engine/exeengine.cpp +++ b/src/burn/engine/exeengine.cpp | |||
@@ -308,6 +308,12 @@ extern "C" HRESULT ExeEnginePlanAddPackage( | |||
308 | ExitOnFailure(hr, "Failed to allocate the list of ancestors."); | 308 | ExitOnFailure(hr, "Failed to allocate the list of ancestors."); |
309 | } | 309 | } |
310 | 310 | ||
311 | if (pPackage->Exe.wzEngineWorkingDirectory) | ||
312 | { | ||
313 | hr = StrAllocString(&pAction->exePackage.sczEngineWorkingDirectory, pPackage->Exe.wzEngineWorkingDirectory, 0); | ||
314 | ExitOnFailure(hr, "Failed to allocate the custom working directory."); | ||
315 | } | ||
316 | |||
311 | LoggingSetPackageVariable(pPackage, NULL, FALSE, pLog, pVariables, NULL); // ignore errors. | 317 | LoggingSetPackageVariable(pPackage, NULL, FALSE, pLog, pVariables, NULL); // ignore errors. |
312 | } | 318 | } |
313 | 319 | ||
@@ -488,6 +494,9 @@ extern "C" HRESULT ExeEngineExecutePackage( | |||
488 | 494 | ||
489 | if (BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol) | 495 | if (BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol) |
490 | { | 496 | { |
497 | hr = CoreAppendEngineWorkingDirectoryToCommandLine(pExecuteAction->exePackage.sczEngineWorkingDirectory, &sczCommand, &sczCommandObfuscated); | ||
498 | ExitOnFailure(hr, "Failed to append the custom working directory to the exepackage command line."); | ||
499 | |||
491 | hr = CoreAppendFileHandleSelfToCommandLine(sczExecutablePath, &hExecutableFile, &sczCommand, &sczCommandObfuscated); | 500 | hr = CoreAppendFileHandleSelfToCommandLine(sczExecutablePath, &hExecutableFile, &sczCommand, &sczCommandObfuscated); |
492 | ExitOnFailure(hr, "Failed to append %ls", BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF); | 501 | ExitOnFailure(hr, "Failed to append %ls", BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF); |
493 | } | 502 | } |
diff --git a/src/burn/engine/package.h b/src/burn/engine/package.h index 94f27c23..f14064db 100644 --- a/src/burn/engine/package.h +++ b/src/burn/engine/package.h | |||
@@ -267,6 +267,7 @@ typedef struct _BURN_PACKAGE | |||
267 | LPWSTR sczUninstallArguments; | 267 | LPWSTR sczUninstallArguments; |
268 | LPWSTR sczIgnoreDependencies; | 268 | LPWSTR sczIgnoreDependencies; |
269 | LPCWSTR wzAncestors; // points directly into engine state. | 269 | LPCWSTR wzAncestors; // points directly into engine state. |
270 | LPCWSTR wzEngineWorkingDirectory; // points directly into engine state. | ||
270 | 271 | ||
271 | BOOL fPseudoBundle; | 272 | BOOL fPseudoBundle; |
272 | 273 | ||
diff --git a/src/burn/engine/plan.cpp b/src/burn/engine/plan.cpp index f77e8e2a..04da2a9d 100644 --- a/src/burn/engine/plan.cpp +++ b/src/burn/engine/plan.cpp | |||
@@ -266,6 +266,7 @@ extern "C" void PlanUninitializeExecuteAction( | |||
266 | case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE: | 266 | case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE: |
267 | ReleaseStr(pExecuteAction->exePackage.sczIgnoreDependencies); | 267 | ReleaseStr(pExecuteAction->exePackage.sczIgnoreDependencies); |
268 | ReleaseStr(pExecuteAction->exePackage.sczAncestors); | 268 | ReleaseStr(pExecuteAction->exePackage.sczAncestors); |
269 | ReleaseStr(pExecuteAction->exePackage.sczEngineWorkingDirectory); | ||
269 | break; | 270 | break; |
270 | 271 | ||
271 | case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE: | 272 | case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE: |
@@ -1282,6 +1283,7 @@ extern "C" HRESULT PlanRelatedBundlesBegin( | |||
1282 | 1283 | ||
1283 | // Pass along any ancestors and ourself to prevent infinite loops. | 1284 | // Pass along any ancestors and ourself to prevent infinite loops. |
1284 | pRelatedBundle->package.Exe.wzAncestors = pRegistration->sczBundlePackageAncestors; | 1285 | pRelatedBundle->package.Exe.wzAncestors = pRegistration->sczBundlePackageAncestors; |
1286 | pRelatedBundle->package.Exe.wzEngineWorkingDirectory = pPlan->pInternalCommand->sczWorkingDirectory; | ||
1285 | 1287 | ||
1286 | hr = PlanDefaultRelatedBundleRequestState(relationType, pRelatedBundle->relationType, pPlan->action, pRegistration->pVersion, pRelatedBundle->pVersion, &pRelatedBundle->package.requested); | 1288 | hr = PlanDefaultRelatedBundleRequestState(relationType, pRelatedBundle->relationType, pPlan->action, pRegistration->pVersion, pRelatedBundle->pVersion, &pRelatedBundle->package.requested); |
1287 | ExitOnFailure(hr, "Failed to get default request state for related bundle."); | 1289 | ExitOnFailure(hr, "Failed to get default request state for related bundle."); |
diff --git a/src/burn/engine/plan.h b/src/burn/engine/plan.h index 224f3806..b148c75b 100644 --- a/src/burn/engine/plan.h +++ b/src/burn/engine/plan.h | |||
@@ -164,6 +164,7 @@ typedef struct _BURN_EXECUTE_ACTION | |||
164 | BOOTSTRAPPER_ACTION_STATE action; | 164 | BOOTSTRAPPER_ACTION_STATE action; |
165 | LPWSTR sczIgnoreDependencies; | 165 | LPWSTR sczIgnoreDependencies; |
166 | LPWSTR sczAncestors; | 166 | LPWSTR sczAncestors; |
167 | LPWSTR sczEngineWorkingDirectory; | ||
167 | } exePackage; | 168 | } exePackage; |
168 | struct | 169 | struct |
169 | { | 170 | { |
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; | |||
20 | typedef BOOL(WINAPI *LPFN_SETDEFAULTDLLDIRECTORIES)(DWORD); | 20 | typedef BOOL(WINAPI *LPFN_SETDEFAULTDLLDIRECTORIES)(DWORD); |
21 | typedef BOOL(WINAPI *LPFN_SETDLLDIRECTORYW)(LPCWSTR); | 21 | typedef BOOL(WINAPI *LPFN_SETDLLDIRECTORYW)(LPCWSTR); |
22 | 22 | ||
23 | extern "C" void DAPI AppFreeCommandLineArgs( | 23 | /******************************************************************** |
24 | EscapeCommandLineArgument - encodes wzArgument such that | ||
25 | ::CommandLineToArgv() will parse it back unaltered. If no escaping | ||
26 | was required, *psczEscaped is NULL. | ||
27 | |||
28 | ********************************************************************/ | ||
29 | static HRESULT EscapeCommandLineArgument( | ||
30 | __in_z LPCWSTR wzArgument, | ||
31 | __out_z LPWSTR* psczEscaped | ||
32 | ); | ||
33 | |||
34 | DAPI_(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 | ********************************************************************/ |
37 | extern "C" void DAPI AppInitialize( | 48 | DAPI_(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 | ||
88 | extern "C" void DAPI AppInitializeUnsafe() | 99 | DAPI_(void) AppInitializeUnsafe() |
89 | { | 100 | { |
90 | ::HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0); | 101 | ::HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0); |
91 | } | 102 | } |
92 | 103 | ||
93 | extern "C" DAPI_(HRESULT) AppParseCommandLine( | 104 | DAPI_(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 | |||
137 | DAPI_(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 | |||
159 | LExit: | ||
160 | ReleaseStr(sczQuotedArg); | ||
161 | |||
162 | return hr; | ||
163 | } | ||
164 | |||
165 | DAPIV_(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 | |||
181 | DAPI_(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 | |||
204 | LExit: | ||
205 | ReleaseStr(sczQuotedArg); | ||
206 | |||
207 | return hr; | ||
208 | } | ||
209 | |||
210 | DAPIV_(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 | |||
226 | DAPI_(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 | |||
253 | LExit: | ||
254 | ReleaseStr(sczFormattedArg); | ||
255 | ReleaseStr(sczQuotedArg); | ||
256 | |||
257 | return hr; | ||
258 | } | ||
259 | |||
260 | static 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 | |||
345 | LExit: | ||
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 | ********************************************************************/ |
37 | DAPI_(HRESULT) AppParseCommandLine( | 37 | HRESULT 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 | ********************************************************************/ | ||
48 | HRESULT DAPI AppAppendCommandLineArgument( | ||
49 | __deref_inout_z LPWSTR* psczCommandLine, | ||
50 | __in_z LPCWSTR wzArgument | ||
51 | ); | ||
52 | |||
53 | HRESULT DAPIV AppAppendCommandLineArgumentFormatted( | ||
54 | __deref_inout_z LPWSTR* psczCommandLine, | ||
55 | __in __format_string LPCWSTR wzFormat, | ||
56 | ... | ||
57 | ); | ||
58 | |||
59 | HRESULT DAPI AppAppendCommandLineArgumentFormattedArgs( | ||
60 | __deref_inout_z LPWSTR* psczCommandLine, | ||
61 | __in __format_string LPCWSTR wzFormat, | ||
62 | __in va_list args | ||
63 | ); | ||
64 | |||
65 | /******************************************************************** | ||
66 | AppEscapeCommandLineArgumentFormatted - formats a string and then | ||
67 | escapes it such that ::CommandLineToArgv() will parse it back unaltered. | ||
68 | |||
69 | ********************************************************************/ | ||
70 | HRESULT DAPIV AppEscapeCommandLineArgumentFormatted( | ||
71 | __deref_inout_z LPWSTR* psczEscapedArgument, | ||
72 | __in __format_string LPCWSTR wzFormat, | ||
73 | ... | ||
74 | ); | ||
75 | |||
76 | HRESULT 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 | ********************************************************************/ | ||
21 | DAPI_(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 | ********************************************************************/ |
29 | DAPI_(LPWSTR) PathFile( | 19 | DAPI_(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 | ||
24 | DAPI_(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 | |||
119 | LExit: | ||
120 | ReleaseStr(sczQuotedArg); | ||
121 | |||
122 | return hr; | ||
123 | } | ||
124 | |||
125 | |||
126 | DAPI_(LPWSTR) PathFile( | 24 | DAPI_(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" |