IParentalControlService.cs 8.1 KB

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