arp.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <memory>
  5. #include "common/logging/log.h"
  6. #include "core/core.h"
  7. #include "core/file_sys/control_metadata.h"
  8. #include "core/hle/ipc_helpers.h"
  9. #include "core/hle/kernel/k_process.h"
  10. #include "core/hle/kernel/kernel.h"
  11. #include "core/hle/service/glue/arp.h"
  12. #include "core/hle/service/glue/errors.h"
  13. #include "core/hle/service/glue/glue_manager.h"
  14. namespace Service::Glue {
  15. namespace {
  16. std::optional<u64> GetTitleIDForProcessID(const Core::System& system, u64 process_id) {
  17. const auto& list = system.Kernel().GetProcessList();
  18. const auto iter = std::find_if(list.begin(), list.end(), [&process_id](const auto& process) {
  19. return process->GetProcessID() == process_id;
  20. });
  21. if (iter == list.end()) {
  22. return std::nullopt;
  23. }
  24. return (*iter)->GetTitleID();
  25. }
  26. } // Anonymous namespace
  27. ARP_R::ARP_R(Core::System& system_, const ARPManager& manager_)
  28. : ServiceFramework{system_, "arp:r"}, manager{manager_} {
  29. // clang-format off
  30. static const FunctionInfo functions[] = {
  31. {0, &ARP_R::GetApplicationLaunchProperty, "GetApplicationLaunchProperty"},
  32. {1, &ARP_R::GetApplicationLaunchPropertyWithApplicationId, "GetApplicationLaunchPropertyWithApplicationId"},
  33. {2, &ARP_R::GetApplicationControlProperty, "GetApplicationControlProperty"},
  34. {3, &ARP_R::GetApplicationControlPropertyWithApplicationId, "GetApplicationControlPropertyWithApplicationId"},
  35. {4, nullptr, "GetApplicationInstanceUnregistrationNotifier"},
  36. {5, nullptr, "ListApplicationInstanceId"},
  37. {6, nullptr, "GetMicroApplicationInstanceId"},
  38. {7, nullptr, "GetApplicationCertificate"},
  39. {9998, nullptr, "GetPreomiaApplicationLaunchProperty"},
  40. {9999, nullptr, "GetPreomiaApplicationControlProperty"},
  41. };
  42. // clang-format on
  43. RegisterHandlers(functions);
  44. }
  45. ARP_R::~ARP_R() = default;
  46. void ARP_R::GetApplicationLaunchProperty(Kernel::HLERequestContext& ctx) {
  47. IPC::RequestParser rp{ctx};
  48. const auto process_id = rp.PopRaw<u64>();
  49. LOG_DEBUG(Service_ARP, "called, process_id={:016X}", process_id);
  50. const auto title_id = GetTitleIDForProcessID(system, process_id);
  51. if (!title_id.has_value()) {
  52. LOG_ERROR(Service_ARP, "Failed to get title ID for process ID!");
  53. IPC::ResponseBuilder rb{ctx, 2};
  54. rb.Push(ERR_NOT_REGISTERED);
  55. return;
  56. }
  57. const auto res = manager.GetLaunchProperty(*title_id);
  58. if (res.Failed()) {
  59. LOG_ERROR(Service_ARP, "Failed to get launch property!");
  60. IPC::ResponseBuilder rb{ctx, 2};
  61. rb.Push(res.Code());
  62. return;
  63. }
  64. IPC::ResponseBuilder rb{ctx, 6};
  65. rb.Push(ResultSuccess);
  66. rb.PushRaw(*res);
  67. }
  68. void ARP_R::GetApplicationLaunchPropertyWithApplicationId(Kernel::HLERequestContext& ctx) {
  69. IPC::RequestParser rp{ctx};
  70. const auto title_id = rp.PopRaw<u64>();
  71. LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id);
  72. const auto res = manager.GetLaunchProperty(title_id);
  73. if (res.Failed()) {
  74. LOG_ERROR(Service_ARP, "Failed to get launch property!");
  75. IPC::ResponseBuilder rb{ctx, 2};
  76. rb.Push(res.Code());
  77. return;
  78. }
  79. IPC::ResponseBuilder rb{ctx, 6};
  80. rb.Push(ResultSuccess);
  81. rb.PushRaw(*res);
  82. }
  83. void ARP_R::GetApplicationControlProperty(Kernel::HLERequestContext& ctx) {
  84. IPC::RequestParser rp{ctx};
  85. const auto process_id = rp.PopRaw<u64>();
  86. LOG_DEBUG(Service_ARP, "called, process_id={:016X}", process_id);
  87. const auto title_id = GetTitleIDForProcessID(system, process_id);
  88. if (!title_id.has_value()) {
  89. LOG_ERROR(Service_ARP, "Failed to get title ID for process ID!");
  90. IPC::ResponseBuilder rb{ctx, 2};
  91. rb.Push(ERR_NOT_REGISTERED);
  92. return;
  93. }
  94. const auto res = manager.GetControlProperty(*title_id);
  95. if (res.Failed()) {
  96. LOG_ERROR(Service_ARP, "Failed to get control property!");
  97. IPC::ResponseBuilder rb{ctx, 2};
  98. rb.Push(res.Code());
  99. return;
  100. }
  101. ctx.WriteBuffer(*res);
  102. IPC::ResponseBuilder rb{ctx, 2};
  103. rb.Push(ResultSuccess);
  104. }
  105. void ARP_R::GetApplicationControlPropertyWithApplicationId(Kernel::HLERequestContext& ctx) {
  106. IPC::RequestParser rp{ctx};
  107. const auto title_id = rp.PopRaw<u64>();
  108. LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id);
  109. const auto res = manager.GetControlProperty(title_id);
  110. if (res.Failed()) {
  111. LOG_ERROR(Service_ARP, "Failed to get control property!");
  112. IPC::ResponseBuilder rb{ctx, 2};
  113. rb.Push(res.Code());
  114. return;
  115. }
  116. ctx.WriteBuffer(*res);
  117. IPC::ResponseBuilder rb{ctx, 2};
  118. rb.Push(ResultSuccess);
  119. }
  120. class IRegistrar final : public ServiceFramework<IRegistrar> {
  121. friend class ARP_W;
  122. public:
  123. using IssuerFn = std::function<ResultCode(u64, ApplicationLaunchProperty, std::vector<u8>)>;
  124. explicit IRegistrar(Core::System& system_, IssuerFn&& issuer)
  125. : ServiceFramework{system_, "IRegistrar"}, issue_process_id{std::move(issuer)} {
  126. // clang-format off
  127. static const FunctionInfo functions[] = {
  128. {0, &IRegistrar::Issue, "Issue"},
  129. {1, &IRegistrar::SetApplicationLaunchProperty, "SetApplicationLaunchProperty"},
  130. {2, &IRegistrar::SetApplicationControlProperty, "SetApplicationControlProperty"},
  131. };
  132. // clang-format on
  133. RegisterHandlers(functions);
  134. }
  135. private:
  136. void Issue(Kernel::HLERequestContext& ctx) {
  137. IPC::RequestParser rp{ctx};
  138. const auto process_id = rp.PopRaw<u64>();
  139. LOG_DEBUG(Service_ARP, "called, process_id={:016X}", process_id);
  140. if (process_id == 0) {
  141. LOG_ERROR(Service_ARP, "Must have non-zero process ID!");
  142. IPC::ResponseBuilder rb{ctx, 2};
  143. rb.Push(ERR_INVALID_PROCESS_ID);
  144. return;
  145. }
  146. if (issued) {
  147. LOG_ERROR(Service_ARP,
  148. "Attempted to issue registrar, but registrar is already issued!");
  149. IPC::ResponseBuilder rb{ctx, 2};
  150. rb.Push(ERR_INVALID_ACCESS);
  151. return;
  152. }
  153. issue_process_id(process_id, launch, std::move(control));
  154. issued = true;
  155. IPC::ResponseBuilder rb{ctx, 2};
  156. rb.Push(ResultSuccess);
  157. }
  158. void SetApplicationLaunchProperty(Kernel::HLERequestContext& ctx) {
  159. LOG_DEBUG(Service_ARP, "called");
  160. if (issued) {
  161. LOG_ERROR(
  162. Service_ARP,
  163. "Attempted to set application launch property, but registrar is already issued!");
  164. IPC::ResponseBuilder rb{ctx, 2};
  165. rb.Push(ERR_INVALID_ACCESS);
  166. return;
  167. }
  168. IPC::RequestParser rp{ctx};
  169. launch = rp.PopRaw<ApplicationLaunchProperty>();
  170. IPC::ResponseBuilder rb{ctx, 2};
  171. rb.Push(ResultSuccess);
  172. }
  173. void SetApplicationControlProperty(Kernel::HLERequestContext& ctx) {
  174. LOG_DEBUG(Service_ARP, "called");
  175. if (issued) {
  176. LOG_ERROR(
  177. Service_ARP,
  178. "Attempted to set application control property, but registrar is already issued!");
  179. IPC::ResponseBuilder rb{ctx, 2};
  180. rb.Push(ERR_INVALID_ACCESS);
  181. return;
  182. }
  183. control = ctx.ReadBuffer();
  184. IPC::ResponseBuilder rb{ctx, 2};
  185. rb.Push(ResultSuccess);
  186. }
  187. IssuerFn issue_process_id;
  188. bool issued = false;
  189. ApplicationLaunchProperty launch{};
  190. std::vector<u8> control;
  191. };
  192. ARP_W::ARP_W(Core::System& system_, ARPManager& manager_)
  193. : ServiceFramework{system_, "arp:w"}, manager{manager_} {
  194. // clang-format off
  195. static const FunctionInfo functions[] = {
  196. {0, &ARP_W::AcquireRegistrar, "AcquireRegistrar"},
  197. {1, &ARP_W::UnregisterApplicationInstance , "UnregisterApplicationInstance "},
  198. {2, nullptr, "AcquireUpdater"},
  199. };
  200. // clang-format on
  201. RegisterHandlers(functions);
  202. }
  203. ARP_W::~ARP_W() = default;
  204. void ARP_W::AcquireRegistrar(Kernel::HLERequestContext& ctx) {
  205. LOG_DEBUG(Service_ARP, "called");
  206. registrar = std::make_shared<IRegistrar>(
  207. system, [this](u64 process_id, ApplicationLaunchProperty launch, std::vector<u8> control) {
  208. const auto res = GetTitleIDForProcessID(system, process_id);
  209. if (!res.has_value()) {
  210. return ERR_NOT_REGISTERED;
  211. }
  212. return manager.Register(*res, launch, std::move(control));
  213. });
  214. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  215. rb.Push(ResultSuccess);
  216. rb.PushIpcInterface(registrar);
  217. }
  218. void ARP_W::UnregisterApplicationInstance(Kernel::HLERequestContext& ctx) {
  219. IPC::RequestParser rp{ctx};
  220. const auto process_id = rp.PopRaw<u64>();
  221. LOG_DEBUG(Service_ARP, "called, process_id={:016X}", process_id);
  222. if (process_id == 0) {
  223. LOG_ERROR(Service_ARP, "Must have non-zero process ID!");
  224. IPC::ResponseBuilder rb{ctx, 2};
  225. rb.Push(ERR_INVALID_PROCESS_ID);
  226. return;
  227. }
  228. const auto title_id = GetTitleIDForProcessID(system, process_id);
  229. if (!title_id.has_value()) {
  230. LOG_ERROR(Service_ARP, "No title ID for process ID!");
  231. IPC::ResponseBuilder rb{ctx, 2};
  232. rb.Push(ERR_NOT_REGISTERED);
  233. return;
  234. }
  235. IPC::ResponseBuilder rb{ctx, 2};
  236. rb.Push(manager.Unregister(*title_id));
  237. }
  238. } // namespace Service::Glue