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