init-hook-files.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. #include <windows.h>
  2. #include <strsafe.h>
  3. #include <shlobj.h>
  4. #include <stdbool.h>
  5. #include <aclapi.h>
  6. #include <sddl.h>
  7. static bool add_aap_perms(const wchar_t *dir)
  8. {
  9. PSECURITY_DESCRIPTOR sd = NULL;
  10. SID *aap_sid = NULL;
  11. SID *bu_sid = NULL;
  12. PACL new_dacl1 = NULL;
  13. PACL new_dacl2 = NULL;
  14. bool success = false;
  15. PACL dacl;
  16. if (GetNamedSecurityInfoW(dir, SE_FILE_OBJECT,
  17. DACL_SECURITY_INFORMATION, NULL, NULL, &dacl,
  18. NULL, &sd) != ERROR_SUCCESS) {
  19. goto fail;
  20. }
  21. EXPLICIT_ACCESSW ea = {0};
  22. ea.grfAccessPermissions = GENERIC_READ | GENERIC_EXECUTE;
  23. ea.grfAccessMode = GRANT_ACCESS;
  24. ea.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  25. ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
  26. /* ALL_APP_PACKAGES */
  27. ConvertStringSidToSidW(L"S-1-15-2-1", &aap_sid);
  28. ea.Trustee.ptstrName = (wchar_t *)aap_sid;
  29. if (SetEntriesInAclW(1, &ea, dacl, &new_dacl1) != ERROR_SUCCESS) {
  30. goto fail;
  31. }
  32. ea.grfAccessPermissions = GENERIC_READ | GENERIC_WRITE |
  33. GENERIC_EXECUTE;
  34. /* BUILTIN_USERS */
  35. ConvertStringSidToSidW(L"S-1-5-32-545", &bu_sid);
  36. ea.Trustee.ptstrName = (wchar_t *)bu_sid;
  37. DWORD s = SetEntriesInAclW(1, &ea, new_dacl1, &new_dacl2);
  38. if (s != ERROR_SUCCESS) {
  39. goto fail;
  40. }
  41. if (SetNamedSecurityInfoW((wchar_t *)dir, SE_FILE_OBJECT,
  42. DACL_SECURITY_INFORMATION, NULL, NULL,
  43. new_dacl2, NULL) != ERROR_SUCCESS) {
  44. goto fail;
  45. }
  46. success = true;
  47. fail:
  48. if (sd)
  49. LocalFree(sd);
  50. if (new_dacl1)
  51. LocalFree(new_dacl1);
  52. if (new_dacl2)
  53. LocalFree(new_dacl2);
  54. if (aap_sid)
  55. LocalFree(aap_sid);
  56. if (bu_sid)
  57. LocalFree(bu_sid);
  58. return success;
  59. }
  60. static inline bool file_exists(const wchar_t *path)
  61. {
  62. WIN32_FIND_DATAW wfd;
  63. HANDLE h = FindFirstFileW(path, &wfd);
  64. if (h == INVALID_HANDLE_VALUE)
  65. return false;
  66. FindClose(h);
  67. return true;
  68. }
  69. static LSTATUS get_reg(HKEY hkey, LPCWSTR sub_key, LPCWSTR value_name, bool b64)
  70. {
  71. HKEY key;
  72. LSTATUS status;
  73. DWORD flags = b64 ? KEY_WOW64_64KEY : KEY_WOW64_32KEY;
  74. DWORD size = sizeof(DWORD);
  75. DWORD val;
  76. status = RegOpenKeyEx(hkey, sub_key, 0, KEY_READ | flags, &key);
  77. if (status == ERROR_SUCCESS) {
  78. status = RegQueryValueExW(key, value_name, NULL, NULL,
  79. (LPBYTE)&val, &size);
  80. RegCloseKey(key);
  81. }
  82. return status;
  83. }
  84. #define get_programdata_path(path, subpath) \
  85. do { \
  86. SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, \
  87. SHGFP_TYPE_CURRENT, path); \
  88. StringCbCatW(path, sizeof(path), L"\\"); \
  89. StringCbCatW(path, sizeof(path), subpath); \
  90. } while (false)
  91. #define make_filename(str, name, ext) \
  92. do { \
  93. StringCbCatW(str, sizeof(str), name); \
  94. StringCbCatW(str, sizeof(str), b64 ? L"64" : L"32"); \
  95. StringCbCatW(str, sizeof(str), ext); \
  96. } while (false)
  97. #define IMPLICIT_LAYERS L"SOFTWARE\\Khronos\\Vulkan\\ImplicitLayers"
  98. #define HOOK_LOCATION L"\\data\\obs-plugins\\win-capture\\"
  99. static bool update_hook_file(bool b64)
  100. {
  101. wchar_t temp[MAX_PATH];
  102. wchar_t src[MAX_PATH];
  103. wchar_t dst[MAX_PATH];
  104. wchar_t src_json[MAX_PATH];
  105. wchar_t dst_json[MAX_PATH];
  106. GetCurrentDirectoryW(_countof(src_json), src_json);
  107. StringCbCat(src_json, sizeof(src_json), HOOK_LOCATION);
  108. make_filename(src_json, L"obs-vulkan", L".json");
  109. GetCurrentDirectoryW(_countof(src), src);
  110. StringCbCat(src, sizeof(src), HOOK_LOCATION);
  111. make_filename(src, L"graphics-hook", L".dll");
  112. get_programdata_path(temp, L"obs-studio-hook\\");
  113. StringCbCopyW(dst_json, sizeof(dst_json), temp);
  114. StringCbCopyW(dst, sizeof(dst), temp);
  115. make_filename(dst_json, L"obs-vulkan", L".json");
  116. make_filename(dst, L"graphics-hook", L".dll");
  117. if (!file_exists(src)) {
  118. return false;
  119. }
  120. CreateDirectoryW(temp, NULL);
  121. add_aap_perms(temp);
  122. CopyFileW(src, dst, false);
  123. CopyFileW(src_json, dst_json, false);
  124. return true;
  125. }
  126. static void update_vulkan_registry(bool b64)
  127. {
  128. DWORD flags = b64 ? KEY_WOW64_64KEY : KEY_WOW64_32KEY;
  129. wchar_t path[MAX_PATH];
  130. DWORD temp;
  131. LSTATUS s;
  132. HKEY key;
  133. get_programdata_path(path, L"obs-studio-hook\\");
  134. make_filename(path, L"obs-vulkan", L".json");
  135. s = get_reg(HKEY_CURRENT_USER, IMPLICIT_LAYERS, path, b64);
  136. if (s == ERROR_SUCCESS) {
  137. s = RegOpenKeyEx(HKEY_CURRENT_USER, IMPLICIT_LAYERS, 0,
  138. KEY_WRITE | flags, &key);
  139. if (s == ERROR_SUCCESS) {
  140. RegDeleteValueW(key, path);
  141. RegCloseKey(key);
  142. }
  143. }
  144. s = get_reg(HKEY_LOCAL_MACHINE, IMPLICIT_LAYERS, path, b64);
  145. if (s == ERROR_SUCCESS) {
  146. return;
  147. }
  148. /* ------------------- */
  149. s = RegCreateKeyExW(HKEY_LOCAL_MACHINE, IMPLICIT_LAYERS, 0, NULL, 0,
  150. KEY_WRITE | flags, NULL, &key, &temp);
  151. if (s != ERROR_SUCCESS) {
  152. goto finish;
  153. }
  154. DWORD zero = 0;
  155. s = RegSetValueExW(key, path, 0, REG_DWORD, (const BYTE *)&zero,
  156. sizeof(zero));
  157. if (s != ERROR_SUCCESS) {
  158. goto finish;
  159. }
  160. finish:
  161. if (key)
  162. RegCloseKey(key);
  163. }
  164. void UpdateHookFiles(void)
  165. {
  166. if (update_hook_file(true))
  167. update_vulkan_registry(true);
  168. if (update_hook_file(false))
  169. update_vulkan_registry(false);
  170. }