main
cpp 152 lines 6.35 KB
Raw
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 #define PathExitOnPathFailure(x, b, s, ...) ExitOnPathFailureSource(DUTIL_SOURCE_PATHUTIL, x, b, s, __VA_ARGS__)
21
22 static HRESULT GetTempPathFromSystemEnvironmentVariable(
23 __in HKEY hKey,
24 __in_z LPCWSTR wzName,
25 __out_z LPWSTR* psczPath
26 );
27
28 DAPI_(HRESULT) PathGetSystemTempPaths(
29 __inout_z LPWSTR** prgsczSystemTempPaths,
30 __inout DWORD* pcSystemTempPaths
31 )
32 {
33 HRESULT hr = S_OK;
34 HMODULE hModule = NULL;
35 BOOL fSystem = FALSE;
36 BOOL fExists = FALSE;
37 HKEY hKey = NULL;
38 LPWSTR sczTemp = NULL;
39
40 // Follow documented precedence rules for SystemTemp/%TMP%/%TEMP% from ::GetTempPath2.
41 hr = LoadSystemLibrary(L"kernel32.dll", &hModule);
42 PathExitOnFailure(hr, "Failed to load kernel32.dll");
43
44 // The SystemTemp folder was added at the same time as ::GetTempPath2.
45 if (::GetProcAddress(hModule, "GetTempPath2W"))
46 {
47 hr = ProcSystem(::GetCurrentProcess(), &fSystem);
48 PathExitOnFailure(hr, "Failed to check if running as system.");
49
50 if (fSystem)
51 {
52 hr = PathSystemWindowsSubdirectory(L"SystemTemp", &sczTemp);
53 PathExitOnFailure(hr, "Failed to get system Windows subdirectory path SystemTemp.");
54
55 hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczSystemTempPaths), *pcSystemTempPaths, 1, sizeof(LPWSTR), 4);
56 PathExitOnFailure(hr, "Failed to ensure array size for Windows\\SystemTemp value.");
57
58 (*prgsczSystemTempPaths)[*pcSystemTempPaths] = sczTemp;
59 sczTemp = NULL;
60 *pcSystemTempPaths += 1;
61 }
62 }
63
64 // There is no documented API to get system environment variables, so read them from the registry.
65 hr = RegOpen(HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Control\\Session Manager\\Environment", KEY_READ, &hKey);
66 PathExitOnPathFailure(hr, fExists, "Failed to open system environment registry key.");
67
68 if (fExists)
69 {
70 hr = GetTempPathFromSystemEnvironmentVariable(hKey, L"TMP", &sczTemp);
71 PathExitOnFailure(hr, "Failed to get temp path from system TMP.");
72
73 if (S_FALSE != hr)
74 {
75 hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczSystemTempPaths), *pcSystemTempPaths, 1, sizeof(LPWSTR), 3);
76 PathExitOnFailure(hr, "Failed to ensure array size for system TMP value.");
77
78 (*prgsczSystemTempPaths)[*pcSystemTempPaths] = sczTemp;
79 sczTemp = NULL;
80 *pcSystemTempPaths += 1;
81 }
82
83 hr = GetTempPathFromSystemEnvironmentVariable(hKey, L"TEMP", &sczTemp);
84 PathExitOnFailure(hr, "Failed to get temp path from system TEMP.");
85
86 if (S_FALSE != hr)
87 {
88 hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczSystemTempPaths), *pcSystemTempPaths, 1, sizeof(LPWSTR), 2);
89 PathExitOnFailure(hr, "Failed to ensure array size for system TEMP value.");
90
91 (*prgsczSystemTempPaths)[*pcSystemTempPaths] = sczTemp;
92 sczTemp = NULL;
93 *pcSystemTempPaths += 1;
94 }
95 }
96
97 hr = PathSystemWindowsSubdirectory(L"TEMP", &sczTemp);
98 PathExitOnFailure(hr, "Failed to get system Windows subdirectory path TEMP.");
99
100 hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczSystemTempPaths), *pcSystemTempPaths, 1, sizeof(LPWSTR), 1);
101 PathExitOnFailure(hr, "Failed to ensure array size for Windows\\TEMP value.");
102
103 (*prgsczSystemTempPaths)[*pcSystemTempPaths] = sczTemp;
104 sczTemp = NULL;
105 *pcSystemTempPaths += 1;
106
107 LExit:
108 ReleaseRegKey(hKey);
109 ReleaseStr(sczTemp);
110
111 return hr;
112 }
113
114 static HRESULT GetTempPathFromSystemEnvironmentVariable(
115 __in HKEY hKey,
116 __in_z LPCWSTR wzName,
117 __out_z LPWSTR* psczPath
118 )
119 {
120 HRESULT hr = S_OK;
121 LPWSTR sczValue = NULL;
122 BOOL fNeedsExpansion = FALSE;
123 BOOL fExists = FALSE;
124
125 // Read the value unexpanded so that it can be expanded with system environment variables.
126 hr = RegReadUnexpandedString(hKey, wzName, &fNeedsExpansion, &sczValue);
127 PathExitOnPathFailure(hr, fExists, "Failed to get system '%ls' value.", wzName);
128
129 if (!fExists)
130 {
131 ExitFunction1(hr = S_FALSE);
132 }
133
134 if (fNeedsExpansion)
135 {
136 hr = EnvExpandEnvironmentStringsForUser(NULL, sczValue, psczPath, NULL);
137 PathExitOnFailure(hr, "Failed to expand environment variables for system in string: %ls", sczValue);
138 }
139 else
140 {
141 hr = StrAllocString(psczPath, sczValue, 0);
142 PathExitOnFailure(hr, "Failed to copy environment variable: %ls", wzName);
143 }
144
145 hr = PathBackslashTerminate(psczPath);
146 PathExitOnFailure(hr, "Failed to backslash terminate system '%ls' value.", wzName);
147
148 LExit:
149 ReleaseStr(sczValue);
150
151 return hr;
152 }