Skip to content

Instantly share code, notes, and snippets.

@sylveon
Created July 29, 2019 08:13
Show Gist options
  • Save sylveon/6da0b12e67d36740be7c68092e75ea7c to your computer and use it in GitHub Desktop.
Save sylveon/6da0b12e67d36740be7c68092e75ea7c to your computer and use it in GitHub Desktop.
#include <cstddef>
#include <filesystem>
#include <iostream>
#include <memory>
#include <Shlobj.h>
#include <string>
#include <winver.h>
#include <wil/resource.h>
#include "version.hpp"
std::pair<std::unique_ptr<std::byte[]>, HRESULT> LoadFileVersionInfo(const std::filesystem::path& file, DWORD flags = 0)
{
const DWORD size = GetFileVersionInfoSizeEx(flags, file.c_str(), nullptr);
if (!size)
{
return { nullptr, HRESULT_FROM_WIN32(GetLastError()) };
}
auto data = std::make_unique<std::byte[]>(size);
if (!GetFileVersionInfoEx(flags, file.c_str(), 0, size, data.get()))
{
return { nullptr, HRESULT_FROM_WIN32(GetLastError()) };
}
return { std::move(data), S_OK };
}
std::pair<Version, HRESULT> GetFixedFileVersion(const std::filesystem::path &file)
{
const auto [data, hr] = LoadFileVersionInfo(file, FILE_VER_GET_NEUTRAL);
if (FAILED(hr))
{
return { { }, hr };
}
VS_FIXEDFILEINFO *fixedFileInfo;
unsigned int length;
if (!VerQueryValue(data.get(), L"\\", reinterpret_cast<void **>(&fixedFileInfo), &length))
{
return { { }, HRESULT_FROM_WIN32(GetLastError()) };
}
return { Version::FromHighLow(fixedFileInfo->dwProductVersionMS, fixedFileInfo->dwProductVersionLS), S_OK };
}
std::pair<std::wstring, HRESULT> GetWindowsBuild()
{
// Microsoft recommends this themselves
// https://docs.microsoft.com/en-us/windows/desktop/SysInfo/getting-the-system-version
wil::unique_cotaskmem_string system32;
const HRESULT hr = SHGetKnownFolderPath(FOLDERID_System, KF_FLAG_DEFAULT, nullptr, system32.put());
if (FAILED(hr))
{
return { { }, hr };
}
std::filesystem::path user32 = system32.get();
user32 /= L"user32.dll";
const auto [version, hr2] = GetFixedFileVersion(user32);
if (SUCCEEDED(hr2))
{
return { version.ToString(), S_OK };
}
else
{
return { { }, hr2 };
}
}
int main()
{
const auto [build, hr] = GetWindowsBuild();
if (SUCCEEDED(hr))
{
std::wcout << build << std:endl;
}
}
#pragma once
#include <cstdint>
#include <fmt/format.h>
#include <string>
#include <Windows.h>
#include <winrt/Windows.ApplicationModel.h>
struct Version {
uint16_t Major;
uint16_t Minor;
uint16_t Build;
uint16_t Revision;
inline std::wstring ToString() const
{
return fmt::format(fmt(L"{}.{}.{}.{}"), Major, Minor, Build, Revision);
}
inline static Version FromHighLow(DWORD high, DWORD low)
{
return { HIWORD(high), LOWORD(high), HIWORD(low), LOWORD(low) };
}
inline static Version FromPackageVersion(winrt::Windows::ApplicationModel::PackageVersion version)
{
return { version.Major, version.Minor, version.Build, version.Revision };
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment