summaryrefslogtreecommitdiff
path: root/src/libs/dutil/WixToolset.DUtil/path3utl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/dutil/WixToolset.DUtil/path3utl.cpp')
-rw-r--r--src/libs/dutil/WixToolset.DUtil/path3utl.cpp143
1 files changed, 143 insertions, 0 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/path3utl.cpp b/src/libs/dutil/WixToolset.DUtil/path3utl.cpp
new file mode 100644
index 00000000..cb6ce6d5
--- /dev/null
+++ b/src/libs/dutil/WixToolset.DUtil/path3utl.cpp
@@ -0,0 +1,143 @@
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 PathExitOnLastError(x, s, ...) ExitOnLastErrorSource(DUTIL_SOURCE_PATHUTIL, x, s, __VA_ARGS__)
8#define PathExitOnLastErrorDebugTrace(x, s, ...) ExitOnLastErrorDebugTraceSource(DUTIL_SOURCE_PATHUTIL, x, s, __VA_ARGS__)
9#define PathExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_PATHUTIL, x, s, __VA_ARGS__)
10#define PathExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_PATHUTIL, x, s, __VA_ARGS__)
11#define PathExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_PATHUTIL, x, s, __VA_ARGS__)
12#define PathExitWithRootFailure(x, e, s, ...) ExitWithRootFailureSource(DUTIL_SOURCE_PATHUTIL, x, e, s, __VA_ARGS__)
13#define PathExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_PATHUTIL, x, s, __VA_ARGS__)
14#define PathExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_PATHUTIL, p, x, e, s, __VA_ARGS__)
15#define PathExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_PATHUTIL, p, x, s, __VA_ARGS__)
16#define PathExitOnNullDebugTrace(p, x, e, s, ...) ExitOnNullDebugTraceSource(DUTIL_SOURCE_PATHUTIL, p, x, e, s, __VA_ARGS__)
17#define PathExitOnInvalidHandleWithLastError(p, x, s, ...) ExitOnInvalidHandleWithLastErrorSource(DUTIL_SOURCE_PATHUTIL, p, x, s, __VA_ARGS__)
18#define PathExitOnWin32Error(e, x, s, ...) ExitOnWin32ErrorSource(DUTIL_SOURCE_PATHUTIL, e, x, s, __VA_ARGS__)
19#define PathExitOnGdipFailure(g, x, s, ...) ExitOnGdipFailureSource(DUTIL_SOURCE_PATHUTIL, g, x, s, __VA_ARGS__)
20
21static HRESULT GetTempPathFromSystemEnvironmentVariable(
22 __in HKEY hKey,
23 __in_z LPCWSTR wzName,
24 __out_z LPWSTR* psczPath
25 );
26
27DAPI_(HRESULT) PathGetSystemTempPaths(
28 __inout_z LPWSTR** prgsczSystemTempPaths,
29 __inout DWORD* pcSystemTempPaths
30 )
31{
32 HRESULT hr = S_OK;
33 HMODULE hModule = NULL;
34 BOOL fSystem = FALSE;
35 HKEY hKey = NULL;
36 LPWSTR sczTemp = NULL;
37
38 // Follow documented precedence rules for SystemTemp/%TMP%/%TEMP% from ::GetTempPath2.
39 hr = LoadSystemLibrary(L"kernel32.dll", &hModule);
40 PathExitOnFailure(hr, "Failed to load kernel32.dll");
41
42 // The SystemTemp folder was added at the same time as ::GetTempPath2.
43 if (::GetProcAddress(hModule, "GetTempPath2W"))
44 {
45 hr = ProcSystem(::GetCurrentProcess(), &fSystem);
46 PathExitOnFailure(hr, "Failed to check if running as system.");
47
48 if (fSystem)
49 {
50 hr = PathSystemWindowsSubdirectory(L"SystemTemp", &sczTemp);
51 PathExitOnFailure(hr, "Failed to get system Windows subdirectory path SystemTemp.");
52
53 hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczSystemTempPaths), *pcSystemTempPaths, 1, sizeof(LPWSTR), 4);
54 PathExitOnFailure(hr, "Failed to ensure array size for Windows\\SystemTemp value.");
55
56 (*prgsczSystemTempPaths)[*pcSystemTempPaths] = sczTemp;
57 sczTemp = NULL;
58 *pcSystemTempPaths += 1;
59 }
60 }
61
62 // There is no documented API to get system environment variables, so read them from the registry.
63 hr = RegOpen(HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Control\\Session Manager\\Environment", KEY_READ, &hKey);
64 if (E_FILENOTFOUND != hr)
65 {
66 PathExitOnFailure(hr, "Failed to open system environment registry key.");
67
68 hr = GetTempPathFromSystemEnvironmentVariable(hKey, L"TMP", &sczTemp);
69 PathExitOnFailure(hr, "Failed to get temp path from system TMP.");
70
71 if (S_FALSE != hr)
72 {
73 hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczSystemTempPaths), *pcSystemTempPaths, 1, sizeof(LPWSTR), 3);
74 PathExitOnFailure(hr, "Failed to ensure array size for system TMP value.");
75
76 (*prgsczSystemTempPaths)[*pcSystemTempPaths] = sczTemp;
77 sczTemp = NULL;
78 *pcSystemTempPaths += 1;
79 }
80
81 hr = GetTempPathFromSystemEnvironmentVariable(hKey, L"TEMP", &sczTemp);
82 PathExitOnFailure(hr, "Failed to get temp path from system TEMP.");
83
84 if (S_FALSE != hr)
85 {
86 hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczSystemTempPaths), *pcSystemTempPaths, 1, sizeof(LPWSTR), 2);
87 PathExitOnFailure(hr, "Failed to ensure array size for system TEMP value.");
88
89 (*prgsczSystemTempPaths)[*pcSystemTempPaths] = sczTemp;
90 sczTemp = NULL;
91 *pcSystemTempPaths += 1;
92 }
93 }
94
95 hr = PathSystemWindowsSubdirectory(L"TEMP", &sczTemp);
96 PathExitOnFailure(hr, "Failed to get system Windows subdirectory path TEMP.");
97
98 hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczSystemTempPaths), *pcSystemTempPaths, 1, sizeof(LPWSTR), 1);
99 PathExitOnFailure(hr, "Failed to ensure array size for Windows\\TEMP value.");
100
101 (*prgsczSystemTempPaths)[*pcSystemTempPaths] = sczTemp;
102 sczTemp = NULL;
103 *pcSystemTempPaths += 1;
104
105LExit:
106 ReleaseRegKey(hKey);
107 ReleaseStr(sczTemp);
108
109 return hr;
110}
111
112static HRESULT GetTempPathFromSystemEnvironmentVariable(
113 __in HKEY hKey,
114 __in_z LPCWSTR wzName,
115 __out_z LPWSTR* psczPath
116 )
117{
118 HRESULT hr = S_OK;
119 LPWSTR sczValue = NULL;
120 BOOL fNeedsExpansion = FALSE;
121
122 // Read the value unexpanded so that it can be expanded with system environment variables.
123 hr = RegReadUnexpandedString(hKey, wzName, &fNeedsExpansion, &sczValue);
124 if (E_FILENOTFOUND == hr)
125 {
126 ExitFunction1(hr = S_FALSE);
127 }
128 PathExitOnFailure(hr, "Failed to get system '%ls' value.", wzName);
129
130 if (fNeedsExpansion)
131 {
132 hr = EnvExpandEnvironmentStringsForUser(NULL, sczValue, psczPath, NULL);
133 PathExitOnFailure(hr, "Failed to expand environment variables for system in string: %ls", sczValue);
134 }
135
136 hr = PathBackslashTerminate(psczPath);
137 PathExitOnFailure(hr, "Failed to backslash terminate system '%ls' value.", wzName);
138
139LExit:
140 ReleaseStr(sczValue);
141
142 return hr;
143}