load-graphics-offsets.c 5.9 KB

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