#include <internal/facts/windows/operating_system_resolver.hpp> #include <leatherman/windows/system_error.hpp> #include <leatherman/windows/wmi.hpp> #include <leatherman/windows/windows.hpp> #include <facter/facts/collection.hpp> #include <facter/facts/os_family.hpp> #include <leatherman/logging/logging.hpp> #include <leatherman/util/regex.hpp> #include <intrin.h> #include <winnt.h> #include <Shlobj.h> #include <map> #include <boost/filesystem.hpp> using namespace std; using namespace leatherman::util; using namespace leatherman::windows; using namespace boost::filesystem; namespace facter { namespace facts { namespace windows { static string get_hardware() { SYSTEM_INFO sysInfo; GetNativeSystemInfo(&sysInfo); switch (sysInfo.wProcessorArchitecture) { case PROCESSOR_ARCHITECTURE_AMD64: return "x86_64"; case PROCESSOR_ARCHITECTURE_ARM: return "arm"; case PROCESSOR_ARCHITECTURE_IA64: return "ia64"; case PROCESSOR_ARCHITECTURE_INTEL: return "i" + to_string((sysInfo.wProcessorLevel > 5) ? 6 : sysInfo.wProcessorLevel) + "86"; default: return "unknown"; } } static string get_architecture(string const& hardware) { // Use "x86" for 32-bit systems if (re_search(hardware, boost::regex("i[3456]86"))) { return "x86"; } else if (hardware == "x86_64") { return "x64"; } return hardware; } static string get_system32() { // When facter is a 32-bit process running on 64-bit windows (such as in a 32-bit puppet installation that // includes native facter), system32 points to 32-bit executables; Windows invisibly redirects it. It also // provides a link at %SYSTEMROOT%\sysnative for the 64-bit versions. Return the system path where OS-native // executables can be found. TCHAR szPath[MAX_PATH]; if (!SUCCEEDED(SHGetFolderPath(NULL, CSIDL_WINDOWS, NULL, 0, szPath))) { LOG_DEBUG("error finding SYSTEMROOT: {1}", leatherman::windows::system_error()); } auto pathNative = path(szPath) / "sysnative"; boost::system::error_code ec; if (is_directory(pathNative, ec)) { return pathNative.string(); } LOG_TRACE("sysnative path does not exist"); auto path32 = path(szPath) / "system32"; return path32.string(); } operating_system_resolver::operating_system_resolver(shared_ptr<wmi> wmi_conn) : resolvers::operating_system_resolver(), _wmi(move(wmi_conn)) { } operating_system_resolver::data operating_system_resolver::collect_data(collection& facts) { // Default to the base implementation data result = resolvers::operating_system_resolver::collect_data(facts); result.family = os_family::windows; result.hardware = get_hardware(); result.architecture = get_architecture(result.hardware); result.win.system32 = get_system32(); auto lastDot = result.release.rfind('.'); if (lastDot == string::npos) { return result; } auto vals = _wmi->query(wmi::operatingsystem, {wmi::producttype, wmi::othertypedescription}); if (vals.empty()) { return result; } // Override default release with Windows release names auto version = result.release.substr(0, lastDot); bool consumerrel = (wmi::get(vals, wmi::producttype) == "1"); if (version == "10.0") { result.release = consumerrel ? "10" : "2016"; } else if (version == "6.3") { result.release = consumerrel ? "8.1" : "2012 R2"; } else if (version == "6.2") { result.release = consumerrel ? "8" : "2012"; } else if (version == "6.1") { result.release = consumerrel ? "7" : "2008 R2"; } else if (version == "6.0") { result.release = consumerrel ? "Vista" : "2008"; } else if (version == "5.2") { if (consumerrel) { result.release = "XP"; } else { result.release = (wmi::get(vals, wmi::othertypedescription) == "R2") ? "2003 R2" : "2003"; } } result.major = result.release; return result; } }}} // namespace facter::facts::windows