diff options
Diffstat (limited to 'src/libs/dutil/WixToolset.DUtil/osutil.cpp')
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/osutil.cpp | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/osutil.cpp b/src/libs/dutil/WixToolset.DUtil/osutil.cpp new file mode 100644 index 00000000..880ec3ea --- /dev/null +++ b/src/libs/dutil/WixToolset.DUtil/osutil.cpp | |||
@@ -0,0 +1,251 @@ | |||
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 OsExitOnLastError(x, s, ...) ExitOnLastErrorSource(DUTIL_SOURCE_OSUTIL, x, s, __VA_ARGS__) | ||
8 | #define OsExitOnLastErrorDebugTrace(x, s, ...) ExitOnLastErrorDebugTraceSource(DUTIL_SOURCE_OSUTIL, x, s, __VA_ARGS__) | ||
9 | #define OsExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_OSUTIL, x, s, __VA_ARGS__) | ||
10 | #define OsExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_OSUTIL, x, s, __VA_ARGS__) | ||
11 | #define OsExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_OSUTIL, x, s, __VA_ARGS__) | ||
12 | #define OsExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_OSUTIL, x, s, __VA_ARGS__) | ||
13 | #define OsExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_OSUTIL, p, x, e, s, __VA_ARGS__) | ||
14 | #define OsExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_OSUTIL, p, x, s, __VA_ARGS__) | ||
15 | #define OsExitOnNullDebugTrace(p, x, e, s, ...) ExitOnNullDebugTraceSource(DUTIL_SOURCE_OSUTIL, p, x, e, s, __VA_ARGS__) | ||
16 | #define OsExitOnInvalidHandleWithLastError(p, x, s, ...) ExitOnInvalidHandleWithLastErrorSource(DUTIL_SOURCE_OSUTIL, p, x, s, __VA_ARGS__) | ||
17 | #define OsExitOnWin32Error(e, x, s, ...) ExitOnWin32ErrorSource(DUTIL_SOURCE_OSUTIL, e, x, s, __VA_ARGS__) | ||
18 | #define OsExitOnGdipFailure(g, x, s, ...) ExitOnGdipFailureSource(DUTIL_SOURCE_OSUTIL, g, x, s, __VA_ARGS__) | ||
19 | |||
20 | typedef NTSTATUS(NTAPI* PFN_RTL_GET_VERSION)(_Out_ PRTL_OSVERSIONINFOEXW lpVersionInformation); | ||
21 | |||
22 | OS_VERSION vOsVersion = OS_VERSION_UNKNOWN; | ||
23 | DWORD vdwOsServicePack = 0; | ||
24 | RTL_OSVERSIONINFOEXW vovix = { }; | ||
25 | |||
26 | /******************************************************************** | ||
27 | OsGetVersion | ||
28 | |||
29 | ********************************************************************/ | ||
30 | extern "C" void DAPI OsGetVersion( | ||
31 | __out OS_VERSION* pVersion, | ||
32 | __out DWORD* pdwServicePack | ||
33 | ) | ||
34 | { | ||
35 | OSVERSIONINFOEXW ovi = { }; | ||
36 | |||
37 | if (OS_VERSION_UNKNOWN == vOsVersion) | ||
38 | { | ||
39 | ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); | ||
40 | |||
41 | #pragma warning (push) | ||
42 | #pragma warning(suppress: 4996) // deprecated | ||
43 | #pragma warning (push) | ||
44 | #pragma warning(suppress: 28159)// deprecated, use other function instead | ||
45 | ::GetVersionExW(reinterpret_cast<OSVERSIONINFOW*>(&ovi)); // only fails if version info size is set incorrectly. | ||
46 | #pragma warning (pop) | ||
47 | #pragma warning (pop) | ||
48 | |||
49 | vdwOsServicePack = static_cast<DWORD>(ovi.wServicePackMajor) << 16 | ovi.wServicePackMinor; | ||
50 | if (4 == ovi.dwMajorVersion) | ||
51 | { | ||
52 | vOsVersion = OS_VERSION_WINNT; | ||
53 | } | ||
54 | else if (5 == ovi.dwMajorVersion) | ||
55 | { | ||
56 | if (0 == ovi.dwMinorVersion) | ||
57 | { | ||
58 | vOsVersion = OS_VERSION_WIN2000; | ||
59 | } | ||
60 | else if (1 == ovi.dwMinorVersion) | ||
61 | { | ||
62 | vOsVersion = OS_VERSION_WINXP; | ||
63 | } | ||
64 | else if (2 == ovi.dwMinorVersion) | ||
65 | { | ||
66 | vOsVersion = OS_VERSION_WIN2003; | ||
67 | } | ||
68 | else | ||
69 | { | ||
70 | vOsVersion = OS_VERSION_FUTURE; | ||
71 | } | ||
72 | } | ||
73 | else if (6 == ovi.dwMajorVersion) | ||
74 | { | ||
75 | if (0 == ovi.dwMinorVersion) | ||
76 | { | ||
77 | vOsVersion = (VER_NT_WORKSTATION == ovi.wProductType) ? OS_VERSION_VISTA : OS_VERSION_WIN2008; | ||
78 | } | ||
79 | else if (1 == ovi.dwMinorVersion) | ||
80 | { | ||
81 | vOsVersion = (VER_NT_WORKSTATION == ovi.wProductType) ? OS_VERSION_WIN7 : OS_VERSION_WIN2008_R2; | ||
82 | } | ||
83 | else | ||
84 | { | ||
85 | vOsVersion = OS_VERSION_FUTURE; | ||
86 | } | ||
87 | } | ||
88 | else | ||
89 | { | ||
90 | vOsVersion = OS_VERSION_FUTURE; | ||
91 | } | ||
92 | } | ||
93 | |||
94 | *pVersion = vOsVersion; | ||
95 | *pdwServicePack = vdwOsServicePack; | ||
96 | } | ||
97 | |||
98 | extern "C" HRESULT DAPI OsCouldRunPrivileged( | ||
99 | __out BOOL* pfPrivileged | ||
100 | ) | ||
101 | { | ||
102 | HRESULT hr = S_OK; | ||
103 | BOOL fUacEnabled = FALSE; | ||
104 | SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; | ||
105 | PSID AdministratorsGroup = NULL; | ||
106 | |||
107 | // Do a best effort check to see if UAC is enabled on this machine. | ||
108 | OsIsUacEnabled(&fUacEnabled); | ||
109 | |||
110 | // If UAC is enabled then the process could run privileged by asking to elevate. | ||
111 | if (fUacEnabled) | ||
112 | { | ||
113 | *pfPrivileged = TRUE; | ||
114 | } | ||
115 | else // no UAC so only privilged if user is in administrators group. | ||
116 | { | ||
117 | *pfPrivileged = ::AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdministratorsGroup); | ||
118 | if (*pfPrivileged) | ||
119 | { | ||
120 | if (!::CheckTokenMembership(NULL, AdministratorsGroup, pfPrivileged)) | ||
121 | { | ||
122 | *pfPrivileged = FALSE; | ||
123 | } | ||
124 | } | ||
125 | } | ||
126 | |||
127 | ReleaseSid(AdministratorsGroup); | ||
128 | return hr; | ||
129 | } | ||
130 | |||
131 | extern "C" HRESULT DAPI OsIsRunningPrivileged( | ||
132 | __out BOOL* pfPrivileged | ||
133 | ) | ||
134 | { | ||
135 | HRESULT hr = S_OK; | ||
136 | UINT er = ERROR_SUCCESS; | ||
137 | HANDLE hToken = NULL; | ||
138 | TOKEN_ELEVATION_TYPE elevationType = TokenElevationTypeDefault; | ||
139 | DWORD dwSize = 0; | ||
140 | SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; | ||
141 | PSID AdministratorsGroup = NULL; | ||
142 | |||
143 | if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &hToken)) | ||
144 | { | ||
145 | OsExitOnLastError(hr, "Failed to open process token."); | ||
146 | } | ||
147 | |||
148 | if (::GetTokenInformation(hToken, TokenElevationType, &elevationType, sizeof(TOKEN_ELEVATION_TYPE), &dwSize)) | ||
149 | { | ||
150 | *pfPrivileged = (TokenElevationTypeFull == elevationType); | ||
151 | ExitFunction1(hr = S_OK); | ||
152 | } | ||
153 | |||
154 | // If it's invalid argument, this means they don't support TokenElevationType, and we should fallback to another check | ||
155 | er = ::GetLastError(); | ||
156 | if (ERROR_INVALID_FUNCTION == er) | ||
157 | { | ||
158 | er = ERROR_SUCCESS; | ||
159 | } | ||
160 | OsExitOnWin32Error(er, hr, "Failed to get process token information."); | ||
161 | |||
162 | // Fallback to this check for some OS's (like XP) | ||
163 | *pfPrivileged = ::AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdministratorsGroup); | ||
164 | if (*pfPrivileged) | ||
165 | { | ||
166 | if (!::CheckTokenMembership(NULL, AdministratorsGroup, pfPrivileged)) | ||
167 | { | ||
168 | *pfPrivileged = FALSE; | ||
169 | } | ||
170 | } | ||
171 | |||
172 | LExit: | ||
173 | ReleaseSid(AdministratorsGroup); | ||
174 | |||
175 | if (hToken) | ||
176 | { | ||
177 | ::CloseHandle(hToken); | ||
178 | } | ||
179 | |||
180 | return hr; | ||
181 | } | ||
182 | |||
183 | extern "C" HRESULT DAPI OsIsUacEnabled( | ||
184 | __out BOOL* pfUacEnabled | ||
185 | ) | ||
186 | { | ||
187 | HRESULT hr = S_OK; | ||
188 | HKEY hk = NULL; | ||
189 | DWORD dwUacEnabled = 0; | ||
190 | |||
191 | *pfUacEnabled = FALSE; // assume UAC not enabled. | ||
192 | |||
193 | hr = RegOpen(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", KEY_READ, &hk); | ||
194 | if (E_FILENOTFOUND == hr) | ||
195 | { | ||
196 | ExitFunction1(hr = S_OK); | ||
197 | } | ||
198 | OsExitOnFailure(hr, "Failed to open system policy key to detect UAC."); | ||
199 | |||
200 | hr = RegReadNumber(hk, L"EnableLUA", &dwUacEnabled); | ||
201 | if (E_FILENOTFOUND == hr) | ||
202 | { | ||
203 | ExitFunction1(hr = S_OK); | ||
204 | } | ||
205 | OsExitOnFailure(hr, "Failed to read registry value to detect UAC."); | ||
206 | |||
207 | *pfUacEnabled = (0 != dwUacEnabled); | ||
208 | |||
209 | LExit: | ||
210 | ReleaseRegKey(hk); | ||
211 | |||
212 | return hr; | ||
213 | } | ||
214 | |||
215 | HRESULT DAPI OsRtlGetVersion( | ||
216 | __inout RTL_OSVERSIONINFOEXW* pOvix | ||
217 | ) | ||
218 | { | ||
219 | HRESULT hr = S_OK; | ||
220 | HMODULE hNtdll = NULL; | ||
221 | PFN_RTL_GET_VERSION pfnRtlGetVersion = NULL; | ||
222 | |||
223 | if (vovix.dwOSVersionInfoSize) | ||
224 | { | ||
225 | ExitFunction(); | ||
226 | } | ||
227 | |||
228 | vovix.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW); | ||
229 | |||
230 | hr = LoadSystemLibrary(L"ntdll.dll", &hNtdll); | ||
231 | if (E_MODNOTFOUND == hr) | ||
232 | { | ||
233 | OsExitOnRootFailure(hr = E_NOTIMPL, "Failed to load ntdll.dll"); | ||
234 | } | ||
235 | OsExitOnFailure(hr, "Failed to load ntdll.dll."); | ||
236 | |||
237 | pfnRtlGetVersion = reinterpret_cast<PFN_RTL_GET_VERSION>(::GetProcAddress(hNtdll, "RtlGetVersion")); | ||
238 | OsExitOnNullWithLastError(pfnRtlGetVersion, hr, "Failed to locate RtlGetVersion."); | ||
239 | |||
240 | hr = static_cast<HRESULT>(pfnRtlGetVersion(&vovix)); | ||
241 | |||
242 | LExit: | ||
243 | memcpy(pOvix, &vovix, sizeof(RTL_OSVERSIONINFOEXW)); | ||
244 | |||
245 | if (hNtdll) | ||
246 | { | ||
247 | ::FreeLibrary(hNtdll); | ||
248 | } | ||
249 | |||
250 | return hr; | ||
251 | } | ||