load-graphics-offsets.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <obs-module.h>
  3. #include <util/windows/win-version.h>
  4. #include <util/platform.h>
  5. #include <util/dstr.h>
  6. #include <util/config-file.h>
  7. #include <util/pipe.h>
  8. #include <windows.h>
  9. #include "graphics-hook-info.h"
  10. extern struct graphics_offsets offsets32;
  11. extern struct graphics_offsets offsets64;
  12. static inline bool load_offsets_from_string(struct graphics_offsets *offsets,
  13. const char *str)
  14. {
  15. config_t *config;
  16. if (config_open_string(&config, str) != CONFIG_SUCCESS) {
  17. return false;
  18. }
  19. offsets->d3d8.present =
  20. (uint32_t)config_get_uint(config, "d3d8", "present");
  21. offsets->d3d9.present =
  22. (uint32_t)config_get_uint(config, "d3d9", "present");
  23. offsets->d3d9.present_ex =
  24. (uint32_t)config_get_uint(config, "d3d9", "present_ex");
  25. offsets->d3d9.present_swap =
  26. (uint32_t)config_get_uint(config, "d3d9", "present_swap");
  27. offsets->dxgi.present =
  28. (uint32_t)config_get_uint(config, "dxgi", "present");
  29. offsets->dxgi.resize =
  30. (uint32_t)config_get_uint(config, "dxgi", "resize");
  31. config_close(config);
  32. return true;
  33. }
  34. static inline bool load_offsets_from_file(struct graphics_offsets *offsets,
  35. const char *file)
  36. {
  37. char *str = os_quick_read_utf8_file(file);
  38. bool success = false;
  39. if (str && *str)
  40. success = load_offsets_from_string(offsets, str);
  41. bfree(str);
  42. return success;
  43. }
  44. static inline bool config_ver_mismatch(
  45. config_t *ver_config,
  46. const char *section,
  47. struct win_version_info *ver)
  48. {
  49. struct win_version_info config_ver;
  50. bool mismatch = false;
  51. #define get_sub_ver(subver) \
  52. config_ver.subver = (int)config_get_int(ver_config, section, #subver); \
  53. mismatch |= config_ver.subver != ver->subver;
  54. get_sub_ver(major);
  55. get_sub_ver(minor);
  56. get_sub_ver(build);
  57. get_sub_ver(revis);
  58. #undef get_sub_ver
  59. return mismatch;
  60. }
  61. static inline void write_config_ver(config_t *ver_config, const char *section,
  62. struct win_version_info *ver)
  63. {
  64. #define set_sub_ver(subver) \
  65. config_set_int(ver_config, section, #subver, ver->subver);
  66. set_sub_ver(major);
  67. set_sub_ver(minor);
  68. set_sub_ver(build);
  69. set_sub_ver(revis);
  70. #undef set_sub_ver
  71. }
  72. static bool get_32bit_system_dll_ver(const wchar_t *system_lib,
  73. struct win_version_info *ver)
  74. {
  75. wchar_t path[MAX_PATH];
  76. UINT ret;
  77. #ifdef _WIN64
  78. ret = GetSystemWow64DirectoryW(path, MAX_PATH);
  79. #else
  80. ret = GetSystemDirectoryW(path, MAX_PATH);
  81. #endif
  82. if (!ret) {
  83. blog(LOG_ERROR, "Failed to get windows 32bit system path: "
  84. "%lu", GetLastError());
  85. return false;
  86. }
  87. wcscat(path, L"\\");
  88. wcscat(path, system_lib);
  89. return get_dll_ver(path, ver);
  90. }
  91. bool cached_versions_match(void)
  92. {
  93. struct win_version_info d3d8_ver = {0};
  94. struct win_version_info d3d9_ver = {0};
  95. struct win_version_info dxgi_ver = {0};
  96. bool ver_mismatch = false;
  97. config_t *config;
  98. char *ver_file;
  99. int ret;
  100. ver_mismatch |= !get_32bit_system_dll_ver(L"d3d8.dll", &d3d8_ver);
  101. ver_mismatch |= !get_32bit_system_dll_ver(L"d3d9.dll", &d3d9_ver);
  102. ver_mismatch |= !get_32bit_system_dll_ver(L"dxgi.dll", &dxgi_ver);
  103. ver_file = obs_module_config_path("version.ini");
  104. if (!ver_file)
  105. return false;
  106. ret = config_open(&config, ver_file, CONFIG_OPEN_ALWAYS);
  107. if (ret != CONFIG_SUCCESS)
  108. goto failed;
  109. ver_mismatch |= config_ver_mismatch(config, "d3d8", &d3d8_ver);
  110. ver_mismatch |= config_ver_mismatch(config, "d3d9", &d3d9_ver);
  111. ver_mismatch |= config_ver_mismatch(config, "dxgi", &dxgi_ver);
  112. if (ver_mismatch) {
  113. write_config_ver(config, "d3d8", &d3d8_ver);
  114. write_config_ver(config, "d3d9", &d3d9_ver);
  115. write_config_ver(config, "dxgi", &dxgi_ver);
  116. config_save_safe(config, "tmp", NULL);
  117. }
  118. failed:
  119. bfree(ver_file);
  120. config_close(config);
  121. return !ver_mismatch;
  122. }
  123. bool load_graphics_offsets(bool is32bit)
  124. {
  125. char *offset_exe_path = NULL;
  126. struct dstr offset_exe = {0};
  127. char *config_ini = NULL;
  128. struct dstr str = {0};
  129. os_process_pipe_t *pp;
  130. bool success = false;
  131. char data[128];
  132. dstr_copy(&offset_exe, "get-graphics-offsets");
  133. dstr_cat(&offset_exe, is32bit ? "32.exe" : "64.exe");
  134. offset_exe_path = obs_module_file(offset_exe.array);
  135. pp = os_process_pipe_create(offset_exe_path, "r");
  136. if (!pp) {
  137. blog(LOG_INFO, "load_graphics_offsets: Failed to start '%s'",
  138. offset_exe.array);
  139. goto error;
  140. }
  141. for (;;) {
  142. size_t len = os_process_pipe_read(pp, (uint8_t*)data, 128);
  143. if (!len)
  144. break;
  145. dstr_ncat(&str, data, len);
  146. }
  147. config_ini = obs_module_config_path(is32bit ? "32.ini" : "64.ini");
  148. os_quick_write_utf8_file_safe(config_ini, str.array, str.len, false,
  149. "tmp", NULL);
  150. bfree(config_ini);
  151. success = load_offsets_from_string(is32bit ? &offsets32 : &offsets64,
  152. str.array);
  153. if (!success) {
  154. blog(LOG_INFO, "load_graphics_offsets: Failed to load string");
  155. }
  156. os_process_pipe_destroy(pp);
  157. error:
  158. bfree(offset_exe_path);
  159. dstr_free(&offset_exe);
  160. dstr_free(&str);
  161. return success;
  162. }
  163. bool load_cached_graphics_offsets(bool is32bit)
  164. {
  165. char *config_ini = NULL;
  166. bool success;
  167. config_ini = obs_module_config_path(is32bit ? "32.ini" : "64.ini");
  168. success = load_offsets_from_file(is32bit ? &offsets32 : &offsets64,
  169. config_ini);
  170. if (!success)
  171. success = load_graphics_offsets(is32bit);
  172. bfree(config_ini);
  173. return success;
  174. }