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 | } | ||
