#include #include #include #include #include #include #include #include #include using namespace std; using namespace leatherman::windows; namespace facter { namespace facts { namespace windows { static boost::optional get_release() { // GetVersionEx requires the manifest is correct, and is essentially deprecated. // Another method of getting the OS version can be found at // http://msdn.microsoft.com/en-us/library/windows/desktop/ms724429(v=vs.85).aspx // and is what we use here. auto fileName = L"Kernel32.dll"; auto fileVerSize = GetFileVersionInfoSizeW(fileName, nullptr); if (fileVerSize == 0) { return boost::none; } vector buffer(fileVerSize); if (!GetFileVersionInfoW(fileName, 0, fileVerSize, buffer.data())) { return boost::none; } struct LANGANDCODEPAGE { WORD wLanguage, wCodePage; } *lpTranslate; UINT cbTranslate; if (!VerQueryValueW(buffer.data(), L"\\VarFileinfo\\Translation", reinterpret_cast(&lpTranslate), &cbTranslate)) { return boost::none; } // Use the 1st language found, as ProductVersion should be language-independent. wstring subBlock = str(boost::wformat(L"\\StringFileInfo\\%04x%04x\\ProductVersion") % lpTranslate->wLanguage % lpTranslate->wCodePage); wchar_t *version; UINT versionLen; if (!VerQueryValueW(buffer.data(), subBlock.c_str(), reinterpret_cast(&version), &versionLen)) { return boost::none; } // Strip the last (file version) token to get just the OS version. wstring versionStrW(version, versionLen); auto versionStr = boost::nowide::narrow(versionStrW); boost::trim_right_if(versionStr, [](char c) { return c != '.'; }); // Remove everything after '.' boost::trim_right_if(versionStr, [](char c) { return c == '.'; }); // Remove '.' return versionStr; } kernel_resolver::data kernel_resolver::collect_data(collection& facts) { data result; auto release = get_release(); if (release) { result.release = move(*release); result.version = result.release; } else { LOG_DEBUG("failed to retrieve kernel facts: {1}", leatherman::windows::system_error()); } result.name = os::windows; return result; } }}} // namespace facter::facts::windows