indiaai-hackathon
/
datalab
/web
/node_modules
/node-pty
/deps
/winpty
/src
/shared
/WindowsVersion.cc
| // Copyright (c) 2016 Ryan Prichard | |
| // | |
| // Permission is hereby granted, free of charge, to any person obtaining a copy | |
| // of this software and associated documentation files (the "Software"), to | |
| // deal in the Software without restriction, including without limitation the | |
| // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | |
| // sell copies of the Software, and to permit persons to whom the Software is | |
| // furnished to do so, subject to the following conditions: | |
| // | |
| // The above copyright notice and this permission notice shall be included in | |
| // all copies or substantial portions of the Software. | |
| // | |
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | |
| // IN THE SOFTWARE. | |
| namespace { | |
| typedef std::tuple<DWORD, DWORD> Version; | |
| // This function can only return a version up to 6.2 unless the executable is | |
| // manifested for a newer version of Windows. See the MSDN documentation for | |
| // GetVersionEx. | |
| OSVERSIONINFOEX getWindowsVersionInfo() { | |
| // Allow use of deprecated functions (i.e. GetVersionEx). We need to use | |
| // GetVersionEx for the old MinGW toolchain and with MSVC when it targets XP. | |
| // Having two code paths makes code harder to test, and it's not obvious how | |
| // to detect the presence of a new enough SDK. (Including ntverp.h and | |
| // examining VER_PRODUCTBUILD apparently works, but even then, MinGW-w64 and | |
| // MSVC seem to use different version numbers.) | |
| OSVERSIONINFOEX info = {}; | |
| info.dwOSVersionInfoSize = sizeof(info); | |
| const auto success = GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&info)); | |
| ASSERT(success && "GetVersionEx failed"); | |
| return info; | |
| } | |
| Version getWindowsVersion() { | |
| const auto info = getWindowsVersionInfo(); | |
| return Version(info.dwMajorVersion, info.dwMinorVersion); | |
| } | |
| struct ModuleNotFound : WinptyException { | |
| virtual const wchar_t *what() const WINPTY_NOEXCEPT override { | |
| return L"ModuleNotFound"; | |
| } | |
| }; | |
| // Throws WinptyException on error. | |
| std::wstring getSystemDirectory() { | |
| wchar_t systemDirectory[MAX_PATH]; | |
| const UINT size = GetSystemDirectoryW(systemDirectory, MAX_PATH); | |
| if (size == 0) { | |
| throwWindowsError(L"GetSystemDirectory failed"); | |
| } else if (size >= MAX_PATH) { | |
| throwWinptyException( | |
| L"GetSystemDirectory: path is longer than MAX_PATH"); | |
| } | |
| return systemDirectory; | |
| } | |
| // Throws WinptyException on error. | |
| VS_FIXEDFILEINFO getFixedFileInfo(const std::wstring &path) { | |
| // version.dll is not a conventional KnownDll, so if we link to it, there's | |
| // a danger of accidentally loading a malicious DLL. In a more typical | |
| // application, perhaps we'd guard against this security issue by | |
| // controlling which directories this code runs in (e.g. *not* the | |
| // "Downloads" directory), but that's harder for the winpty library. | |
| OsModule versionDll( | |
| (getSystemDirectory() + L"\\version.dll").c_str(), | |
| OsModule::LoadErrorBehavior::Throw); | |
| GET_VERSION_DLL_API(GetFileVersionInfoSizeW); | |
| GET_VERSION_DLL_API(GetFileVersionInfoW); | |
| GET_VERSION_DLL_API(VerQueryValueW); | |
| DWORD size = pGetFileVersionInfoSizeW(path.c_str(), nullptr); | |
| if (!size) { | |
| // I see ERROR_FILE_NOT_FOUND on Win7 and | |
| // ERROR_RESOURCE_DATA_NOT_FOUND on WinXP. | |
| if (GetLastError() == ERROR_FILE_NOT_FOUND || | |
| GetLastError() == ERROR_RESOURCE_DATA_NOT_FOUND) { | |
| throw ModuleNotFound(); | |
| } else { | |
| throwWindowsError( | |
| (L"GetFileVersionInfoSizeW failed on " + path).c_str()); | |
| } | |
| } | |
| std::unique_ptr<char[]> versionBuffer(new char[size]); | |
| if (!pGetFileVersionInfoW(path.c_str(), 0, size, versionBuffer.get())) { | |
| throwWindowsError((L"GetFileVersionInfoW failed on " + path).c_str()); | |
| } | |
| VS_FIXEDFILEINFO *versionInfo = nullptr; | |
| UINT versionInfoSize = 0; | |
| if (!pVerQueryValueW( | |
| versionBuffer.get(), L"\\", | |
| reinterpret_cast<void**>(&versionInfo), &versionInfoSize) || | |
| versionInfo == nullptr || | |
| versionInfoSize != sizeof(VS_FIXEDFILEINFO) || | |
| versionInfo->dwSignature != 0xFEEF04BD) { | |
| throwWinptyException((L"VerQueryValueW failed on " + path).c_str()); | |
| } | |
| return *versionInfo; | |
| } | |
| uint64_t productVersionFromInfo(const VS_FIXEDFILEINFO &info) { | |
| return (static_cast<uint64_t>(info.dwProductVersionMS) << 32) | | |
| (static_cast<uint64_t>(info.dwProductVersionLS)); | |
| } | |
| uint64_t fileVersionFromInfo(const VS_FIXEDFILEINFO &info) { | |
| return (static_cast<uint64_t>(info.dwFileVersionMS) << 32) | | |
| (static_cast<uint64_t>(info.dwFileVersionLS)); | |
| } | |
| std::string versionToString(uint64_t version) { | |
| StringBuilder b(32); | |
| b << ((uint16_t)(version >> 48)); | |
| b << '.'; | |
| b << ((uint16_t)(version >> 32)); | |
| b << '.'; | |
| b << ((uint16_t)(version >> 16)); | |
| b << '.'; | |
| b << ((uint16_t)(version >> 0)); | |
| return b.str_moved(); | |
| } | |
| } // anonymous namespace | |
| // Returns true for Windows Vista (or Windows Server 2008) or newer. | |
| bool isAtLeastWindowsVista() { | |
| return getWindowsVersion() >= Version(6, 0); | |
| } | |
| // Returns true for Windows 7 (or Windows Server 2008 R2) or newer. | |
| bool isAtLeastWindows7() { | |
| return getWindowsVersion() >= Version(6, 1); | |
| } | |
| // Returns true for Windows 8 (or Windows Server 2012) or newer. | |
| bool isAtLeastWindows8() { | |
| return getWindowsVersion() >= Version(6, 2); | |
| } | |
| typedef BOOL WINAPI IsWow64Process_t(HANDLE hProcess, PBOOL Wow64Process); | |
| void dumpWindowsVersion() { | |
| if (!isTracingEnabled()) { | |
| return; | |
| } | |
| const auto info = getWindowsVersionInfo(); | |
| StringBuilder b; | |
| b << info.dwMajorVersion << '.' << info.dwMinorVersion | |
| << '.' << info.dwBuildNumber << ' ' | |
| << "SP" << info.wServicePackMajor << '.' << info.wServicePackMinor | |
| << ' '; | |
| switch (info.wProductType) { | |
| case VER_NT_WORKSTATION: b << "Client"; break; | |
| case VER_NT_DOMAIN_CONTROLLER: b << "DomainController"; break; | |
| case VER_NT_SERVER: b << "Server"; break; | |
| default: | |
| b << "product=" << info.wProductType; break; | |
| } | |
| b << ' '; | |
| b << "IA32"; | |
| OsModule kernel32(L"kernel32.dll"); | |
| IsWow64Process_t *pIsWow64Process = | |
| reinterpret_cast<IsWow64Process_t*>( | |
| kernel32.proc("IsWow64Process")); | |
| if (pIsWow64Process != nullptr) { | |
| BOOL result = false; | |
| const BOOL success = pIsWow64Process(GetCurrentProcess(), &result); | |
| if (!success) { | |
| b << " WOW64:error"; | |
| } else if (success && result) { | |
| b << " WOW64"; | |
| } | |
| } else { | |
| b << " WOW64:missingapi"; | |
| } | |
| b << "X64"; | |
| const auto dllVersion = [](const wchar_t *dllPath) -> std::string { | |
| try { | |
| const auto info = getFixedFileInfo(dllPath); | |
| StringBuilder fb(64); | |
| fb << utf8FromWide(dllPath) << ':'; | |
| fb << "F:" << versionToString(fileVersionFromInfo(info)) << '/' | |
| << "P:" << versionToString(productVersionFromInfo(info)); | |
| return fb.str_moved(); | |
| } catch (const ModuleNotFound&) { | |
| return utf8FromWide(dllPath) + ":none"; | |
| } catch (const WinptyException &e) { | |
| trace("Error getting %s version: %s", | |
| utf8FromWide(dllPath).c_str(), utf8FromWide(e.what()).c_str()); | |
| return utf8FromWide(dllPath) + ":error"; | |
| } | |
| }; | |
| b << ' ' << dllVersion(L"kernel32.dll"); | |
| // ConEmu provides a DLL that hooks many Windows APIs, especially console | |
| // APIs. Its existence and version number could be useful in debugging. | |
| b << ' ' << dllVersion(L"ConEmuHk.dll"); | |
| b << ' ' << dllVersion(L"ConEmuHk64.dll"); | |
| trace("Windows version: %s", b.c_str()); | |
| } | |