Minimize chance of user arguments messing up the command line to avoid variations of issue 3890
Minimize chance of user arguments messing up the command line to avoid variations of issue 3890
Sean Hall committed
Mar 30, 2022 at 17:05 UTC
ae3a31795614000207470e6824887c414366a681
8 files changed
+119
-91
src/burn/engine/bundlepackageengine.cpp
+34
-37
@@ -252,12 +252,12 @@ extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle(
252
{
253
HRESULT hr = S_OK;
254
LPCWSTR wzArguments = NULL;
255
- LPWSTR sczArguments = NULL;
256
- LPWSTR sczArgumentsFormatted = NULL;
257
- LPWSTR sczArgumentsObfuscated = NULL;
255
LPWSTR sczCachedDirectory = 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;
262
HANDLE hExecutableFile = INVALID_HANDLE_VALUE;
263
STARTUPINFOW si = { };
@@ -309,7 +309,7 @@ extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle(
309
// now add optional arguments
310
if (wzArguments && *wzArguments)
311
{
312
- hr = StrAllocString(&sczArguments, wzArguments, 0);
312
+ hr = StrAllocString(&sczUnformattedUserArgs, wzArguments, 0);
313
ExitOnFailure(hr, "Failed to copy package arguments.");
314
}
315
@@ -323,26 +323,26 @@ extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle(
323
324
if (fCondition)
325
{
326
- if (sczArguments)
326
+ if (sczUnformattedUserArgs)
327
{
328
- hr = StrAllocConcat(&sczArguments, L" ", 0);
328
+ hr = StrAllocConcat(&sczUnformattedUserArgs, L" ", 0);
329
ExitOnFailure(hr, "Failed to separate command-line arguments.");
330
}
331
332
switch (action)
333
{
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.");
337
break;
338
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.");
342
break;
343
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.");
347
break;
348
@@ -353,75 +353,72 @@ extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle(
353
}
354
}
355
356
- // build command
357
- AppAppendCommandLineArgument(&sczCommand, sczExecutablePath);
358
- ExitOnFailure(hr, "Failed to create executable command.");
356
+ // build base command
357
+ hr = StrAllocFormatted(&sczBaseCommand, L"\"%ls\"", sczExecutablePath);
358
+ ExitOnFailure(hr, "Failed to allocate base command.");
359
360
if (!fRunEmbedded)
361
{
362
- hr = StrAllocConcat(&sczCommand, L" -quiet", 0);
362
+ hr = StrAllocConcat(&sczBaseCommand, L" -quiet", 0);
363
ExitOnFailure(hr, "Failed to append quiet argument.");
364
}
365
366
if (wzOperationCommandLine)
367
{
368
- hr = StrAllocConcatFormatted(&sczCommand, L" %ls", wzOperationCommandLine);
368
+ hr = StrAllocConcatFormatted(&sczBaseCommand, L" %ls", wzOperationCommandLine);
369
ExitOnFailure(hr, "Failed to append operation argument.");
370
}
371
372
if (wzRelationTypeCommandLine)
373
{
374
- hr = StrAllocConcatFormatted(&sczCommand, L" -%ls", wzRelationTypeCommandLine);
374
+ hr = StrAllocConcatFormatted(&sczBaseCommand, L" -%ls", wzRelationTypeCommandLine);
375
ExitOnFailure(hr, "Failed to append relation type argument.");
376
}
377
378
// Add the list of dependencies to ignore, if any, to the burn command line.
379
if (pExecuteAction->relatedBundle.sczIgnoreDependencies)
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.");
383
}
384
385
// Add the list of ancestors, if any, to the burn command line.
386
if (pExecuteAction->relatedBundle.sczAncestors)
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.");
390
}
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.");
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);
397
398
- // Always add user supplied arguments last.
399
- if (sczArguments && *sczArguments)
398
+ // build user args
399
+ if (sczUnformattedUserArgs && *sczUnformattedUserArgs)
400
{
401
- hr = VariableFormatString(pVariables, sczArguments, &sczArgumentsFormatted, NULL);
401
+ hr = VariableFormatString(pVariables, sczUnformattedUserArgs, &sczUserArgs, NULL);
402
ExitOnFailure(hr, "Failed to format argument string.");
403
404
- hr = VariableFormatStringObfuscated(pVariables, sczArguments, &sczArgumentsObfuscated, NULL);
404
+ hr = VariableFormatStringObfuscated(pVariables, sczUnformattedUserArgs, &sczUserArgsObfuscated, NULL);
405
ExitOnFailure(hr, "Failed to format obfuscated argument string.");
406
407
- hr = StrAllocFormatted(&sczCommandObfuscated, L"%ls %ls", sczCommand, sczArgumentsObfuscated);
408
- ExitOnFailure(hr, "Failed to copy obfuscated formatted arguments.");
409
-
410
- hr = StrAllocConcatFormattedSecure(&sczCommand, L" %ls", sczArgumentsFormatted);
411
- ExitOnFailure(hr, "Failed to copy formatted arguments.");
407
+ hr = StrAllocFormatted(&sczCommandObfuscated, L"%ls %ls", sczBaseCommand, sczUserArgsObfuscated);
408
+ ExitOnFailure(hr, "Failed to allocate obfuscated bundle command.");
409
}
410
414
- // Log before we add the secret pipe name and client token for embedded processes.
415
- LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(action), sczExecutablePath, sczCommandObfuscated);
411
+ // Log obfuscated command, which won't include raw hidden variable values or protocol specific arguments to avoid exposing secrets.
412
+ LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(action), sczExecutablePath, sczCommandObfuscated ? sczCommandObfuscated : sczBaseCommand);
413
414
if (fRunEmbedded)
415
{
419
- hr = EmbeddedRunBundle(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode);
416
+ hr = EmbeddedRunBundle(sczExecutablePath, sczBaseCommand, sczUserArgs, pfnGenericMessageHandler, pvContext, &dwExitCode);
417
ExitOnFailure(hr, "Failed to run bundle as embedded from path: %ls", sczExecutablePath);
418
}
419
else
420
{
424
- hr = ExeEngineRunProcess(pfnGenericMessageHandler, pvContext, pPackage, sczExecutablePath, sczCommand, sczCachedDirectory, &dwExitCode);
421
+ hr = ExeEngineRunProcess(pfnGenericMessageHandler, pvContext, pPackage, sczExecutablePath, sczBaseCommand, sczUserArgs, sczCachedDirectory, &dwExitCode);
422
ExitOnFailure(hr, "Failed to run BUNDLE process");
423
}
424
@@ -429,12 +426,12 @@ extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle(
426
ExitOnRootFailure(hr, "Process returned error: 0x%x", dwExitCode);
427
428
LExit:
432
- StrSecureZeroFreeString(sczArguments);
433
- StrSecureZeroFreeString(sczArgumentsFormatted);
434
- ReleaseStr(sczArgumentsObfuscated);
429
ReleaseStr(sczCachedDirectory);
430
ReleaseStr(sczExecutablePath);
437
- StrSecureZeroFreeString(sczCommand);
431
+ ReleaseStr(sczBaseCommand);
432
+ ReleaseStr(sczUnformattedUserArgs);
433
+ StrSecureZeroFreeString(sczUserArgs);
434
+ ReleaseStr(sczUserArgsObfuscated);
435
ReleaseStr(sczCommandObfuscated);
436
437
ReleaseHandle(pi.hThread);
src/burn/engine/embedded.cpp
+13
-5
@@ -36,12 +36,13 @@ static HRESULT OnEmbeddedProgress(
36
// function definitions
37
38
/*******************************************************************
39
- EmbeddedLaunchChildProcess -
39
+ EmbeddedRunBundle -
40
41
*******************************************************************/
42
extern "C" HRESULT EmbeddedRunBundle(
43
- __in LPCWSTR wzExecutablePath,
44
- __in LPCWSTR wzArguments,
43
+ __in_z LPCWSTR wzExecutablePath,
44
+ __in_z LPWSTR sczBaseCommand,
45
+ __in_z_opt LPCWSTR wzUserArgs,
46
__in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
47
__in LPVOID pvContext,
48
__out DWORD* pdwExitCode
@@ -68,8 +69,15 @@ extern "C" HRESULT EmbeddedRunBundle(
69
hr = PipeCreatePipes(&connection, FALSE, &hCreatedPipesEvent);
70
ExitOnFailure(hr, "Failed to create embedded pipe.");
71
71
- hr = StrAllocFormattedSecure(&sczCommand, L"%ls -%ls %ls %ls %u", wzArguments, BURN_COMMANDLINE_SWITCH_EMBEDDED, connection.sczName, connection.sczSecret, dwCurrentProcessId);
72
- ExitOnFailure(hr, "Failed to allocate embedded command.");
72
+ hr = StrAllocFormatted(&sczCommand, L"%ls -%ls %ls %ls %u", sczBaseCommand, BURN_COMMANDLINE_SWITCH_EMBEDDED, connection.sczName, connection.sczSecret, dwCurrentProcessId);
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
+ }
81
82
if (!::CreateProcessW(wzExecutablePath, sczCommand, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
83
{
src/burn/engine/embedded.h
+3
-2
@@ -15,8 +15,9 @@ typedef enum _BURN_EMBEDDED_MESSAGE_TYPE
15
16
17
HRESULT EmbeddedRunBundle(
18
- __in LPCWSTR wzExecutablePath,
19
- __in LPCWSTR wzArguments,
18
+ __in_z LPCWSTR wzExecutablePath,
19
+ __in_z LPWSTR sczBaseCommand,
20
+ __in_z_opt LPCWSTR wzUserArgs,
21
__in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
22
__in LPVOID pvContext,
23
__out DWORD* pdwExitCode
src/burn/engine/exeengine.cpp
+45
-38
@@ -362,12 +362,12 @@ extern "C" HRESULT ExeEngineExecutePackage(
362
{
363
HRESULT hr = S_OK;
364
LPCWSTR wzArguments = NULL;
365
- LPWSTR sczArguments = NULL;
366
- LPWSTR sczArgumentsFormatted = NULL;
367
- LPWSTR sczArgumentsObfuscated = NULL;
365
LPWSTR sczCachedDirectory = 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;
372
HANDLE hExecutableFile = INVALID_HANDLE_VALUE;
373
DWORD dwExitCode = 0;
@@ -406,7 +406,7 @@ extern "C" HRESULT ExeEngineExecutePackage(
406
}
407
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.");
411
412
for (DWORD i = 0; i < pPackage->Exe.cCommandLineArguments; ++i)
@@ -419,23 +419,23 @@ extern "C" HRESULT ExeEngineExecutePackage(
419
420
if (fCondition)
421
{
422
- hr = StrAllocConcat(&sczArguments, L" ", 0);
422
+ hr = StrAllocConcat(&sczUnformattedUserArgs, L" ", 0);
423
ExitOnFailure(hr, "Failed to separate command-line arguments.");
424
425
switch (pExecuteAction->exePackage.action)
426
{
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.");
430
break;
431
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.");
435
break;
436
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.");
440
break;
441
@@ -446,71 +446,68 @@ extern "C" HRESULT ExeEngineExecutePackage(
446
}
447
}
448
449
- // build command
450
- AppAppendCommandLineArgument(&sczCommand, sczExecutablePath);
451
- ExitOnFailure(hr, "Failed to create executable command.");
449
+ // build base command
450
+ hr = StrAllocFormatted(&sczBaseCommand, L"\"%ls\"", sczExecutablePath);
451
+ ExitOnFailure(hr, "Failed to allocate base command.");
452
453
if (pPackage->Exe.fBundle)
454
{
455
- hr = StrAllocConcat(&sczCommand, L" -norestart", 0);
456
- ExitOnFailure(hr, "Failed to append quiet argument.");
455
+ hr = StrAllocConcat(&sczBaseCommand, L" -norestart", 0);
456
+ ExitOnFailure(hr, "Failed to append norestart argument.");
457
458
// Add the list of dependencies to ignore, if any, to the burn command line.
459
if (pExecuteAction->exePackage.sczIgnoreDependencies)
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.");
463
}
464
465
// Add the list of ancestors, if any, to the burn command line.
466
if (pExecuteAction->exePackage.sczAncestors)
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.");
470
}
471
472
if (pExecuteAction->exePackage.sczEngineWorkingDirectory)
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.");
476
}
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);
480
}
481
482
- // Always add user supplied arguments last.
483
- if (sczArguments && *sczArguments)
482
+ // build user args
483
+ if (sczUnformattedUserArgs && *sczUnformattedUserArgs)
484
{
485
- hr = VariableFormatString(pVariables, sczArguments, &sczArgumentsFormatted, NULL);
485
+ hr = VariableFormatString(pVariables, sczUnformattedUserArgs, &sczUserArgs, NULL);
486
ExitOnFailure(hr, "Failed to format argument string.");
487
488
- hr = VariableFormatStringObfuscated(pVariables, sczArguments, &sczArgumentsObfuscated, NULL);
488
+ hr = VariableFormatStringObfuscated(pVariables, sczUnformattedUserArgs, &sczUserArgsObfuscated, NULL);
489
ExitOnFailure(hr, "Failed to format obfuscated argument string.");
490
491
- hr = StrAllocFormatted(&sczCommandObfuscated, L"%ls %ls", sczCommand, sczArgumentsObfuscated);
492
- ExitOnFailure(hr, "Failed to copy obfuscated formatted arguments.");
493
-
494
- hr = StrAllocConcatFormattedSecure(&sczCommand, L" %ls", sczArgumentsFormatted);
495
- ExitOnFailure(hr, "Failed to copy formatted arguments.");
491
+ hr = StrAllocFormatted(&sczCommandObfuscated, L"%ls %ls", sczBaseCommand, sczUserArgsObfuscated);
492
+ ExitOnFailure(hr, "Failed to allocate obfuscated exe command.");
493
}
494
498
- // Log before we add the secret pipe name and client token for embedded processes.
499
- LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(pExecuteAction->exePackage.action), sczExecutablePath, sczCommandObfuscated);
495
+ // Log obfuscated command, which won't include raw hidden variable values or protocol specific arguments to avoid exposing secrets.
496
+ LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(pExecuteAction->exePackage.action), sczExecutablePath, sczCommandObfuscated ? sczCommandObfuscated : sczBaseCommand);
497
498
if (!pPackage->Exe.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol)
499
{
503
- hr = EmbeddedRunBundle(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode);
500
+ hr = EmbeddedRunBundle(sczExecutablePath, sczBaseCommand, sczUserArgs, pfnGenericMessageHandler, pvContext, &dwExitCode);
501
ExitOnFailure(hr, "Failed to run exe with Burn protocol from path: %ls", sczExecutablePath);
502
}
503
else if (!pPackage->Exe.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_NETFX4 == pPackage->Exe.protocol)
504
{
508
- hr = NetFxRunChainer(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode);
505
+ hr = NetFxRunChainer(sczExecutablePath, sczBaseCommand, sczUserArgs, pfnGenericMessageHandler, pvContext, &dwExitCode);
506
ExitOnFailure(hr, "Failed to run netfx chainer: %ls", sczExecutablePath);
507
}
508
else
509
{
513
- hr = ExeEngineRunProcess(pfnGenericMessageHandler, pvContext, pPackage, sczExecutablePath, sczCommand, sczCachedDirectory, &dwExitCode);
510
+ hr = ExeEngineRunProcess(pfnGenericMessageHandler, pvContext, pPackage, sczExecutablePath, sczBaseCommand, sczUserArgs, sczCachedDirectory, &dwExitCode);
511
ExitOnFailure(hr, "Failed to run EXE process");
512
}
513
@@ -518,12 +515,12 @@ extern "C" HRESULT ExeEngineExecutePackage(
515
ExitOnRootFailure(hr, "Process returned error: 0x%x", dwExitCode);
516
517
LExit:
521
- StrSecureZeroFreeString(sczArguments);
522
- StrSecureZeroFreeString(sczArgumentsFormatted);
523
- ReleaseStr(sczArgumentsObfuscated);
518
ReleaseStr(sczCachedDirectory);
519
ReleaseStr(sczExecutablePath);
526
- StrSecureZeroFreeString(sczCommand);
520
+ ReleaseStr(sczBaseCommand);
521
+ ReleaseStr(sczUnformattedUserArgs);
522
+ StrSecureZeroFreeString(sczUserArgs);
523
+ ReleaseStr(sczUserArgsObfuscated);
524
ReleaseStr(sczCommandObfuscated);
525
526
ReleaseFileHandle(hExecutableFile);
@@ -540,12 +537,14 @@ extern "C" HRESULT ExeEngineRunProcess(
537
__in LPVOID pvContext,
538
__in BURN_PACKAGE* pPackage,
539
__in_z LPCWSTR wzExecutablePath,
543
- __in_z LPWSTR wzCommand,
540
+ __in_z LPWSTR sczBaseCommand,
541
+ __in_z_opt LPCWSTR wzUserArgs,
542
__in_z_opt LPCWSTR wzCachedDirectory,
543
__inout DWORD* pdwExitCode
544
)
545
{
546
HRESULT hr = S_OK;
547
+ LPWSTR sczCommand = NULL;
548
STARTUPINFOW si = { };
549
PROCESS_INFORMATION pi = { };
550
GENERIC_EXECUTE_MESSAGE message = { };
@@ -555,10 +554,17 @@ extern "C" HRESULT ExeEngineRunProcess(
554
BOOL fFireAndForget = BURN_PACKAGE_TYPE_EXE == pPackage->type && pPackage->Exe.fFireAndForget;
555
BOOL fInheritHandles = BURN_PACKAGE_TYPE_BUNDLE == pPackage->type;
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
+
564
// Make the cache location of the executable the current directory to help those executables
565
// that expect stuff to be relative to them.
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))
568
{
569
ExitWithLastError(hr, "Failed to CreateProcess on path: %ls", wzExecutablePath);
570
}
@@ -632,6 +638,7 @@ extern "C" HRESULT ExeEngineRunProcess(
638
}
639
640
LExit:
641
+ StrSecureZeroFreeString(sczCommand);
642
ReleaseHandle(pi.hThread);
643
ReleaseHandle(pi.hProcess);
644
src/burn/engine/exeengine.h
+2
-1
@@ -47,7 +47,8 @@ HRESULT ExeEngineRunProcess(
47
__in LPVOID pvContext,
48
__in BURN_PACKAGE* pPackage,
49
__in_z LPCWSTR wzExecutablePath,
50
- __in_z LPWSTR wzCommand,
50
+ __in_z LPWSTR sczBaseCommand,
51
+ __in_z_opt LPCWSTR wzUserArgs,
52
__in_z_opt LPCWSTR wzCachedDirectory,
53
__inout DWORD* pdwExitCode
54
);
src/burn/engine/msuengine.cpp
+7
-2
@@ -273,6 +273,7 @@ extern "C" HRESULT MsuEngineExecutePackage(
273
LPWSTR sczSystemPath = NULL;
274
LPWSTR sczWusaPath = NULL;
275
LPWSTR sczCommand = NULL;
276
+ LPWSTR sczEscapedKB = NULL;
277
SC_HANDLE schWu = NULL;
278
BOOL fWuWasDisabled = FALSE;
279
STARTUPINFOW si = { };
@@ -328,8 +329,11 @@ extern "C" HRESULT MsuEngineExecutePackage(
329
break;
330
331
case BOOTSTRAPPER_ACTION_STATE_UNINSTALL:
332
+ hr = AppEscapeCommandLineArgumentFormatted(&sczEscapedKB, L"%ls", pPackage->Msu.sczKB);
333
+ ExitOnFailure(hr, "Failed to escape MSU KB.");
334
+
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);
337
ExitOnFailure(hr, "Failed to format MSU uninstall command.");
338
break;
339
@@ -352,7 +356,7 @@ extern "C" HRESULT MsuEngineExecutePackage(
356
hr = EnsureWUServiceEnabled(fStopWusaService, &schWu, &fWuWasDisabled);
357
ExitOnFailure(hr, "Failed to ensure WU service was enabled to install MSU package.");
358
355
- hr = ExeEngineRunProcess(pfnGenericMessageHandler, pvContext, pPackage, sczWusaPath, sczCommand, NULL, &dwExitCode);
359
+ hr = ExeEngineRunProcess(pfnGenericMessageHandler, pvContext, pPackage, sczWusaPath, sczCommand, NULL, NULL, &dwExitCode);
360
ExitOnFailure(hr, "Failed to run MSU process");
361
362
// We'll normalize the restart required error code from wusa.exe just in case. Most likely
@@ -389,6 +393,7 @@ LExit:
393
ReleaseStr(sczWindowsPath);
394
ReleaseStr(sczWusaPath);
395
ReleaseStr(sczCommand);
396
+ ReleaseStr(sczEscapedKB);
397
398
ReleaseHandle(pi.hProcess);
399
ReleaseHandle(pi.hThread);
src/burn/engine/netfxchainer.cpp
+12
-4
@@ -329,8 +329,9 @@ LExit:
329
}
330
331
extern "C" HRESULT NetFxRunChainer(
332
- __in LPCWSTR wzExecutablePath,
333
- __in LPCWSTR wzArguments,
332
+ __in_z LPCWSTR wzExecutablePath,
333
+ __in_z LPWSTR sczBaseCommand,
334
+ __in_z_opt LPCWSTR wzUserArgs,
335
__in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
336
__in LPVOID pvContext,
337
__out DWORD* pdwExitCode
@@ -360,8 +361,15 @@ extern "C" HRESULT NetFxRunChainer(
361
hr = CreateNetFxChainer(sczSectionName, sczEventName, &pNetfxChainer);
362
ExitOnFailure(hr, "Failed to create netfx chainer.");
363
363
- hr = StrAllocFormattedSecure(&sczCommand, L"%ls /pipe %ls", wzArguments, sczSectionName);
364
- ExitOnFailure(hr, "Failed to allocate netfx chainer arguments.");
364
+ hr = StrAllocFormatted(&sczCommand, L"%ls /pipe %ls", sczBaseCommand, sczSectionName);
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
+ }
373
374
si.cb = sizeof(si);
375
if (!::CreateProcessW(wzExecutablePath, sczCommand, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
src/burn/engine/netfxchainer.h
+3
-2
@@ -87,8 +87,9 @@ struct NetFxCloseApplications
87
};
88
89
HRESULT NetFxRunChainer(
90
- __in LPCWSTR wzExecutablePath,
91
- __in LPCWSTR wzArguments,
90
+ __in_z LPCWSTR wzExecutablePath,
91
+ __in_z LPWSTR sczBaseCommand,
92
+ __in_z_opt LPCWSTR wzUserArgs,
93
__in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
94
__in LPVOID pvContext,
95
__out DWORD* pdwExitCode