aboutsummaryrefslogtreecommitdiff
path: root/src/libs/dutil/WixToolset.DUtil/env2util.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/dutil/WixToolset.DUtil/env2util.cpp')
-rw-r--r--src/libs/dutil/WixToolset.DUtil/env2util.cpp80
1 files changed, 80 insertions, 0 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/env2util.cpp b/src/libs/dutil/WixToolset.DUtil/env2util.cpp
new file mode 100644
index 00000000..21bbd101
--- /dev/null
+++ b/src/libs/dutil/WixToolset.DUtil/env2util.cpp
@@ -0,0 +1,80 @@
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 ENV2_GOOD_ENOUGH 64
22
23DAPI_(HRESULT) EnvExpandEnvironmentStringsForUser(
24 __in_opt HANDLE hToken,
25 __in LPCWSTR wzSource,
26 __out LPWSTR* psczExpanded,
27 __out_opt SIZE_T* pcchExpanded
28 )
29{
30 HRESULT hr = S_OK;
31 DWORD cchExpanded = 0;
32 SIZE_T cchMax = 0;
33 const DWORD dwMaxAttempts = 20;
34
35 if (*psczExpanded)
36 {
37 hr = StrMaxLength(*psczExpanded, &cchMax);
38 EnvExitOnFailure(hr, "Failed to get max length of input buffer.");
39
40 cchExpanded = (DWORD)min(DWORD_MAX, cchMax);
41 }
42 else
43 {
44 cchExpanded = ENV2_GOOD_ENOUGH;
45
46 hr = StrAlloc(psczExpanded, cchExpanded);
47 EnvExitOnFailure(hr, "Failed to allocate space for expanded path.");
48 }
49
50 for (DWORD i = 0; i < dwMaxAttempts; ++i)
51 {
52 if (::ExpandEnvironmentStringsForUserW(hToken, wzSource, *psczExpanded, cchExpanded))
53 {
54 break;
55 }
56
57 hr = HRESULT_FROM_WIN32(::GetLastError());
58 if (E_INSUFFICIENT_BUFFER != hr || (dwMaxAttempts - 1) == i)
59 {
60 EnvExitWithRootFailure(hr, hr, "Failed to expand environment variables in string: %ls", wzSource);
61 }
62
63 cchExpanded *= 2;
64
65 hr = StrAlloc(psczExpanded, cchExpanded);
66 EnvExitOnFailure(hr, "Failed to re-allocate more space for expanded path.");
67 }
68
69 if (pcchExpanded)
70 {
71 hr = ::StringCchLengthW(*psczExpanded, STRSAFE_MAX_LENGTH, reinterpret_cast<size_t*>(pcchExpanded));
72 EnvExitOnFailure(hr, "Failed to get max length of written input buffer.");
73
74 // Add 1 for null terminator.
75 *pcchExpanded += 1;
76 }
77
78LExit:
79 return hr;
80}