FileNotifyInformation.cs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  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 enum FileAction : uint
  13. {
  14. Added = 0x00000001, // FILE_ACTION_ADDED
  15. Removed = 0x00000002, // FILE_ACTION_REMOVED
  16. Modified = 0x00000003, // FILE_ACTION_MODIFIED
  17. RenamedOldName = 0x00000004, // FILE_ACTION_RENAMED_OLD_NAME
  18. RenamedNewName = 0x00000005, // FILE_ACTION_RENAMED_NEW_NAME
  19. AddedStream = 0x00000006, // FILE_ACTION_ADDED_STREAM
  20. RemovedStream = 0x00000007, // FILE_ACTION_REMOVED_STREAM
  21. ModifiedStream = 0x00000008, // FILE_ACTION_MODIFIED_STREAM
  22. RemovedByDelete = 0x00000009, // FILE_ACTION_REMOVED_BY_DELETE
  23. IDNotTunneled = 0x0000000A, // FILE_ACTION_ID_NOT_TUNNELLED
  24. TunneledIDCollision = 0x0000000B, // FILE_ACTION_TUNNELLED_ID_COLLISION
  25. }
  26. /// <summary>
  27. /// [MS-FSCC] 2.4.42 - FileNotifyInformation
  28. /// </summary>
  29. public class FileNotifyInformation
  30. {
  31. public const int FixedLength = 12;
  32. public uint NextEntryOffset;
  33. public FileAction Action;
  34. private uint FileNameLength;
  35. public string FileName;
  36. public FileNotifyInformation()
  37. {
  38. FileName = String.Empty;
  39. }
  40. public FileNotifyInformation(byte[] buffer, int offset)
  41. {
  42. NextEntryOffset = LittleEndianConverter.ToUInt32(buffer, offset + 0);
  43. Action = (FileAction)LittleEndianConverter.ToUInt32(buffer, offset + 4);
  44. FileNameLength = LittleEndianConverter.ToUInt32(buffer, offset + 8);
  45. FileName = ByteReader.ReadUTF16String(buffer, offset + 12, (int)(FileNameLength / 2));
  46. }
  47. public void WriteBytes(byte[] buffer, int offset)
  48. {
  49. FileNameLength = (uint)(FileName.Length * 2);
  50. LittleEndianWriter.WriteUInt32(buffer, offset + 0, NextEntryOffset);
  51. LittleEndianWriter.WriteUInt32(buffer, offset + 4, (uint)Action);
  52. LittleEndianWriter.WriteUInt32(buffer, offset + 8, FileNameLength);
  53. ByteWriter.WriteUTF16String(buffer, offset + 12, FileName);
  54. }
  55. public int Length
  56. {
  57. get
  58. {
  59. return FixedLength + FileName.Length * 2;
  60. }
  61. }
  62. public static List<FileNotifyInformation> ReadList(byte[] buffer, int offset)
  63. {
  64. List<FileNotifyInformation> result = new List<FileNotifyInformation>();
  65. FileNotifyInformation entry;
  66. do
  67. {
  68. entry = new FileNotifyInformation(buffer, offset);
  69. result.Add(entry);
  70. offset += (int)entry.NextEntryOffset;
  71. }
  72. while (entry.NextEntryOffset != 0);
  73. return result;
  74. }
  75. public static byte[] GetBytes(List<FileNotifyInformation> notifyInformationList)
  76. {
  77. int listLength = GetListLength(notifyInformationList);
  78. byte[] buffer = new byte[listLength];
  79. int offset = 0;
  80. for (int index = 0; index < notifyInformationList.Count; index++)
  81. {
  82. FileNotifyInformation entry = notifyInformationList[index];
  83. int length = entry.Length;
  84. int paddedLength = (int)Math.Ceiling((double)length / 4) * 4;
  85. if (index < notifyInformationList.Count - 1)
  86. {
  87. entry.NextEntryOffset = (uint)paddedLength;
  88. }
  89. else
  90. {
  91. entry.NextEntryOffset = 0;
  92. }
  93. entry.WriteBytes(buffer, offset);
  94. offset += paddedLength;
  95. }
  96. return buffer;
  97. }
  98. public static int GetListLength(List<FileNotifyInformation> notifyInformationList)
  99. {
  100. int result = 0;
  101. for (int index = 0; index < notifyInformationList.Count; index++)
  102. {
  103. FileNotifyInformation entry = notifyInformationList[index];
  104. int length = entry.Length;
  105. // [MS-FSCC] NextEntryOffset MUST always be an integral multiple of 4.
  106. // The FileName array MUST be padded to the next 4-byte boundary counted from the beginning of the structure.
  107. if (index < notifyInformationList.Count - 1)
  108. {
  109. // No padding is required following the last data element.
  110. int paddedLength = (int)Math.Ceiling((double)length / 4) * 4;
  111. result += paddedLength;
  112. }
  113. else
  114. {
  115. result += length;
  116. }
  117. }
  118. return result;
  119. }
  120. }
  121. }