@joebigelow / wix-1 / commits / 266b097c

REG_EXPAND_SZ values are not necessarily a path.

Sean Hall committed Jun 3, 2022 at 17:49 UTC 266b097c0b0a13dd4934f55f61cad62ffcbb953d
13 files changed +211 -32
src/libs/dutil/WixToolset.DUtil/dutil.vcxproj
+2
@@ -65,6 +65,7 @@
65 <PrecompiledHeader>Create</PrecompiledHeader>
66 <DisableSpecificWarnings>4091;4458</DisableSpecificWarnings>
67 </ClCompile>
68 + <ClCompile Include="envutil.cpp" />
69 <ClCompile Include="eseutil.cpp" />
70 <ClCompile Include="file2utl.cpp" />
71 <ClCompile Include="fileutil.cpp" />
@@ -130,6 +131,7 @@
131 <ClInclude Include="inc\dpiutil.h" />
132 <ClInclude Include="inc\dutil.h" />
133 <ClInclude Include="inc\dutilsources.h" />
134 + <ClInclude Include="inc\envutil.h" />
135 <ClInclude Include="inc\eseutil.h" />
136 <ClInclude Include="inc\fileutil.h" />
137 <ClInclude Include="inc\gdiputil.h" />
src/libs/dutil/WixToolset.DUtil/dutil.vcxproj.filters
+6
@@ -66,6 +66,9 @@
66 <ClCompile Include="dutil.cpp">
67 <Filter>Source Files</Filter>
68 </ClCompile>
69 + <ClCompile Include="envutil.cpp">
70 + <Filter>Source Files</Filter>
71 + </ClCompile>
72 <ClCompile Include="eseutil.cpp">
73 <Filter>Source Files</Filter>
74 </ClCompile>
@@ -251,6 +254,9 @@
254 <ClInclude Include="inc\dutilsources.h">
255 <Filter>Header Files</Filter>
256 </ClInclude>
257 + <ClInclude Include="inc\envutil.h">
258 + <Filter>Header Files</Filter>
259 + </ClInclude>
260 <ClInclude Include="inc\eseutil.h">
261 <Filter>Header Files</Filter>
262 </ClInclude>
src/libs/dutil/WixToolset.DUtil/envutil.cpp new
+78
@@ -0,0 +1,78 @@
1 +// 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.
2 +
3 +#include "precomp.h"
4 +
5 +
6 +// Exit macros
7 +#define EnvExitOnLastError(x, s, ...) ExitOnLastErrorSource(DUTIL_SOURCE_ENVUTIL, x, s, __VA_ARGS__)
8 +#define EnvExitOnLastErrorDebugTrace(x, s, ...) ExitOnLastErrorDebugTraceSource(DUTIL_SOURCE_ENVUTIL, x, s, __VA_ARGS__)
9 +#define EnvExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_ENVUTIL, x, s, __VA_ARGS__)
10 +#define EnvExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_ENVUTIL, x, s, __VA_ARGS__)
11 +#define EnvExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_ENVUTIL, x, s, __VA_ARGS__)
12 +#define EnvExitWithRootFailure(x, e, s, ...) ExitWithRootFailureSource(DUTIL_SOURCE_ENVUTIL, x, e, s, __VA_ARGS__)
13 +#define EnvExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_ENVUTIL, x, s, __VA_ARGS__)
14 +#define EnvExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_ENVUTIL, p, x, e, s, __VA_ARGS__)
15 +#define EnvExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_ENVUTIL, p, x, s, __VA_ARGS__)
16 +#define EnvExitOnNullDebugTrace(p, x, e, s, ...) ExitOnNullDebugTraceSource(DUTIL_SOURCE_ENVUTIL, p, x, e, s, __VA_ARGS__)
17 +#define EnvExitOnInvalidHandleWithLastError(p, x, s, ...) ExitOnInvalidHandleWithLastErrorSource(DUTIL_SOURCE_ENVUTIL, p, x, s, __VA_ARGS__)
18 +#define EnvExitOnWin32Error(e, x, s, ...) ExitOnWin32ErrorSource(DUTIL_SOURCE_ENVUTIL, e, x, s, __VA_ARGS__)
19 +#define EnvExitOnGdipFailure(g, x, s, ...) ExitOnGdipFailureSource(DUTIL_SOURCE_ENVUTIL, g, x, s, __VA_ARGS__)
20 +
21 +#define ENV_GOOD_ENOUGH 64
22 +
23 +DAPI_(HRESULT) EnvExpandEnvironmentStrings(
24 + __in LPCWSTR wzSource,
25 + __out LPWSTR* psczExpanded,
26 + __out_opt SIZE_T* pcchExpanded
27 + )
28 +{
29 + HRESULT hr = S_OK;
30 + DWORD cch = 0;
31 + DWORD cchExpanded = 0;
32 + SIZE_T cchMax = 0;
33 +
34 + if (*psczExpanded)
35 + {
36 + hr = StrMaxLength(*psczExpanded, &cchMax);
37 + EnvExitOnFailure(hr, "Failed to get max length of input buffer.");
38 +
39 + cchExpanded = (DWORD)min(DWORD_MAX, cchMax);
40 + }
41 + else
42 + {
43 + cchExpanded = ENV_GOOD_ENOUGH;
44 +
45 + hr = StrAlloc(psczExpanded, cchExpanded);
46 + EnvExitOnFailure(hr, "Failed to allocate space for expanded path.");
47 + }
48 +
49 + cch = ::ExpandEnvironmentStringsW(wzSource, *psczExpanded, cchExpanded);
50 + if (!cch)
51 + {
52 + EnvExitWithLastError(hr, "Failed to expand environment variables in string: %ls", wzSource);
53 + }
54 + else if (cchExpanded < cch)
55 + {
56 + cchExpanded = cch;
57 + hr = StrAlloc(psczExpanded, cchExpanded);
58 + EnvExitOnFailure(hr, "Failed to re-allocate more space for expanded path.");
59 +
60 + cch = ::ExpandEnvironmentStringsW(wzSource, *psczExpanded, cchExpanded);
61 + if (!cch)
62 + {
63 + EnvExitWithLastError(hr, "Failed to expand environment variables in string: %ls", wzSource);
64 + }
65 + else if (cchExpanded < cch)
66 + {
67 + EnvExitWithRootFailure(hr, HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), "Failed to allocate buffer for expanded string.");
68 + }
69 + }
70 +
71 + if (pcchExpanded)
72 + {
73 + *pcchExpanded = cch;
74 + }
75 +
76 +LExit:
77 + return hr;
78 +}
src/libs/dutil/WixToolset.DUtil/inc/dutilsources.h
+1
@@ -62,6 +62,7 @@ typedef enum DUTIL_SOURCE
62 DUTIL_SOURCE_XMLUTIL,
63 DUTIL_SOURCE_VERUTIL,
64 DUTIL_SOURCE_WNDUTIL,
65 + DUTIL_SOURCE_ENVUTIL,
66
67 DUTIL_SOURCE_EXTERNAL = 256,
68 } DUTIL_SOURCE;
src/libs/dutil/WixToolset.DUtil/inc/envutil.h new
+22
@@ -0,0 +1,22 @@
1 +#pragma once
2 +// 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.
3 +
4 +
5 +#ifdef __cplusplus
6 +extern "C" {
7 +#endif
8 +
9 +/********************************************************************
10 + EnvExpandEnvironmentStrings - Wrapper for ::ExpandEnvironmentStrings.
11 +
12 + *******************************************************************/
13 +HRESULT DAPI EnvExpandEnvironmentStrings(
14 + __in LPCWSTR wzSource,
15 + __out LPWSTR* psczExpanded,
16 + __out_opt SIZE_T* pcchExpanded
17 + );
18 +
19 +#ifdef __cplusplus
20 +}
21 +#endif
22 +
src/libs/dutil/WixToolset.DUtil/pathutil.cpp
+2 -31
@@ -181,10 +181,8 @@ DAPI_(HRESULT) PathExpand(
181 Assert(wzRelativePath);
182
183 HRESULT hr = S_OK;
184 - DWORD cch = 0;
184 LPWSTR sczExpandedPath = NULL;
185 SIZE_T cchWritten = 0;
187 - DWORD cchExpandedPath = 0;
186 LPWSTR sczFullPath = NULL;
187 DWORD dwPrefixFlags = 0;
188
@@ -193,35 +191,8 @@ DAPI_(HRESULT) PathExpand(
191 //
192 if (dwResolveFlags & PATH_EXPAND_ENVIRONMENT)
193 {
196 - cchExpandedPath = PATH_GOOD_ENOUGH;
197 -
198 - hr = StrAlloc(&sczExpandedPath, cchExpandedPath);
199 - PathExitOnFailure(hr, "Failed to allocate space for expanded path.");
200 -
201 - cch = ::ExpandEnvironmentStringsW(wzRelativePath, sczExpandedPath, cchExpandedPath);
202 - if (0 == cch)
203 - {
204 - PathExitWithLastError(hr, "Failed to expand environment variables in string: %ls", wzRelativePath);
205 - }
206 - else if (cchExpandedPath < cch)
207 - {
208 - cchExpandedPath = cch;
209 - hr = StrAlloc(&sczExpandedPath, cchExpandedPath);
210 - PathExitOnFailure(hr, "Failed to re-allocate more space for expanded path.");
211 -
212 - cch = ::ExpandEnvironmentStringsW(wzRelativePath, sczExpandedPath, cchExpandedPath);
213 - if (0 == cch)
214 - {
215 - PathExitWithLastError(hr, "Failed to expand environment variables in string: %ls", wzRelativePath);
216 - }
217 - else if (cchExpandedPath < cch)
218 - {
219 - hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
220 - PathExitOnRootFailure(hr, "Failed to allocate buffer for expanded path.");
221 - }
222 - }
223 -
224 - cchWritten = cch;
194 + hr = EnvExpandEnvironmentStrings(wzRelativePath, &sczExpandedPath, &cchWritten);
195 + PathExitOnFailure(hr, "Failed to expand environment variables in string: %ls", wzRelativePath);
196 }
197
198 //
src/libs/dutil/WixToolset.DUtil/precomp.h
+1
@@ -52,6 +52,7 @@
52 #include "cabutil.h"
53 #include "conutil.h"
54 #include "cryputil.h"
55 +#include "envutil.h"
56 #include "eseutil.h"
57 #include "dirutil.h"
58 #include "dlutil.h"
src/libs/dutil/WixToolset.DUtil/regutil.cpp
+1 -1
@@ -444,7 +444,7 @@ DAPI_(HRESULT) RegReadValue(
444 if (fExpand && SUCCEEDED(hr) && REG_EXPAND_SZ == *pdwType)
445 {
446 LPWSTR sczValue = reinterpret_cast<LPWSTR>(*ppbBuffer);
447 - hr = PathExpand(&sczExpand, sczValue, PATH_EXPAND_ENVIRONMENT);
447 + hr = EnvExpandEnvironmentStrings(sczValue, &sczExpand, NULL);
448 RegExitOnFailure(hr, "Failed to expand registry value: %ls", sczValue);
449
450 *ppbBuffer = reinterpret_cast<LPBYTE>(sczExpand);
src/libs/dutil/test/DUtilUnitTest/DUtilUnitTest.vcxproj
+1
@@ -49,6 +49,7 @@
49 <ClCompile Include="DictUtilTest.cpp" />
50 <ClCompile Include="DirUtilTests.cpp" />
51 <ClCompile Include="DUtilTests.cpp" />
52 + <ClCompile Include="EnvUtilTests.cpp" />
53 <ClCompile Include="error.cpp" />
54 <ClCompile Include="FileUtilTest.cpp" />
55 <ClCompile Include="GuidUtilTest.cpp" />
src/libs/dutil/test/DUtilUnitTest/DUtilUnitTest.vcxproj.filters
+3
@@ -30,6 +30,9 @@
30 <ClCompile Include="DUtilTests.cpp">
31 <Filter>Source Files</Filter>
32 </ClCompile>
33 + <ClCompile Include="EnvUtilTests.cpp">
34 + <Filter>Source Files</Filter>
35 + </ClCompile>
36 <ClCompile Include="error.cpp">
37 <Filter>Source Files</Filter>
38 </ClCompile>
src/libs/dutil/test/DUtilUnitTest/EnvUtilTests.cpp new
+50
@@ -0,0 +1,50 @@
1 +// 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.
2 +
3 +#include "precomp.h"
4 +
5 +using namespace System;
6 +using namespace Xunit;
7 +using namespace WixBuildTools::TestSupport;
8 +
9 +namespace DutilTests
10 +{
11 + public ref class EnvUtil
12 + {
13 + public:
14 + [Fact]
15 + void EnvExpandEnvironmentStringsTest()
16 + {
17 + HRESULT hr = S_OK;
18 + LPWSTR sczExpanded = NULL;
19 + SIZE_T cchExpanded = 0;
20 + LPCWSTR wzSimpleString = L"%USERPROFILE%";
21 + LPCWSTR wzMultipleString = L"%TEMP%;%PATH%";
22 + LPCWSTR wzLongMultipleString = L"%TEMP%;%PATH%;C:\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789";
23 + String^ expandedSimpleString = Environment::ExpandEnvironmentVariables(gcnew String(wzSimpleString));
24 + String^ expandedMultipleString = Environment::ExpandEnvironmentVariables(gcnew String(wzMultipleString));
25 + String^ expandedLongMultipleString = Environment::ExpandEnvironmentVariables(gcnew String(wzLongMultipleString));
26 +
27 + try
28 + {
29 + hr = EnvExpandEnvironmentStrings(wzSimpleString, &sczExpanded, &cchExpanded);
30 + NativeAssert::Succeeded(hr, "Failed to expand simple string.");
31 + WixAssert::StringEqual(expandedSimpleString, gcnew String(sczExpanded), false);
32 + NativeAssert::Equal<SIZE_T>(expandedSimpleString->Length + 1, cchExpanded);
33 +
34 + hr = EnvExpandEnvironmentStrings(wzMultipleString, &sczExpanded, &cchExpanded);
35 + NativeAssert::Succeeded(hr, "Failed to expand multiple string.");
36 + WixAssert::StringEqual(expandedMultipleString, gcnew String(sczExpanded), false);
37 + NativeAssert::Equal<SIZE_T>(expandedMultipleString->Length + 1, cchExpanded);
38 +
39 + hr = EnvExpandEnvironmentStrings(wzLongMultipleString, &sczExpanded, &cchExpanded);
40 + NativeAssert::Succeeded(hr, "Failed to expand long multiple string.");
41 + WixAssert::StringEqual(expandedLongMultipleString, gcnew String(sczExpanded), false);
42 + NativeAssert::Equal<SIZE_T>(expandedLongMultipleString->Length + 1, cchExpanded);
43 + }
44 + finally
45 + {
46 + ReleaseStr(sczExpanded);
47 + }
48 + }
49 + };
50 +}
src/libs/dutil/test/DUtilUnitTest/RegUtilTest.cpp
+43
@@ -207,6 +207,49 @@ namespace DutilTests
207 }
208 }
209
210 + [Fact]
211 + void RegUtilExpandLongStringValueTest()
212 + {
213 + this->ExpandLongStringValueTest();
214 + }
215 +
216 + [Fact]
217 + void RegUtilExpandLongStringValueFallbackTest()
218 + {
219 + RegFunctionForceFallback();
220 + this->ExpandLongStringValueTest();
221 + }
222 +
223 + void ExpandLongStringValueTest()
224 + {
225 + HRESULT hr = S_OK;
226 + LPWSTR sczValue = NULL;
227 + LPCWSTR wzValue = L"%TEMP%;%PATH%;C:\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789";
228 + String^ expandedValue = Environment::ExpandEnvironmentVariables(gcnew String(wzValue));
229 +
230 + try
231 + {
232 + this->CreateBaseKey();
233 +
234 + hr = RegWriteExpandString(hkBase, L"ExpandString", wzValue);
235 + NativeAssert::Succeeded(hr, "Failed to write expand string value.");
236 +
237 + hr = RegReadString(hkBase, L"ExpandString", &sczValue);
238 + NativeAssert::Succeeded(hr, "Failed to read expand string value.");
239 + WixAssert::StringEqual(expandedValue, gcnew String(sczValue), false);
240 +
241 + ReleaseNullStr(sczValue);
242 +
243 + hr = RegReadString(hkBase, L"ExpandString", &sczValue);
244 + NativeAssert::Succeeded(hr, "Failed to read expand string value.");
245 + WixAssert::StringEqual(expandedValue, gcnew String(sczValue), false);
246 + }
247 + finally
248 + {
249 + ReleaseStr(sczValue);
250 + }
251 + }
252 +
253 [Fact]
254 void RegUtilNotExpandStringValueTest()
255 {
src/libs/dutil/test/DUtilUnitTest/precomp.h
+1
@@ -15,6 +15,7 @@
15 #include <atomutil.h>
16 #include <dictutil.h>
17 #include <dirutil.h>
18 +#include <envutil.h>
19 #include <fileutil.h>
20 #include <guidutil.h>
21 #include <iniutil.h>