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.
 
 

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