From 266b097c0b0a13dd4934f55f61cad62ffcbb953d Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Fri, 3 Jun 2022 17:49:33 -0500 Subject: REG_EXPAND_SZ values are not necessarily a path. --- src/libs/dutil/WixToolset.DUtil/dutil.vcxproj | 2 + .../dutil/WixToolset.DUtil/dutil.vcxproj.filters | 6 ++ src/libs/dutil/WixToolset.DUtil/envutil.cpp | 78 ++++++++++++++++++++++ src/libs/dutil/WixToolset.DUtil/inc/dutilsources.h | 1 + src/libs/dutil/WixToolset.DUtil/inc/envutil.h | 22 ++++++ src/libs/dutil/WixToolset.DUtil/pathutil.cpp | 33 +-------- src/libs/dutil/WixToolset.DUtil/precomp.h | 1 + src/libs/dutil/WixToolset.DUtil/regutil.cpp | 2 +- .../dutil/test/DUtilUnitTest/DUtilUnitTest.vcxproj | 1 + .../DUtilUnitTest/DUtilUnitTest.vcxproj.filters | 3 + src/libs/dutil/test/DUtilUnitTest/EnvUtilTests.cpp | 50 ++++++++++++++ src/libs/dutil/test/DUtilUnitTest/RegUtilTest.cpp | 43 ++++++++++++ src/libs/dutil/test/DUtilUnitTest/precomp.h | 1 + 13 files changed, 211 insertions(+), 32 deletions(-) create mode 100644 src/libs/dutil/WixToolset.DUtil/envutil.cpp create mode 100644 src/libs/dutil/WixToolset.DUtil/inc/envutil.h create mode 100644 src/libs/dutil/test/DUtilUnitTest/EnvUtilTests.cpp (limited to 'src/libs') diff --git a/src/libs/dutil/WixToolset.DUtil/dutil.vcxproj b/src/libs/dutil/WixToolset.DUtil/dutil.vcxproj index 8a6f3b13..9d057461 100644 --- a/src/libs/dutil/WixToolset.DUtil/dutil.vcxproj +++ b/src/libs/dutil/WixToolset.DUtil/dutil.vcxproj @@ -65,6 +65,7 @@ Create 4091;4458 + @@ -130,6 +131,7 @@ + diff --git a/src/libs/dutil/WixToolset.DUtil/dutil.vcxproj.filters b/src/libs/dutil/WixToolset.DUtil/dutil.vcxproj.filters index dbbe68f4..556468b7 100644 --- a/src/libs/dutil/WixToolset.DUtil/dutil.vcxproj.filters +++ b/src/libs/dutil/WixToolset.DUtil/dutil.vcxproj.filters @@ -66,6 +66,9 @@ Source Files + + Source Files + Source Files @@ -251,6 +254,9 @@ Header Files + + Header Files + Header Files diff --git a/src/libs/dutil/WixToolset.DUtil/envutil.cpp b/src/libs/dutil/WixToolset.DUtil/envutil.cpp new file mode 100644 index 00000000..aa9da233 --- /dev/null +++ b/src/libs/dutil/WixToolset.DUtil/envutil.cpp @@ -0,0 +1,78 @@ +// 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" + + +// Exit macros +#define EnvExitOnLastError(x, s, ...) ExitOnLastErrorSource(DUTIL_SOURCE_ENVUTIL, x, s, __VA_ARGS__) +#define EnvExitOnLastErrorDebugTrace(x, s, ...) ExitOnLastErrorDebugTraceSource(DUTIL_SOURCE_ENVUTIL, x, s, __VA_ARGS__) +#define EnvExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_ENVUTIL, x, s, __VA_ARGS__) +#define EnvExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_ENVUTIL, x, s, __VA_ARGS__) +#define EnvExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_ENVUTIL, x, s, __VA_ARGS__) +#define EnvExitWithRootFailure(x, e, s, ...) ExitWithRootFailureSource(DUTIL_SOURCE_ENVUTIL, x, e, s, __VA_ARGS__) +#define EnvExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_ENVUTIL, x, s, __VA_ARGS__) +#define EnvExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_ENVUTIL, p, x, e, s, __VA_ARGS__) +#define EnvExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_ENVUTIL, p, x, s, __VA_ARGS__) +#define EnvExitOnNullDebugTrace(p, x, e, s, ...) ExitOnNullDebugTraceSource(DUTIL_SOURCE_ENVUTIL, p, x, e, s, __VA_ARGS__) +#define EnvExitOnInvalidHandleWithLastError(p, x, s, ...) ExitOnInvalidHandleWithLastErrorSource(DUTIL_SOURCE_ENVUTIL, p, x, s, __VA_ARGS__) +#define EnvExitOnWin32Error(e, x, s, ...) ExitOnWin32ErrorSource(DUTIL_SOURCE_ENVUTIL, e, x, s, __VA_ARGS__) +#define EnvExitOnGdipFailure(g, x, s, ...) ExitOnGdipFailureSource(DUTIL_SOURCE_ENVUTIL, g, x, s, __VA_ARGS__) + +#define ENV_GOOD_ENOUGH 64 + +DAPI_(HRESULT) EnvExpandEnvironmentStrings( + __in LPCWSTR wzSource, + __out LPWSTR* psczExpanded, + __out_opt SIZE_T* pcchExpanded + ) +{ + HRESULT hr = S_OK; + DWORD cch = 0; + DWORD cchExpanded = 0; + SIZE_T cchMax = 0; + + if (*psczExpanded) + { + hr = StrMaxLength(*psczExpanded, &cchMax); + EnvExitOnFailure(hr, "Failed to get max length of input buffer."); + + cchExpanded = (DWORD)min(DWORD_MAX, cchMax); + } + else + { + cchExpanded = ENV_GOOD_ENOUGH; + + hr = StrAlloc(psczExpanded, cchExpanded); + EnvExitOnFailure(hr, "Failed to allocate space for expanded path."); + } + + cch = ::ExpandEnvironmentStringsW(wzSource, *psczExpanded, cchExpanded); + if (!cch) + { + EnvExitWithLastError(hr, "Failed to expand environment variables in string: %ls", wzSource); + } + else if (cchExpanded < cch) + { + cchExpanded = cch; + hr = StrAlloc(psczExpanded, cchExpanded); + EnvExitOnFailure(hr, "Failed to re-allocate more space for expanded path."); + + cch = ::ExpandEnvironmentStringsW(wzSource, *psczExpanded, cchExpanded); + if (!cch) + { + EnvExitWithLastError(hr, "Failed to expand environment variables in string: %ls", wzSource); + } + else if (cchExpanded < cch) + { + EnvExitWithRootFailure(hr, HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), "Failed to allocate buffer for expanded string."); + } + } + + if (pcchExpanded) + { + *pcchExpanded = cch; + } + +LExit: + return hr; +} diff --git a/src/libs/dutil/WixToolset.DUtil/inc/dutilsources.h b/src/libs/dutil/WixToolset.DUtil/inc/dutilsources.h index 6affb392..f1dd5d1a 100644 --- a/src/libs/dutil/WixToolset.DUtil/inc/dutilsources.h +++ b/src/libs/dutil/WixToolset.DUtil/inc/dutilsources.h @@ -62,6 +62,7 @@ typedef enum DUTIL_SOURCE DUTIL_SOURCE_XMLUTIL, DUTIL_SOURCE_VERUTIL, DUTIL_SOURCE_WNDUTIL, + DUTIL_SOURCE_ENVUTIL, DUTIL_SOURCE_EXTERNAL = 256, } DUTIL_SOURCE; diff --git a/src/libs/dutil/WixToolset.DUtil/inc/envutil.h b/src/libs/dutil/WixToolset.DUtil/inc/envutil.h new file mode 100644 index 00000000..8491b27b --- /dev/null +++ b/src/libs/dutil/WixToolset.DUtil/inc/envutil.h @@ -0,0 +1,22 @@ +#pragma once +// 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. + + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************************************** + EnvExpandEnvironmentStrings - Wrapper for ::ExpandEnvironmentStrings. + + *******************************************************************/ +HRESULT DAPI EnvExpandEnvironmentStrings( + __in LPCWSTR wzSource, + __out LPWSTR* psczExpanded, + __out_opt SIZE_T* pcchExpanded + ); + +#ifdef __cplusplus +} +#endif + diff --git a/src/libs/dutil/WixToolset.DUtil/pathutil.cpp b/src/libs/dutil/WixToolset.DUtil/pathutil.cpp index dc33e656..becfc67e 100644 --- a/src/libs/dutil/WixToolset.DUtil/pathutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/pathutil.cpp @@ -181,10 +181,8 @@ DAPI_(HRESULT) PathExpand( Assert(wzRelativePath); HRESULT hr = S_OK; - DWORD cch = 0; LPWSTR sczExpandedPath = NULL; SIZE_T cchWritten = 0; - DWORD cchExpandedPath = 0; LPWSTR sczFullPath = NULL; DWORD dwPrefixFlags = 0; @@ -193,35 +191,8 @@ DAPI_(HRESULT) PathExpand( // if (dwResolveFlags & PATH_EXPAND_ENVIRONMENT) { - cchExpandedPath = PATH_GOOD_ENOUGH; - - hr = StrAlloc(&sczExpandedPath, cchExpandedPath); - PathExitOnFailure(hr, "Failed to allocate space for expanded path."); - - cch = ::ExpandEnvironmentStringsW(wzRelativePath, sczExpandedPath, cchExpandedPath); - if (0 == cch) - { - PathExitWithLastError(hr, "Failed to expand environment variables in string: %ls", wzRelativePath); - } - else if (cchExpandedPath < cch) - { - cchExpandedPath = cch; - hr = StrAlloc(&sczExpandedPath, cchExpandedPath); - PathExitOnFailure(hr, "Failed to re-allocate more space for expanded path."); - - cch = ::ExpandEnvironmentStringsW(wzRelativePath, sczExpandedPath, cchExpandedPath); - if (0 == cch) - { - PathExitWithLastError(hr, "Failed to expand environment variables in string: %ls", wzRelativePath); - } - else if (cchExpandedPath < cch) - { - hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - PathExitOnRootFailure(hr, "Failed to allocate buffer for expanded path."); - } - } - - cchWritten = cch; + hr = EnvExpandEnvironmentStrings(wzRelativePath, &sczExpandedPath, &cchWritten); + PathExitOnFailure(hr, "Failed to expand environment variables in string: %ls", wzRelativePath); } // diff --git a/src/libs/dutil/WixToolset.DUtil/precomp.h b/src/libs/dutil/WixToolset.DUtil/precomp.h index 902fe3e3..c9e4f74a 100644 --- a/src/libs/dutil/WixToolset.DUtil/precomp.h +++ b/src/libs/dutil/WixToolset.DUtil/precomp.h @@ -52,6 +52,7 @@ #include "cabutil.h" #include "conutil.h" #include "cryputil.h" +#include "envutil.h" #include "eseutil.h" #include "dirutil.h" #include "dlutil.h" diff --git a/src/libs/dutil/WixToolset.DUtil/regutil.cpp b/src/libs/dutil/WixToolset.DUtil/regutil.cpp index 584966ed..9a1b9ced 100644 --- a/src/libs/dutil/WixToolset.DUtil/regutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/regutil.cpp @@ -444,7 +444,7 @@ DAPI_(HRESULT) RegReadValue( if (fExpand && SUCCEEDED(hr) && REG_EXPAND_SZ == *pdwType) { LPWSTR sczValue = reinterpret_cast(*ppbBuffer); - hr = PathExpand(&sczExpand, sczValue, PATH_EXPAND_ENVIRONMENT); + hr = EnvExpandEnvironmentStrings(sczValue, &sczExpand, NULL); RegExitOnFailure(hr, "Failed to expand registry value: %ls", sczValue); *ppbBuffer = reinterpret_cast(sczExpand); diff --git a/src/libs/dutil/test/DUtilUnitTest/DUtilUnitTest.vcxproj b/src/libs/dutil/test/DUtilUnitTest/DUtilUnitTest.vcxproj index 5b40eaf1..ee9f505e 100644 --- a/src/libs/dutil/test/DUtilUnitTest/DUtilUnitTest.vcxproj +++ b/src/libs/dutil/test/DUtilUnitTest/DUtilUnitTest.vcxproj @@ -49,6 +49,7 @@ + diff --git a/src/libs/dutil/test/DUtilUnitTest/DUtilUnitTest.vcxproj.filters b/src/libs/dutil/test/DUtilUnitTest/DUtilUnitTest.vcxproj.filters index fde49348..bcda6df0 100644 --- a/src/libs/dutil/test/DUtilUnitTest/DUtilUnitTest.vcxproj.filters +++ b/src/libs/dutil/test/DUtilUnitTest/DUtilUnitTest.vcxproj.filters @@ -30,6 +30,9 @@ Source Files + + Source Files + Source Files diff --git a/src/libs/dutil/test/DUtilUnitTest/EnvUtilTests.cpp b/src/libs/dutil/test/DUtilUnitTest/EnvUtilTests.cpp new file mode 100644 index 00000000..76dfa774 --- /dev/null +++ b/src/libs/dutil/test/DUtilUnitTest/EnvUtilTests.cpp @@ -0,0 +1,50 @@ +// 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" + +using namespace System; +using namespace Xunit; +using namespace WixBuildTools::TestSupport; + +namespace DutilTests +{ + public ref class EnvUtil + { + public: + [Fact] + void EnvExpandEnvironmentStringsTest() + { + HRESULT hr = S_OK; + LPWSTR sczExpanded = NULL; + SIZE_T cchExpanded = 0; + LPCWSTR wzSimpleString = L"%USERPROFILE%"; + LPCWSTR wzMultipleString = L"%TEMP%;%PATH%"; + LPCWSTR wzLongMultipleString = L"%TEMP%;%PATH%;C:\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789"; + String^ expandedSimpleString = Environment::ExpandEnvironmentVariables(gcnew String(wzSimpleString)); + String^ expandedMultipleString = Environment::ExpandEnvironmentVariables(gcnew String(wzMultipleString)); + String^ expandedLongMultipleString = Environment::ExpandEnvironmentVariables(gcnew String(wzLongMultipleString)); + + try + { + hr = EnvExpandEnvironmentStrings(wzSimpleString, &sczExpanded, &cchExpanded); + NativeAssert::Succeeded(hr, "Failed to expand simple string."); + WixAssert::StringEqual(expandedSimpleString, gcnew String(sczExpanded), false); + NativeAssert::Equal(expandedSimpleString->Length + 1, cchExpanded); + + hr = EnvExpandEnvironmentStrings(wzMultipleString, &sczExpanded, &cchExpanded); + NativeAssert::Succeeded(hr, "Failed to expand multiple string."); + WixAssert::StringEqual(expandedMultipleString, gcnew String(sczExpanded), false); + NativeAssert::Equal(expandedMultipleString->Length + 1, cchExpanded); + + hr = EnvExpandEnvironmentStrings(wzLongMultipleString, &sczExpanded, &cchExpanded); + NativeAssert::Succeeded(hr, "Failed to expand long multiple string."); + WixAssert::StringEqual(expandedLongMultipleString, gcnew String(sczExpanded), false); + NativeAssert::Equal(expandedLongMultipleString->Length + 1, cchExpanded); + } + finally + { + ReleaseStr(sczExpanded); + } + } + }; +} diff --git a/src/libs/dutil/test/DUtilUnitTest/RegUtilTest.cpp b/src/libs/dutil/test/DUtilUnitTest/RegUtilTest.cpp index 575e3238..9e97f5e0 100644 --- a/src/libs/dutil/test/DUtilUnitTest/RegUtilTest.cpp +++ b/src/libs/dutil/test/DUtilUnitTest/RegUtilTest.cpp @@ -207,6 +207,49 @@ namespace DutilTests } } + [Fact] + void RegUtilExpandLongStringValueTest() + { + this->ExpandLongStringValueTest(); + } + + [Fact] + void RegUtilExpandLongStringValueFallbackTest() + { + RegFunctionForceFallback(); + this->ExpandLongStringValueTest(); + } + + void ExpandLongStringValueTest() + { + HRESULT hr = S_OK; + LPWSTR sczValue = NULL; + LPCWSTR wzValue = L"%TEMP%;%PATH%;C:\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789"; + String^ expandedValue = Environment::ExpandEnvironmentVariables(gcnew String(wzValue)); + + try + { + this->CreateBaseKey(); + + hr = RegWriteExpandString(hkBase, L"ExpandString", wzValue); + NativeAssert::Succeeded(hr, "Failed to write expand string value."); + + hr = RegReadString(hkBase, L"ExpandString", &sczValue); + NativeAssert::Succeeded(hr, "Failed to read expand string value."); + WixAssert::StringEqual(expandedValue, gcnew String(sczValue), false); + + ReleaseNullStr(sczValue); + + hr = RegReadString(hkBase, L"ExpandString", &sczValue); + NativeAssert::Succeeded(hr, "Failed to read expand string value."); + WixAssert::StringEqual(expandedValue, gcnew String(sczValue), false); + } + finally + { + ReleaseStr(sczValue); + } + } + [Fact] void RegUtilNotExpandStringValueTest() { diff --git a/src/libs/dutil/test/DUtilUnitTest/precomp.h b/src/libs/dutil/test/DUtilUnitTest/precomp.h index e9f8770b..bc628816 100644 --- a/src/libs/dutil/test/DUtilUnitTest/precomp.h +++ b/src/libs/dutil/test/DUtilUnitTest/precomp.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3-55-g6feb