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.
 
 

979 lines
60 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 System;
  22. using System.Collections.Generic;
  23. using System.Diagnostics.CodeAnalysis;
  24. using System.IO;
  25. using System.Security;
  26. namespace Alphaleonis.Win32.Filesystem
  27. {
  28. partial class Directory
  29. {
  30. #region Copy
  31. // .NET: Directory class does not contain the Copy() method.
  32. // Mimic .NET File.Copy() methods.
  33. /// <summary>[AlphaFS] Copies an existing directory to a new directory. Overwriting a directory of the same name is not allowed.
  34. /// <remarks>
  35. /// <para>Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method.</para>
  36. /// <para>If two directories have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior.</para>
  37. /// </remarks>
  38. /// </summary>
  39. /// <returns>A <see cref="CopyMoveResult"/> class with details of the Copy action.</returns>
  40. /// <exception cref="ArgumentException"/>
  41. /// <exception cref="ArgumentNullException"/>
  42. /// <exception cref="DirectoryNotFoundException"/>
  43. /// <exception cref="IOException"/>
  44. /// <exception cref="NotSupportedException"/>
  45. /// <exception cref="UnauthorizedAccessException"/>
  46. /// <param name="sourcePath">The source directory path.</param>
  47. /// <param name="destinationPath">The destination directory path.</param>
  48. [SecurityCritical]
  49. public static CopyMoveResult Copy(string sourcePath, string destinationPath)
  50. {
  51. return CopyMoveCore(null, sourcePath, destinationPath, CopyOptions.FailIfExists, null, null, null, null, PathFormat.RelativePath);
  52. }
  53. /// <summary>[AlphaFS] Copies an existing directory to a new directory. Overwriting a directory of the same name is not allowed.
  54. /// <remarks>
  55. /// <para>Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method.</para>
  56. /// <para>If two directories have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior.</para>
  57. /// </remarks>
  58. /// </summary>
  59. /// <returns>A <see cref="CopyMoveResult"/> class with details of the Copy action.</returns>
  60. /// <exception cref="ArgumentException"/>
  61. /// <exception cref="ArgumentNullException"/>
  62. /// <exception cref="DirectoryNotFoundException"/>
  63. /// <exception cref="IOException"/>
  64. /// <exception cref="NotSupportedException"/>
  65. /// <exception cref="UnauthorizedAccessException"/>
  66. /// <param name="sourcePath">The source directory path.</param>
  67. /// <param name="destinationPath">The destination directory path.</param>
  68. /// <param name="pathFormat">Indicates the format of the path parameter(s).</param>
  69. [SecurityCritical]
  70. public static CopyMoveResult Copy(string sourcePath, string destinationPath, PathFormat pathFormat)
  71. {
  72. return CopyMoveCore(null, sourcePath, destinationPath, CopyOptions.FailIfExists, null, null, null, null, pathFormat);
  73. }
  74. /// <summary>[AlphaFS] Copies an existing directory to a new directory. Overwriting a directory of the same name is allowed.
  75. /// <remarks>
  76. /// <para>Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method.</para>
  77. /// <para>If two directories have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior.</para>
  78. /// </remarks>
  79. /// </summary>
  80. /// <returns>A <see cref="CopyMoveResult"/> class with details of the Copy action.</returns>
  81. /// <exception cref="ArgumentException"/>
  82. /// <exception cref="ArgumentNullException"/>
  83. /// <exception cref="DirectoryNotFoundException"/>
  84. /// <exception cref="IOException"/>
  85. /// <exception cref="NotSupportedException"/>
  86. /// <exception cref="UnauthorizedAccessException"/>
  87. /// <param name="sourcePath">The source directory path.</param>
  88. /// <param name="destinationPath">The destination directory path.</param>
  89. /// <param name="overwrite"><see langword="true"/> if the destination directory should ignoring the read-only and hidden attributes and overwrite; otherwise, <see langword="false"/>.</param>
  90. [SecurityCritical]
  91. public static CopyMoveResult Copy(string sourcePath, string destinationPath, bool overwrite)
  92. {
  93. return CopyMoveCore(null, sourcePath, destinationPath, overwrite ? CopyOptions.None : CopyOptions.FailIfExists, null, null, null, null, PathFormat.RelativePath);
  94. }
  95. /// <summary>[AlphaFS] Copies an existing directory to a new directory. Overwriting a directory of the same name is allowed.
  96. /// <remarks>
  97. /// <para>Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method.</para>
  98. /// <para>If two directories have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior.</para>
  99. /// </remarks>
  100. /// </summary>
  101. /// <returns>A <see cref="CopyMoveResult"/> class with details of the Copy action.</returns>
  102. /// <exception cref="ArgumentException"/>
  103. /// <exception cref="ArgumentNullException"/>
  104. /// <exception cref="DirectoryNotFoundException"/>
  105. /// <exception cref="IOException"/>
  106. /// <exception cref="NotSupportedException"/>
  107. /// <exception cref="UnauthorizedAccessException"/>
  108. /// <param name="sourcePath">The source directory path.</param>
  109. /// <param name="destinationPath">The destination directory path.</param>
  110. /// <param name="overwrite"><see langword="true"/> if the destination directory should ignoring the read-only and hidden attributes and overwrite; otherwise, <see langword="false"/>.</param>
  111. /// <param name="pathFormat">Indicates the format of the path parameter(s).</param>
  112. [SecurityCritical]
  113. public static CopyMoveResult Copy(string sourcePath, string destinationPath, bool overwrite, PathFormat pathFormat)
  114. {
  115. return CopyMoveCore(null, sourcePath, destinationPath, overwrite ? CopyOptions.None : CopyOptions.FailIfExists, null, null, null, null, pathFormat);
  116. }
  117. #region Transactional
  118. /// <summary>[AlphaFS] Copies an existing directory to a new directory. Overwriting a directory of the same name is not allowed.
  119. /// <remarks>
  120. /// <para>Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method.</para>
  121. /// <para>If two directories have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior.</para>
  122. /// </remarks>
  123. /// </summary>
  124. /// <returns>A <see cref="CopyMoveResult"/> class with details of the Copy action.</returns>
  125. /// <exception cref="ArgumentException"/>
  126. /// <exception cref="ArgumentNullException"/>
  127. /// <exception cref="DirectoryNotFoundException"/>
  128. /// <exception cref="IOException"/>
  129. /// <exception cref="NotSupportedException"/>
  130. /// <exception cref="UnauthorizedAccessException"/>
  131. /// <param name="transaction">The transaction.</param>
  132. /// <param name="sourcePath">The source directory path.</param>
  133. /// <param name="destinationPath">The destination directory path.</param>
  134. [SecurityCritical]
  135. public static CopyMoveResult CopyTransacted(KernelTransaction transaction, string sourcePath, string destinationPath)
  136. {
  137. return CopyMoveCore(transaction, sourcePath, destinationPath, CopyOptions.FailIfExists, null, null, null, null, PathFormat.RelativePath);
  138. }
  139. /// <summary>[AlphaFS] Copies an existing directory to a new directory. Overwriting a directory of the same name is not allowed.
  140. /// <remarks>
  141. /// <para>Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method.</para>
  142. /// <para>If two directories have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior.</para>
  143. /// </remarks>
  144. /// </summary>
  145. /// <returns>A <see cref="CopyMoveResult"/> class with details of the Copy action.</returns>
  146. /// <exception cref="ArgumentException"/>
  147. /// <exception cref="ArgumentNullException"/>
  148. /// <exception cref="DirectoryNotFoundException"/>
  149. /// <exception cref="IOException"/>
  150. /// <exception cref="NotSupportedException"/>
  151. /// <exception cref="UnauthorizedAccessException"/>
  152. /// <param name="transaction">The transaction.</param>
  153. /// <param name="sourcePath">The source directory path.</param>
  154. /// <param name="destinationPath">The destination directory path.</param>
  155. /// <param name="pathFormat">Indicates the format of the path parameter(s).</param>
  156. [SecurityCritical]
  157. public static CopyMoveResult CopyTransacted(KernelTransaction transaction, string sourcePath, string destinationPath, PathFormat pathFormat)
  158. {
  159. return CopyMoveCore(transaction, sourcePath, destinationPath, CopyOptions.FailIfExists, null, null, null, null, pathFormat);
  160. }
  161. /// <summary>[AlphaFS] Copies an existing directory to a new directory. Overwriting a directory of the same name is allowed.
  162. /// <remarks>
  163. /// <para>Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method.</para>
  164. /// <para>If two directories have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior.</para>
  165. /// </remarks>
  166. /// </summary>
  167. /// <returns>A <see cref="CopyMoveResult"/> class with details of the Copy action.</returns>
  168. /// <exception cref="ArgumentException"/>
  169. /// <exception cref="ArgumentNullException"/>
  170. /// <exception cref="DirectoryNotFoundException"/>
  171. /// <exception cref="IOException"/>
  172. /// <exception cref="NotSupportedException"/>
  173. /// <exception cref="UnauthorizedAccessException"/>
  174. /// <param name="transaction">The transaction.</param>
  175. /// <param name="sourcePath">The source directory path.</param>
  176. /// <param name="destinationPath">The destination directory path.</param>
  177. /// <param name="overwrite"><see langword="true"/> if the destination directory should ignoring the read-only and hidden attributes and overwrite; otherwise, <see langword="false"/>.</param>
  178. [SecurityCritical]
  179. public static CopyMoveResult CopyTransacted(KernelTransaction transaction, string sourcePath, string destinationPath, bool overwrite)
  180. {
  181. return CopyMoveCore(transaction, sourcePath, destinationPath, overwrite ? CopyOptions.None : CopyOptions.FailIfExists, null, null, null, null, PathFormat.RelativePath);
  182. }
  183. /// <summary>[AlphaFS] Copies an existing directory to a new directory. Overwriting a directory of the same name is allowed.
  184. /// <remarks>
  185. /// <para>Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method.</para>
  186. /// <para>If two directories have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior.</para>
  187. /// </remarks>
  188. /// </summary>
  189. /// <returns>A <see cref="CopyMoveResult"/> class with details of the Copy action.</returns>
  190. /// <exception cref="ArgumentException"/>
  191. /// <exception cref="ArgumentNullException"/>
  192. /// <exception cref="DirectoryNotFoundException"/>
  193. /// <exception cref="IOException"/>
  194. /// <exception cref="NotSupportedException"/>
  195. /// <exception cref="UnauthorizedAccessException"/>
  196. /// <param name="transaction">The transaction.</param>
  197. /// <param name="sourcePath">The source directory path.</param>
  198. /// <param name="destinationPath">The destination directory path.</param>
  199. /// <param name="overwrite"><see langword="true"/> if the destination directory should ignoring the read-only and hidden attributes and overwrite; otherwise, <see langword="false"/>.</param>
  200. /// <param name="pathFormat">Indicates the format of the path parameter(s).</param>
  201. [SecurityCritical]
  202. public static CopyMoveResult CopyTransacted(KernelTransaction transaction, string sourcePath, string destinationPath, bool overwrite, PathFormat pathFormat)
  203. {
  204. return CopyMoveCore(transaction, sourcePath, destinationPath, overwrite ? CopyOptions.None : CopyOptions.FailIfExists, null, null, null, null, pathFormat);
  205. }
  206. #endregion // Transactional
  207. #endregion // Copy
  208. #region Copy (CopyOptions)
  209. /// <summary>[AlphaFS] Copies a directory and its contents to a new location, <see cref="CopyOptions"/> can be specified.
  210. /// <remarks>
  211. /// <para>Option <see cref="CopyOptions.NoBuffering"/> is recommended for very large file transfers.</para>
  212. /// <para>Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method.</para>
  213. /// <para>If two directories have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior.</para>
  214. /// </remarks>
  215. /// </summary>
  216. /// <returns>A <see cref="CopyMoveResult"/> class with details of the Copy action.</returns>
  217. /// <exception cref="ArgumentException"/>
  218. /// <exception cref="ArgumentNullException"/>
  219. /// <exception cref="DirectoryNotFoundException"/>
  220. /// <exception cref="IOException"/>
  221. /// <exception cref="NotSupportedException"/>
  222. /// <exception cref="UnauthorizedAccessException"/>
  223. /// <param name="sourcePath">The source directory path.</param>
  224. /// <param name="destinationPath">The destination directory path.</param>
  225. /// <param name="copyOptions"><see cref="CopyOptions"/> that specify how the directory is to be copied. This parameter can be <see langword="null"/>.</param>
  226. [SecurityCritical]
  227. public static CopyMoveResult Copy(string sourcePath, string destinationPath, CopyOptions copyOptions)
  228. {
  229. return CopyMoveCore(null, sourcePath, destinationPath, copyOptions, null, null, null, null, PathFormat.RelativePath);
  230. }
  231. /// <summary>[AlphaFS] Copies a directory and its contents to a new location, <see cref="CopyOptions"/> can be specified.
  232. /// <remarks>
  233. /// <para>Option <see cref="CopyOptions.NoBuffering"/> is recommended for very large file transfers.</para>
  234. /// <para>Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method.</para>
  235. /// <para>If two directories have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior.</para>
  236. /// </remarks>
  237. /// </summary>
  238. /// <returns>A <see cref="CopyMoveResult"/> class with details of the Copy action.</returns>
  239. /// <exception cref="ArgumentException"/>
  240. /// <exception cref="ArgumentNullException"/>
  241. /// <exception cref="DirectoryNotFoundException"/>
  242. /// <exception cref="IOException"/>
  243. /// <exception cref="NotSupportedException"/>
  244. /// <exception cref="UnauthorizedAccessException"/>
  245. /// <param name="sourcePath">The source directory path.</param>
  246. /// <param name="destinationPath">The destination directory path.</param>
  247. /// <param name="copyOptions"><see cref="CopyOptions"/> that specify how the directory is to be copied. This parameter can be <see langword="null"/>.</param>
  248. /// <param name="pathFormat">Indicates the format of the path parameter(s).</param>
  249. [SecurityCritical]
  250. public static CopyMoveResult Copy(string sourcePath, string destinationPath, CopyOptions copyOptions, PathFormat pathFormat)
  251. {
  252. return CopyMoveCore(null, sourcePath, destinationPath, copyOptions, null, null, null, null, pathFormat);
  253. }
  254. /// <summary>[AlphaFS] Copies a directory and its contents to a new location, <see cref="CopyOptions"/> can be specified,
  255. /// and the possibility of notifying the application of its progress through a callback function.
  256. /// <remarks>
  257. /// <para>Option <see cref="CopyOptions.NoBuffering"/> is recommended for very large file transfers.</para>
  258. /// <para>Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method.</para>
  259. /// <para>If two directories have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior.</para>
  260. /// </remarks>
  261. /// </summary>
  262. /// <returns>A <see cref="CopyMoveResult"/> class with details of the Copy action.</returns>
  263. /// <exception cref="ArgumentException"/>
  264. /// <exception cref="ArgumentNullException"/>
  265. /// <exception cref="DirectoryNotFoundException"/>
  266. /// <exception cref="IOException"/>
  267. /// <exception cref="NotSupportedException"/>
  268. /// <exception cref="UnauthorizedAccessException"/>
  269. /// <param name="sourcePath">The source directory path.</param>
  270. /// <param name="destinationPath">The destination directory path.</param>
  271. /// <param name="copyOptions"><see cref="CopyOptions"/> that specify how the directory is to be copied. This parameter can be <see langword="null"/>.</param>
  272. /// <param name="progressHandler">A callback function that is called each time another portion of the directory has been copied. This parameter can be <see langword="null"/>.</param>
  273. /// <param name="userProgressData">The argument to be passed to the callback function. This parameter can be <see langword="null"/>.</param>
  274. [SecurityCritical]
  275. public static CopyMoveResult Copy(string sourcePath, string destinationPath, CopyOptions copyOptions, CopyMoveProgressRoutine progressHandler, object userProgressData)
  276. {
  277. return CopyMoveCore(null, sourcePath, destinationPath, copyOptions, null, progressHandler, userProgressData, null, PathFormat.RelativePath);
  278. }
  279. /// <summary>[AlphaFS] Copies a directory and its contents to a new location, <see cref="CopyOptions"/> can be specified,
  280. /// and the possibility of notifying the application of its progress through a callback function.
  281. /// <remarks>
  282. /// <para>Option <see cref="CopyOptions.NoBuffering"/> is recommended for very large file transfers.</para>
  283. /// <para>Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method.</para>
  284. /// <para>If two directories have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior.</para>
  285. /// </remarks>
  286. /// </summary>
  287. /// <returns>A <see cref="CopyMoveResult"/> class with details of the Copy action.</returns>
  288. /// <exception cref="ArgumentException"/>
  289. /// <exception cref="ArgumentNullException"/>
  290. /// <exception cref="DirectoryNotFoundException"/>
  291. /// <exception cref="IOException"/>
  292. /// <exception cref="NotSupportedException"/>
  293. /// <exception cref="UnauthorizedAccessException"/>
  294. /// <param name="sourcePath">The source directory path.</param>
  295. /// <param name="destinationPath">The destination directory path.</param>
  296. /// <param name="copyOptions"><see cref="CopyOptions"/> that specify how the directory is to be copied. This parameter can be <see langword="null"/>.</param>
  297. /// <param name="progressHandler">A callback function that is called each time another portion of the directory has been copied. This parameter can be <see langword="null"/>.</param>
  298. /// <param name="userProgressData">The argument to be passed to the callback function. This parameter can be <see langword="null"/>.</param>
  299. /// <param name="pathFormat">Indicates the format of the path parameter(s).</param>
  300. [SecurityCritical]
  301. public static CopyMoveResult Copy(string sourcePath, string destinationPath, CopyOptions copyOptions, CopyMoveProgressRoutine progressHandler, object userProgressData, PathFormat pathFormat)
  302. {
  303. return CopyMoveCore(null, sourcePath, destinationPath, copyOptions, null, progressHandler, userProgressData, null, pathFormat);
  304. }
  305. #region Transactional
  306. /// <summary>[AlphaFS] Copies a directory and its contents to a new location, <see cref="CopyOptions"/> can be specified.
  307. /// <remarks>
  308. /// <para>Option <see cref="CopyOptions.NoBuffering"/> is recommended for very large file transfers.</para>
  309. /// <para>Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method.</para>
  310. /// <para>If two directories have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior.</para>
  311. /// </remarks>
  312. /// </summary>
  313. /// <returns>A <see cref="CopyMoveResult"/> class with details of the Copy action.</returns>
  314. /// <exception cref="ArgumentException"/>
  315. /// <exception cref="ArgumentNullException"/>
  316. /// <exception cref="DirectoryNotFoundException"/>
  317. /// <exception cref="IOException"/>
  318. /// <exception cref="NotSupportedException"/>
  319. /// <exception cref="UnauthorizedAccessException"/>
  320. /// <param name="transaction">The transaction.</param>
  321. /// <param name="sourcePath">The source directory path.</param>
  322. /// <param name="destinationPath">The destination directory path.</param>
  323. /// <param name="copyOptions"><see cref="CopyOptions"/> that specify how the directory is to be copied. This parameter can be <see langword="null"/>.</param>
  324. [SecurityCritical]
  325. public static CopyMoveResult CopyTransacted(KernelTransaction transaction, string sourcePath, string destinationPath, CopyOptions copyOptions)
  326. {
  327. return CopyMoveCore(transaction, sourcePath, destinationPath, copyOptions, null, null, null, null, PathFormat.RelativePath);
  328. }
  329. /// <summary>[AlphaFS] Copies a directory and its contents to a new location, <see cref="CopyOptions"/> can be specified.
  330. /// <remarks>
  331. /// <para>Option <see cref="CopyOptions.NoBuffering"/> is recommended for very large file transfers.</para>
  332. /// <para>Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method.</para>
  333. /// <para>If two directories have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior.</para>
  334. /// </remarks>
  335. /// </summary>
  336. /// <returns>A <see cref="CopyMoveResult"/> class with details of the Copy action.</returns>
  337. /// <exception cref="ArgumentException"/>
  338. /// <exception cref="ArgumentNullException"/>
  339. /// <exception cref="DirectoryNotFoundException"/>
  340. /// <exception cref="IOException"/>
  341. /// <exception cref="NotSupportedException"/>
  342. /// <exception cref="UnauthorizedAccessException"/>
  343. /// <param name="transaction">The transaction.</param>
  344. /// <param name="sourcePath">The source directory path.</param>
  345. /// <param name="destinationPath">The destination directory path.</param>
  346. /// <param name="copyOptions"><see cref="CopyOptions"/> that specify how the directory is to be copied. This parameter can be <see langword="null"/>.</param>
  347. /// <param name="pathFormat">Indicates the format of the path parameter(s).</param>
  348. [SecurityCritical]
  349. public static CopyMoveResult CopyTransacted(KernelTransaction transaction, string sourcePath, string destinationPath, CopyOptions copyOptions, PathFormat pathFormat)
  350. {
  351. return CopyMoveCore(transaction, sourcePath, destinationPath, copyOptions, null, null, null, null, pathFormat);
  352. }
  353. /// <summary>[AlphaFS] Copies a directory and its contents to a new location, <see cref="CopyOptions"/> can be specified,
  354. /// and the possibility of notifying the application of its progress through a callback function.
  355. /// <remarks>
  356. /// <para>Option <see cref="CopyOptions.NoBuffering"/> is recommended for very large file transfers.</para>
  357. /// <para>Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method.</para>
  358. /// <para>If two directories have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior.</para>
  359. /// </remarks>
  360. /// </summary>
  361. /// <returns>A <see cref="CopyMoveResult"/> class with details of the Copy action.</returns>
  362. /// <exception cref="ArgumentException"/>
  363. /// <exception cref="ArgumentNullException"/>
  364. /// <exception cref="DirectoryNotFoundException"/>
  365. /// <exception cref="IOException"/>
  366. /// <exception cref="NotSupportedException"/>
  367. /// <exception cref="UnauthorizedAccessException"/>
  368. /// <param name="transaction">The transaction.</param>
  369. /// <param name="sourcePath">The source directory path.</param>
  370. /// <param name="destinationPath">The destination directory path.</param>
  371. /// <param name="copyOptions"><see cref="CopyOptions"/> that specify how the directory is to be copied. This parameter can be <see langword="null"/>.</param>
  372. /// <param name="progressHandler">A callback function that is called each time another portion of the directory has been copied. This parameter can be <see langword="null"/>.</param>
  373. /// <param name="userProgressData">The argument to be passed to the callback function. This parameter can be <see langword="null"/>.</param>
  374. [SecurityCritical]
  375. public static CopyMoveResult CopyTransacted(KernelTransaction transaction, string sourcePath, string destinationPath, CopyOptions copyOptions, CopyMoveProgressRoutine progressHandler, object userProgressData)
  376. {
  377. return CopyMoveCore(transaction, sourcePath, destinationPath, copyOptions, null, progressHandler, userProgressData, null, PathFormat.RelativePath);
  378. }
  379. /// <summary>[AlphaFS] Copies a directory and its contents to a new location, <see cref="CopyOptions"/> can be specified,
  380. /// and the possibility of notifying the application of its progress through a callback function.
  381. /// <remarks>
  382. /// <para>Option <see cref="CopyOptions.NoBuffering"/> is recommended for very large file transfers.</para>
  383. /// <para>Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method.</para>
  384. /// <para>If two directories have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior.</para>
  385. /// </remarks>
  386. /// </summary>
  387. /// <returns>A <see cref="CopyMoveResult"/> class with details of the Copy action.</returns>
  388. /// <exception cref="ArgumentException"/>
  389. /// <exception cref="ArgumentNullException"/>
  390. /// <exception cref="DirectoryNotFoundException"/>
  391. /// <exception cref="IOException"/>
  392. /// <exception cref="NotSupportedException"/>
  393. /// <exception cref="UnauthorizedAccessException"/>
  394. /// <param name="transaction">The transaction.</param>
  395. /// <param name="sourcePath">The source directory path.</param>
  396. /// <param name="destinationPath">The destination directory path.</param>
  397. /// <param name="copyOptions"><see cref="CopyOptions"/> that specify how the directory is to be copied. This parameter can be <see langword="null"/>.</param>
  398. /// <param name="progressHandler">A callback function that is called each time another portion of the directory has been copied. This parameter can be <see langword="null"/>.</param>
  399. /// <param name="userProgressData">The argument to be passed to the callback function. This parameter can be <see langword="null"/>.</param>
  400. /// <param name="pathFormat">Indicates the format of the path parameter(s).</param>
  401. [SecurityCritical]
  402. public static CopyMoveResult CopyTransacted(KernelTransaction transaction, string sourcePath, string destinationPath, CopyOptions copyOptions, CopyMoveProgressRoutine progressHandler, object userProgressData, PathFormat pathFormat)
  403. {
  404. return CopyMoveCore(transaction, sourcePath, destinationPath, copyOptions, null, progressHandler, userProgressData, null, pathFormat);
  405. }
  406. #endregion // Transactional
  407. #endregion // Copy (CopyOptions)
  408. #region Move
  409. #region .NET
  410. /// <summary>Moves a file or a directory and its contents to a new location.
  411. /// <remarks>
  412. /// <para>This method does not work across disk volumes.</para>
  413. /// <para>Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method.</para>
  414. /// <para>If two directories have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior.</para>
  415. /// </remarks>
  416. /// </summary>
  417. /// <returns>A <see cref="CopyMoveResult"/> class with details of the Move action.</returns>
  418. /// <exception cref="ArgumentException"/>
  419. /// <exception cref="ArgumentNullException"/>
  420. /// <exception cref="DirectoryNotFoundException"/>
  421. /// <exception cref="IOException"/>
  422. /// <exception cref="NotSupportedException"/>
  423. /// <exception cref="UnauthorizedAccessException"/>
  424. /// <param name="sourcePath">The source directory path.</param>
  425. /// <param name="destinationPath">The destination directory path.</param>
  426. [SecurityCritical]
  427. public static CopyMoveResult Move(string sourcePath, string destinationPath)
  428. {
  429. return CopyMoveCore(null, sourcePath, destinationPath, null, MoveOptions.None, null, null, null, PathFormat.RelativePath);
  430. }
  431. #endregion // .NET
  432. /// <summary>[AlphaFS] Moves a file or a directory and its contents to a new location.
  433. /// <remarks>
  434. /// <para>This method does not work across disk volumes.</para>
  435. /// <para>Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method.</para>
  436. /// <para>If two directories have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior.</para>
  437. /// </remarks>
  438. /// </summary>
  439. /// <returns>A <see cref="CopyMoveResult"/> class with details of the Move action.</returns>
  440. /// <exception cref="ArgumentException"/>
  441. /// <exception cref="ArgumentNullException"/>
  442. /// <exception cref="DirectoryNotFoundException"/>
  443. /// <exception cref="IOException"/>
  444. /// <exception cref="NotSupportedException"/>
  445. /// <exception cref="UnauthorizedAccessException"/>
  446. /// <param name="sourcePath">The source directory path.</param>
  447. /// <param name="destinationPath">The destination directory path.</param>
  448. /// <param name="pathFormat">Indicates the format of the path parameter(s).</param>
  449. [SecurityCritical]
  450. public static CopyMoveResult Move(string sourcePath, string destinationPath, PathFormat pathFormat)
  451. {
  452. return CopyMoveCore(null, sourcePath, destinationPath, null, MoveOptions.None, null, null, null, pathFormat);
  453. }
  454. #region Transactional
  455. /// <summary>[AlphaFS] Moves a file or a directory and its contents to a new location.
  456. /// <remarks>
  457. /// <para>This method does not work across disk volumes.</para>
  458. /// <para>Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method.</para>
  459. /// <para>If two directories have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior.</para>
  460. /// </remarks>
  461. /// </summary>
  462. /// <returns>A <see cref="CopyMoveResult"/> class with details of the Move action.</returns>
  463. /// <exception cref="ArgumentException"/>
  464. /// <exception cref="ArgumentNullException"/>
  465. /// <exception cref="DirectoryNotFoundException"/>
  466. /// <exception cref="IOException"/>
  467. /// <exception cref="NotSupportedException"/>
  468. /// <exception cref="UnauthorizedAccessException"/>
  469. /// <param name="transaction">The transaction.</param>
  470. /// <param name="sourcePath">The source directory path.</param>
  471. /// <param name="destinationPath">The destination directory path.</param>
  472. [SecurityCritical]
  473. public static CopyMoveResult MoveTransacted(KernelTransaction transaction, string sourcePath, string destinationPath)
  474. {
  475. return CopyMoveCore(transaction, sourcePath, destinationPath, null, MoveOptions.None, null, null, null, PathFormat.RelativePath);
  476. }
  477. /// <summary>[AlphaFS] Moves a file or a directory and its contents to a new location.
  478. /// <remarks>
  479. /// <para>This method does not work across disk volumes.</para>
  480. /// <para>Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method.</para>
  481. /// <para>If two directories have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior.</para>
  482. /// </remarks>
  483. /// </summary>
  484. /// <returns>A <see cref="CopyMoveResult"/> class with details of the Move action.</returns>
  485. /// <exception cref="ArgumentException"/>
  486. /// <exception cref="ArgumentNullException"/>
  487. /// <exception cref="DirectoryNotFoundException"/>
  488. /// <exception cref="IOException"/>
  489. /// <exception cref="NotSupportedException"/>
  490. /// <exception cref="UnauthorizedAccessException"/>
  491. /// <param name="transaction">The transaction.</param>
  492. /// <param name="sourcePath">The source directory path.</param>
  493. /// <param name="destinationPath">The destination directory path.</param>
  494. /// <param name="pathFormat">Indicates the format of the path parameter(s).</param>
  495. [SecurityCritical]
  496. public static CopyMoveResult MoveTransacted(KernelTransaction transaction, string sourcePath, string destinationPath, PathFormat pathFormat)
  497. {
  498. return CopyMoveCore(transaction, sourcePath, destinationPath, null, MoveOptions.None, null, null, null, pathFormat);
  499. }
  500. #endregion // Transactional
  501. #endregion // Move
  502. #region Move (MoveOptions)
  503. /// <summary>[AlphaFS] Moves a file or a directory and its contents to a new location, <see cref="MoveOptions"/> can be specified.
  504. /// <remarks>
  505. /// <para>This method does not work across disk volumes unless <paramref name="moveOptions"/> contains <see cref="MoveOptions.CopyAllowed"/>.</para>
  506. /// <para>Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method.</para>
  507. /// <para>If two directories have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior.</para>
  508. /// </remarks>
  509. /// </summary>
  510. /// <returns>A <see cref="CopyMoveResult"/> class with details of the Move action.</returns>
  511. /// <exception cref="ArgumentException"/>
  512. /// <exception cref="ArgumentNullException"/>
  513. /// <exception cref="DirectoryNotFoundException"/>
  514. /// <exception cref="IOException"/>
  515. /// <exception cref="NotSupportedException"/>
  516. /// <exception cref="UnauthorizedAccessException"/>
  517. /// <param name="sourcePath">The source directory path.</param>
  518. /// <param name="destinationPath">The destination directory path.</param>
  519. /// <param name="moveOptions"><see cref="MoveOptions"/> that specify how the directory is to be moved. This parameter can be <see langword="null"/>.</param>
  520. [SecurityCritical]
  521. public static CopyMoveResult Move(string sourcePath, string destinationPath, MoveOptions moveOptions)
  522. {
  523. return CopyMoveCore(null, sourcePath, destinationPath, null, moveOptions, null, null, null, PathFormat.RelativePath);
  524. }
  525. /// <summary>[AlphaFS] Moves a file or a directory and its contents to a new location, <see cref="MoveOptions"/> can be specified.
  526. /// <remarks>
  527. /// <para>This method does not work across disk volumes unless <paramref name="moveOptions"/> contains <see cref="MoveOptions.CopyAllowed"/>.</para>
  528. /// <para>Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method.</para>
  529. /// <para>If two directories have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior.</para>
  530. /// </remarks>
  531. /// </summary>
  532. /// <returns>A <see cref="CopyMoveResult"/> class with details of the Move action.</returns>
  533. /// <exception cref="ArgumentException"/>
  534. /// <exception cref="ArgumentNullException"/>
  535. /// <exception cref="DirectoryNotFoundException"/>
  536. /// <exception cref="IOException"/>
  537. /// <exception cref="NotSupportedException"/>
  538. /// <exception cref="UnauthorizedAccessException"/>
  539. /// <param name="sourcePath">The source directory path.</param>
  540. /// <param name="destinationPath">The destination directory path.</param>
  541. /// <param name="moveOptions"><see cref="MoveOptions"/> that specify how the directory is to be moved. This parameter can be <see langword="null"/>.</param>
  542. /// <param name="pathFormat">Indicates the format of the path parameter(s).</param>
  543. [SecurityCritical]
  544. public static CopyMoveResult Move(string sourcePath, string destinationPath, MoveOptions moveOptions, PathFormat pathFormat)
  545. {
  546. return CopyMoveCore(null, sourcePath, destinationPath, null, moveOptions, null, null, null, pathFormat);
  547. }
  548. /// <summary>[AlphaFS] Moves a file or a directory and its contents to a new location, <see cref="MoveOptions"/> can be specified,
  549. /// and the possibility of notifying the application of its progress through a callback function.
  550. /// <remarks>
  551. /// <para>This method does not work across disk volumes unless <paramref name="moveOptions"/> contains <see cref="MoveOptions.CopyAllowed"/>.</para>
  552. /// <para>Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method.</para>
  553. /// <para>If two directories have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior.</para>
  554. /// </remarks>
  555. /// </summary>
  556. /// <returns>A <see cref="CopyMoveResult"/> class with details of the Move action.</returns>
  557. /// <exception cref="ArgumentException"/>
  558. /// <exception cref="ArgumentNullException"/>
  559. /// <exception cref="DirectoryNotFoundException"/>
  560. /// <exception cref="IOException"/>
  561. /// <exception cref="NotSupportedException"/>
  562. /// <exception cref="UnauthorizedAccessException"/>
  563. /// <param name="sourcePath">The source directory path.</param>
  564. /// <param name="destinationPath">The destination directory path.</param>
  565. /// <param name="moveOptions"><see cref="MoveOptions"/> that specify how the directory is to be moved. This parameter can be <see langword="null"/>.</param>
  566. /// <param name="progressHandler">A callback function that is called each time another portion of the directory has been moved. This parameter can be <see langword="null"/>.</param>
  567. /// <param name="userProgressData">The argument to be passed to the callback function. This parameter can be <see langword="null"/>.</param>
  568. [SecurityCritical]
  569. public static CopyMoveResult Move(string sourcePath, string destinationPath, MoveOptions moveOptions, CopyMoveProgressRoutine progressHandler, object userProgressData)
  570. {
  571. return CopyMoveCore(null, sourcePath, destinationPath, null, moveOptions, progressHandler, userProgressData, null, PathFormat.RelativePath);
  572. }
  573. /// <summary>[AlphaFS] Moves a file or a directory and its contents to a new location, <see cref="MoveOptions"/> can be specified,
  574. /// and the possibility of notifying the application of its progress through a callback function.
  575. /// <remarks>
  576. /// <para>This method does not work across disk volumes unless <paramref name="moveOptions"/> contains <see cref="MoveOptions.CopyAllowed"/>.</para>
  577. /// <para>Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method.</para>
  578. /// <para>If two directories have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior.</para>
  579. /// </remarks>
  580. /// </summary>
  581. /// <returns>A <see cref="CopyMoveResult"/> class with details of the Move action.</returns>
  582. /// <exception cref="ArgumentException"/>
  583. /// <exception cref="ArgumentNullException"/>
  584. /// <exception cref="DirectoryNotFoundException"/>
  585. /// <exception cref="IOException"/>
  586. /// <exception cref="NotSupportedException"/>
  587. /// <exception cref="UnauthorizedAccessException"/>
  588. /// <param name="sourcePath">The source directory path.</param>
  589. /// <param name="destinationPath">The destination directory path.</param>
  590. /// <param name="moveOptions"><see cref="MoveOptions"/> that specify how the directory is to be moved. This parameter can be <see langword="null"/>.</param>
  591. /// <param name="progressHandler">A callback function that is called each time another portion of the directory has been moved. This parameter can be <see langword="null"/>.</param>
  592. /// <param name="userProgressData">The argument to be passed to the callback function. This parameter can be <see langword="null"/>.</param>
  593. /// <param name="pathFormat">Indicates the format of the path parameter(s).</param>
  594. [SecurityCritical]
  595. public static CopyMoveResult Move(string sourcePath, string destinationPath, MoveOptions moveOptions, CopyMoveProgressRoutine progressHandler, object userProgressData, PathFormat pathFormat)
  596. {
  597. return CopyMoveCore(null, sourcePath, destinationPath, null, moveOptions, progressHandler, userProgressData, null, pathFormat);
  598. }
  599. #region Transactional
  600. /// <summary>[AlphaFS] Moves a file or a directory and its contents to a new location, <see cref="MoveOptions"/> can be specified.
  601. /// <remarks>
  602. /// <para>This method does not work across disk volumes unless <paramref name="moveOptions"/> contains <see cref="MoveOptions.CopyAllowed"/>.</para>
  603. /// <para>Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method.</para>
  604. /// <para>If two directories have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior.</para>
  605. /// </remarks>
  606. /// </summary>
  607. /// <returns>A <see cref="CopyMoveResult"/> class with details of the Move action.</returns>
  608. /// <exception cref="ArgumentException"/>
  609. /// <exception cref="ArgumentNullException"/>
  610. /// <exception cref="DirectoryNotFoundException"/>
  611. /// <exception cref="IOException"/>
  612. /// <exception cref="NotSupportedException"/>
  613. /// <exception cref="UnauthorizedAccessException"/>
  614. /// <param name="transaction">The transaction.</param>
  615. /// <param name="sourcePath">The source directory path.</param>
  616. /// <param name="destinationPath">The destination directory path.</param>
  617. /// <param name="moveOptions"><see cref="MoveOptions"/> that specify how the directory is to be moved. This parameter can be <see langword="null"/>.</param>
  618. [SecurityCritical]
  619. public static CopyMoveResult MoveTransacted(KernelTransaction transaction, string sourcePath, string destinationPath, MoveOptions moveOptions)
  620. {
  621. return CopyMoveCore(transaction, sourcePath, destinationPath, null, moveOptions, null, null, null, PathFormat.RelativePath);
  622. }
  623. /// <summary>[AlphaFS] Moves a file or a directory and its contents to a new location, <see cref="MoveOptions"/> can be specified.
  624. /// <remarks>
  625. /// <para>This method does not work across disk volumes unless <paramref name="moveOptions"/> contains <see cref="MoveOptions.CopyAllowed"/>.</para>
  626. /// <para>Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method.</para>
  627. /// <para>If two directories have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior.</para>
  628. /// </remarks>
  629. /// </summary>
  630. /// <returns>A <see cref="CopyMoveResult"/> class with details of the Move action.</returns>
  631. /// <exception cref="ArgumentException"/>
  632. /// <exception cref="ArgumentNullException"/>
  633. /// <exception cref="DirectoryNotFoundException"/>
  634. /// <exception cref="IOException"/>
  635. /// <exception cref="NotSupportedException"/>
  636. /// <exception cref="UnauthorizedAccessException"/>
  637. /// <param name="transaction">The transaction.</param>
  638. /// <param name="sourcePath">The source directory path.</param>
  639. /// <param name="destinationPath">The destination directory path.</param>
  640. /// <param name="moveOptions"><see cref="MoveOptions"/> that specify how the directory is to be moved. This parameter can be <see langword="null"/>.</param>
  641. /// <param name="pathFormat">Indicates the format of the path parameter(s).</param>
  642. [SecurityCritical]
  643. public static CopyMoveResult MoveTransacted(KernelTransaction transaction, string sourcePath, string destinationPath, MoveOptions moveOptions, PathFormat pathFormat)
  644. {
  645. return CopyMoveCore(transaction, sourcePath, destinationPath, null, moveOptions, null, null, null, pathFormat);
  646. }
  647. /// <summary>[AlphaFS] Moves a file or a directory and its contents to a new location, <see cref="MoveOptions"/> can be specified,
  648. /// and the possibility of notifying the application of its progress through a callback function.
  649. /// <remarks>
  650. /// <para>This method does not work across disk volumes unless <paramref name="moveOptions"/> contains <see cref="MoveOptions.CopyAllowed"/>.</para>
  651. /// <para>Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method.</para>
  652. /// <para>If two directories have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior.</para>
  653. /// </remarks>
  654. /// </summary>
  655. /// <returns>A <see cref="CopyMoveResult"/> class with details of the Move action.</returns>
  656. /// <exception cref="ArgumentException"/>
  657. /// <exception cref="ArgumentNullException"/>
  658. /// <exception cref="DirectoryNotFoundException"/>
  659. /// <exception cref="IOException"/>
  660. /// <exception cref="NotSupportedException"/>
  661. /// <exception cref="UnauthorizedAccessException"/>
  662. /// <param name="transaction">The transaction.</param>
  663. /// <param name="sourcePath">The source directory path.</param>
  664. /// <param name="destinationPath">The destination directory path.</param>
  665. /// <param name="moveOptions"><see cref="MoveOptions"/> that specify how the directory is to be moved. This parameter can be <see langword="null"/>.</param>
  666. /// <param name="progressHandler">A callback function that is called each time another portion of the directory has been moved. This parameter can be <see langword="null"/>.</param>
  667. /// <param name="userProgressData">The argument to be passed to the callback function. This parameter can be <see langword="null"/>.</param>
  668. [SecurityCritical]
  669. public static CopyMoveResult MoveTransacted(KernelTransaction transaction, string sourcePath, string destinationPath, MoveOptions moveOptions, CopyMoveProgressRoutine progressHandler, object userProgressData)
  670. {
  671. return CopyMoveCore(transaction, sourcePath, destinationPath, null, moveOptions, progressHandler, userProgressData, null, PathFormat.RelativePath);
  672. }
  673. /// <summary>[AlphaFS] Moves a file or a directory and its contents to a new location, <see cref="MoveOptions"/> can be specified,
  674. /// and the possibility of notifying the application of its progress through a callback function.
  675. /// <returns>A <see cref="CopyMoveResult"/> class with the status of the Move action.</returns>
  676. /// <remarks>
  677. /// <para>This method does not work across disk volumes unless <paramref name="moveOptions"/> contains <see cref="MoveOptions.CopyAllowed"/>.</para>
  678. /// <para>Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method.</para>
  679. /// <para>If two directories have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior.</para>
  680. /// </remarks>
  681. /// </summary>
  682. /// <returns>A <see cref="CopyMoveResult"/> class with details of the Move action.</returns>
  683. /// <exception cref="ArgumentException"/>
  684. /// <exception cref="ArgumentNullException"/>
  685. /// <exception cref="DirectoryNotFoundException"/>
  686. /// <exception cref="IOException"/>
  687. /// <exception cref="NotSupportedException"/>
  688. /// <exception cref="UnauthorizedAccessException"/>
  689. /// <param name="transaction">The transaction.</param>
  690. /// <param name="sourcePath">The source directory path.</param>
  691. /// <param name="destinationPath">The destination directory path.</param>
  692. /// <param name="moveOptions"><see cref="MoveOptions"/> that specify how the directory is to be moved. This parameter can be <see langword="null"/>.</param>
  693. /// <param name="progressHandler">A callback function that is called each time another portion of the directory has been moved. This parameter can be <see langword="null"/>.</param>
  694. /// <param name="userProgressData">The argument to be passed to the callback function. This parameter can be <see langword="null"/>.</param>
  695. /// <param name="pathFormat">Indicates the format of the path parameter(s).</param>
  696. [SecurityCritical]
  697. public static CopyMoveResult MoveTransacted(KernelTransaction transaction, string sourcePath, string destinationPath, MoveOptions moveOptions, CopyMoveProgressRoutine progressHandler, object userProgressData, PathFormat pathFormat)
  698. {
  699. return CopyMoveCore(transaction, sourcePath, destinationPath, null, moveOptions, progressHandler, userProgressData, null, pathFormat);
  700. }
  701. #endregion // Transactional
  702. #endregion // Move (MoveOptions)
  703. #region Internal Methods
  704. /// <summary>Copy/move a Non-/Transacted file or directory including its children to a new location,
  705. /// <see cref="CopyOptions"/> or <see cref="MoveOptions"/> can be specified,
  706. /// and the possibility of notifying the application of its progress through a callback function.
  707. /// <remarks>
  708. /// <para>Option <see cref="CopyOptions.NoBuffering"/> is recommended for very large file transfers.</para>
  709. /// <para>You cannot use the Move method to overwrite an existing file, unless <paramref name="moveOptions"/> contains <see cref="MoveOptions.ReplaceExisting"/>.</para>
  710. /// <para>Note that if you attempt to replace a file by moving a file of the same name into that directory, you get an IOException.</para>
  711. /// </remarks>
  712. /// </summary>
  713. /// <returns>A <see cref="CopyMoveResult"/> class with the status of the Copy or Move action.</returns>
  714. /// <exception cref="ArgumentException"/>
  715. /// <exception cref="ArgumentNullException"/>
  716. /// <exception cref="DirectoryNotFoundException"/>
  717. /// <exception cref="IOException"/>
  718. /// <exception cref="NotSupportedException"/>
  719. /// <exception cref="UnauthorizedAccessException"/>
  720. /// <param name="transaction">The transaction.</param>
  721. /// <param name="sourcePath">The source directory path.</param>
  722. /// <param name="destinationPath">The destination directory path.</param>
  723. /// <param name="copyOptions"><see cref="CopyOptions"/> that specify how the directory is to be copied. This parameter can be <see langword="null"/>.</param>
  724. /// <param name="moveOptions"><see cref="MoveOptions"/> that specify how the directory is to be moved. This parameter can be <see langword="null"/>.</param>
  725. /// <param name="progressHandler">A callback function that is called each time another portion of the file has been copied/moved. This parameter can be <see langword="null"/>.</param>
  726. /// <param name="userProgressData">The argument to be passed to the callback function. This parameter can be <see langword="null"/>.</param>
  727. /// <param name="copyMoveResult"></param>
  728. /// <param name="pathFormat">Indicates the format of the path parameter(s).</param>
  729. [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
  730. [SecurityCritical]
  731. internal static CopyMoveResult CopyMoveCore(KernelTransaction transaction, string sourcePath, string destinationPath, CopyOptions? copyOptions, MoveOptions? moveOptions, CopyMoveProgressRoutine progressHandler, object userProgressData, CopyMoveResult copyMoveResult, PathFormat pathFormat)
  732. {
  733. #region Setup
  734. var sourcePathLp = sourcePath;
  735. var destinationPathLp = destinationPath;
  736. var emulateMove = false;
  737. // Determine Copy or Move action.
  738. var isCopy = File.DetermineIsCopy(copyOptions, moveOptions);
  739. var isMove = !isCopy;
  740. var cmr = copyMoveResult ?? new CopyMoveResult(sourcePath, destinationPath, false, (int) Win32Errors.ERROR_SUCCESS);
  741. if (pathFormat != PathFormat.LongFullPath)
  742. {
  743. Path.CheckSupportedPathFormat(sourcePathLp, true, true);
  744. Path.CheckSupportedPathFormat(destinationPathLp, true, true);
  745. // MSDN: .NET 4+ Trailing spaces are removed from the end of the path parameters before moving the directory.
  746. // TrimEnd() is also applied for AlphaFS implementation of method Directory.Copy(), .NET does not have this method.
  747. const GetFullPathOptions fullPathOptions = GetFullPathOptions.TrimEnd | GetFullPathOptions.RemoveTrailingDirectorySeparator;
  748. sourcePathLp = Path.GetExtendedLengthPathCore(transaction, sourcePath, pathFormat, fullPathOptions);
  749. destinationPathLp = Path.GetExtendedLengthPathCore(transaction, destinationPath, pathFormat, fullPathOptions);
  750. // MSDN: .NET3.5+: IOException: The sourceDirName and destDirName parameters refer to the same file or directory.
  751. if (sourcePathLp.Equals(destinationPathLp, StringComparison.OrdinalIgnoreCase))
  752. NativeError.ThrowException(Win32Errors.ERROR_SAME_DRIVE, destinationPathLp);
  753. // Execute once only.
  754. if (isMove)
  755. {
  756. // Compare the root part of both paths.
  757. var equalRootPaths = Path.GetPathRoot(sourcePathLp, false).Equals(Path.GetPathRoot(destinationPathLp, false), StringComparison.OrdinalIgnoreCase);
  758. // Method Volume.IsSameVolume() returns true when both paths refer to the same volume, even if one of the paths is a UNC path.
  759. // For example, src = C:\TempSrc and dst = \\localhost\C$\TempDst
  760. var isSameVolume = equalRootPaths || Volume.IsSameVolume(sourcePathLp, destinationPathLp);
  761. isMove = isSameVolume && equalRootPaths;
  762. if (!isMove)
  763. {
  764. // A Move() can be emulated by using Copy() and Delete(), but only if the CopyAllowed flag is set.
  765. isMove = ((MoveOptions) moveOptions & MoveOptions.CopyAllowed) != 0;
  766. // MSDN: .NET3.5+: IOException: An attempt was made to move a directory to a different volume.
  767. if (!isMove)
  768. NativeError.ThrowException(Win32Errors.ERROR_NOT_SAME_DEVICE, sourcePathLp, destinationPathLp);
  769. }
  770. // The NativeMethod.MoveFileXxx() methods fail when:
  771. // - A directory is being moved;
  772. // - One of the paths is a UNC path, even though both paths refer to the same volume.
  773. // For example, src = C:\TempSrc and dst = \\localhost\C$\TempDst
  774. if (isMove)
  775. {
  776. var srcIsUncPath = Path.IsUncPathCore(sourcePathLp, false, false);
  777. var dstIsUncPath = Path.IsUncPathCore(destinationPathLp, false, false);
  778. isMove = srcIsUncPath && dstIsUncPath;
  779. if (!isMove)
  780. isMove = !srcIsUncPath && !dstIsUncPath;
  781. }
  782. isMove = isMove && isSameVolume && equalRootPaths;
  783. // Emulate Move().
  784. if (!isMove)
  785. {
  786. emulateMove = true;
  787. moveOptions = null;
  788. isCopy = true;
  789. copyOptions = CopyOptions.FailIfExists;
  790. }
  791. }
  792. }
  793. #endregion // Setup
  794. #region Copy
  795. if (isCopy)
  796. {
  797. CreateDirectoryCore(transaction, destinationPathLp, null, null, false, PathFormat.LongFullPath);
  798. var dirs = new Queue<string>(1000);
  799. dirs.Enqueue(sourcePathLp);
  800. while (dirs.Count > 0)
  801. {
  802. var srcLp = dirs.Dequeue();
  803. var dstLp = srcLp.Replace(sourcePathLp, destinationPathLp);
  804. foreach (var fsei in EnumerateFileSystemEntryInfosCore<FileSystemEntryInfo>(transaction, srcLp, Path.WildcardStarMatchAll, DirectoryEnumerationOptions.FilesAndFolders, PathFormat.LongFullPath))
  805. {
  806. var newDestinationPathLp = Path.CombineCore(false, dstLp, fsei.FileName);
  807. if (fsei.IsDirectory)
  808. {
  809. CreateDirectoryCore(transaction, newDestinationPathLp, null, null, false, PathFormat.LongFullPath);
  810. dirs.Enqueue(fsei.LongFullPath);
  811. cmr.TotalFolders++;
  812. continue;
  813. }
  814. cmr = File.CopyMoveCore(false, transaction, fsei.LongFullPath, newDestinationPathLp, false, copyOptions, moveOptions, progressHandler, userProgressData, cmr, PathFormat.LongFullPath);
  815. if (cmr.ErrorCode == Win32Errors.ERROR_SUCCESS)
  816. {
  817. cmr.TotalFiles++;
  818. cmr.TotalBytes += fsei.FileSize;
  819. // Remove the folder or file when copying was successful.
  820. if (emulateMove)
  821. {
  822. if (fsei.IsDirectory)
  823. DeleteDirectoryCore(fsei, transaction, null, true, true, true, PathFormat.LongFullPath);
  824. else
  825. File.DeleteFileCore(transaction, fsei.LongFullPath, true, PathFormat.LongFullPath);
  826. }
  827. }
  828. if (cmr.IsCanceled)
  829. return cmr;
  830. }
  831. }
  832. // Remove source folder.
  833. if (emulateMove && cmr.ErrorCode == Win32Errors.ERROR_SUCCESS)
  834. DeleteDirectoryCore(null, transaction, sourcePathLp, true, true, true, PathFormat.LongFullPath);
  835. }
  836. #endregion // Copy
  837. #region Move
  838. else
  839. {
  840. // MoveOptions.ReplaceExisting: This value cannot be used if lpNewFileName or lpExistingFileName names a directory.
  841. if (((MoveOptions) moveOptions & MoveOptions.ReplaceExisting) != 0)
  842. DeleteDirectoryCore(null, transaction, destinationPathLp, true, true, true, PathFormat.LongFullPath);
  843. // Moves a file or directory, including its children.
  844. // Copies an existing directory, including its children to a new directory.
  845. cmr = File.CopyMoveCore(true, transaction, sourcePathLp, destinationPathLp, false, copyOptions, moveOptions, progressHandler, userProgressData, cmr, PathFormat.LongFullPath);
  846. }
  847. #endregion // Move
  848. return isMove ? null : cmr;
  849. }
  850. #endregion // Internal Methods
  851. }
  852. }