aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/burn/engine/bundlepackageengine.cpp71
-rw-r--r--src/burn/engine/embedded.cpp18
-rw-r--r--src/burn/engine/embedded.h5
-rw-r--r--src/burn/engine/exeengine.cpp83
-rw-r--r--src/burn/engine/exeengine.h3
-rw-r--r--src/burn/engine/msuengine.cpp9
-rw-r--r--src/burn/engine/netfxchainer.cpp16
-rw-r--r--src/burn/engine/netfxchainer.h5
8 files changed, 119 insertions, 91 deletions
diff --git a/src/burn/engine/bundlepackageengine.cpp b/src/burn/engine/bundlepackageengine.cpp
index 0bee054f..89488b91 100644
--- a/src/burn/engine/bundlepackageengine.cpp
+++ b/src/burn/engine/bundlepackageengine.cpp
@@ -252,12 +252,12 @@ extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle(
252{ 252{
253 HRESULT hr = S_OK; 253 HRESULT hr = S_OK;
254 LPCWSTR wzArguments = NULL; 254 LPCWSTR wzArguments = NULL;
255 LPWSTR sczArguments = NULL;
256 LPWSTR sczArgumentsFormatted = NULL;
257 LPWSTR sczArgumentsObfuscated = NULL;
258 LPWSTR sczCachedDirectory = NULL; 255 LPWSTR sczCachedDirectory = NULL;
259 LPWSTR sczExecutablePath = NULL; 256 LPWSTR sczExecutablePath = NULL;
260 LPWSTR sczCommand = NULL; 257 LPWSTR sczBaseCommand = NULL;
258 LPWSTR sczUnformattedUserArgs = NULL;
259 LPWSTR sczUserArgs = NULL;
260 LPWSTR sczUserArgsObfuscated = NULL;
261 LPWSTR sczCommandObfuscated = NULL; 261 LPWSTR sczCommandObfuscated = NULL;
262 HANDLE hExecutableFile = INVALID_HANDLE_VALUE; 262 HANDLE hExecutableFile = INVALID_HANDLE_VALUE;
263 STARTUPINFOW si = { }; 263 STARTUPINFOW si = { };
@@ -309,7 +309,7 @@ extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle(
309 // now add optional arguments 309 // now add optional arguments
310 if (wzArguments && *wzArguments) 310 if (wzArguments && *wzArguments)
311 { 311 {
312 hr = StrAllocString(&sczArguments, wzArguments, 0); 312 hr = StrAllocString(&sczUnformattedUserArgs, wzArguments, 0);
313 ExitOnFailure(hr, "Failed to copy package arguments."); 313 ExitOnFailure(hr, "Failed to copy package arguments.");
314 } 314 }
315 315
@@ -323,26 +323,26 @@ extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle(
323 323
324 if (fCondition) 324 if (fCondition)
325 { 325 {
326 if (sczArguments) 326 if (sczUnformattedUserArgs)
327 { 327 {
328 hr = StrAllocConcat(&sczArguments, L" ", 0); 328 hr = StrAllocConcat(&sczUnformattedUserArgs, L" ", 0);
329 ExitOnFailure(hr, "Failed to separate command-line arguments."); 329 ExitOnFailure(hr, "Failed to separate command-line arguments.");
330 } 330 }
331 331
332 switch (action) 332 switch (action)
333 { 333 {
334 case BOOTSTRAPPER_ACTION_STATE_INSTALL: 334 case BOOTSTRAPPER_ACTION_STATE_INSTALL:
335 hr = StrAllocConcat(&sczArguments, commandLineArgument->sczInstallArgument, 0); 335 hr = StrAllocConcat(&sczUnformattedUserArgs, commandLineArgument->sczInstallArgument, 0);
336 ExitOnFailure(hr, "Failed to get command-line argument for install."); 336 ExitOnFailure(hr, "Failed to get command-line argument for install.");
337 break; 337 break;
338 338
339 case BOOTSTRAPPER_ACTION_STATE_UNINSTALL: 339 case BOOTSTRAPPER_ACTION_STATE_UNINSTALL:
340 hr = StrAllocConcat(&sczArguments, commandLineArgument->sczUninstallArgument, 0); 340 hr = StrAllocConcat(&sczUnformattedUserArgs, commandLineArgument->sczUninstallArgument, 0);
341 ExitOnFailure(hr, "Failed to get command-line argument for uninstall."); 341 ExitOnFailure(hr, "Failed to get command-line argument for uninstall.");
342 break; 342 break;
343 343
344 case BOOTSTRAPPER_ACTION_STATE_REPAIR: 344 case BOOTSTRAPPER_ACTION_STATE_REPAIR:
345 hr = StrAllocConcat(&sczArguments, commandLineArgument->sczRepairArgument, 0); 345 hr = StrAllocConcat(&sczUnformattedUserArgs, commandLineArgument->sczRepairArgument, 0);
346 ExitOnFailure(hr, "Failed to get command-line argument for repair."); 346 ExitOnFailure(hr, "Failed to get command-line argument for repair.");
347 break; 347 break;
348 348
@@ -353,75 +353,72 @@ extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle(
353 } 353 }
354 } 354 }
355 355
356 // build command 356 // build base command
357 AppAppendCommandLineArgument(&sczCommand, sczExecutablePath); 357 hr = StrAllocFormatted(&sczBaseCommand, L"\"%ls\"", sczExecutablePath);
358 ExitOnFailure(hr, "Failed to create executable command."); 358 ExitOnFailure(hr, "Failed to allocate base command.");
359 359
360 if (!fRunEmbedded) 360 if (!fRunEmbedded)
361 { 361 {
362 hr = StrAllocConcat(&sczCommand, L" -quiet", 0); 362 hr = StrAllocConcat(&sczBaseCommand, L" -quiet", 0);
363 ExitOnFailure(hr, "Failed to append quiet argument."); 363 ExitOnFailure(hr, "Failed to append quiet argument.");
364 } 364 }
365 365
366 if (wzOperationCommandLine) 366 if (wzOperationCommandLine)
367 { 367 {
368 hr = StrAllocConcatFormatted(&sczCommand, L" %ls", wzOperationCommandLine); 368 hr = StrAllocConcatFormatted(&sczBaseCommand, L" %ls", wzOperationCommandLine);
369 ExitOnFailure(hr, "Failed to append operation argument."); 369 ExitOnFailure(hr, "Failed to append operation argument.");
370 } 370 }
371 371
372 if (wzRelationTypeCommandLine) 372 if (wzRelationTypeCommandLine)
373 { 373 {
374 hr = StrAllocConcatFormatted(&sczCommand, L" -%ls", wzRelationTypeCommandLine); 374 hr = StrAllocConcatFormatted(&sczBaseCommand, L" -%ls", wzRelationTypeCommandLine);
375 ExitOnFailure(hr, "Failed to append relation type argument."); 375 ExitOnFailure(hr, "Failed to append relation type argument.");
376 } 376 }
377 377
378 // Add the list of dependencies to ignore, if any, to the burn command line. 378 // Add the list of dependencies to ignore, if any, to the burn command line.
379 if (pExecuteAction->relatedBundle.sczIgnoreDependencies) 379 if (pExecuteAction->relatedBundle.sczIgnoreDependencies)
380 { 380 {
381 hr = StrAllocConcatFormatted(&sczCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->relatedBundle.sczIgnoreDependencies); 381 hr = StrAllocConcatFormatted(&sczBaseCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->relatedBundle.sczIgnoreDependencies);
382 ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the command line."); 382 ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the command line.");
383 } 383 }
384 384
385 // Add the list of ancestors, if any, to the burn command line. 385 // Add the list of ancestors, if any, to the burn command line.
386 if (pExecuteAction->relatedBundle.sczAncestors) 386 if (pExecuteAction->relatedBundle.sczAncestors)
387 { 387 {
388 hr = StrAllocConcatFormatted(&sczCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_ANCESTORS, pExecuteAction->relatedBundle.sczAncestors); 388 hr = StrAllocConcatFormatted(&sczBaseCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_ANCESTORS, pExecuteAction->relatedBundle.sczAncestors);
389 ExitOnFailure(hr, "Failed to append the list of ancestors to the command line."); 389 ExitOnFailure(hr, "Failed to append the list of ancestors to the command line.");
390 } 390 }
391 391
392 hr = CoreAppendEngineWorkingDirectoryToCommandLine(pExecuteAction->relatedBundle.sczEngineWorkingDirectory, &sczCommand, NULL); 392 hr = CoreAppendEngineWorkingDirectoryToCommandLine(pExecuteAction->relatedBundle.sczEngineWorkingDirectory, &sczBaseCommand, NULL);
393 ExitOnFailure(hr, "Failed to append the custom working directory to the bundlepackage command line."); 393 ExitOnFailure(hr, "Failed to append the custom working directory to the bundlepackage command line.");
394 394
395 hr = CoreAppendFileHandleSelfToCommandLine(sczExecutablePath, &hExecutableFile, &sczCommand, NULL); 395 hr = CoreAppendFileHandleSelfToCommandLine(sczExecutablePath, &hExecutableFile, &sczBaseCommand, NULL);
396 ExitOnFailure(hr, "Failed to append %ls", BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF); 396 ExitOnFailure(hr, "Failed to append %ls", BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF);
397 397
398 // Always add user supplied arguments last. 398 // build user args
399 if (sczArguments && *sczArguments) 399 if (sczUnformattedUserArgs && *sczUnformattedUserArgs)
400 { 400 {
401 hr = VariableFormatString(pVariables, sczArguments, &sczArgumentsFormatted, NULL); 401 hr = VariableFormatString(pVariables, sczUnformattedUserArgs, &sczUserArgs, NULL);
402 ExitOnFailure(hr, "Failed to format argument string."); 402 ExitOnFailure(hr, "Failed to format argument string.");
403 403
404 hr = VariableFormatStringObfuscated(pVariables, sczArguments, &sczArgumentsObfuscated, NULL); 404 hr = VariableFormatStringObfuscated(pVariables, sczUnformattedUserArgs, &sczUserArgsObfuscated, NULL);
405 ExitOnFailure(hr, "Failed to format obfuscated argument string."); 405 ExitOnFailure(hr, "Failed to format obfuscated argument string.");
406 406
407 hr = StrAllocFormatted(&sczCommandObfuscated, L"%ls %ls", sczCommand, sczArgumentsObfuscated); 407 hr = StrAllocFormatted(&sczCommandObfuscated, L"%ls %ls", sczBaseCommand, sczUserArgsObfuscated);
408 ExitOnFailure(hr, "Failed to copy obfuscated formatted arguments."); 408 ExitOnFailure(hr, "Failed to allocate obfuscated bundle command.");
409
410 hr = StrAllocConcatFormattedSecure(&sczCommand, L" %ls", sczArgumentsFormatted);
411 ExitOnFailure(hr, "Failed to copy formatted arguments.");
412 } 409 }
413 410
414 // Log before we add the secret pipe name and client token for embedded processes. 411 // Log obfuscated command, which won't include raw hidden variable values or protocol specific arguments to avoid exposing secrets.
415 LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(action), sczExecutablePath, sczCommandObfuscated); 412 LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(action), sczExecutablePath, sczCommandObfuscated ? sczCommandObfuscated : sczBaseCommand);
416 413
417 if (fRunEmbedded) 414 if (fRunEmbedded)
418 { 415 {
419 hr = EmbeddedRunBundle(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode); 416 hr = EmbeddedRunBundle(sczExecutablePath, sczBaseCommand, sczUserArgs, pfnGenericMessageHandler, pvContext, &dwExitCode);
420 ExitOnFailure(hr, "Failed to run bundle as embedded from path: %ls", sczExecutablePath); 417 ExitOnFailure(hr, "Failed to run bundle as embedded from path: %ls", sczExecutablePath);
421 } 418 }
422 else 419 else
423 { 420 {
424 hr = ExeEngineRunProcess(pfnGenericMessageHandler, pvContext, pPackage, sczExecutablePath, sczCommand, sczCachedDirectory, &dwExitCode); 421 hr = ExeEngineRunProcess(pfnGenericMessageHandler, pvContext, pPackage, sczExecutablePath, sczBaseCommand, sczUserArgs, sczCachedDirectory, &dwExitCode);
425 ExitOnFailure(hr, "Failed to run BUNDLE process"); 422 ExitOnFailure(hr, "Failed to run BUNDLE process");
426 } 423 }
427 424
@@ -429,12 +426,12 @@ extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle(
429 ExitOnRootFailure(hr, "Process returned error: 0x%x", dwExitCode); 426 ExitOnRootFailure(hr, "Process returned error: 0x%x", dwExitCode);
430 427
431LExit: 428LExit:
432 StrSecureZeroFreeString(sczArguments);
433 StrSecureZeroFreeString(sczArgumentsFormatted);
434 ReleaseStr(sczArgumentsObfuscated);
435 ReleaseStr(sczCachedDirectory); 429 ReleaseStr(sczCachedDirectory);
436 ReleaseStr(sczExecutablePath); 430 ReleaseStr(sczExecutablePath);
437 StrSecureZeroFreeString(sczCommand); 431 ReleaseStr(sczBaseCommand);
432 ReleaseStr(sczUnformattedUserArgs);
433 StrSecureZeroFreeString(sczUserArgs);
434 ReleaseStr(sczUserArgsObfuscated);
438 ReleaseStr(sczCommandObfuscated); 435 ReleaseStr(sczCommandObfuscated);
439 436
440 ReleaseHandle(pi.hThread); 437 ReleaseHandle(pi.hThread);
diff --git a/src/burn/engine/embedded.cpp b/src/burn/engine/embedded.cpp
index 1c295d59..58af5574 100644
--- a/src/burn/engine/embedded.cpp
+++ b/src/burn/engine/embedded.cpp
@@ -36,12 +36,13 @@ static HRESULT OnEmbeddedProgress(
36// function definitions 36// function definitions
37 37
38/******************************************************************* 38/*******************************************************************
39 EmbeddedLaunchChildProcess - 39 EmbeddedRunBundle -
40 40
41*******************************************************************/ 41*******************************************************************/
42extern "C" HRESULT EmbeddedRunBundle( 42extern "C" HRESULT EmbeddedRunBundle(
43 __in LPCWSTR wzExecutablePath, 43 __in_z LPCWSTR wzExecutablePath,
44 __in LPCWSTR wzArguments, 44 __in_z LPWSTR sczBaseCommand,
45 __in_z_opt LPCWSTR wzUserArgs,
45 __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler, 46 __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
46 __in LPVOID pvContext, 47 __in LPVOID pvContext,
47 __out DWORD* pdwExitCode 48 __out DWORD* pdwExitCode
@@ -68,8 +69,15 @@ extern "C" HRESULT EmbeddedRunBundle(
68 hr = PipeCreatePipes(&connection, FALSE, &hCreatedPipesEvent); 69 hr = PipeCreatePipes(&connection, FALSE, &hCreatedPipesEvent);
69 ExitOnFailure(hr, "Failed to create embedded pipe."); 70 ExitOnFailure(hr, "Failed to create embedded pipe.");
70 71
71 hr = StrAllocFormattedSecure(&sczCommand, L"%ls -%ls %ls %ls %u", wzArguments, BURN_COMMANDLINE_SWITCH_EMBEDDED, connection.sczName, connection.sczSecret, dwCurrentProcessId); 72 hr = StrAllocFormatted(&sczCommand, L"%ls -%ls %ls %ls %u", sczBaseCommand, BURN_COMMANDLINE_SWITCH_EMBEDDED, connection.sczName, connection.sczSecret, dwCurrentProcessId);
72 ExitOnFailure(hr, "Failed to allocate embedded command."); 73 ExitOnFailure(hr, "Failed to append embedded args.");
74
75 // Always add user supplied arguments last.
76 if (wzUserArgs)
77 {
78 hr = StrAllocConcatFormattedSecure(&sczCommand, L" %ls", wzUserArgs);
79 ExitOnFailure(hr, "Failed to append user args.");
80 }
73 81
74 if (!::CreateProcessW(wzExecutablePath, sczCommand, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) 82 if (!::CreateProcessW(wzExecutablePath, sczCommand, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
75 { 83 {
diff --git a/src/burn/engine/embedded.h b/src/burn/engine/embedded.h
index 08adeae0..905b227f 100644
--- a/src/burn/engine/embedded.h
+++ b/src/burn/engine/embedded.h
@@ -15,8 +15,9 @@ typedef enum _BURN_EMBEDDED_MESSAGE_TYPE
15 15
16 16
17HRESULT EmbeddedRunBundle( 17HRESULT EmbeddedRunBundle(
18 __in LPCWSTR wzExecutablePath, 18 __in_z LPCWSTR wzExecutablePath,
19 __in LPCWSTR wzArguments, 19 __in_z LPWSTR sczBaseCommand,
20 __in_z_opt LPCWSTR wzUserArgs,
20 __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler, 21 __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
21 __in LPVOID pvContext, 22 __in LPVOID pvContext,
22 __out DWORD* pdwExitCode 23 __out DWORD* pdwExitCode
diff --git a/src/burn/engine/exeengine.cpp b/src/burn/engine/exeengine.cpp
index 9754002f..0a2084e5 100644
--- a/src/burn/engine/exeengine.cpp
+++ b/src/burn/engine/exeengine.cpp
@@ -362,12 +362,12 @@ extern "C" HRESULT ExeEngineExecutePackage(
362{ 362{
363 HRESULT hr = S_OK; 363 HRESULT hr = S_OK;
364 LPCWSTR wzArguments = NULL; 364 LPCWSTR wzArguments = NULL;
365 LPWSTR sczArguments = NULL;
366 LPWSTR sczArgumentsFormatted = NULL;
367 LPWSTR sczArgumentsObfuscated = NULL;
368 LPWSTR sczCachedDirectory = NULL; 365 LPWSTR sczCachedDirectory = NULL;
369 LPWSTR sczExecutablePath = NULL; 366 LPWSTR sczExecutablePath = NULL;
370 LPWSTR sczCommand = NULL; 367 LPWSTR sczBaseCommand = NULL;
368 LPWSTR sczUnformattedUserArgs = NULL;
369 LPWSTR sczUserArgs = NULL;
370 LPWSTR sczUserArgsObfuscated = NULL;
371 LPWSTR sczCommandObfuscated = NULL; 371 LPWSTR sczCommandObfuscated = NULL;
372 HANDLE hExecutableFile = INVALID_HANDLE_VALUE; 372 HANDLE hExecutableFile = INVALID_HANDLE_VALUE;
373 DWORD dwExitCode = 0; 373 DWORD dwExitCode = 0;
@@ -406,7 +406,7 @@ extern "C" HRESULT ExeEngineExecutePackage(
406 } 406 }
407 407
408 // now add optional arguments 408 // now add optional arguments
409 hr = StrAllocString(&sczArguments, wzArguments && *wzArguments ? wzArguments : L"", 0); 409 hr = StrAllocString(&sczUnformattedUserArgs, wzArguments && *wzArguments ? wzArguments : L"", 0);
410 ExitOnFailure(hr, "Failed to copy package arguments."); 410 ExitOnFailure(hr, "Failed to copy package arguments.");
411 411
412 for (DWORD i = 0; i < pPackage->Exe.cCommandLineArguments; ++i) 412 for (DWORD i = 0; i < pPackage->Exe.cCommandLineArguments; ++i)
@@ -419,23 +419,23 @@ extern "C" HRESULT ExeEngineExecutePackage(
419 419
420 if (fCondition) 420 if (fCondition)
421 { 421 {
422 hr = StrAllocConcat(&sczArguments, L" ", 0); 422 hr = StrAllocConcat(&sczUnformattedUserArgs, L" ", 0);
423 ExitOnFailure(hr, "Failed to separate command-line arguments."); 423 ExitOnFailure(hr, "Failed to separate command-line arguments.");
424 424
425 switch (pExecuteAction->exePackage.action) 425 switch (pExecuteAction->exePackage.action)
426 { 426 {
427 case BOOTSTRAPPER_ACTION_STATE_INSTALL: 427 case BOOTSTRAPPER_ACTION_STATE_INSTALL:
428 hr = StrAllocConcat(&sczArguments, commandLineArgument->sczInstallArgument, 0); 428 hr = StrAllocConcat(&sczUnformattedUserArgs, commandLineArgument->sczInstallArgument, 0);
429 ExitOnFailure(hr, "Failed to get command-line argument for install."); 429 ExitOnFailure(hr, "Failed to get command-line argument for install.");
430 break; 430 break;
431 431
432 case BOOTSTRAPPER_ACTION_STATE_UNINSTALL: 432 case BOOTSTRAPPER_ACTION_STATE_UNINSTALL:
433 hr = StrAllocConcat(&sczArguments, commandLineArgument->sczUninstallArgument, 0); 433 hr = StrAllocConcat(&sczUnformattedUserArgs, commandLineArgument->sczUninstallArgument, 0);
434 ExitOnFailure(hr, "Failed to get command-line argument for uninstall."); 434 ExitOnFailure(hr, "Failed to get command-line argument for uninstall.");
435 break; 435 break;
436 436
437 case BOOTSTRAPPER_ACTION_STATE_REPAIR: 437 case BOOTSTRAPPER_ACTION_STATE_REPAIR:
438 hr = StrAllocConcat(&sczArguments, commandLineArgument->sczRepairArgument, 0); 438 hr = StrAllocConcat(&sczUnformattedUserArgs, commandLineArgument->sczRepairArgument, 0);
439 ExitOnFailure(hr, "Failed to get command-line argument for repair."); 439 ExitOnFailure(hr, "Failed to get command-line argument for repair.");
440 break; 440 break;
441 441
@@ -446,71 +446,68 @@ extern "C" HRESULT ExeEngineExecutePackage(
446 } 446 }
447 } 447 }
448 448
449 // build command 449 // build base command
450 AppAppendCommandLineArgument(&sczCommand, sczExecutablePath); 450 hr = StrAllocFormatted(&sczBaseCommand, L"\"%ls\"", sczExecutablePath);
451 ExitOnFailure(hr, "Failed to create executable command."); 451 ExitOnFailure(hr, "Failed to allocate base command.");
452 452
453 if (pPackage->Exe.fBundle) 453 if (pPackage->Exe.fBundle)
454 { 454 {
455 hr = StrAllocConcat(&sczCommand, L" -norestart", 0); 455 hr = StrAllocConcat(&sczBaseCommand, L" -norestart", 0);
456 ExitOnFailure(hr, "Failed to append quiet argument."); 456 ExitOnFailure(hr, "Failed to append norestart argument.");
457 457
458 // Add the list of dependencies to ignore, if any, to the burn command line. 458 // Add the list of dependencies to ignore, if any, to the burn command line.
459 if (pExecuteAction->exePackage.sczIgnoreDependencies) 459 if (pExecuteAction->exePackage.sczIgnoreDependencies)
460 { 460 {
461 hr = StrAllocConcatFormatted(&sczCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->exePackage.sczIgnoreDependencies); 461 hr = StrAllocConcatFormatted(&sczBaseCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->exePackage.sczIgnoreDependencies);
462 ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the command line."); 462 ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the command line.");
463 } 463 }
464 464
465 // Add the list of ancestors, if any, to the burn command line. 465 // Add the list of ancestors, if any, to the burn command line.
466 if (pExecuteAction->exePackage.sczAncestors) 466 if (pExecuteAction->exePackage.sczAncestors)
467 { 467 {
468 hr = StrAllocConcatFormatted(&sczCommand, L" -%ls=%ls", sczCommand, BURN_COMMANDLINE_SWITCH_ANCESTORS, pExecuteAction->exePackage.sczAncestors); 468 hr = StrAllocConcatFormatted(&sczBaseCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_ANCESTORS, pExecuteAction->exePackage.sczAncestors);
469 ExitOnFailure(hr, "Failed to append the list of ancestors to the command line."); 469 ExitOnFailure(hr, "Failed to append the list of ancestors to the command line.");
470 } 470 }
471 471
472 if (pExecuteAction->exePackage.sczEngineWorkingDirectory) 472 if (pExecuteAction->exePackage.sczEngineWorkingDirectory)
473 { 473 {
474 hr = CoreAppendEngineWorkingDirectoryToCommandLine(pExecuteAction->exePackage.sczEngineWorkingDirectory, &sczCommand, NULL); 474 hr = CoreAppendEngineWorkingDirectoryToCommandLine(pExecuteAction->exePackage.sczEngineWorkingDirectory, &sczBaseCommand, NULL);
475 ExitOnFailure(hr, "Failed to append the custom working directory to the exepackage command line."); 475 ExitOnFailure(hr, "Failed to append the custom working directory to the exepackage command line.");
476 } 476 }
477 477
478 hr = CoreAppendFileHandleSelfToCommandLine(sczExecutablePath, &hExecutableFile, &sczCommand, NULL); 478 hr = CoreAppendFileHandleSelfToCommandLine(sczExecutablePath, &hExecutableFile, &sczBaseCommand, NULL);
479 ExitOnFailure(hr, "Failed to append %ls", BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF); 479 ExitOnFailure(hr, "Failed to append %ls", BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF);
480 } 480 }
481 481
482 // Always add user supplied arguments last. 482 // build user args
483 if (sczArguments && *sczArguments) 483 if (sczUnformattedUserArgs && *sczUnformattedUserArgs)
484 { 484 {
485 hr = VariableFormatString(pVariables, sczArguments, &sczArgumentsFormatted, NULL); 485 hr = VariableFormatString(pVariables, sczUnformattedUserArgs, &sczUserArgs, NULL);
486 ExitOnFailure(hr, "Failed to format argument string."); 486 ExitOnFailure(hr, "Failed to format argument string.");
487 487
488 hr = VariableFormatStringObfuscated(pVariables, sczArguments, &sczArgumentsObfuscated, NULL); 488 hr = VariableFormatStringObfuscated(pVariables, sczUnformattedUserArgs, &sczUserArgsObfuscated, NULL);
489 ExitOnFailure(hr, "Failed to format obfuscated argument string."); 489 ExitOnFailure(hr, "Failed to format obfuscated argument string.");
490 490
491 hr = StrAllocFormatted(&sczCommandObfuscated, L"%ls %ls", sczCommand, sczArgumentsObfuscated); 491 hr = StrAllocFormatted(&sczCommandObfuscated, L"%ls %ls", sczBaseCommand, sczUserArgsObfuscated);
492 ExitOnFailure(hr, "Failed to copy obfuscated formatted arguments."); 492 ExitOnFailure(hr, "Failed to allocate obfuscated exe command.");
493
494 hr = StrAllocConcatFormattedSecure(&sczCommand, L" %ls", sczArgumentsFormatted);
495 ExitOnFailure(hr, "Failed to copy formatted arguments.");
496 } 493 }
497 494
498 // Log before we add the secret pipe name and client token for embedded processes. 495 // Log obfuscated command, which won't include raw hidden variable values or protocol specific arguments to avoid exposing secrets.
499 LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(pExecuteAction->exePackage.action), sczExecutablePath, sczCommandObfuscated); 496 LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(pExecuteAction->exePackage.action), sczExecutablePath, sczCommandObfuscated ? sczCommandObfuscated : sczBaseCommand);
500 497
501 if (!pPackage->Exe.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol) 498 if (!pPackage->Exe.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol)
502 { 499 {
503 hr = EmbeddedRunBundle(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode); 500 hr = EmbeddedRunBundle(sczExecutablePath, sczBaseCommand, sczUserArgs, pfnGenericMessageHandler, pvContext, &dwExitCode);
504 ExitOnFailure(hr, "Failed to run exe with Burn protocol from path: %ls", sczExecutablePath); 501 ExitOnFailure(hr, "Failed to run exe with Burn protocol from path: %ls", sczExecutablePath);
505 } 502 }
506 else if (!pPackage->Exe.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_NETFX4 == pPackage->Exe.protocol) 503 else if (!pPackage->Exe.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_NETFX4 == pPackage->Exe.protocol)
507 { 504 {
508 hr = NetFxRunChainer(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode); 505 hr = NetFxRunChainer(sczExecutablePath, sczBaseCommand, sczUserArgs, pfnGenericMessageHandler, pvContext, &dwExitCode);
509 ExitOnFailure(hr, "Failed to run netfx chainer: %ls", sczExecutablePath); 506 ExitOnFailure(hr, "Failed to run netfx chainer: %ls", sczExecutablePath);
510 } 507 }
511 else 508 else
512 { 509 {
513 hr = ExeEngineRunProcess(pfnGenericMessageHandler, pvContext, pPackage, sczExecutablePath, sczCommand, sczCachedDirectory, &dwExitCode); 510 hr = ExeEngineRunProcess(pfnGenericMessageHandler, pvContext, pPackage, sczExecutablePath, sczBaseCommand, sczUserArgs, sczCachedDirectory, &dwExitCode);
514 ExitOnFailure(hr, "Failed to run EXE process"); 511 ExitOnFailure(hr, "Failed to run EXE process");
515 } 512 }
516 513
@@ -518,12 +515,12 @@ extern "C" HRESULT ExeEngineExecutePackage(
518 ExitOnRootFailure(hr, "Process returned error: 0x%x", dwExitCode); 515 ExitOnRootFailure(hr, "Process returned error: 0x%x", dwExitCode);
519 516
520LExit: 517LExit:
521 StrSecureZeroFreeString(sczArguments);
522 StrSecureZeroFreeString(sczArgumentsFormatted);
523 ReleaseStr(sczArgumentsObfuscated);
524 ReleaseStr(sczCachedDirectory); 518 ReleaseStr(sczCachedDirectory);
525 ReleaseStr(sczExecutablePath); 519 ReleaseStr(sczExecutablePath);
526 StrSecureZeroFreeString(sczCommand); 520 ReleaseStr(sczBaseCommand);
521 ReleaseStr(sczUnformattedUserArgs);
522 StrSecureZeroFreeString(sczUserArgs);
523 ReleaseStr(sczUserArgsObfuscated);
527 ReleaseStr(sczCommandObfuscated); 524 ReleaseStr(sczCommandObfuscated);
528 525
529 ReleaseFileHandle(hExecutableFile); 526 ReleaseFileHandle(hExecutableFile);
@@ -540,12 +537,14 @@ extern "C" HRESULT ExeEngineRunProcess(
540 __in LPVOID pvContext, 537 __in LPVOID pvContext,
541 __in BURN_PACKAGE* pPackage, 538 __in BURN_PACKAGE* pPackage,
542 __in_z LPCWSTR wzExecutablePath, 539 __in_z LPCWSTR wzExecutablePath,
543 __in_z LPWSTR wzCommand, 540 __in_z LPWSTR sczBaseCommand,
541 __in_z_opt LPCWSTR wzUserArgs,
544 __in_z_opt LPCWSTR wzCachedDirectory, 542 __in_z_opt LPCWSTR wzCachedDirectory,
545 __inout DWORD* pdwExitCode 543 __inout DWORD* pdwExitCode
546 ) 544 )
547{ 545{
548 HRESULT hr = S_OK; 546 HRESULT hr = S_OK;
547 LPWSTR sczCommand = NULL;
549 STARTUPINFOW si = { }; 548 STARTUPINFOW si = { };
550 PROCESS_INFORMATION pi = { }; 549 PROCESS_INFORMATION pi = { };
551 GENERIC_EXECUTE_MESSAGE message = { }; 550 GENERIC_EXECUTE_MESSAGE message = { };
@@ -555,10 +554,17 @@ extern "C" HRESULT ExeEngineRunProcess(
555 BOOL fFireAndForget = BURN_PACKAGE_TYPE_EXE == pPackage->type && pPackage->Exe.fFireAndForget; 554 BOOL fFireAndForget = BURN_PACKAGE_TYPE_EXE == pPackage->type && pPackage->Exe.fFireAndForget;
556 BOOL fInheritHandles = BURN_PACKAGE_TYPE_BUNDLE == pPackage->type; 555 BOOL fInheritHandles = BURN_PACKAGE_TYPE_BUNDLE == pPackage->type;
557 556
557 // Always add user supplied arguments last.
558 if (wzUserArgs)
559 {
560 hr = StrAllocFormattedSecure(&sczCommand, L"%ls %ls", sczBaseCommand, wzUserArgs);
561 ExitOnFailure(hr, "Failed to append user args.");
562 }
563
558 // Make the cache location of the executable the current directory to help those executables 564 // Make the cache location of the executable the current directory to help those executables
559 // that expect stuff to be relative to them. 565 // that expect stuff to be relative to them.
560 si.cb = sizeof(si); 566 si.cb = sizeof(si);
561 if (!::CreateProcessW(wzExecutablePath, wzCommand, NULL, NULL, fInheritHandles, CREATE_NO_WINDOW, NULL, wzCachedDirectory, &si, &pi)) 567 if (!::CreateProcessW(wzExecutablePath, sczCommand ? sczCommand : sczBaseCommand, NULL, NULL, fInheritHandles, CREATE_NO_WINDOW, NULL, wzCachedDirectory, &si, &pi))
562 { 568 {
563 ExitWithLastError(hr, "Failed to CreateProcess on path: %ls", wzExecutablePath); 569 ExitWithLastError(hr, "Failed to CreateProcess on path: %ls", wzExecutablePath);
564 } 570 }
@@ -632,6 +638,7 @@ extern "C" HRESULT ExeEngineRunProcess(
632 } 638 }
633 639
634LExit: 640LExit:
641 StrSecureZeroFreeString(sczCommand);
635 ReleaseHandle(pi.hThread); 642 ReleaseHandle(pi.hThread);
636 ReleaseHandle(pi.hProcess); 643 ReleaseHandle(pi.hProcess);
637 644
diff --git a/src/burn/engine/exeengine.h b/src/burn/engine/exeengine.h
index 636988f1..b74d5c9a 100644
--- a/src/burn/engine/exeengine.h
+++ b/src/burn/engine/exeengine.h
@@ -47,7 +47,8 @@ HRESULT ExeEngineRunProcess(
47 __in LPVOID pvContext, 47 __in LPVOID pvContext,
48 __in BURN_PACKAGE* pPackage, 48 __in BURN_PACKAGE* pPackage,
49 __in_z LPCWSTR wzExecutablePath, 49 __in_z LPCWSTR wzExecutablePath,
50 __in_z LPWSTR wzCommand, 50 __in_z LPWSTR sczBaseCommand,
51 __in_z_opt LPCWSTR wzUserArgs,
51 __in_z_opt LPCWSTR wzCachedDirectory, 52 __in_z_opt LPCWSTR wzCachedDirectory,
52 __inout DWORD* pdwExitCode 53 __inout DWORD* pdwExitCode
53 ); 54 );
diff --git a/src/burn/engine/msuengine.cpp b/src/burn/engine/msuengine.cpp
index 2591973f..de8e8c38 100644
--- a/src/burn/engine/msuengine.cpp
+++ b/src/burn/engine/msuengine.cpp
@@ -273,6 +273,7 @@ extern "C" HRESULT MsuEngineExecutePackage(
273 LPWSTR sczSystemPath = NULL; 273 LPWSTR sczSystemPath = NULL;
274 LPWSTR sczWusaPath = NULL; 274 LPWSTR sczWusaPath = NULL;
275 LPWSTR sczCommand = NULL; 275 LPWSTR sczCommand = NULL;
276 LPWSTR sczEscapedKB = NULL;
276 SC_HANDLE schWu = NULL; 277 SC_HANDLE schWu = NULL;
277 BOOL fWuWasDisabled = FALSE; 278 BOOL fWuWasDisabled = FALSE;
278 STARTUPINFOW si = { }; 279 STARTUPINFOW si = { };
@@ -328,8 +329,11 @@ extern "C" HRESULT MsuEngineExecutePackage(
328 break; 329 break;
329 330
330 case BOOTSTRAPPER_ACTION_STATE_UNINSTALL: 331 case BOOTSTRAPPER_ACTION_STATE_UNINSTALL:
332 hr = AppEscapeCommandLineArgumentFormatted(&sczEscapedKB, L"%ls", pPackage->Msu.sczKB);
333 ExitOnFailure(hr, "Failed to escape MSU KB.");
334
331 // format command 335 // format command
332 hr = StrAllocFormatted(&sczCommand, L"\"%ls\" /uninstall /kb:%ls /quiet /norestart", sczWusaPath, pPackage->Msu.sczKB); 336 hr = StrAllocFormatted(&sczCommand, L"\"%ls\" /uninstall /kb:%ls /quiet /norestart", sczWusaPath, sczEscapedKB);
333 ExitOnFailure(hr, "Failed to format MSU uninstall command."); 337 ExitOnFailure(hr, "Failed to format MSU uninstall command.");
334 break; 338 break;
335 339
@@ -352,7 +356,7 @@ extern "C" HRESULT MsuEngineExecutePackage(
352 hr = EnsureWUServiceEnabled(fStopWusaService, &schWu, &fWuWasDisabled); 356 hr = EnsureWUServiceEnabled(fStopWusaService, &schWu, &fWuWasDisabled);
353 ExitOnFailure(hr, "Failed to ensure WU service was enabled to install MSU package."); 357 ExitOnFailure(hr, "Failed to ensure WU service was enabled to install MSU package.");
354 358
355 hr = ExeEngineRunProcess(pfnGenericMessageHandler, pvContext, pPackage, sczWusaPath, sczCommand, NULL, &dwExitCode); 359 hr = ExeEngineRunProcess(pfnGenericMessageHandler, pvContext, pPackage, sczWusaPath, sczCommand, NULL, NULL, &dwExitCode);
356 ExitOnFailure(hr, "Failed to run MSU process"); 360 ExitOnFailure(hr, "Failed to run MSU process");
357 361
358 // We'll normalize the restart required error code from wusa.exe just in case. Most likely 362 // We'll normalize the restart required error code from wusa.exe just in case. Most likely
@@ -389,6 +393,7 @@ LExit:
389 ReleaseStr(sczWindowsPath); 393 ReleaseStr(sczWindowsPath);
390 ReleaseStr(sczWusaPath); 394 ReleaseStr(sczWusaPath);
391 ReleaseStr(sczCommand); 395 ReleaseStr(sczCommand);
396 ReleaseStr(sczEscapedKB);
392 397
393 ReleaseHandle(pi.hProcess); 398 ReleaseHandle(pi.hProcess);
394 ReleaseHandle(pi.hThread); 399 ReleaseHandle(pi.hThread);
diff --git a/src/burn/engine/netfxchainer.cpp b/src/burn/engine/netfxchainer.cpp
index af4f03f5..6f223eed 100644
--- a/src/burn/engine/netfxchainer.cpp
+++ b/src/burn/engine/netfxchainer.cpp
@@ -329,8 +329,9 @@ LExit:
329} 329}
330 330
331extern "C" HRESULT NetFxRunChainer( 331extern "C" HRESULT NetFxRunChainer(
332 __in LPCWSTR wzExecutablePath, 332 __in_z LPCWSTR wzExecutablePath,
333 __in LPCWSTR wzArguments, 333 __in_z LPWSTR sczBaseCommand,
334 __in_z_opt LPCWSTR wzUserArgs,
334 __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler, 335 __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
335 __in LPVOID pvContext, 336 __in LPVOID pvContext,
336 __out DWORD* pdwExitCode 337 __out DWORD* pdwExitCode
@@ -360,8 +361,15 @@ extern "C" HRESULT NetFxRunChainer(
360 hr = CreateNetFxChainer(sczSectionName, sczEventName, &pNetfxChainer); 361 hr = CreateNetFxChainer(sczSectionName, sczEventName, &pNetfxChainer);
361 ExitOnFailure(hr, "Failed to create netfx chainer."); 362 ExitOnFailure(hr, "Failed to create netfx chainer.");
362 363
363 hr = StrAllocFormattedSecure(&sczCommand, L"%ls /pipe %ls", wzArguments, sczSectionName); 364 hr = StrAllocFormatted(&sczCommand, L"%ls /pipe %ls", sczBaseCommand, sczSectionName);
364 ExitOnFailure(hr, "Failed to allocate netfx chainer arguments."); 365 ExitOnFailure(hr, "Failed to append netfx chainer args.");
366
367 // Always add user supplied arguments last.
368 if (wzUserArgs)
369 {
370 hr = StrAllocConcatFormattedSecure(&sczCommand, L" %ls", wzUserArgs);
371 ExitOnFailure(hr, "Failed to append user args.");
372 }
365 373
366 si.cb = sizeof(si); 374 si.cb = sizeof(si);
367 if (!::CreateProcessW(wzExecutablePath, sczCommand, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) 375 if (!::CreateProcessW(wzExecutablePath, sczCommand, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
diff --git a/src/burn/engine/netfxchainer.h b/src/burn/engine/netfxchainer.h
index 7d3aff1c..d59b28f3 100644
--- a/src/burn/engine/netfxchainer.h
+++ b/src/burn/engine/netfxchainer.h
@@ -87,8 +87,9 @@ struct NetFxCloseApplications
87}; 87};
88 88
89HRESULT NetFxRunChainer( 89HRESULT NetFxRunChainer(
90 __in LPCWSTR wzExecutablePath, 90 __in_z LPCWSTR wzExecutablePath,
91 __in LPCWSTR wzArguments, 91 __in_z LPWSTR sczBaseCommand,
92 __in_z_opt LPCWSTR wzUserArgs,
92 __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler, 93 __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
93 __in LPVOID pvContext, 94 __in LPVOID pvContext,
94 __out DWORD* pdwExitCode 95 __out DWORD* pdwExitCode