system_version.cpp 3.9 KB

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