From 9af6ee7031536ccb91fc2eb2f8521a0ac286db2c Mon Sep 17 00:00:00 2001 From: Nir Bar Date: Thu, 3 Apr 2025 09:26:20 +0300 Subject: Support launching rundll32.exe as a safe executable if the dll it loads is in a secure location --- src/burn/engine/approvedexe.cpp | 105 ++++++- src/burn/engine/approvedexe.h | 4 +- src/burn/engine/bundlepackageengine.cpp | 2 +- src/burn/engine/elevation.cpp | 2 +- src/burn/engine/exeengine.cpp | 29 +- src/burn/test/BurnUnitTest/ApprovedExeTest.cpp | 312 +++++++++++++++++++++ src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj | 1 + .../test/BurnUnitTest/BurnUnitTest.vcxproj.filters | 5 +- src/burn/test/BurnUnitTest/precomp.h | 1 + .../burn/WixToolsetTest.BurnE2E/ExePackageTests.cs | 14 +- 10 files changed, 450 insertions(+), 25 deletions(-) create mode 100644 src/burn/test/BurnUnitTest/ApprovedExeTest.cpp (limited to 'src') diff --git a/src/burn/engine/approvedexe.cpp b/src/burn/engine/approvedexe.cpp index 28b26d6d..383ee7fa 100644 --- a/src/burn/engine/approvedexe.cpp +++ b/src/burn/engine/approvedexe.cpp @@ -3,6 +3,13 @@ #include "precomp.h" +// internal function declarations + +static HRESULT IsRunDll32( + __in BURN_VARIABLES* pVariables, + __in LPCWSTR wzExecutablePath + ); + // function definitions extern "C" HRESULT ApprovedExesParseFromXml( @@ -221,12 +228,15 @@ LExit: extern "C" HRESULT ApprovedExesVerifySecureLocation( __in BURN_CACHE* pCache, __in BURN_VARIABLES* pVariables, - __in LPCWSTR wzExecutablePath + __in LPCWSTR wzExecutablePath, + __in int argc, + __in LPCWSTR* argv ) { HRESULT hr = S_OK; LPWSTR scz = NULL; LPWSTR sczSecondary = NULL; + LPWSTR sczRunDll32Param = NULL; const LPCWSTR vrgSecureFolderVariables[] = { L"ProgramFiles64Folder", @@ -273,11 +283,104 @@ extern "C" HRESULT ApprovedExesVerifySecureLocation( ExitFunction(); } + // Test if executable is rundll32.exe, and it's target is in a secure location + // Example for CUDA UninstallString: "C:\WINDOWS\SysWOW64\RunDll32.EXE" "C:\Program Files\NVIDIA Corporation\Installer2\InstallerCore\NVI2.DLL",UninstallPackage CUDAToolkit_12.8 + if (argc && argv && argv[0] && *argv[0]) + { + hr = IsRunDll32(pVariables, wzExecutablePath); + ExitOnFailure(hr, "Failed to test whether executable is rundll32"); + + if (hr == S_OK) + { + LPCWSTR szComma = wcschr(argv[0], L','); + if (szComma && *szComma) + { + hr = StrAllocString(&sczRunDll32Param, argv[0], szComma - argv[0]); + ExitOnFailure(hr, "Failed to allocate string"); + } + else + { + hr = StrAllocString(&sczRunDll32Param, argv[0], 0); + ExitOnFailure(hr, "Failed to allocate string"); + } + + hr = ApprovedExesVerifySecureLocation(pCache, pVariables, sczRunDll32Param, 0, NULL); + ExitOnFailure(hr, "Failed to test whether rundll32's parameter, '%ls', is in a secure location", sczRunDll32Param); + if (hr == S_OK) + { + ExitFunction(); + } + } + } + hr = S_FALSE; LExit: ReleaseStr(scz); ReleaseStr(sczSecondary); + ReleaseStr(sczRunDll32Param); + + return hr; +} + +static HRESULT IsRunDll32( + __in BURN_VARIABLES* pVariables, + __in LPCWSTR wzExecutablePath + ) +{ + HRESULT hr = S_OK; + LPWSTR sczFolder = NULL; + LPWSTR sczFullPath = NULL; + BOOL fEqual = FALSE; + + hr = VariableGetString(pVariables, L"SystemFolder", &sczFolder); + ExitOnFailure(hr, "Failed to get the variable: SystemFolder"); + + hr = PathConcat(sczFolder, L"rundll32.exe", &sczFullPath); + ExitOnFailure(hr, "Failed to combine paths"); + + hr = PathCompareCanonicalized(wzExecutablePath, sczFullPath, &fEqual); + ExitOnFailure(hr, "Failed to compare paths"); + if (fEqual) + { + hr = S_OK; + ExitFunction(); + } + + hr = VariableGetString(pVariables, L"System64Folder", &sczFolder); + ExitOnFailure(hr, "Failed to get the variable: System64Folder"); + + hr = PathConcat(sczFolder, L"rundll32.exe", &sczFullPath); + ExitOnFailure(hr, "Failed to combine paths"); + + hr = PathCompareCanonicalized(wzExecutablePath, sczFullPath, &fEqual); + ExitOnFailure(hr, "Failed to compare paths"); + if (fEqual) + { + hr = S_OK; + ExitFunction(); + } + + // Sysnative + hr = PathSystemWindowsSubdirectory(L"SysNative\\", &sczFolder); + ExitOnFailure(hr, "Failed to append SysNative directory."); + + hr = PathConcat(sczFolder, L"rundll32.exe", &sczFullPath); + ExitOnFailure(hr, "Failed to combine paths"); + + hr = PathCompareCanonicalized(wzExecutablePath, sczFullPath, &fEqual); + ExitOnFailure(hr, "Failed to compare paths"); + if (fEqual) + { + hr = S_OK; + ExitFunction(); + } + + hr = S_FALSE; + +LExit: + ReleaseStr(sczFolder); + ReleaseStr(sczFullPath); return hr; } diff --git a/src/burn/engine/approvedexe.h b/src/burn/engine/approvedexe.h index 7a68c174..0f441485 100644 --- a/src/burn/engine/approvedexe.h +++ b/src/burn/engine/approvedexe.h @@ -58,7 +58,9 @@ HRESULT ApprovedExesLaunch( HRESULT ApprovedExesVerifySecureLocation( __in BURN_CACHE* pCache, __in BURN_VARIABLES* pVariables, - __in LPCWSTR wzExecutablePath + __in LPCWSTR wzExecutablePath, + __in int argc, + __in LPCWSTR* argv ); diff --git a/src/burn/engine/bundlepackageengine.cpp b/src/burn/engine/bundlepackageengine.cpp index 574317e1..db433918 100644 --- a/src/burn/engine/bundlepackageengine.cpp +++ b/src/burn/engine/bundlepackageengine.cpp @@ -817,7 +817,7 @@ static HRESULT ExecuteBundle( if (pPackage->fPerMachine) { - hr = ApprovedExesVerifySecureLocation(pCache, pVariables, sczExecutablePath); + hr = ApprovedExesVerifySecureLocation(pCache, pVariables, sczExecutablePath, argcArp - 1, (argcArp > 1) ? const_cast(argvArp + 1) : NULL); ExitOnFailure(hr, "Failed to verify the QuietUninstallString executable path is in a secure location: %ls", sczExecutablePath); if (S_FALSE == hr) { diff --git a/src/burn/engine/elevation.cpp b/src/burn/engine/elevation.cpp index 90e9db01..f208efc9 100644 --- a/src/burn/engine/elevation.cpp +++ b/src/burn/engine/elevation.cpp @@ -3876,7 +3876,7 @@ static HRESULT OnLaunchApprovedExe( hr = RegReadString(hKey, pApprovedExe->sczValueName, &pLaunchApprovedExe->sczExecutablePath); ExitOnFailure(hr, "Failed to read the value for the approved exe path."); - hr = ApprovedExesVerifySecureLocation(pCache, pVariables, pLaunchApprovedExe->sczExecutablePath); + hr = ApprovedExesVerifySecureLocation(pCache, pVariables, pLaunchApprovedExe->sczExecutablePath, 0, NULL); ExitOnFailure(hr, "Failed to verify the executable path is in a secure location: %ls", pLaunchApprovedExe->sczExecutablePath); if (S_FALSE == hr) { diff --git a/src/burn/engine/exeengine.cpp b/src/burn/engine/exeengine.cpp index 85168943..3a2816dd 100644 --- a/src/burn/engine/exeengine.cpp +++ b/src/burn/engine/exeengine.cpp @@ -489,29 +489,30 @@ extern "C" HRESULT ExeEngineExecutePackage( } else if (BURN_EXE_DETECTION_TYPE_ARP == pPackage->Exe.detectionType && BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pExecuteAction->exePackage.action) { - ExitOnNull(sczArpUninstallString, hr, E_INVALIDARG, "%hs is null.", pPackage->Exe.fArpUseUninstallString ? "UninstallString" : "QuietUninstallString"); + LPCWSTR szRegName = pPackage->Exe.fArpUseUninstallString ? L"UninstallString" : L"QuietUninstallString"; + ExitOnNull(sczArpUninstallString, hr, E_INVALIDARG, "%ls is null.", szRegName); hr = AppParseCommandLine(sczArpUninstallString, &argcArp, &argvArp); - ExitOnFailure(hr, "Failed to parse QuietUninstallString: %ls.", sczArpUninstallString); + ExitOnFailure(hr, "Failed to parse %ls: %ls.", szRegName, sczArpUninstallString); - ExitOnNull(argcArp, hr, E_INVALIDARG, "QuietUninstallString must contain an executable path."); + ExitOnNull(argcArp, hr, E_INVALIDARG, "%ls must contain an executable path.", szRegName); hr = StrAllocString(&sczExecutablePath, argvArp[0], 0); ExitOnFailure(hr, "Failed to copy executable path."); if (pPackage->fPerMachine) { - hr = ApprovedExesVerifySecureLocation(pCache, pVariables, sczExecutablePath); - ExitOnFailure(hr, "Failed to verify the QuietUninstallString executable path is in a secure location: %ls", sczExecutablePath); + hr = ApprovedExesVerifySecureLocation(pCache, pVariables, sczExecutablePath, argcArp - 1, (argcArp > 1) ? const_cast(argvArp + 1) : NULL); + ExitOnFailure(hr, "Failed to verify the %ls executable path is in a secure location: %ls", szRegName, sczExecutablePath); if (S_FALSE == hr) { - LogStringLine(REPORT_STANDARD, "The QuietUninstallString executable path is not in a secure location: %ls", sczExecutablePath); + LogStringLine(REPORT_STANDARD, "The %ls executable path is not in a secure location: %ls", szRegName, sczExecutablePath); ExitFunction1(hr = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)); } } hr = PathGetDirectory(sczExecutablePath, &sczCachedDirectory); - ExitOnFailure(hr, "Failed to get parent directory for QuietUninstallString executable path: %ls", sczExecutablePath); + ExitOnFailure(hr, "Failed to get parent directory for %ls executable path: %ls", szRegName, sczExecutablePath); } else { @@ -587,13 +588,15 @@ extern "C" HRESULT ExeEngineExecutePackage( } // build base command - hr = StrAllocFormatted(&sczBaseCommand, L"\"%ls\"", sczExecutablePath); - ExitOnFailure(hr, "Failed to allocate base command."); - - for (int i = 1; i < argcArp; ++i) + if (sczArpUninstallString && *sczArpUninstallString) + { + hr = StrAllocString(&sczBaseCommand, sczArpUninstallString, 0); + ExitOnFailure(hr, "Failed to allocate base command."); + } + else { - hr = AppAppendCommandLineArgument(&sczBaseCommand, argvArp[i]); - ExitOnFailure(hr, "Failed to append argument from ARP."); + hr = StrAllocFormatted(&sczBaseCommand, L"\"%ls\"", sczExecutablePath); + ExitOnFailure(hr, "Failed to allocate base command."); } if (pPackage->Exe.fBundle) diff --git a/src/burn/test/BurnUnitTest/ApprovedExeTest.cpp b/src/burn/test/BurnUnitTest/ApprovedExeTest.cpp new file mode 100644 index 00000000..da51f1f8 --- /dev/null +++ b/src/burn/test/BurnUnitTest/ApprovedExeTest.cpp @@ -0,0 +1,312 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +#include "precomp.h" + +namespace Microsoft +{ +namespace Tools +{ +namespace WindowsInstallerXml +{ +namespace Test +{ +namespace Bootstrapper +{ + using namespace System; + using namespace System::IO; + using namespace Xunit; + + public ref class ApprovedExeTest : BurnUnitTest + { + public: + ApprovedExeTest(BurnTestFixture^ fixture) : BurnUnitTest(fixture) + { + } + + [Fact] + void ApprovedExesVerifyPFilesTest() + { + HRESULT hr = S_OK; + BURN_CACHE cache = { }; + BURN_ENGINE_COMMAND internalCommand = { }; + BURN_VARIABLES variables = { }; + LPWSTR scz = NULL; + LPWSTR scz2 = NULL; + + try + { + hr = VariableInitialize(&variables); + NativeAssert::Succeeded(hr, L"Failed to initialize variables."); + + hr = CacheInitialize(&cache, &internalCommand); + NativeAssert::Succeeded(hr, "Failed to initialize cache."); + + hr = VariableGetString(&variables, L"ProgramFilesFolder", &scz); + NativeAssert::Succeeded(hr, "Failed to get variable ProgramFilesFolder."); + + hr = PathConcat(scz, L"a.exe", &scz2); + NativeAssert::Succeeded(hr, "Failed to combine paths"); + + hr = ApprovedExesVerifySecureLocation(&cache, &variables, scz2, 0, NULL); + NativeAssert::Succeeded(hr, "Failed to test secure location under ProgramFilesFolder"); + Assert::True((hr == S_OK), "Path under ProgramFilesFolder was expected to be safe"); + } + finally + { + ReleaseStr(internalCommand.sczEngineWorkingDirectory); + ReleaseStr(scz); + ReleaseStr(scz2); + + CacheUninitialize(&cache); + VariablesUninitialize(&variables); + } + } + + [Fact] + void ApprovedExesVerifyPFilesWithRelativeTest() + { + HRESULT hr = S_OK; + BURN_CACHE cache = { }; + BURN_ENGINE_COMMAND internalCommand = { }; + BURN_VARIABLES variables = { }; + LPWSTR scz = NULL; + LPWSTR scz2 = NULL; + + try + { + hr = VariableInitialize(&variables); + NativeAssert::Succeeded(hr, L"Failed to initialize variables."); + + hr = CacheInitialize(&cache, &internalCommand); + NativeAssert::Succeeded(hr, "Failed to initialize cache."); + cache.fPerMachineCacheRootVerified = TRUE; + cache.fOriginalPerMachineCacheRootVerified = TRUE; + + hr = VariableGetString(&variables, L"ProgramFilesFolder", &scz); + NativeAssert::Succeeded(hr, "Failed to get variable ProgramFilesFolder."); + + hr = PathConcat(scz, L"..\\a.exe", &scz2); + NativeAssert::Succeeded(hr, "Failed to combine paths"); + + hr = ApprovedExesVerifySecureLocation(&cache, &variables, scz2, 0, NULL); + NativeAssert::Succeeded(hr, "Failed to test secure location under ProgramFilesFolder"); + Assert::True((hr == S_FALSE), "Path pretending to be under ProgramFilesFolder was expected to be unsafe"); + } + finally + { + ReleaseStr(internalCommand.sczEngineWorkingDirectory); + ReleaseStr(scz); + ReleaseStr(scz2); + + CacheUninitialize(&cache); + VariablesUninitialize(&variables); + } + } + + [Fact] + void ApprovedExesVerifyPFiles64Test() + { + HRESULT hr = S_OK; + BURN_CACHE cache = { }; + BURN_ENGINE_COMMAND internalCommand = { }; + BURN_VARIABLES variables = { }; + LPWSTR scz = NULL; + LPWSTR scz2 = NULL; + + try + { + hr = VariableInitialize(&variables); + NativeAssert::Succeeded(hr, L"Failed to initialize variables."); + + hr = CacheInitialize(&cache, &internalCommand); + NativeAssert::Succeeded(hr, "Failed to initialize cache."); + + hr = VariableGetString(&variables, L"ProgramFiles64Folder", &scz); + NativeAssert::Succeeded(hr, "Failed to get variable ProgramFiles64Folder."); + + hr = PathConcat(scz, L"a.exe", &scz2); + NativeAssert::Succeeded(hr, "Failed to combine paths"); + + hr = ApprovedExesVerifySecureLocation(&cache, &variables, scz2, 0, NULL); + NativeAssert::Succeeded(hr, "Failed to test secure location under ProgramFiles64Folder"); + Assert::True((hr == S_OK), "Path under ProgramFiles64Folder was expected to be safe"); + } + finally + { + ReleaseStr(internalCommand.sczEngineWorkingDirectory); + ReleaseStr(scz); + ReleaseStr(scz2); + + CacheUninitialize(&cache); + VariablesUninitialize(&variables); + } + } + + [Fact] + void ApprovedExesVerifySys64FolderTest() + { + HRESULT hr = S_OK; + BURN_CACHE cache = { }; + BURN_ENGINE_COMMAND internalCommand = { }; + BURN_VARIABLES variables = { }; + LPWSTR scz = NULL; + LPWSTR scz2 = NULL; + + try + { + hr = VariableInitialize(&variables); + NativeAssert::Succeeded(hr, L"Failed to initialize variables."); + + hr = CacheInitialize(&cache, &internalCommand); + NativeAssert::Succeeded(hr, "Failed to initialize cache."); + cache.fPerMachineCacheRootVerified = TRUE; + cache.fOriginalPerMachineCacheRootVerified = TRUE; + + hr = VariableGetString(&variables, L"System64Folder", &scz); + NativeAssert::Succeeded(hr, "Failed to get variable System64Folder."); + + hr = PathConcat(scz, L"a.exe", &scz2); + NativeAssert::Succeeded(hr, "Failed to combine paths"); + + hr = ApprovedExesVerifySecureLocation(&cache, &variables, scz2, 0, NULL); + NativeAssert::Succeeded(hr, "Failed to test secure location under System64Folder"); + Assert::True((hr == S_FALSE), "Path under System64Folder was expected to be unsafe"); + } + finally + { + ReleaseStr(internalCommand.sczEngineWorkingDirectory); + ReleaseStr(scz); + ReleaseStr(scz2); + + CacheUninitialize(&cache); + VariablesUninitialize(&variables); + } + } + + [Fact] + void ApprovedExesVerifySys64Rundll32UnsafeTest() + { + HRESULT hr = S_OK; + BURN_CACHE cache = { }; + BURN_ENGINE_COMMAND internalCommand = { }; + BURN_VARIABLES variables = { }; + LPWSTR scz = NULL; + LPWSTR scz2 = NULL; + LPWSTR szArgs = NULL; + + try + { + hr = VariableInitialize(&variables); + NativeAssert::Succeeded(hr, L"Failed to initialize variables."); + + hr = CacheInitialize(&cache, &internalCommand); + NativeAssert::Succeeded(hr, "Failed to initialize cache."); + cache.fPerMachineCacheRootVerified = TRUE; + cache.fOriginalPerMachineCacheRootVerified = TRUE; + + hr = VariableGetString(&variables, L"System64Folder", &scz); + NativeAssert::Succeeded(hr, "Failed to get variable System64Folder."); + + hr = PathConcat(scz, L"rundll32.exe", &scz2); + NativeAssert::Succeeded(hr, "Failed to combine paths"); + + hr = ApprovedExesVerifySecureLocation(&cache, &variables, scz2, 1, const_cast(&scz2)); + NativeAssert::Succeeded(hr, "Failed to test secure location under System64Folder"); + Assert::True((hr == S_FALSE), "Path under System64Folder was expected to be unsafe for rundll32 target"); + } + finally + { + ReleaseStr(internalCommand.sczEngineWorkingDirectory); + ReleaseStr(scz); + ReleaseStr(scz2); + ReleaseStr(szArgs); + + CacheUninitialize(&cache); + VariablesUninitialize(&variables); + } + } + + [Fact] + void ApprovedExesVerifySys64Rundll32SafeTest() + { + HRESULT hr = S_OK; + BURN_CACHE cache = { }; + BURN_ENGINE_COMMAND internalCommand = { }; + BURN_VARIABLES variables = { }; + LPWSTR scz = NULL; + LPWSTR scz2 = NULL; + LPWSTR scz3 = NULL; + + try + { + hr = VariableInitialize(&variables); + NativeAssert::Succeeded(hr, L"Failed to initialize variables."); + + hr = CacheInitialize(&cache, &internalCommand); + NativeAssert::Succeeded(hr, "Failed to initialize cache."); + cache.fPerMachineCacheRootVerified = TRUE; + cache.fOriginalPerMachineCacheRootVerified = TRUE; + + // System64Folder + hr = VariableGetString(&variables, L"System64Folder", &scz); + NativeAssert::Succeeded(hr, "Failed to get variable System64Folder."); + + hr = PathConcat(scz, L"rundll32.exe", &scz2); + NativeAssert::Succeeded(hr, "Failed to combine paths"); + + hr = VariableGetString(&variables, L"ProgramFiles64Folder", &scz); + NativeAssert::Succeeded(hr, "Failed to get variable ProgramFiles64Folder."); + + hr = PathConcat(scz, L"a.dll", &scz3); + NativeAssert::Succeeded(hr, "Failed to combine paths"); + + hr = ApprovedExesVerifySecureLocation(&cache, &variables, scz2, 1, const_cast(&scz3)); + NativeAssert::Succeeded(hr, "Failed to test secure location under ProgramFiles64Folder for System64Folder/rundll32 target"); + Assert::True((hr == S_OK), "Path under ProgramFiles64Folder was expected to be safe for System64Folder/rundll32 target"); + + hr = PathConcat(scz, L"a.dll,somthing else", &scz3); + NativeAssert::Succeeded(hr, "Failed to combine paths"); + + hr = ApprovedExesVerifySecureLocation(&cache, &variables, scz2, 1, const_cast(&scz3)); + NativeAssert::Succeeded(hr, "Failed to test secure location under ProgramFiles64Folder for rundll32 target"); + Assert::True((hr == S_OK), "Path under ProgramFiles64Folder was expected to be safe for System64Folder/rundll32 target"); + + // SystemFolder + hr = VariableGetString(&variables, L"SystemFolder", &scz); + NativeAssert::Succeeded(hr, "Failed to get variable System64Folder."); + + hr = PathConcat(scz, L"rundll32.exe", &scz2); + NativeAssert::Succeeded(hr, "Failed to combine paths"); + + hr = ApprovedExesVerifySecureLocation(&cache, &variables, scz2, 1, const_cast(&scz3)); + NativeAssert::Succeeded(hr, "Failed to test secure location under ProgramFiles64Folder for SystemFolder/rundll32 target"); + Assert::True((hr == S_OK), "Path under ProgramFiles64Folder was expected to be safe for SystemFolder/rundll32 target"); + + // Sysnative + hr = PathSystemWindowsSubdirectory(L"SysNative\\", &scz); + NativeAssert::Succeeded(hr, "Failed to get SysNative Folder."); + + hr = PathConcat(scz, L"rundll32.exe", &scz2); + NativeAssert::Succeeded(hr, "Failed to combine paths"); + + hr = ApprovedExesVerifySecureLocation(&cache, &variables, scz2, 1, const_cast(&scz3)); + NativeAssert::Succeeded(hr, "Failed to test secure location under ProgramFiles64Folder for Sysnative/rundll32 target"); + Assert::True((hr == S_OK), "Path under ProgramFiles64Folder was expected to be safe for Sysnative/rundll32 target"); + } + finally + { + ReleaseStr(internalCommand.sczEngineWorkingDirectory); + ReleaseStr(scz); + ReleaseStr(scz2); + ReleaseStr(scz3); + + CacheUninitialize(&cache); + VariablesUninitialize(&variables); + } + } + }; +} +} +} +} +} diff --git a/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj b/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj index 331d237b..63d089e4 100644 --- a/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj +++ b/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj @@ -45,6 +45,7 @@ + diff --git a/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj.filters b/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj.filters index 82725436..59aea6e9 100644 --- a/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj.filters +++ b/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj.filters @@ -66,6 +66,9 @@ Source Files + + Source Files + @@ -95,4 +98,4 @@ Resource Files - \ No newline at end of file + diff --git a/src/burn/test/BurnUnitTest/precomp.h b/src/burn/test/BurnUnitTest/precomp.h index f07f5968..ec6fb7d1 100644 --- a/src/burn/test/BurnUnitTest/precomp.h +++ b/src/burn/test/BurnUnitTest/precomp.h @@ -74,6 +74,7 @@ #include "splashscreen.h" #include "detect.h" #include "externalengine.h" +#include "approvedexe.h" #include "engine.version.h" diff --git a/src/test/burn/WixToolsetTest.BurnE2E/ExePackageTests.cs b/src/test/burn/WixToolsetTest.BurnE2E/ExePackageTests.cs index a7438564..e7c7ee5b 100644 --- a/src/test/burn/WixToolsetTest.BurnE2E/ExePackageTests.cs +++ b/src/test/burn/WixToolsetTest.BurnE2E/ExePackageTests.cs @@ -30,7 +30,7 @@ namespace WixToolsetTest.BurnE2E perMachineArpEntryExePackageBundle.VerifyUnregisteredAndRemovedFromPackageCache(); arpEntryExePackage.VerifyRegistered(false); - Assert.True(LogVerifier.MessageInLogFile(uninstallLogPath, $"testexe.exe\" /regd HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId}")); + Assert.True(LogVerifier.MessageInLogFile(uninstallLogPath, $"testexe.exe\" /regd \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId}\"")); } [RuntimeFact] @@ -52,7 +52,7 @@ namespace WixToolsetTest.BurnE2E perMachineArpEntryExePackageBundle.VerifyUnregisteredAndRemovedFromPackageCache(); arpEntryExePackage.VerifyRegistered(false); - Assert.True(LogVerifier.MessageInLogFile(uninstallLogPath, $"testexe.exe\" /regd HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId}")); + Assert.True(LogVerifier.MessageInLogFile(uninstallLogPath, $"testexe.exe\" /regd \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId}\"")); } [RuntimeFact] @@ -85,7 +85,7 @@ namespace WixToolsetTest.BurnE2E packageTestExe.VerifyInstalled(true); Assert.True(LogVerifier.MessageInLogFile(uninstallLogPath, "TESTBA: OnCachePackageNonVitalValidationFailure() - id: TestExe, default: None, requested: Acquire")); - Assert.True(LogVerifier.MessageInLogFile(uninstallLogPath, $"testexe.exe\" /regd HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId}")); + Assert.True(LogVerifier.MessageInLogFile(uninstallLogPath, $"testexe.exe\" /regd \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId}\"")); Assert.True(LogVerifier.MessageInLogFile(uninstallLogPath, $"TestExe.exe\" /regw \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},DisplayVersion,String,1.0.0.0\" /regw \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},QuietUninstallString,String,\\\"")); } @@ -113,7 +113,7 @@ namespace WixToolsetTest.BurnE2E packageTestExe.VerifyInstalled(true); Assert.False(LogVerifier.MessageInLogFile(uninstallLogPath, "TESTBA: OnCachePackageNonVitalValidationFailure() - id: TestExe")); - Assert.True(LogVerifier.MessageInLogFile(uninstallLogPath, $"testexe.exe\" /regd HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId}")); + Assert.True(LogVerifier.MessageInLogFile(uninstallLogPath, $"testexe.exe\" /regd \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId}\"")); Assert.True(LogVerifier.MessageInLogFile(uninstallLogPath, $"TestExe.exe\" /regw \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},DisplayVersion,String,1.0.0.0\" /regw \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},QuietUninstallString,String,\\\"")); } @@ -144,7 +144,7 @@ namespace WixToolsetTest.BurnE2E packageTestExe.VerifyInstalled(true); Assert.True(LogVerifier.MessageInLogFile(uninstallLogPath, "TESTBA: OnCachePackageNonVitalValidationFailure() - id: TestExe, default: None, requested: None")); - Assert.True(LogVerifier.MessageInLogFile(uninstallLogPath, $"testexe.exe\" /regd HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId}")); + Assert.True(LogVerifier.MessageInLogFile(uninstallLogPath, $"testexe.exe\" /regd \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId}\"")); } [RuntimeFact] @@ -161,7 +161,7 @@ namespace WixToolsetTest.BurnE2E arpEntryExePackage.VerifyRegistered(false); Assert.True(LogVerifier.MessageInLogFile(installLogPath, $"TestExe.exe\" /regw \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},DisplayVersion,String,1.0.0.0\" /regw \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},QuietUninstallString,String,\\\"")); - Assert.True(LogVerifier.MessageInLogFile(installLogPath, $"testexe.exe\" /regd HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId}")); + Assert.True(LogVerifier.MessageInLogFile(installLogPath, $"testexe.exe\" /regd \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId}\"")); } [RuntimeFact] @@ -209,7 +209,7 @@ namespace WixToolsetTest.BurnE2E perUserArpEntryExePackageBundle.VerifyUnregisteredAndRemovedFromPackageCache(); arpEntryExePackage.VerifyRegistered(false); - Assert.True(LogVerifier.MessageInLogFile(uninstallLogPath, $"testexe.exe\" /regd HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId}")); + Assert.True(LogVerifier.MessageInLogFile(uninstallLogPath, $"testexe.exe\" /regd \"HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId}\"")); } [RuntimeFact] -- cgit v1.2.3-55-g6feb