IDirectory.cs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. using Ryujinx.HLE.OsHle.Ipc;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Text;
  6. namespace Ryujinx.HLE.OsHle.Services.FspSrv
  7. {
  8. class IDirectory : IpcService, IDisposable
  9. {
  10. private const int DirectoryEntrySize = 0x310;
  11. private Dictionary<int, ServiceProcessRequest> m_Commands;
  12. public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
  13. private List<string> DirectoryEntries;
  14. private int CurrentItemIndex;
  15. public event EventHandler<EventArgs> Disposed;
  16. public string HostPath { get; private set; }
  17. public IDirectory(string HostPath, int Flags)
  18. {
  19. m_Commands = new Dictionary<int, ServiceProcessRequest>()
  20. {
  21. { 0, Read },
  22. { 1, GetEntryCount }
  23. };
  24. this.HostPath = HostPath;
  25. DirectoryEntries = new List<string>();
  26. if ((Flags & 1) != 0)
  27. {
  28. DirectoryEntries.AddRange(Directory.GetDirectories(HostPath));
  29. }
  30. if ((Flags & 2) != 0)
  31. {
  32. DirectoryEntries.AddRange(Directory.GetFiles(HostPath));
  33. }
  34. CurrentItemIndex = 0;
  35. }
  36. public long Read(ServiceCtx Context)
  37. {
  38. long BufferPosition = Context.Request.ReceiveBuff[0].Position;
  39. long BufferLen = Context.Request.ReceiveBuff[0].Size;
  40. int MaxReadCount = (int)(BufferLen / DirectoryEntrySize);
  41. int Count = Math.Min(DirectoryEntries.Count - CurrentItemIndex, MaxReadCount);
  42. for (int Index = 0; Index < Count; Index++)
  43. {
  44. long Position = BufferPosition + Index * DirectoryEntrySize;
  45. WriteDirectoryEntry(Context, Position, DirectoryEntries[CurrentItemIndex++]);
  46. }
  47. Context.ResponseData.Write((long)Count);
  48. return 0;
  49. }
  50. private void WriteDirectoryEntry(ServiceCtx Context, long Position, string FullPath)
  51. {
  52. for (int Offset = 0; Offset < 0x300; Offset += 8)
  53. {
  54. Context.Memory.WriteInt64(Position + Offset, 0);
  55. }
  56. byte[] NameBuffer = Encoding.UTF8.GetBytes(Path.GetFileName(FullPath));
  57. Context.Memory.WriteBytes(Position, NameBuffer);
  58. int Type = 0;
  59. long Size = 0;
  60. if (File.Exists(FullPath))
  61. {
  62. Type = 1;
  63. Size = new FileInfo(FullPath).Length;
  64. }
  65. Context.Memory.WriteInt32(Position + 0x300, 0); //Padding?
  66. Context.Memory.WriteInt32(Position + 0x304, Type);
  67. Context.Memory.WriteInt64(Position + 0x308, Size);
  68. }
  69. public long GetEntryCount(ServiceCtx Context)
  70. {
  71. Context.ResponseData.Write((long)DirectoryEntries.Count);
  72. return 0;
  73. }
  74. public void Dispose()
  75. {
  76. Dispose(true);
  77. }
  78. protected virtual void Dispose(bool disposing)
  79. {
  80. if (disposing)
  81. {
  82. Disposed?.Invoke(this, EventArgs.Empty);
  83. }
  84. }
  85. }
  86. }