IParentalControlService.cs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. using Ryujinx.Common.Logging;
  2. using Ryujinx.HLE.HOS.Services.Arp;
  3. using System;
  4. using static LibHac.Ns.ApplicationControlProperty;
  5. namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory
  6. {
  7. class IParentalControlService : IpcService
  8. {
  9. private ulong _pid;
  10. private int _permissionFlag;
  11. private ulong _titleId;
  12. private ParentalControlFlagValue _parentalControlFlag;
  13. private int[] _ratingAge;
  14. #pragma warning disable CS0414
  15. // TODO: Find where they are set.
  16. private bool _restrictionEnabled = false;
  17. private bool _featuresRestriction = false;
  18. private bool _freeCommunicationEnabled = false;
  19. private bool _stereoVisionRestrictionConfigurable = true;
  20. private bool _stereoVisionRestriction = false;
  21. #pragma warning restore CS0414
  22. public IParentalControlService(ServiceCtx context, ulong pid, bool withInitialize, int permissionFlag)
  23. {
  24. _pid = pid;
  25. _permissionFlag = permissionFlag;
  26. if (withInitialize)
  27. {
  28. Initialize(context);
  29. }
  30. }
  31. [CommandHipc(1)] // 4.0.0+
  32. // Initialize()
  33. public ResultCode Initialize(ServiceCtx context)
  34. {
  35. if ((_permissionFlag & 0x8001) == 0)
  36. {
  37. return ResultCode.PermissionDenied;
  38. }
  39. ResultCode resultCode = ResultCode.InvalidPid;
  40. if (_pid != 0)
  41. {
  42. if ((_permissionFlag & 0x40) == 0)
  43. {
  44. ulong titleId = ApplicationLaunchProperty.GetByPid(context).TitleId;
  45. if (titleId != 0)
  46. {
  47. _titleId = titleId;
  48. // TODO: Call nn::arp::GetApplicationControlProperty here when implemented, if it return ResultCode.Success we assign fields.
  49. _ratingAge = Array.ConvertAll(context.Device.Application.ControlData.Value.RatingAge.ItemsRo.ToArray(), Convert.ToInt32);
  50. _parentalControlFlag = context.Device.Application.ControlData.Value.ParentalControlFlag;
  51. }
  52. }
  53. if (_titleId != 0)
  54. {
  55. // TODO: Service store some private fields in another static object.
  56. if ((_permissionFlag & 0x8040) == 0)
  57. {
  58. // TODO: Service store TitleId and FreeCommunicationEnabled in another static object.
  59. // When it's done it signal an event in this static object.
  60. Logger.Stub?.PrintStub(LogClass.ServicePctl);
  61. }
  62. }
  63. resultCode = ResultCode.Success;
  64. }
  65. return resultCode;
  66. }
  67. [CommandHipc(1001)]
  68. // CheckFreeCommunicationPermission()
  69. public ResultCode CheckFreeCommunicationPermission(ServiceCtx context)
  70. {
  71. if (_parentalControlFlag == ParentalControlFlagValue.FreeCommunication && _restrictionEnabled)
  72. {
  73. // TODO: It seems to checks if an entry exists in the FreeCommunicationApplicationList using the TitleId.
  74. // Then it returns FreeCommunicationDisabled if the entry doesn't exist.
  75. return ResultCode.FreeCommunicationDisabled;
  76. }
  77. _freeCommunicationEnabled = true;
  78. Logger.Stub?.PrintStub(LogClass.ServicePctl);
  79. return ResultCode.Success;
  80. }
  81. [CommandHipc(1017)] // 10.0.0+
  82. // EndFreeCommunication()
  83. public ResultCode EndFreeCommunication(ServiceCtx context)
  84. {
  85. _freeCommunicationEnabled = false;
  86. return ResultCode.Success;
  87. }
  88. [CommandHipc(1013)] // 4.0.0+
  89. // ConfirmStereoVisionPermission()
  90. public ResultCode ConfirmStereoVisionPermission(ServiceCtx context)
  91. {
  92. return IsStereoVisionPermittedImpl();
  93. }
  94. [CommandHipc(1018)]
  95. // IsFreeCommunicationAvailable()
  96. public ResultCode IsFreeCommunicationAvailable(ServiceCtx context)
  97. {
  98. if (_parentalControlFlag == ParentalControlFlagValue.FreeCommunication && _restrictionEnabled)
  99. {
  100. // TODO: It seems to checks if an entry exists in the FreeCommunicationApplicationList using the TitleId.
  101. // Then it returns FreeCommunicationDisabled if the entry doesn't exist.
  102. return ResultCode.FreeCommunicationDisabled;
  103. }
  104. Logger.Stub?.PrintStub(LogClass.ServicePctl);
  105. return ResultCode.Success;
  106. }
  107. [CommandHipc(1031)]
  108. // IsRestrictionEnabled() -> b8
  109. public ResultCode IsRestrictionEnabled(ServiceCtx context)
  110. {
  111. if ((_permissionFlag & 0x140) == 0)
  112. {
  113. return ResultCode.PermissionDenied;
  114. }
  115. context.ResponseData.Write(_restrictionEnabled);
  116. return ResultCode.Success;
  117. }
  118. [CommandHipc(1061)] // 4.0.0+
  119. // ConfirmStereoVisionRestrictionConfigurable()
  120. public ResultCode ConfirmStereoVisionRestrictionConfigurable(ServiceCtx context)
  121. {
  122. if ((_permissionFlag & 2) == 0)
  123. {
  124. return ResultCode.PermissionDenied;
  125. }
  126. if (_stereoVisionRestrictionConfigurable)
  127. {
  128. return ResultCode.Success;
  129. }
  130. else
  131. {
  132. return ResultCode.StereoVisionRestrictionConfigurableDisabled;
  133. }
  134. }
  135. [CommandHipc(1062)] // 4.0.0+
  136. // GetStereoVisionRestriction() -> bool
  137. public ResultCode GetStereoVisionRestriction(ServiceCtx context)
  138. {
  139. if ((_permissionFlag & 0x200) == 0)
  140. {
  141. return ResultCode.PermissionDenied;
  142. }
  143. bool stereoVisionRestriction = false;
  144. if (_stereoVisionRestrictionConfigurable)
  145. {
  146. stereoVisionRestriction = _stereoVisionRestriction;
  147. }
  148. context.ResponseData.Write(stereoVisionRestriction);
  149. return ResultCode.Success;
  150. }
  151. [CommandHipc(1063)] // 4.0.0+
  152. // SetStereoVisionRestriction(bool)
  153. public ResultCode SetStereoVisionRestriction(ServiceCtx context)
  154. {
  155. if ((_permissionFlag & 0x200) == 0)
  156. {
  157. return ResultCode.PermissionDenied;
  158. }
  159. bool stereoVisionRestriction = context.RequestData.ReadBoolean();
  160. if (!_featuresRestriction)
  161. {
  162. if (_stereoVisionRestrictionConfigurable)
  163. {
  164. _stereoVisionRestriction = stereoVisionRestriction;
  165. // TODO: It signals an internal event of service. We have to determine where this event is used.
  166. }
  167. }
  168. return ResultCode.Success;
  169. }
  170. [CommandHipc(1064)] // 5.0.0+
  171. // ResetConfirmedStereoVisionPermission()
  172. public ResultCode ResetConfirmedStereoVisionPermission(ServiceCtx context)
  173. {
  174. return ResultCode.Success;
  175. }
  176. [CommandHipc(1065)] // 5.0.0+
  177. // IsStereoVisionPermitted() -> bool
  178. public ResultCode IsStereoVisionPermitted(ServiceCtx context)
  179. {
  180. bool isStereoVisionPermitted = false;
  181. ResultCode resultCode = IsStereoVisionPermittedImpl();
  182. if (resultCode == ResultCode.Success)
  183. {
  184. isStereoVisionPermitted = true;
  185. }
  186. context.ResponseData.Write(isStereoVisionPermitted);
  187. return resultCode;
  188. }
  189. private ResultCode IsStereoVisionPermittedImpl()
  190. {
  191. /*
  192. // TODO: Application Exemptions are read from file "appExemptions.dat" in the service savedata.
  193. // Since we don't support the pctl savedata for now, this can be implemented later.
  194. if (appExemption)
  195. {
  196. return ResultCode.Success;
  197. }
  198. */
  199. if (_stereoVisionRestrictionConfigurable && _stereoVisionRestriction)
  200. {
  201. return ResultCode.StereoVisionDenied;
  202. }
  203. else
  204. {
  205. return ResultCode.Success;
  206. }
  207. }
  208. }
  209. }