aboutsummaryrefslogtreecommitdiff
path: root/src/burn
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/burn
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/burn')
-rw-r--r--src/burn/engine/cache.cpp65
-rw-r--r--src/burn/engine/core.cpp151
-rw-r--r--src/burn/engine/core.h7
-rw-r--r--src/burn/engine/elevation.cpp14
-rw-r--r--src/burn/engine/engine.cpp1
-rw-r--r--src/burn/engine/exeengine.cpp9
-rw-r--r--src/burn/engine/package.h1
-rw-r--r--src/burn/engine/plan.cpp2
-rw-r--r--src/burn/engine/plan.h1
9 files changed, 235 insertions, 16 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 );
17static HRESULT CalculateBaseWorkingFolder(
18 __in BURN_ENGINE_COMMAND* pInternalCommand,
19 __inout_z LPWSTR* psczBaseWorkingFolder
20 );
17static HRESULT CalculateWorkingFolder( 21static 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
1340static HRESULT CalculateWorkingFolder( 1344static 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
1388LExit:
1389 return hr;
1390}
1391
1392static 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 );
25static HRESULT AppendEscapedArgumentToCommandLine(
26 __in_z LPCWSTR wzEscapedArgument,
27 __deref_inout_z LPWSTR* psczCommandLine,
28 __deref_inout_z_opt LPWSTR* psczObfuscatedCommandLine
29 );
30static HRESULT EscapeAndAppendArgumentToCommandLineFormatted(
31 __deref_inout_z LPWSTR* psczCommandLine,
32 __deref_inout_z_opt LPWSTR* psczObfuscatedCommandLine,
33 __in __format_string LPCWSTR wzFormat,
34 ...
35 );
36static 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 );
25static HRESULT AppendLayoutToCommandLine( 42static 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
1280extern "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
1295LExit:
1296 ReleaseStr(sczArgument);
1297
1298 return hr;
1299}
1300
1301
1259extern "C" void CoreCleanup( 1302extern "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
1874static 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
1905LExit:
1906 return hr;
1907}
1908
1909static 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
1926static 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
1941LExit:
1942 ReleaseStr(sczArgument);
1943
1944 return hr;
1945}
1946
1810static HRESULT AppendLayoutToCommandLine( 1947static 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";
14const LPCWSTR BURN_COMMANDLINE_SWITCH_PARENT = L"parent"; 14const LPCWSTR BURN_COMMANDLINE_SWITCH_PARENT = L"parent";
15const LPCWSTR BURN_COMMANDLINE_SWITCH_PARENT_NONE = L"parent:none"; 15const LPCWSTR BURN_COMMANDLINE_SWITCH_PARENT_NONE = L"parent:none";
16const LPCWSTR BURN_COMMANDLINE_SWITCH_CLEAN_ROOM = L"burn.clean.room"; 16const LPCWSTR BURN_COMMANDLINE_SWITCH_CLEAN_ROOM = L"burn.clean.room";
17const LPCWSTR BURN_COMMANDLINE_SWITCH_WORKING_DIRECTORY = L"burn.working.directory";
17const LPCWSTR BURN_COMMANDLINE_SWITCH_ELEVATED = L"burn.elevated"; 18const LPCWSTR BURN_COMMANDLINE_SWITCH_ELEVATED = L"burn.elevated";
18const LPCWSTR BURN_COMMANDLINE_SWITCH_EMBEDDED = L"burn.embedded"; 19const LPCWSTR BURN_COMMANDLINE_SWITCH_EMBEDDED = L"burn.embedded";
19const LPCWSTR BURN_COMMANDLINE_SWITCH_RUNONCE = L"burn.runonce"; 20const 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 );
259HRESULT CoreAppendEngineWorkingDirectoryToCommandLine(
260 __in_z_opt LPCWSTR wzEngineWorkingDirectory,
261 __deref_inout_z LPWSTR* psczCommandLine,
262 __deref_inout_z_opt LPWSTR* psczObfuscatedCommandLine
263 );
257void CoreCleanup( 264void 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
2527LExit: 2540LExit:
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 {