From ae3a31795614000207470e6824887c414366a681 Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Wed, 30 Mar 2022 17:05:56 -0500 Subject: Minimize chance of user arguments messing up the command line to avoid variations of issue 3890 --- src/burn/engine/bundlepackageengine.cpp | 71 ++++++++++++++-------------- src/burn/engine/embedded.cpp | 18 +++++-- src/burn/engine/embedded.h | 5 +- src/burn/engine/exeengine.cpp | 83 ++++++++++++++++++--------------- src/burn/engine/exeengine.h | 3 +- src/burn/engine/msuengine.cpp | 9 +++- src/burn/engine/netfxchainer.cpp | 16 +++++-- src/burn/engine/netfxchainer.h | 5 +- 8 files changed, 119 insertions(+), 91 deletions(-) (limited to 'src/burn') 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( { HRESULT hr = S_OK; LPCWSTR wzArguments = NULL; - LPWSTR sczArguments = NULL; - LPWSTR sczArgumentsFormatted = NULL; - LPWSTR sczArgumentsObfuscated = NULL; LPWSTR sczCachedDirectory = NULL; LPWSTR sczExecutablePath = NULL; - LPWSTR sczCommand = NULL; + LPWSTR sczBaseCommand = NULL; + LPWSTR sczUnformattedUserArgs = NULL; + LPWSTR sczUserArgs = NULL; + LPWSTR sczUserArgsObfuscated = NULL; LPWSTR sczCommandObfuscated = NULL; HANDLE hExecutableFile = INVALID_HANDLE_VALUE; STARTUPINFOW si = { }; @@ -309,7 +309,7 @@ extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle( // now add optional arguments if (wzArguments && *wzArguments) { - hr = StrAllocString(&sczArguments, wzArguments, 0); + hr = StrAllocString(&sczUnformattedUserArgs, wzArguments, 0); ExitOnFailure(hr, "Failed to copy package arguments."); } @@ -323,26 +323,26 @@ extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle( if (fCondition) { - if (sczArguments) + if (sczUnformattedUserArgs) { - hr = StrAllocConcat(&sczArguments, L" ", 0); + hr = StrAllocConcat(&sczUnformattedUserArgs, L" ", 0); ExitOnFailure(hr, "Failed to separate command-line arguments."); } switch (action) { case BOOTSTRAPPER_ACTION_STATE_INSTALL: - hr = StrAllocConcat(&sczArguments, commandLineArgument->sczInstallArgument, 0); + hr = StrAllocConcat(&sczUnformattedUserArgs, commandLineArgument->sczInstallArgument, 0); ExitOnFailure(hr, "Failed to get command-line argument for install."); break; case BOOTSTRAPPER_ACTION_STATE_UNINSTALL: - hr = StrAllocConcat(&sczArguments, commandLineArgument->sczUninstallArgument, 0); + hr = StrAllocConcat(&sczUnformattedUserArgs, commandLineArgument->sczUninstallArgument, 0); ExitOnFailure(hr, "Failed to get command-line argument for uninstall."); break; case BOOTSTRAPPER_ACTION_STATE_REPAIR: - hr = StrAllocConcat(&sczArguments, commandLineArgument->sczRepairArgument, 0); + hr = StrAllocConcat(&sczUnformattedUserArgs, commandLineArgument->sczRepairArgument, 0); ExitOnFailure(hr, "Failed to get command-line argument for repair."); break; @@ -353,75 +353,72 @@ extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle( } } - // build command - AppAppendCommandLineArgument(&sczCommand, sczExecutablePath); - ExitOnFailure(hr, "Failed to create executable command."); + // build base command + hr = StrAllocFormatted(&sczBaseCommand, L"\"%ls\"", sczExecutablePath); + ExitOnFailure(hr, "Failed to allocate base command."); if (!fRunEmbedded) { - hr = StrAllocConcat(&sczCommand, L" -quiet", 0); + hr = StrAllocConcat(&sczBaseCommand, L" -quiet", 0); ExitOnFailure(hr, "Failed to append quiet argument."); } if (wzOperationCommandLine) { - hr = StrAllocConcatFormatted(&sczCommand, L" %ls", wzOperationCommandLine); + hr = StrAllocConcatFormatted(&sczBaseCommand, L" %ls", wzOperationCommandLine); ExitOnFailure(hr, "Failed to append operation argument."); } if (wzRelationTypeCommandLine) { - hr = StrAllocConcatFormatted(&sczCommand, L" -%ls", wzRelationTypeCommandLine); + hr = StrAllocConcatFormatted(&sczBaseCommand, L" -%ls", wzRelationTypeCommandLine); ExitOnFailure(hr, "Failed to append relation type argument."); } // Add the list of dependencies to ignore, if any, to the burn command line. if (pExecuteAction->relatedBundle.sczIgnoreDependencies) { - hr = StrAllocConcatFormatted(&sczCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->relatedBundle.sczIgnoreDependencies); + hr = StrAllocConcatFormatted(&sczBaseCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->relatedBundle.sczIgnoreDependencies); ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the command line."); } // Add the list of ancestors, if any, to the burn command line. if (pExecuteAction->relatedBundle.sczAncestors) { - hr = StrAllocConcatFormatted(&sczCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_ANCESTORS, pExecuteAction->relatedBundle.sczAncestors); + hr = StrAllocConcatFormatted(&sczBaseCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_ANCESTORS, pExecuteAction->relatedBundle.sczAncestors); ExitOnFailure(hr, "Failed to append the list of ancestors to the command line."); } - hr = CoreAppendEngineWorkingDirectoryToCommandLine(pExecuteAction->relatedBundle.sczEngineWorkingDirectory, &sczCommand, NULL); + hr = CoreAppendEngineWorkingDirectoryToCommandLine(pExecuteAction->relatedBundle.sczEngineWorkingDirectory, &sczBaseCommand, NULL); ExitOnFailure(hr, "Failed to append the custom working directory to the bundlepackage command line."); - hr = CoreAppendFileHandleSelfToCommandLine(sczExecutablePath, &hExecutableFile, &sczCommand, NULL); + hr = CoreAppendFileHandleSelfToCommandLine(sczExecutablePath, &hExecutableFile, &sczBaseCommand, NULL); ExitOnFailure(hr, "Failed to append %ls", BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF); - // Always add user supplied arguments last. - if (sczArguments && *sczArguments) + // build user args + if (sczUnformattedUserArgs && *sczUnformattedUserArgs) { - hr = VariableFormatString(pVariables, sczArguments, &sczArgumentsFormatted, NULL); + hr = VariableFormatString(pVariables, sczUnformattedUserArgs, &sczUserArgs, NULL); ExitOnFailure(hr, "Failed to format argument string."); - hr = VariableFormatStringObfuscated(pVariables, sczArguments, &sczArgumentsObfuscated, NULL); + hr = VariableFormatStringObfuscated(pVariables, sczUnformattedUserArgs, &sczUserArgsObfuscated, NULL); ExitOnFailure(hr, "Failed to format obfuscated argument string."); - hr = StrAllocFormatted(&sczCommandObfuscated, L"%ls %ls", sczCommand, sczArgumentsObfuscated); - ExitOnFailure(hr, "Failed to copy obfuscated formatted arguments."); - - hr = StrAllocConcatFormattedSecure(&sczCommand, L" %ls", sczArgumentsFormatted); - ExitOnFailure(hr, "Failed to copy formatted arguments."); + hr = StrAllocFormatted(&sczCommandObfuscated, L"%ls %ls", sczBaseCommand, sczUserArgsObfuscated); + ExitOnFailure(hr, "Failed to allocate obfuscated bundle command."); } - // Log before we add the secret pipe name and client token for embedded processes. - LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(action), sczExecutablePath, sczCommandObfuscated); + // Log obfuscated command, which won't include raw hidden variable values or protocol specific arguments to avoid exposing secrets. + LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(action), sczExecutablePath, sczCommandObfuscated ? sczCommandObfuscated : sczBaseCommand); if (fRunEmbedded) { - hr = EmbeddedRunBundle(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode); + hr = EmbeddedRunBundle(sczExecutablePath, sczBaseCommand, sczUserArgs, pfnGenericMessageHandler, pvContext, &dwExitCode); ExitOnFailure(hr, "Failed to run bundle as embedded from path: %ls", sczExecutablePath); } else { - hr = ExeEngineRunProcess(pfnGenericMessageHandler, pvContext, pPackage, sczExecutablePath, sczCommand, sczCachedDirectory, &dwExitCode); + hr = ExeEngineRunProcess(pfnGenericMessageHandler, pvContext, pPackage, sczExecutablePath, sczBaseCommand, sczUserArgs, sczCachedDirectory, &dwExitCode); ExitOnFailure(hr, "Failed to run BUNDLE process"); } @@ -429,12 +426,12 @@ extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle( ExitOnRootFailure(hr, "Process returned error: 0x%x", dwExitCode); LExit: - StrSecureZeroFreeString(sczArguments); - StrSecureZeroFreeString(sczArgumentsFormatted); - ReleaseStr(sczArgumentsObfuscated); ReleaseStr(sczCachedDirectory); ReleaseStr(sczExecutablePath); - StrSecureZeroFreeString(sczCommand); + ReleaseStr(sczBaseCommand); + ReleaseStr(sczUnformattedUserArgs); + StrSecureZeroFreeString(sczUserArgs); + ReleaseStr(sczUserArgsObfuscated); ReleaseStr(sczCommandObfuscated); 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( // function definitions /******************************************************************* - EmbeddedLaunchChildProcess - + EmbeddedRunBundle - *******************************************************************/ extern "C" HRESULT EmbeddedRunBundle( - __in LPCWSTR wzExecutablePath, - __in LPCWSTR wzArguments, + __in_z LPCWSTR wzExecutablePath, + __in_z LPWSTR sczBaseCommand, + __in_z_opt LPCWSTR wzUserArgs, __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler, __in LPVOID pvContext, __out DWORD* pdwExitCode @@ -68,8 +69,15 @@ extern "C" HRESULT EmbeddedRunBundle( hr = PipeCreatePipes(&connection, FALSE, &hCreatedPipesEvent); ExitOnFailure(hr, "Failed to create embedded pipe."); - hr = StrAllocFormattedSecure(&sczCommand, L"%ls -%ls %ls %ls %u", wzArguments, BURN_COMMANDLINE_SWITCH_EMBEDDED, connection.sczName, connection.sczSecret, dwCurrentProcessId); - ExitOnFailure(hr, "Failed to allocate embedded command."); + hr = StrAllocFormatted(&sczCommand, L"%ls -%ls %ls %ls %u", sczBaseCommand, BURN_COMMANDLINE_SWITCH_EMBEDDED, connection.sczName, connection.sczSecret, dwCurrentProcessId); + ExitOnFailure(hr, "Failed to append embedded args."); + + // Always add user supplied arguments last. + if (wzUserArgs) + { + hr = StrAllocConcatFormattedSecure(&sczCommand, L" %ls", wzUserArgs); + ExitOnFailure(hr, "Failed to append user args."); + } if (!::CreateProcessW(wzExecutablePath, sczCommand, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) { 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 HRESULT EmbeddedRunBundle( - __in LPCWSTR wzExecutablePath, - __in LPCWSTR wzArguments, + __in_z LPCWSTR wzExecutablePath, + __in_z LPWSTR sczBaseCommand, + __in_z_opt LPCWSTR wzUserArgs, __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler, __in LPVOID pvContext, __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( { HRESULT hr = S_OK; LPCWSTR wzArguments = NULL; - LPWSTR sczArguments = NULL; - LPWSTR sczArgumentsFormatted = NULL; - LPWSTR sczArgumentsObfuscated = NULL; LPWSTR sczCachedDirectory = NULL; LPWSTR sczExecutablePath = NULL; - LPWSTR sczCommand = NULL; + LPWSTR sczBaseCommand = NULL; + LPWSTR sczUnformattedUserArgs = NULL; + LPWSTR sczUserArgs = NULL; + LPWSTR sczUserArgsObfuscated = NULL; LPWSTR sczCommandObfuscated = NULL; HANDLE hExecutableFile = INVALID_HANDLE_VALUE; DWORD dwExitCode = 0; @@ -406,7 +406,7 @@ extern "C" HRESULT ExeEngineExecutePackage( } // now add optional arguments - hr = StrAllocString(&sczArguments, wzArguments && *wzArguments ? wzArguments : L"", 0); + hr = StrAllocString(&sczUnformattedUserArgs, wzArguments && *wzArguments ? wzArguments : L"", 0); ExitOnFailure(hr, "Failed to copy package arguments."); for (DWORD i = 0; i < pPackage->Exe.cCommandLineArguments; ++i) @@ -419,23 +419,23 @@ extern "C" HRESULT ExeEngineExecutePackage( if (fCondition) { - hr = StrAllocConcat(&sczArguments, L" ", 0); + hr = StrAllocConcat(&sczUnformattedUserArgs, L" ", 0); ExitOnFailure(hr, "Failed to separate command-line arguments."); switch (pExecuteAction->exePackage.action) { case BOOTSTRAPPER_ACTION_STATE_INSTALL: - hr = StrAllocConcat(&sczArguments, commandLineArgument->sczInstallArgument, 0); + hr = StrAllocConcat(&sczUnformattedUserArgs, commandLineArgument->sczInstallArgument, 0); ExitOnFailure(hr, "Failed to get command-line argument for install."); break; case BOOTSTRAPPER_ACTION_STATE_UNINSTALL: - hr = StrAllocConcat(&sczArguments, commandLineArgument->sczUninstallArgument, 0); + hr = StrAllocConcat(&sczUnformattedUserArgs, commandLineArgument->sczUninstallArgument, 0); ExitOnFailure(hr, "Failed to get command-line argument for uninstall."); break; case BOOTSTRAPPER_ACTION_STATE_REPAIR: - hr = StrAllocConcat(&sczArguments, commandLineArgument->sczRepairArgument, 0); + hr = StrAllocConcat(&sczUnformattedUserArgs, commandLineArgument->sczRepairArgument, 0); ExitOnFailure(hr, "Failed to get command-line argument for repair."); break; @@ -446,71 +446,68 @@ extern "C" HRESULT ExeEngineExecutePackage( } } - // build command - AppAppendCommandLineArgument(&sczCommand, sczExecutablePath); - ExitOnFailure(hr, "Failed to create executable command."); + // build base command + hr = StrAllocFormatted(&sczBaseCommand, L"\"%ls\"", sczExecutablePath); + ExitOnFailure(hr, "Failed to allocate base command."); if (pPackage->Exe.fBundle) { - hr = StrAllocConcat(&sczCommand, L" -norestart", 0); - ExitOnFailure(hr, "Failed to append quiet argument."); + hr = StrAllocConcat(&sczBaseCommand, L" -norestart", 0); + ExitOnFailure(hr, "Failed to append norestart argument."); // Add the list of dependencies to ignore, if any, to the burn command line. if (pExecuteAction->exePackage.sczIgnoreDependencies) { - hr = StrAllocConcatFormatted(&sczCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->exePackage.sczIgnoreDependencies); + hr = StrAllocConcatFormatted(&sczBaseCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->exePackage.sczIgnoreDependencies); ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the command line."); } // Add the list of ancestors, if any, to the burn command line. if (pExecuteAction->exePackage.sczAncestors) { - hr = StrAllocConcatFormatted(&sczCommand, L" -%ls=%ls", sczCommand, BURN_COMMANDLINE_SWITCH_ANCESTORS, pExecuteAction->exePackage.sczAncestors); + hr = StrAllocConcatFormatted(&sczBaseCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_ANCESTORS, pExecuteAction->exePackage.sczAncestors); ExitOnFailure(hr, "Failed to append the list of ancestors to the command line."); } if (pExecuteAction->exePackage.sczEngineWorkingDirectory) { - hr = CoreAppendEngineWorkingDirectoryToCommandLine(pExecuteAction->exePackage.sczEngineWorkingDirectory, &sczCommand, NULL); + hr = CoreAppendEngineWorkingDirectoryToCommandLine(pExecuteAction->exePackage.sczEngineWorkingDirectory, &sczBaseCommand, NULL); ExitOnFailure(hr, "Failed to append the custom working directory to the exepackage command line."); } - hr = CoreAppendFileHandleSelfToCommandLine(sczExecutablePath, &hExecutableFile, &sczCommand, NULL); + hr = CoreAppendFileHandleSelfToCommandLine(sczExecutablePath, &hExecutableFile, &sczBaseCommand, NULL); ExitOnFailure(hr, "Failed to append %ls", BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF); } - // Always add user supplied arguments last. - if (sczArguments && *sczArguments) + // build user args + if (sczUnformattedUserArgs && *sczUnformattedUserArgs) { - hr = VariableFormatString(pVariables, sczArguments, &sczArgumentsFormatted, NULL); + hr = VariableFormatString(pVariables, sczUnformattedUserArgs, &sczUserArgs, NULL); ExitOnFailure(hr, "Failed to format argument string."); - hr = VariableFormatStringObfuscated(pVariables, sczArguments, &sczArgumentsObfuscated, NULL); + hr = VariableFormatStringObfuscated(pVariables, sczUnformattedUserArgs, &sczUserArgsObfuscated, NULL); ExitOnFailure(hr, "Failed to format obfuscated argument string."); - hr = StrAllocFormatted(&sczCommandObfuscated, L"%ls %ls", sczCommand, sczArgumentsObfuscated); - ExitOnFailure(hr, "Failed to copy obfuscated formatted arguments."); - - hr = StrAllocConcatFormattedSecure(&sczCommand, L" %ls", sczArgumentsFormatted); - ExitOnFailure(hr, "Failed to copy formatted arguments."); + hr = StrAllocFormatted(&sczCommandObfuscated, L"%ls %ls", sczBaseCommand, sczUserArgsObfuscated); + ExitOnFailure(hr, "Failed to allocate obfuscated exe command."); } - // Log before we add the secret pipe name and client token for embedded processes. - LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(pExecuteAction->exePackage.action), sczExecutablePath, sczCommandObfuscated); + // Log obfuscated command, which won't include raw hidden variable values or protocol specific arguments to avoid exposing secrets. + LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(pExecuteAction->exePackage.action), sczExecutablePath, sczCommandObfuscated ? sczCommandObfuscated : sczBaseCommand); if (!pPackage->Exe.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol) { - hr = EmbeddedRunBundle(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode); + hr = EmbeddedRunBundle(sczExecutablePath, sczBaseCommand, sczUserArgs, pfnGenericMessageHandler, pvContext, &dwExitCode); ExitOnFailure(hr, "Failed to run exe with Burn protocol from path: %ls", sczExecutablePath); } else if (!pPackage->Exe.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_NETFX4 == pPackage->Exe.protocol) { - hr = NetFxRunChainer(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode); + hr = NetFxRunChainer(sczExecutablePath, sczBaseCommand, sczUserArgs, pfnGenericMessageHandler, pvContext, &dwExitCode); ExitOnFailure(hr, "Failed to run netfx chainer: %ls", sczExecutablePath); } else { - hr = ExeEngineRunProcess(pfnGenericMessageHandler, pvContext, pPackage, sczExecutablePath, sczCommand, sczCachedDirectory, &dwExitCode); + hr = ExeEngineRunProcess(pfnGenericMessageHandler, pvContext, pPackage, sczExecutablePath, sczBaseCommand, sczUserArgs, sczCachedDirectory, &dwExitCode); ExitOnFailure(hr, "Failed to run EXE process"); } @@ -518,12 +515,12 @@ extern "C" HRESULT ExeEngineExecutePackage( ExitOnRootFailure(hr, "Process returned error: 0x%x", dwExitCode); LExit: - StrSecureZeroFreeString(sczArguments); - StrSecureZeroFreeString(sczArgumentsFormatted); - ReleaseStr(sczArgumentsObfuscated); ReleaseStr(sczCachedDirectory); ReleaseStr(sczExecutablePath); - StrSecureZeroFreeString(sczCommand); + ReleaseStr(sczBaseCommand); + ReleaseStr(sczUnformattedUserArgs); + StrSecureZeroFreeString(sczUserArgs); + ReleaseStr(sczUserArgsObfuscated); ReleaseStr(sczCommandObfuscated); ReleaseFileHandle(hExecutableFile); @@ -540,12 +537,14 @@ extern "C" HRESULT ExeEngineRunProcess( __in LPVOID pvContext, __in BURN_PACKAGE* pPackage, __in_z LPCWSTR wzExecutablePath, - __in_z LPWSTR wzCommand, + __in_z LPWSTR sczBaseCommand, + __in_z_opt LPCWSTR wzUserArgs, __in_z_opt LPCWSTR wzCachedDirectory, __inout DWORD* pdwExitCode ) { HRESULT hr = S_OK; + LPWSTR sczCommand = NULL; STARTUPINFOW si = { }; PROCESS_INFORMATION pi = { }; GENERIC_EXECUTE_MESSAGE message = { }; @@ -555,10 +554,17 @@ extern "C" HRESULT ExeEngineRunProcess( BOOL fFireAndForget = BURN_PACKAGE_TYPE_EXE == pPackage->type && pPackage->Exe.fFireAndForget; BOOL fInheritHandles = BURN_PACKAGE_TYPE_BUNDLE == pPackage->type; + // Always add user supplied arguments last. + if (wzUserArgs) + { + hr = StrAllocFormattedSecure(&sczCommand, L"%ls %ls", sczBaseCommand, wzUserArgs); + ExitOnFailure(hr, "Failed to append user args."); + } + // Make the cache location of the executable the current directory to help those executables // that expect stuff to be relative to them. si.cb = sizeof(si); - if (!::CreateProcessW(wzExecutablePath, wzCommand, NULL, NULL, fInheritHandles, CREATE_NO_WINDOW, NULL, wzCachedDirectory, &si, &pi)) + if (!::CreateProcessW(wzExecutablePath, sczCommand ? sczCommand : sczBaseCommand, NULL, NULL, fInheritHandles, CREATE_NO_WINDOW, NULL, wzCachedDirectory, &si, &pi)) { ExitWithLastError(hr, "Failed to CreateProcess on path: %ls", wzExecutablePath); } @@ -632,6 +638,7 @@ extern "C" HRESULT ExeEngineRunProcess( } LExit: + StrSecureZeroFreeString(sczCommand); ReleaseHandle(pi.hThread); ReleaseHandle(pi.hProcess); 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( __in LPVOID pvContext, __in BURN_PACKAGE* pPackage, __in_z LPCWSTR wzExecutablePath, - __in_z LPWSTR wzCommand, + __in_z LPWSTR sczBaseCommand, + __in_z_opt LPCWSTR wzUserArgs, __in_z_opt LPCWSTR wzCachedDirectory, __inout DWORD* pdwExitCode ); 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( LPWSTR sczSystemPath = NULL; LPWSTR sczWusaPath = NULL; LPWSTR sczCommand = NULL; + LPWSTR sczEscapedKB = NULL; SC_HANDLE schWu = NULL; BOOL fWuWasDisabled = FALSE; STARTUPINFOW si = { }; @@ -328,8 +329,11 @@ extern "C" HRESULT MsuEngineExecutePackage( break; case BOOTSTRAPPER_ACTION_STATE_UNINSTALL: + hr = AppEscapeCommandLineArgumentFormatted(&sczEscapedKB, L"%ls", pPackage->Msu.sczKB); + ExitOnFailure(hr, "Failed to escape MSU KB."); + // format command - hr = StrAllocFormatted(&sczCommand, L"\"%ls\" /uninstall /kb:%ls /quiet /norestart", sczWusaPath, pPackage->Msu.sczKB); + hr = StrAllocFormatted(&sczCommand, L"\"%ls\" /uninstall /kb:%ls /quiet /norestart", sczWusaPath, sczEscapedKB); ExitOnFailure(hr, "Failed to format MSU uninstall command."); break; @@ -352,7 +356,7 @@ extern "C" HRESULT MsuEngineExecutePackage( hr = EnsureWUServiceEnabled(fStopWusaService, &schWu, &fWuWasDisabled); ExitOnFailure(hr, "Failed to ensure WU service was enabled to install MSU package."); - hr = ExeEngineRunProcess(pfnGenericMessageHandler, pvContext, pPackage, sczWusaPath, sczCommand, NULL, &dwExitCode); + hr = ExeEngineRunProcess(pfnGenericMessageHandler, pvContext, pPackage, sczWusaPath, sczCommand, NULL, NULL, &dwExitCode); ExitOnFailure(hr, "Failed to run MSU process"); // We'll normalize the restart required error code from wusa.exe just in case. Most likely @@ -389,6 +393,7 @@ LExit: ReleaseStr(sczWindowsPath); ReleaseStr(sczWusaPath); ReleaseStr(sczCommand); + ReleaseStr(sczEscapedKB); ReleaseHandle(pi.hProcess); 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: } extern "C" HRESULT NetFxRunChainer( - __in LPCWSTR wzExecutablePath, - __in LPCWSTR wzArguments, + __in_z LPCWSTR wzExecutablePath, + __in_z LPWSTR sczBaseCommand, + __in_z_opt LPCWSTR wzUserArgs, __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler, __in LPVOID pvContext, __out DWORD* pdwExitCode @@ -360,8 +361,15 @@ extern "C" HRESULT NetFxRunChainer( hr = CreateNetFxChainer(sczSectionName, sczEventName, &pNetfxChainer); ExitOnFailure(hr, "Failed to create netfx chainer."); - hr = StrAllocFormattedSecure(&sczCommand, L"%ls /pipe %ls", wzArguments, sczSectionName); - ExitOnFailure(hr, "Failed to allocate netfx chainer arguments."); + hr = StrAllocFormatted(&sczCommand, L"%ls /pipe %ls", sczBaseCommand, sczSectionName); + ExitOnFailure(hr, "Failed to append netfx chainer args."); + + // Always add user supplied arguments last. + if (wzUserArgs) + { + hr = StrAllocConcatFormattedSecure(&sczCommand, L" %ls", wzUserArgs); + ExitOnFailure(hr, "Failed to append user args."); + } si.cb = sizeof(si); 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 }; HRESULT NetFxRunChainer( - __in LPCWSTR wzExecutablePath, - __in LPCWSTR wzArguments, + __in_z LPCWSTR wzExecutablePath, + __in_z LPWSTR sczBaseCommand, + __in_z_opt LPCWSTR wzUserArgs, __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler, __in LPVOID pvContext, __out DWORD* pdwExitCode -- cgit v1.2.3-55-g6feb