IParentalControlService.cs 8.0 KB

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