QueryDirectoryFileInformation.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /* Copyright (C) 2017 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
  2. *
  3. * You can redistribute this program and/or modify it under the terms of
  4. * the GNU Lesser Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. */
  7. using System;
  8. using System.Collections.Generic;
  9. using Utilities;
  10. namespace SMBLibrary
  11. {
  12. public abstract class QueryDirectoryFileInformation : FileInformation
  13. {
  14. public uint NextEntryOffset;
  15. public uint FileIndex;
  16. public QueryDirectoryFileInformation()
  17. {
  18. }
  19. public QueryDirectoryFileInformation(byte[] buffer, int offset)
  20. {
  21. NextEntryOffset = LittleEndianConverter.ToUInt32(buffer, offset + 0);
  22. FileIndex = LittleEndianConverter.ToUInt32(buffer, offset + 4);
  23. }
  24. public override void WriteBytes(byte[] buffer, int offset)
  25. {
  26. LittleEndianWriter.WriteUInt32(buffer, offset + 0, NextEntryOffset);
  27. LittleEndianWriter.WriteUInt32(buffer, offset + 4, FileIndex);
  28. }
  29. public static QueryDirectoryFileInformation ReadFileInformation(byte[] buffer, int offset, FileInformationClass fileInformationClass)
  30. {
  31. switch (fileInformationClass)
  32. {
  33. case FileInformationClass.FileDirectoryInformation:
  34. return new FileDirectoryInformation(buffer, offset);
  35. case FileInformationClass.FileFullDirectoryInformation:
  36. return new FileFullDirectoryInformation(buffer, offset);
  37. case FileInformationClass.FileBothDirectoryInformation:
  38. return new FileBothDirectoryInformation(buffer, offset);
  39. case FileInformationClass.FileNamesInformation:
  40. return new FileNamesInformation(buffer, offset);
  41. case FileInformationClass.FileIdBothDirectoryInformation:
  42. return new FileIdBothDirectoryInformation(buffer, offset);
  43. case FileInformationClass.FileIdFullDirectoryInformation:
  44. return new FileIdFullDirectoryInformation(buffer, offset);
  45. default:
  46. throw new NotImplementedException(String.Format("File information class {0} is not supported.", (int)fileInformationClass));
  47. }
  48. }
  49. public static List<QueryDirectoryFileInformation> ReadFileInformationList(byte[] buffer, int offset, FileInformationClass fileInformationClass)
  50. {
  51. List<QueryDirectoryFileInformation> result = new List<QueryDirectoryFileInformation>();
  52. QueryDirectoryFileInformation entry;
  53. do
  54. {
  55. entry = ReadFileInformation(buffer, offset, fileInformationClass);
  56. result.Add(entry);
  57. offset += (int)entry.NextEntryOffset;
  58. }
  59. while (entry.NextEntryOffset != 0);
  60. return result;
  61. }
  62. public static byte[] GetBytes(List<QueryDirectoryFileInformation> fileInformationList)
  63. {
  64. int listLength = GetListLength(fileInformationList);
  65. byte[] buffer = new byte[listLength];
  66. int offset = 0;
  67. for (int index = 0; index < fileInformationList.Count; index++)
  68. {
  69. QueryDirectoryFileInformation entry = fileInformationList[index];
  70. int length = entry.Length;
  71. int paddedLength = (int)Math.Ceiling((double)length / 8) * 8;
  72. if (index < fileInformationList.Count - 1)
  73. {
  74. entry.NextEntryOffset = (uint)paddedLength;
  75. }
  76. else
  77. {
  78. entry.NextEntryOffset = 0;
  79. }
  80. entry.WriteBytes(buffer, offset);
  81. offset += paddedLength;
  82. }
  83. return buffer;
  84. }
  85. public static int GetListLength(List<QueryDirectoryFileInformation> fileInformationList)
  86. {
  87. int result = 0;
  88. for(int index = 0; index < fileInformationList.Count; index++)
  89. {
  90. QueryDirectoryFileInformation entry = fileInformationList[index];
  91. int length = entry.Length;
  92. // [MS-FSCC] each [entry] MUST be aligned on an 8-byte boundary.
  93. if (index < fileInformationList.Count - 1)
  94. {
  95. // No padding is required following the last data element.
  96. int paddedLength = (int)Math.Ceiling((double)length / 8) * 8;
  97. result += paddedLength;
  98. }
  99. else
  100. {
  101. result += length;
  102. }
  103. }
  104. return result;
  105. }
  106. }
  107. }