system_version.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. #include "system_version.h"
  2. #include <Windows.h>
  3. #include "log_helper.h"
  4. #include "utils_string.h"
  5. #define WINVER_REG_KEY L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"
  6. typedef DWORD(WINAPI *get_file_version_info_size_w_t)(LPCWSTR module, LPDWORD unused);
  7. typedef BOOL(WINAPI *get_file_version_info_w_t)(LPCWSTR module,
  8. DWORD unused,
  9. DWORD len,
  10. LPVOID data);
  11. typedef BOOL(WINAPI *ver_query_value_w_t)(LPVOID data, LPCWSTR subblock, LPVOID *buf, PUINT sizeout);
  12. static get_file_version_info_size_w_t get_file_version_info_size = NULL;
  13. static get_file_version_info_w_t get_file_version_info = NULL;
  14. static ver_query_value_w_t ver_query_value = NULL;
  15. static bool ver_initialized = false;
  16. static bool ver_initialize_success = false;
  17. static bool initialize_version_functions(void)
  18. {
  19. HMODULE ver = GetModuleHandleW(L"version");
  20. ver_initialized = true;
  21. if (!ver) {
  22. ver = LoadLibraryW(L"version");
  23. if (!ver) {
  24. al_error("failed to load windows version library");
  25. return false;
  26. }
  27. }
  28. get_file_version_info_size = (get_file_version_info_size_w_t)
  29. GetProcAddress(ver, "GetFileVersionInfoSizeW");
  30. get_file_version_info = (get_file_version_info_w_t) GetProcAddress(ver, "GetFileVersionInfoW");
  31. ver_query_value = (ver_query_value_w_t) GetProcAddress(ver, "VerQueryValueW");
  32. if (!get_file_version_info_size || !get_file_version_info || !ver_query_value) {
  33. al_error("failed to load windows version functions");
  34. return false;
  35. }
  36. ver_initialize_success = true;
  37. return true;
  38. }
  39. namespace am {
  40. bool system_version::get_dll(const std::string tar, winversion_info *info)
  41. {
  42. VS_FIXEDFILEINFO *file_info = NULL;
  43. UINT len = 0;
  44. BOOL success;
  45. LPVOID data;
  46. DWORD size;
  47. std::wstring wtar = utils_string::ascii_unicode(tar);
  48. if (!ver_initialized && !initialize_version_functions())
  49. return false;
  50. if (!ver_initialize_success)
  51. return false;
  52. size = get_file_version_info_size(wtar.c_str(), NULL);
  53. if (!size) {
  54. al_error("failed to get %s version info size", tar.c_str());
  55. return false;
  56. }
  57. data = malloc(size);
  58. if (!get_file_version_info(wtar.c_str(), 0, size, data)) {
  59. al_error("failed to get %s version info", tar.c_str());
  60. free(data);
  61. return false;
  62. }
  63. success = ver_query_value(data, L"\\", (LPVOID *) &file_info, &len);
  64. if (!success || !file_info || !len) {
  65. al_error("failed to get %s version info value", tar.c_str());
  66. free(data);
  67. return false;
  68. }
  69. info->major = (int) HIWORD(file_info->dwFileVersionMS);
  70. info->minor = (int) LOWORD(file_info->dwFileVersionMS);
  71. info->build = (int) HIWORD(file_info->dwFileVersionLS);
  72. info->revis = (int) LOWORD(file_info->dwFileVersionLS);
  73. free(data);
  74. return true;
  75. }
  76. void system_version::get_win(winversion_info *info)
  77. {
  78. static winversion_info ver = {0};
  79. static bool got_version = false;
  80. if (!info)
  81. return;
  82. if (!got_version) {
  83. get_dll("kernel32", &ver);
  84. got_version = true;
  85. if (ver.major == 10) {
  86. HKEY key;
  87. DWORD size, win10_revision;
  88. LSTATUS status;
  89. status = RegOpenKeyW(HKEY_LOCAL_MACHINE, WINVER_REG_KEY, &key);
  90. if (status != ERROR_SUCCESS)
  91. return;
  92. size = sizeof(win10_revision);
  93. status = RegQueryValueExW(key, L"UBR", NULL, NULL, (LPBYTE) &win10_revision, &size);
  94. if (status == ERROR_SUCCESS)
  95. ver.revis = (int) win10_revision > ver.revis ? (int) win10_revision : ver.revis;
  96. RegCloseKey(key);
  97. }
  98. }
  99. *info = ver;
  100. }
  101. bool system_version::is_win8_or_above()
  102. {
  103. winversion_info info;
  104. get_win(&info);
  105. return info.major > 6 || (info.major == 6 && info.minor >= 2);
  106. }
  107. bool system_version::is_win10_or_above(int build_number)
  108. {
  109. winversion_info info;
  110. get_win(&info);
  111. return info.major > 6 || (info.major == 6 && info.minor >= 2);
  112. }
  113. bool system_version::is_32()
  114. {
  115. #if defined(_WIN64)
  116. return false;
  117. #elif defined(_WIN32)
  118. BOOL b64 = false;
  119. return !(IsWow64Process(GetCurrentProcess(), &b64) && b64);
  120. #endif
  121. }
  122. } // namespace am