diff options
Diffstat (limited to 'src/libs/dutil/WixToolset.DUtil/path3utl.cpp')
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/path3utl.cpp | 143 |
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 | |||
21 | static HRESULT GetTempPathFromSystemEnvironmentVariable( | ||
22 | __in HKEY hKey, | ||
23 | __in_z LPCWSTR wzName, | ||
24 | __out_z LPWSTR* psczPath | ||
25 | ); | ||
26 | |||
27 | DAPI_(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 | |||
105 | LExit: | ||
106 | ReleaseRegKey(hKey); | ||
107 | ReleaseStr(sczTemp); | ||
108 | |||
109 | return hr; | ||
110 | } | ||
111 | |||
112 | static 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 | |||
139 | LExit: | ||
140 | ReleaseStr(sczValue); | ||
141 | |||
142 | return hr; | ||
143 | } | ||