diff --git a/libobs/CMakeLists.txt b/libobs/CMakeLists.txt index 51113acbd..f8c88e393 100644 --- a/libobs/CMakeLists.txt +++ b/libobs/CMakeLists.txt @@ -60,6 +60,7 @@ elseif(APPLE) util/platform-nix.c util/platform-cocoa.m) set(libobs_PLATFORM_HEADERS + util/windows/win-version.h util/windows/ComPtr.hpp util/windows/CoTaskMemPtr.hpp util/windows/HRError.hpp diff --git a/libobs/util/platform-windows.c b/libobs/util/platform-windows.c index 919bc78c5..1048f4201 100644 --- a/libobs/util/platform-windows.c +++ b/libobs/util/platform-windows.c @@ -23,6 +23,7 @@ #include "platform.h" #include "darray.h" #include "dstr.h" +#include "windows/win-version.h" #include "../../deps/w32-pthreads/pthread.h" @@ -569,3 +570,99 @@ int os_chdir(const char *path) return ret; } + +typedef DWORD (WINAPI *get_file_version_info_size_w_t)( + LPCWSTR module, + LPDWORD unused); +typedef BOOL (WINAPI *get_file_version_info_w_t)( + LPCWSTR module, + DWORD unused, + DWORD len, + LPVOID data); +typedef BOOL (WINAPI *ver_query_value_w_t)( + LPVOID data, + LPCWSTR subblock, + LPVOID *buf, + PUINT sizeout); + +static void actually_get_win_ver(struct win_version_info *ver_info) +{ + HMODULE ver = GetModuleHandleW(L"version"); + VS_FIXEDFILEINFO *info = NULL; + UINT len = 0; + BOOL success; + LPVOID data; + DWORD size; + + get_file_version_info_size_w_t get_file_version_info_size; + get_file_version_info_w_t get_file_version_info; + ver_query_value_w_t ver_query_value; + + if (!ver) { + ver = LoadLibraryW(L"version"); + if (!ver) { + blog(LOG_ERROR, "Failed to load windows version " + "library"); + return; + } + } + + get_file_version_info_size = (get_file_version_info_size_w_t) + GetProcAddress(ver, "GetFileVersionInfoSizeW"); + get_file_version_info = (get_file_version_info_w_t) + GetProcAddress(ver, "GetFileVersionInfoW"); + ver_query_value = (ver_query_value_w_t) + GetProcAddress(ver, "VerQueryValueW"); + + if (!get_file_version_info_size || + !get_file_version_info || + !ver_query_value) { + blog(LOG_ERROR, "Failed to load windows version " + "functions"); + return; + } + + size = get_file_version_info_size(L"kernel32", NULL); + if (!size) { + blog(LOG_ERROR, "Failed to get windows version info size"); + return; + } + + data = bmalloc(size); + if (!get_file_version_info(L"kernel32", 0, size, data)) { + blog(LOG_ERROR, "Failed to get windows version info"); + bfree(data); + return; + } + + success = ver_query_value(data, L"\\", (LPVOID*)&info, &len); + if (!success || !info || !len) { + blog(LOG_ERROR, "Failed to get windows version info value"); + bfree(data); + return; + } + + ver_info->major = (int)HIWORD(info->dwFileVersionMS); + ver_info->minor = (int)LOWORD(info->dwFileVersionMS); + ver_info->build = (int)HIWORD(info->dwFileVersionLS); + ver_info->revis = (int)LOWORD(info->dwFileVersionLS); + + bfree(data); + return; +} + +void get_win_ver(struct win_version_info *info) +{ + static struct win_version_info ver = {0}; + static bool got_version = false; + + if (!info) + return; + + if (!got_version) { + actually_get_win_ver(&ver); + got_version = true; + } + + *info = ver; +} diff --git a/libobs/util/windows/win-version.h b/libobs/util/windows/win-version.h new file mode 100644 index 000000000..6e49de2b7 --- /dev/null +++ b/libobs/util/windows/win-version.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2015 Hugh Bailey + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#pragma once + +#include "../c99defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct win_version_info { + int major; + int minor; + int build; + int revis; +}; + +EXPORT void get_win_ver(struct win_version_info *info); + +#ifdef __cplusplus +} +#endif