You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

285 lines
22 KiB

  1. /* Copyright (C) 2008-2016 Peter Palotas, Jeffrey Jangli, Alexandr Normuradov
  2. *
  3. * Permission is hereby granted, free of charge, to any person obtaining a copy
  4. * of this software and associated documentation files (the "Software"), to deal
  5. * in the Software without restriction, including without limitation the rights
  6. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. * copies of the Software, and to permit persons to whom the Software is
  8. * furnished to do so, subject to the following conditions:
  9. *
  10. * The above copyright notice and this permission notice shall be included in
  11. * all copies or substantial portions of the Software.
  12. *
  13. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. * THE SOFTWARE.
  20. */
  21. using Microsoft.Win32.SafeHandles;
  22. using System;
  23. using System.Diagnostics.CodeAnalysis;
  24. using System.IO;
  25. using System.Runtime.InteropServices;
  26. using System.Security;
  27. using System.Text;
  28. namespace Alphaleonis.Win32.Filesystem
  29. {
  30. internal static partial class NativeMethods
  31. {
  32. /// <summary>Defines, redefines, or deletes MS-DOS device names.</summary>
  33. /// <returns>
  34. /// If the function succeeds, the return value is nonzero.
  35. /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
  36. /// </returns>
  37. /// <remarks>Minimum supported client: Windows XP [desktop apps only]</remarks>
  38. /// <remarks>Minimum supported server: Windows Server 2003 [desktop apps only]</remarks>
  39. [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")]
  40. [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "DefineDosDeviceW"), SuppressUnmanagedCodeSecurity]
  41. [return: MarshalAs(UnmanagedType.Bool)]
  42. internal static extern bool DefineDosDevice(DosDeviceAttributes dwFlags, [MarshalAs(UnmanagedType.LPWStr)] string lpDeviceName, [MarshalAs(UnmanagedType.LPWStr)] string lpTargetPath);
  43. /// <summary>Deletes a drive letter or mounted folder.</summary>
  44. /// <returns>
  45. /// If the function succeeds, the return value is nonzero.
  46. /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
  47. /// </returns>
  48. /// <remarks>Minimum supported client: Windows XP [desktop apps only]</remarks>
  49. /// <remarks>Minimum supported server: Windows Server 2003 [desktop apps only]</remarks>
  50. [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")]
  51. [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "DeleteVolumeMountPointW"), SuppressUnmanagedCodeSecurity]
  52. [return: MarshalAs(UnmanagedType.Bool)]
  53. internal static extern bool DeleteVolumeMountPoint([MarshalAs(UnmanagedType.LPWStr)] string lpszVolumeMountPoint);
  54. /// <summary>Retrieves the name of a volume on a computer. FindFirstVolume is used to begin scanning the volumes of a computer.</summary>
  55. /// <returns>
  56. /// If the function succeeds, the return value is a search handle used in a subsequent call to the FindNextVolume and FindVolumeClose functions.
  57. /// If the function fails to find any volumes, the return value is the INVALID_HANDLE_VALUE error code. To get extended error information, call GetLastError.
  58. /// </returns>
  59. /// <remarks>Minimum supported client: Windows XP [desktop apps only]</remarks>
  60. /// <remarks>Minimum supported server: Windows Server 2003 [desktop apps only]</remarks>
  61. [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")]
  62. [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "FindFirstVolumeW"), SuppressUnmanagedCodeSecurity]
  63. internal static extern SafeFindVolumeHandle FindFirstVolume(StringBuilder lpszVolumeName, [MarshalAs(UnmanagedType.U4)] uint cchBufferLength);
  64. /// <summary>Retrieves the name of a mounted folder on the specified volume. FindFirstVolumeMountPoint is used to begin scanning the mounted folders on a volume.</summary>
  65. /// <returns>
  66. /// If the function succeeds, the return value is a search handle used in a subsequent call to the FindNextVolumeMountPoint and FindVolumeMountPointClose functions.
  67. /// If the function fails to find a mounted folder on the volume, the return value is the INVALID_HANDLE_VALUE error code.
  68. /// </returns>
  69. /// <remarks>Minimum supported client: Windows XP [desktop apps only]</remarks>
  70. /// <remarks>Minimum supported server: Windows Server 2003 [desktop apps only]</remarks>
  71. [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")]
  72. [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "FindFirstVolumeMountPointW"), SuppressUnmanagedCodeSecurity]
  73. internal static extern SafeFindVolumeMountPointHandle FindFirstVolumeMountPoint([MarshalAs(UnmanagedType.LPWStr)] string lpszRootPathName, StringBuilder lpszVolumeMountPoint, [MarshalAs(UnmanagedType.U4)] uint cchBufferLength);
  74. /// <summary>Continues a volume search started by a call to the FindFirstVolume function. FindNextVolume finds one volume per call.</summary>
  75. /// <returns>
  76. /// If the function succeeds, the return value is nonzero.
  77. /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
  78. /// </returns>
  79. /// <remarks>Minimum supported client: Windows XP [desktop apps only]</remarks>
  80. /// <remarks>Minimum supported server: Windows Server 2003 [desktop apps only]</remarks>
  81. [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")]
  82. [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "FindNextVolumeW"), SuppressUnmanagedCodeSecurity]
  83. [return: MarshalAs(UnmanagedType.Bool)]
  84. internal static extern bool FindNextVolume(SafeFindVolumeHandle hFindVolume, StringBuilder lpszVolumeName, [MarshalAs(UnmanagedType.U4)] uint cchBufferLength);
  85. /// <summary>Continues a mounted folder search started by a call to the FindFirstVolumeMountPoint function. FindNextVolumeMountPoint finds one mounted folder per call.</summary>
  86. /// <returns>
  87. /// If the function succeeds, the return value is nonzero.
  88. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. If no more mounted folders can be found, the GetLastError function returns the ERROR_NO_MORE_FILES error code.
  89. /// In that case, close the search with the FindVolumeMountPointClose function.
  90. /// </returns>
  91. /// <remarks>Minimum supported client: Windows XP</remarks>
  92. /// <remarks>Minimum supported server: Windows Server 2003</remarks>
  93. [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")]
  94. [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "FindNextVolumeMountPointW"), SuppressUnmanagedCodeSecurity]
  95. [return: MarshalAs(UnmanagedType.Bool)]
  96. internal static extern bool FindNextVolumeMountPoint(SafeFindVolumeMountPointHandle hFindVolume, StringBuilder lpszVolumeName, [MarshalAs(UnmanagedType.U4)] uint cchBufferLength);
  97. /// <summary>Closes the specified volume search handle.</summary>
  98. /// <remarks>
  99. /// <para>SetLastError is set to <see langword="false"/>.</para>
  100. /// Minimum supported client: Windows XP [desktop apps only]. Minimum supported server: Windows Server 2003 [desktop apps only].
  101. /// </remarks>
  102. /// <returns>
  103. /// If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error
  104. /// information, call GetLastError.
  105. /// </returns>
  106. [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")]
  107. [DllImport("kernel32.dll", SetLastError = false, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
  108. [return: MarshalAs(UnmanagedType.Bool)]
  109. internal static extern bool FindVolumeClose(IntPtr hFindVolume);
  110. /// <summary>Closes the specified mounted folder search handle.</summary>
  111. /// <remarks>
  112. /// <para>SetLastError is set to <see langword="false"/>.</para>
  113. /// <para>Minimum supported client: Windows XP</para>
  114. /// <para>Minimum supported server: Windows Server 2003</para>
  115. /// </remarks>
  116. /// <returns>
  117. /// If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error
  118. /// information, call GetLastError.
  119. /// </returns>
  120. [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")]
  121. [DllImport("kernel32.dll", SetLastError = false, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
  122. [return: MarshalAs(UnmanagedType.Bool)]
  123. internal static extern bool FindVolumeMountPointClose(IntPtr hFindVolume);
  124. /// <summary>
  125. /// Determines whether a disk drive is a removable, fixed, CD-ROM, RAM disk, or network drive.
  126. /// <para>To determine whether a drive is a USB-type drive, call <see cref="SetupDiGetDeviceRegistryProperty"/> and specify the
  127. /// SPDRP_REMOVAL_POLICY property.</para>
  128. /// </summary>
  129. /// <remarks>
  130. /// <para>SMB does not support volume management functions.</para>
  131. /// <para>Minimum supported client: Windows XP [desktop apps only]</para>
  132. /// <para>Minimum supported server: Windows Server 2003 [desktop apps only]</para>
  133. /// </remarks>
  134. /// <param name="lpRootPathName">Full pathname of the root file.</param>
  135. /// <returns>
  136. /// <para>The return value specifies the type of drive, see <see cref="DriveType"/>.</para>
  137. /// <para>If the function fails, the return value is zero. To get extended error information, call GetLastError.</para>
  138. /// </returns>
  139. [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")]
  140. [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "GetDriveTypeW"), SuppressUnmanagedCodeSecurity]
  141. [return: MarshalAs(UnmanagedType.U4)]
  142. internal static extern DriveType GetDriveType([MarshalAs(UnmanagedType.LPWStr)] string lpRootPathName);
  143. /// <summary>
  144. /// Retrieves a bitmask representing the currently available disk drives.
  145. /// </summary>
  146. /// <remarks>
  147. /// <para>SMB does not support volume management functions.</para>
  148. /// <para>Minimum supported client: Windows XP [desktop apps only]</para>
  149. /// <para>Minimum supported server: Windows Server 2003 [desktop apps only]</para>
  150. /// </remarks>
  151. /// <returns>
  152. /// <para>If the function succeeds, the return value is a bitmask representing the currently available disk drives.</para>
  153. /// <para>Bit position 0 (the least-significant bit) is drive A, bit position 1 is drive B, bit position 2 is drive C, and so on.</para>
  154. /// <para>If the function fails, the return value is zero. To get extended error information, call GetLastError.</para>
  155. /// </returns>
  156. [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")]
  157. [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
  158. [return: MarshalAs(UnmanagedType.U4)]
  159. internal static extern uint GetLogicalDrives();
  160. /// <summary>Retrieves information about the file system and volume associated with the specified root directory.</summary>
  161. /// <returns>
  162. /// If all the requested information is retrieved, the return value is nonzero.
  163. /// If not all the requested information is retrieved, the return value is zero.
  164. /// </returns>
  165. /// <remarks>Minimum supported client: Windows XP [desktop apps only]</remarks>
  166. /// <remarks>Minimum supported server: Windows Server 2003 [desktop apps only]</remarks>
  167. /// <remarks>"lpRootPathName" must end with a trailing backslash.</remarks>
  168. [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")]
  169. [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "GetVolumeInformationW"), SuppressUnmanagedCodeSecurity]
  170. [return: MarshalAs(UnmanagedType.Bool)]
  171. internal static extern bool GetVolumeInformation([MarshalAs(UnmanagedType.LPWStr)] string lpRootPathName, StringBuilder lpVolumeNameBuffer, [MarshalAs(UnmanagedType.U4)] uint nVolumeNameSize, [MarshalAs(UnmanagedType.U4)] out uint lpVolumeSerialNumber, [MarshalAs(UnmanagedType.U4)] out int lpMaximumComponentLength, [MarshalAs(UnmanagedType.U4)] out VolumeInfoAttributes lpFileSystemAttributes, StringBuilder lpFileSystemNameBuffer, [MarshalAs(UnmanagedType.U4)] uint nFileSystemNameSize);
  172. /// <summary>Retrieves information about the file system and volume associated with the specified file.</summary>
  173. /// <returns>
  174. /// If all the requested information is retrieved, the return value is nonzero.
  175. /// If not all the requested information is retrieved, the return value is zero. To get extended error information, call GetLastError.
  176. /// </returns>
  177. /// <remarks>To retrieve the current compression state of a file or directory, use FSCTL_GET_COMPRESSION.</remarks>
  178. /// <remarks>SMB does not support volume management functions.</remarks>
  179. /// <remarks>Minimum supported client: Windows Vista [desktop apps only]</remarks>
  180. /// <remarks>Minimum supported server: Windows Server 2008 [desktop apps only]</remarks>
  181. [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")]
  182. [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "GetVolumeInformationByHandleW"), SuppressUnmanagedCodeSecurity]
  183. [return: MarshalAs(UnmanagedType.Bool)]
  184. internal static extern bool GetVolumeInformationByHandle(SafeFileHandle hFile, StringBuilder lpVolumeNameBuffer, [MarshalAs(UnmanagedType.U4)] uint nVolumeNameSize, [MarshalAs(UnmanagedType.U4)] out uint lpVolumeSerialNumber, [MarshalAs(UnmanagedType.U4)] out int lpMaximumComponentLength, out VolumeInfoAttributes lpFileSystemAttributes, StringBuilder lpFileSystemNameBuffer, [MarshalAs(UnmanagedType.U4)] uint nFileSystemNameSize);
  185. /// <summary>Retrieves a volume GUID path for the volume that is associated with the specified volume mount point (drive letter, volume GUID path, or mounted folder).</summary>
  186. /// <returns>
  187. /// If the function succeeds, the return value is nonzero.
  188. /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
  189. /// </returns>
  190. /// <remarks>Use GetVolumeNameForVolumeMountPoint to obtain a volume GUID path for use with functions such as SetVolumeMountPoint and FindFirstVolumeMountPoint that require a volume GUID path as an input parameter.</remarks>
  191. /// <remarks>SMB does not support volume management functions.</remarks>
  192. /// <remarks>Mount points aren't supported by ReFS volumes.</remarks>
  193. /// <remarks>Minimum supported client: Windows XP [desktop apps only]</remarks>
  194. /// <remarks>Minimum supported server: Windows Server 2003 [desktop apps only]</remarks>
  195. [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")]
  196. [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "GetVolumeNameForVolumeMountPointW"), SuppressUnmanagedCodeSecurity]
  197. [return: MarshalAs(UnmanagedType.Bool)]
  198. internal static extern bool GetVolumeNameForVolumeMountPoint([MarshalAs(UnmanagedType.LPWStr)] string lpszVolumeMountPoint, StringBuilder lpszVolumeName, [MarshalAs(UnmanagedType.U4)] uint cchBufferLength);
  199. /// <summary>Retrieves the volume mount point where the specified path is mounted.</summary>
  200. /// <remarks>
  201. /// <para>If a specified path is passed, GetVolumePathName returns the path to the volume mount point, which means that it returns the
  202. /// root of the volume where the end point of the specified path is located.</para>
  203. /// <para>For example, assume that you have volume D mounted at C:\Mnt\Ddrive and volume E mounted at "C:\Mnt\Ddrive\Mnt\Edrive". Also
  204. /// assume that you have a file with the path "E:\Dir\Subdir\MyFile".</para>
  205. /// <para>If you pass "C:\Mnt\Ddrive\Mnt\Edrive\Dir\Subdir\MyFile" to GetVolumePathName, it returns the path "C:\Mnt\Ddrive\Mnt\Edrive\".</para>
  206. /// <para>If a network share is specified, GetVolumePathName returns the shortest path for which GetDriveType returns DRIVE_REMOTE,
  207. /// which means that the path is validated as a remote drive that exists, which the current user can access.</para>
  208. /// <para>Minimum supported client: Windows XP [desktop apps only]</para>
  209. /// <para>Minimum supported server: Windows Server 2003 [desktop apps only]</para>
  210. /// </remarks>
  211. /// <returns>
  212. /// <para>If the function succeeds, the return value is nonzero.</para>
  213. /// <para>If the function fails, the return value is zero. To get extended error information, call GetLastError.</para>
  214. /// </returns>
  215. [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")]
  216. [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "GetVolumePathNameW"), SuppressUnmanagedCodeSecurity]
  217. [return: MarshalAs(UnmanagedType.Bool)]
  218. internal static extern bool GetVolumePathName([MarshalAs(UnmanagedType.LPWStr)] string lpszFileName, StringBuilder lpszVolumePathName, [MarshalAs(UnmanagedType.U4)] uint cchBufferLength);
  219. /// <summary>Retrieves a list of drive letters and mounted folder paths for the specified volume.</summary>
  220. /// <remarks>Minimum supported client: Windows XP.</remarks>
  221. /// <remarks>Minimum supported server: Windows Server 2003.</remarks>
  222. /// <returns>
  223. /// If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error
  224. /// information, call GetLastError.
  225. /// </returns>
  226. [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")]
  227. [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "GetVolumePathNamesForVolumeNameW"), SuppressUnmanagedCodeSecurity]
  228. [return: MarshalAs(UnmanagedType.Bool)]
  229. internal static extern bool GetVolumePathNamesForVolumeName([MarshalAs(UnmanagedType.LPWStr)] string lpszVolumeName, char[] lpszVolumePathNames, [MarshalAs(UnmanagedType.U4)] uint cchBuferLength, [MarshalAs(UnmanagedType.U4)] out uint lpcchReturnLength);
  230. /// <summary>Sets the label of a file system volume.</summary>
  231. /// <remarks>Minimum supported client: Windows XP [desktop apps only].</remarks>
  232. /// <remarks>Minimum supported server: Windows Server 2003 [desktop apps only].</remarks>
  233. /// <remarks>"lpRootPathName" must end with a trailing backslash.</remarks>
  234. /// <returns>
  235. /// If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error
  236. /// information, call GetLastError.
  237. /// </returns>
  238. [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")]
  239. [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "SetVolumeLabelW"), SuppressUnmanagedCodeSecurity]
  240. [return: MarshalAs(UnmanagedType.Bool)]
  241. internal static extern bool SetVolumeLabel([MarshalAs(UnmanagedType.LPWStr)] string lpRootPathName, [MarshalAs(UnmanagedType.LPWStr)] string lpVolumeName);
  242. /// <summary>Associates a volume with a drive letter or a directory on another volume.</summary>
  243. /// <remarks>Minimum supported client: Windows XP [desktop apps only].</remarks>
  244. /// <remarks>Minimum supported server: Windows Server 2003 [desktop apps only].</remarks>
  245. /// <returns>
  246. /// If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error
  247. /// information, call GetLastError.
  248. /// </returns>
  249. [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")]
  250. [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "SetVolumeMountPointW"), SuppressUnmanagedCodeSecurity]
  251. [return: MarshalAs(UnmanagedType.Bool)]
  252. internal static extern bool SetVolumeMountPoint([MarshalAs(UnmanagedType.LPWStr)] string lpszVolumeMountPoint, [MarshalAs(UnmanagedType.LPWStr)] string lpszVolumeName);
  253. /// <summary>Retrieves information about MS-DOS device names.</summary>
  254. /// <remarks>Minimum supported client: Windows XP [desktop apps only].</remarks>
  255. /// <remarks>Minimum supported server: Windows Server 2003 [desktop apps only].</remarks>
  256. /// <returns>
  257. /// If the function succeeds, the return value is the number of TCHARs stored into the buffer pointed to by lpTargetPath. If the
  258. /// function fails, the return value is zero. To get extended error information, call GetLastError. If the buffer is too small, the
  259. /// function fails and the last error code is ERROR_INSUFFICIENT_BUFFER.
  260. /// </returns>
  261. [SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")]
  262. [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "QueryDosDeviceW"), SuppressUnmanagedCodeSecurity]
  263. [return: MarshalAs(UnmanagedType.U4)]
  264. internal static extern uint QueryDosDevice([MarshalAs(UnmanagedType.LPWStr)] string lpDeviceName, char[] lpTargetPath, [MarshalAs(UnmanagedType.U4)] uint ucchMax);
  265. }
  266. }