/* Copyright (C) 2008-2016 Peter Palotas, Jeffrey Jangli, Alexandr Normuradov * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ using System; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Runtime.InteropServices; using System.Security; namespace Alphaleonis.Win32.Filesystem { public static partial class File { #region Copy #region .NET /// Copies an existing file to a new file. Overwriting a file of the same name is not allowed. /// /// The attributes of the original file are retained in the copied file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The file to copy. /// The name of the destination file. This cannot be a directory or an existing file. [SecurityCritical] public static void Copy(string sourceFileName, string destinationFileName) { CopyMoveCore(false, null, sourceFileName, destinationFileName, false, CopyOptions.FailIfExists, null, null, null, null, PathFormat.RelativePath); } /// Copies an existing file to a new file. Overwriting a file of the same name is allowed. /// /// The attributes of the original file are retained in the copied file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The file to copy. /// The name of the destination file. This cannot be a directory. /// if the destination file should ignoring the read-only and hidden attributes and overwrite; otherwise, . [SecurityCritical] public static void Copy(string sourceFileName, string destinationFileName, bool overwrite) { CopyMoveCore(false, null, sourceFileName, destinationFileName, false, overwrite ? CopyOptions.None : CopyOptions.FailIfExists, null, null, null, null, PathFormat.RelativePath); } #endregion // .NET #region AlphaFS #region Non-Transactional /// [AlphaFS] Copies an existing file to a new file. Overwriting a file of the same name is not allowed. /// /// The attributes of the original file are retained in the copied file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The file to copy. /// The name of the destination file. This cannot be a directory. /// Indicates the format of the path parameter(s). [SecurityCritical] public static void Copy(string sourceFileName, string destinationFileName, PathFormat pathFormat) { CopyMoveCore(false, null, sourceFileName, destinationFileName, false, CopyOptions.FailIfExists, null, null, null, null, pathFormat); } /// [AlphaFS] Copies an existing file to a new file. Overwriting a file of the same name is allowed. /// /// The attributes of the original file are retained in the copied file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The file to copy. /// The name of the destination file. This cannot be a directory. /// if the destination file should ignoring the read-only and hidden attributes and overwrite; otherwise, . /// Indicates the format of the path parameter(s). [SecurityCritical] public static void Copy(string sourceFileName, string destinationFileName, bool overwrite, PathFormat pathFormat) { CopyMoveCore(false, null, sourceFileName, destinationFileName, false, overwrite ? CopyOptions.None : CopyOptions.FailIfExists, null, null, null, null, pathFormat); } #endregion // Non-Transactional #region Transactional /// [AlphaFS] Copies an existing file to a new file. Overwriting a file of the same name is not allowed. /// /// The attributes of the original file are retained in the copied file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The transaction. /// The file to copy. /// The name of the destination file. This cannot be a directory or an existing file. [SecurityCritical] public static void CopyTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName) { CopyMoveCore(false, transaction, sourceFileName, destinationFileName, false, CopyOptions.FailIfExists, null, null, null, null, PathFormat.RelativePath); } /// [AlphaFS] Copies an existing file to a new file. Overwriting a file of the same name is not allowed. /// /// The attributes of the original file are retained in the copied file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The transaction. /// The file to copy. /// The name of the destination file. This cannot be a directory. /// Indicates the format of the path parameter(s). [SecurityCritical] public static void CopyTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName, PathFormat pathFormat) { CopyMoveCore(false, transaction, sourceFileName, destinationFileName, false, CopyOptions.FailIfExists, null, null, null, null, pathFormat); } /// [AlphaFS] Copies an existing file to a new file. Overwriting a file of the same name is allowed. /// /// The attributes of the original file are retained in the copied file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The transaction. /// The file to copy. /// The name of the destination file. This cannot be a directory. /// if the destination file should ignoring the read-only and hidden attributes and overwrite; otherwise, . [SecurityCritical] public static void CopyTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName, bool overwrite) { CopyMoveCore(false, transaction, sourceFileName, destinationFileName, false, overwrite ? CopyOptions.None : CopyOptions.FailIfExists, null, null, null, null, PathFormat.RelativePath); } /// [AlphaFS] Copies an existing file to a new file. Overwriting a file of the same name is allowed. /// /// The attributes of the original file are retained in the copied file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The transaction. /// The file to copy. /// The name of the destination file. This cannot be a directory. /// if the destination file should ignoring the read-only and hidden attributes and overwrite; otherwise, . /// Indicates the format of the path parameter(s). [SecurityCritical] public static void CopyTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName, bool overwrite, PathFormat pathFormat) { CopyMoveCore(false, transaction, sourceFileName, destinationFileName, false, overwrite ? CopyOptions.None : CopyOptions.FailIfExists, null, null, null, null, pathFormat); } #endregion // Transactional #endregion // AlphaFS #endregion // Copy #region Copy (CopyOptions) #region Non-Transactional /// [AlphaFS] Copies an existing file to a new file. Overwriting a file of the same name is allowed. can be specified. /// /// Option is recommended for very large file transfers. /// The attributes of the original file are retained in the copied file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The file to copy. /// The name of the destination file. This cannot be a directory. /// that specify how the file is to be copied. This parameter can be . [SecurityCritical] public static void Copy(string sourceFileName, string destinationFileName, CopyOptions copyOptions) { CopyMoveCore(false, null, sourceFileName, destinationFileName, false, copyOptions, null, null, null, null, PathFormat.RelativePath); } /// [AlphaFS] Copies an existing file to a new file. Overwriting a file of the same name is allowed. can be specified. /// /// Option is recommended for very large file transfers. /// The attributes of the original file are retained in the copied file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The file to copy. /// The name of the destination file. This cannot be a directory. /// that specify how the file is to be copied. This parameter can be . /// Indicates the format of the path parameter(s). [SecurityCritical] public static void Copy(string sourceFileName, string destinationFileName, CopyOptions copyOptions, PathFormat pathFormat) { CopyMoveCore(false, null, sourceFileName, destinationFileName, false, copyOptions, null, null, null, null, pathFormat); } /// [AlphaFS] Copies an existing file to a new file. Overwriting a file of the same name is allowed. can be specified. /// /// Option is recommended for very large file transfers. /// The attributes of the original file are retained in the copied file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The file to copy. /// The name of the destination file. This cannot be a directory. /// that specify how the file is to be copied. This parameter can be . /// if original Timestamps must be preserved, otherwise. [SecurityCritical] public static void Copy(string sourceFileName, string destinationFileName, CopyOptions copyOptions, bool preserveDates) { CopyMoveCore(false, null, sourceFileName, destinationFileName, preserveDates, copyOptions, null, null, null, null, PathFormat.RelativePath); } /// [AlphaFS] Copies an existing file to a new file. Overwriting a file of the same name is allowed. can be specified. /// /// Option is recommended for very large file transfers. /// The attributes of the original file are retained in the copied file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The file to copy. /// The name of the destination file. This cannot be a directory. /// that specify how the file is to be copied. This parameter can be . /// if original Timestamps must be preserved, otherwise. /// Indicates the format of the path parameter(s). [SecurityCritical] public static void Copy(string sourceFileName, string destinationFileName, CopyOptions copyOptions, bool preserveDates, PathFormat pathFormat) { CopyMoveCore(false, null, sourceFileName, destinationFileName, preserveDates, copyOptions, null, null, null, null, pathFormat); } /// [AlphaFS] Copies an existing file to a new file. Overwriting a file of the same name is allowed. can be specified, /// and the possibility of notifying the application of its progress through a callback function. /// /// A class with details of the Copy action. /// /// Option is recommended for very large file transfers. /// The attributes of the original file are retained in the copied file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The file to copy. /// The name of the destination file. This cannot be a directory. /// that specify how the file is to be copied. This parameter can be . /// A callback function that is called each time another portion of the file has been copied. This parameter can be . /// The argument to be passed to the callback function. This parameter can be . [SecurityCritical] public static void Copy(string sourceFileName, string destinationFileName, CopyOptions copyOptions, CopyMoveProgressRoutine progressHandler, object userProgressData) { CopyMoveCore(false, null, sourceFileName, destinationFileName, false, copyOptions, null, progressHandler, userProgressData, null, PathFormat.RelativePath); } /// [AlphaFS] Copies an existing file to a new file. Overwriting a file of the same name is allowed. can be specified, /// and the possibility of notifying the application of its progress through a callback function. /// /// A class with details of the Copy action. /// /// Option is recommended for very large file transfers. /// The attributes of the original file are retained in the copied file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The file to copy. /// The name of the destination file. This cannot be a directory. /// that specify how the file is to be copied. This parameter can be . /// A callback function that is called each time another portion of the file has been copied. This parameter can be . /// The argument to be passed to the callback function. This parameter can be . /// Indicates the format of the path parameter(s). [SecurityCritical] public static void Copy(string sourceFileName, string destinationFileName, CopyOptions copyOptions, CopyMoveProgressRoutine progressHandler, object userProgressData, PathFormat pathFormat) { CopyMoveCore(false, null, sourceFileName, destinationFileName, false, copyOptions, null, progressHandler, userProgressData, null, pathFormat); } /// [AlphaFS] Copies an existing file to a new file. Overwriting a file of the same name is allowed. can be specified, /// and the possibility of notifying the application of its progress through a callback function. /// /// A class with details of the Copy action. /// /// Option is recommended for very large file transfers. /// The attributes of the original file are retained in the copied file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The file to copy. /// The name of the destination file. This cannot be a directory. /// that specify how the file is to be copied. This parameter can be . /// if original Timestamps must be preserved, otherwise. /// A callback function that is called each time another portion of the file has been copied. This parameter can be . /// The argument to be passed to the callback function. This parameter can be . [SecurityCritical] public static void Copy(string sourceFileName, string destinationFileName, CopyOptions copyOptions, bool preserveDates, CopyMoveProgressRoutine progressHandler, object userProgressData) { CopyMoveCore(false, null, sourceFileName, destinationFileName, preserveDates, copyOptions, null, progressHandler, userProgressData, null, PathFormat.RelativePath); } /// [AlphaFS] Copies an existing file to a new file. Overwriting a file of the same name is allowed. can be specified, /// and the possibility of notifying the application of its progress through a callback function. /// /// A class with details of the Copy action. /// /// Option is recommended for very large file transfers. /// The attributes of the original file are retained in the copied file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The file to copy. /// The name of the destination file. This cannot be a directory. /// that specify how the file is to be copied. This parameter can be . /// if original Timestamps must be preserved, otherwise. /// A callback function that is called each time another portion of the file has been copied. This parameter can be . /// The argument to be passed to the callback function. This parameter can be . /// Indicates the format of the path parameter(s). [SecurityCritical] public static void Copy(string sourceFileName, string destinationFileName, CopyOptions copyOptions, bool preserveDates, CopyMoveProgressRoutine progressHandler, object userProgressData, PathFormat pathFormat) { CopyMoveCore(false, null, sourceFileName, destinationFileName, preserveDates, copyOptions, null, progressHandler, userProgressData, null, pathFormat); } #endregion // Non-Transactional #region Transactional /// [AlphaFS] Copies an existing file to a new file. Overwriting a file of the same name is allowed. can be specified. /// /// Option is recommended for very large file transfers. /// The attributes of the original file are retained in the copied file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The transaction. /// The file to copy. /// The name of the destination file. This cannot be a directory. /// that specify how the file is to be copied. This parameter can be . [SecurityCritical] public static void CopyTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName, CopyOptions copyOptions) { CopyMoveCore(false, transaction, sourceFileName, destinationFileName, false, copyOptions, null, null, null, null, PathFormat.RelativePath); } /// [AlphaFS] Copies an existing file to a new file. Overwriting a file of the same name is allowed. can be specified. /// /// Option is recommended for very large file transfers. /// The attributes of the original file are retained in the copied file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The transaction. /// The file to copy. /// The name of the destination file. This cannot be a directory. /// that specify how the file is to be copied. This parameter can be . /// Indicates the format of the path parameter(s). [SecurityCritical] public static void CopyTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName, CopyOptions copyOptions, PathFormat pathFormat) { CopyMoveCore(false, transaction, sourceFileName, destinationFileName, false, copyOptions, null, null, null, null, pathFormat); } /// [AlphaFS] Copies an existing file to a new file. Overwriting a file of the same name is allowed. can be specified. /// /// Option is recommended for very large file transfers. /// The attributes of the original file are retained in the copied file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The transaction. /// The file to copy. /// The name of the destination file. This cannot be a directory. /// that specify how the file is to be copied. This parameter can be . /// if original Timestamps must be preserved, otherwise. [SecurityCritical] public static void CopyTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName, CopyOptions copyOptions, bool preserveDates) { CopyMoveCore(false, transaction, sourceFileName, destinationFileName, preserveDates, copyOptions, null, null, null, null, PathFormat.RelativePath); } /// [AlphaFS] Copies an existing file to a new file. Overwriting a file of the same name is allowed. can be specified. /// /// Option is recommended for very large file transfers. /// The attributes of the original file are retained in the copied file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The transaction. /// The file to copy. /// The name of the destination file. This cannot be a directory. /// that specify how the file is to be copied. This parameter can be . /// if original Timestamps must be preserved, otherwise. /// Indicates the format of the path parameter(s). [SecurityCritical] public static void CopyTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName, CopyOptions copyOptions, bool preserveDates, PathFormat pathFormat) { CopyMoveCore(false, transaction, sourceFileName, destinationFileName, preserveDates, copyOptions, null, null, null, null, pathFormat); } /// [AlphaFS] Copies an existing file to a new file. Overwriting a file of the same name is allowed. can be specified, /// and the possibility of notifying the application of its progress through a callback function. /// /// A class with details of the Copy action. /// /// Option is recommended for very large file transfers. /// The attributes of the original file are retained in the copied file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The transaction. /// The file to copy. /// The name of the destination file. This cannot be a directory. /// that specify how the file is to be copied. This parameter can be . /// A callback function that is called each time another portion of the file has been copied. This parameter can be . /// The argument to be passed to the callback function. This parameter can be . [SecurityCritical] public static void CopyTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName, CopyOptions copyOptions, CopyMoveProgressRoutine progressHandler, object userProgressData) { CopyMoveCore(false, transaction, sourceFileName, destinationFileName, false, copyOptions, null, progressHandler, userProgressData, null, PathFormat.RelativePath); } /// [AlphaFS] Copies an existing file to a new file. Overwriting a file of the same name is allowed. can be specified, /// and the possibility of notifying the application of its progress through a callback function. /// /// A class with details of the Copy action. /// /// Option is recommended for very large file transfers. /// The attributes of the original file are retained in the copied file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The transaction. /// The file to copy. /// The name of the destination file. This cannot be a directory. /// that specify how the file is to be copied. This parameter can be . /// A callback function that is called each time another portion of the file has been copied. This parameter can be . /// The argument to be passed to the callback function. This parameter can be . /// Indicates the format of the path parameter(s). [SecurityCritical] public static void CopyTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName, CopyOptions copyOptions, CopyMoveProgressRoutine progressHandler, object userProgressData, PathFormat pathFormat) { CopyMoveCore(false, transaction, sourceFileName, destinationFileName, false, copyOptions, null, progressHandler, userProgressData, null, pathFormat); } /// [AlphaFS] Copies an existing file to a new file. Overwriting a file of the same name is allowed. can be specified, /// and the possibility of notifying the application of its progress through a callback function. /// /// A class with details of the Copy action. /// /// Option is recommended for very large file transfers. /// The attributes of the original file are retained in the copied file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The transaction. /// The file to copy. /// The name of the destination file. This cannot be a directory. /// that specify how the file is to be copied. This parameter can be . /// if original Timestamps must be preserved, otherwise. /// A callback function that is called each time another portion of the file has been copied. This parameter can be . /// The argument to be passed to the callback function. This parameter can be . [SecurityCritical] public static void CopyTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName, CopyOptions copyOptions, bool preserveDates, CopyMoveProgressRoutine progressHandler, object userProgressData) { CopyMoveCore(false, transaction, sourceFileName, destinationFileName, preserveDates, copyOptions, null, progressHandler, userProgressData, null, PathFormat.RelativePath); } /// [AlphaFS] Copies an existing file to a new file. Overwriting a file of the same name is allowed. can be specified, /// and the possibility of notifying the application of its progress through a callback function. /// /// A class with details of the Copy action. /// /// Option is recommended for very large file transfers. /// The attributes of the original file are retained in the copied file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// The transaction. /// The file to copy. /// The name of the destination file. This cannot be a directory. /// that specify how the file is to be copied. This parameter can be . /// if original Timestamps must be preserved, otherwise. /// A callback function that is called each time another portion of the file has been copied. This parameter can be . /// The argument to be passed to the callback function. This parameter can be . /// Indicates the format of the path parameter(s). /// /// /// /// /// /// /// [SecurityCritical] public static void CopyTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName, CopyOptions copyOptions, bool preserveDates, CopyMoveProgressRoutine progressHandler, object userProgressData, PathFormat pathFormat) { CopyMoveCore(false, transaction, sourceFileName, destinationFileName, preserveDates, copyOptions, null, progressHandler, userProgressData, null, pathFormat); } #endregion // Transactional #endregion // Copy (CopyOptions) #region Move #region .NET /// Moves a specified file to a new location, providing the option to specify a new file name. /// /// This method works across disk volumes, and it does not throw an exception if the source and destination are the same. /// Note that if you attempt to replace a file by moving a file of the same name into that directory, you get an . /// You cannot use the Move method to overwrite an existing file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The name of the file to move. /// The new path for the file. [SecurityCritical] public static void Move(string sourceFileName, string destinationFileName) { CopyMoveCore(false, null, sourceFileName, destinationFileName, false, null, MoveOptions.CopyAllowed, null, null, null, PathFormat.RelativePath); } #endregion // .NET #region AlphaFS #region Non-Transactional /// [AlphaFS] Moves a specified file to a new location, providing the option to specify a new file name. /// /// This method works across disk volumes, and it does not throw an exception if the source and destination are the same. /// Note that if you attempt to replace a file by moving a file of the same name into that directory, you get an . /// You cannot use the Move method to overwrite an existing file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The name of the file to move. /// The new path for the file. /// Indicates the format of the path parameter(s). [SecurityCritical] public static void Move(string sourceFileName, string destinationFileName, PathFormat pathFormat) { CopyMoveCore(false, null, sourceFileName, destinationFileName, false, null, MoveOptions.CopyAllowed, null, null, null, pathFormat); } #endregion // Non-Transactional #region Transactional /// [AlphaFS] Moves a specified file to a new location, providing the option to specify a new file name. /// /// This method works across disk volumes, and it does not throw an exception if the source and destination are the same. /// Note that if you attempt to replace a file by moving a file of the same name into that directory, you get an . /// You cannot use the Move method to overwrite an existing file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The transaction. /// The name of the file to move. /// The new path for the file. [SecurityCritical] public static void MoveTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName) { CopyMoveCore(false, transaction, sourceFileName, destinationFileName, false, null, MoveOptions.CopyAllowed, null, null, null, PathFormat.RelativePath); } /// [AlphaFS] Moves a specified file to a new location, providing the option to specify a new file name. /// /// This method works across disk volumes, and it does not throw an exception if the source and destination are the same. /// Note that if you attempt to replace a file by moving a file of the same name into that directory, you get an . /// You cannot use the Move method to overwrite an existing file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The transaction. /// The name of the file to move. /// The new path for the file. /// Indicates the format of the path parameter(s). [SecurityCritical] public static void MoveTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName, PathFormat pathFormat) { CopyMoveCore(false, transaction, sourceFileName, destinationFileName, false, null, MoveOptions.CopyAllowed, null, null, null, pathFormat); } #endregion // Transactional #endregion // AlphaFS #endregion // Move #region Move (MoveOptions) #region Non-Transactional /// [AlphaFS] Moves a specified file to a new location, providing the option to specify a new file name. /// /// This method works across disk volumes, and it does not throw an exception if the source and destination are the same. /// Note that if you attempt to replace a file by moving a file of the same name into that directory, you get an . /// You cannot use the Move method to overwrite an existing file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The name of the file to move. /// The new path for the file. /// that specify how the file is to be moved. This parameter can be . [SecurityCritical] public static void Move(string sourceFileName, string destinationFileName, MoveOptions moveOptions) { CopyMoveCore(false, null, sourceFileName, destinationFileName, false, null, moveOptions, null, null, null, PathFormat.RelativePath); } /// [AlphaFS] Moves a specified file to a new location, providing the option to specify a new file name. /// /// This method works across disk volumes, and it does not throw an exception if the source and destination are the same. /// Note that if you attempt to replace a file by moving a file of the same name into that directory, you get an . /// You cannot use the Move method to overwrite an existing file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The name of the file to move. /// The new path for the file. /// that specify how the file is to be moved. This parameter can be . /// Indicates the format of the path parameter(s). [SecurityCritical] public static void Move(string sourceFileName, string destinationFileName, MoveOptions moveOptions, PathFormat pathFormat) { CopyMoveCore(false, null, sourceFileName, destinationFileName, false, null, moveOptions, null, null, null, pathFormat); } /// [AlphaFS] Moves a specified file to a new location, providing the option to specify a new file name. /// A class with the status of the Move action. /// /// This method works across disk volumes, and it does not throw an exception if the source and destination are the same. /// Note that if you attempt to replace a file by moving a file of the same name into that directory, you get an . /// You cannot use the Move method to overwrite an existing file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The name of the file to move. /// The new path for the file. /// that specify how the file is to be moved. This parameter can be . /// A callback function that is called each time another portion of the file has been moved. This parameter can be . /// The argument to be passed to the callback function. This parameter can be . [SecurityCritical] public static void Move(string sourceFileName, string destinationFileName, MoveOptions moveOptions, CopyMoveProgressRoutine progressHandler, object userProgressData) { CopyMoveCore(false, null, sourceFileName, destinationFileName, false, null, moveOptions, progressHandler, userProgressData, null, PathFormat.RelativePath); } /// [AlphaFS] Moves a specified file to a new location, providing the option to specify a new file name. /// A class with the status of the Move action. /// /// This method works across disk volumes, and it does not throw an exception if the source and destination are the same. /// Note that if you attempt to replace a file by moving a file of the same name into that directory, you get an . /// You cannot use the Move method to overwrite an existing file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The name of the file to move. /// The new path for the file. /// that specify how the file is to be moved. This parameter can be . /// A callback function that is called each time another portion of the file has been moved. This parameter can be . /// The argument to be passed to the callback function. This parameter can be . /// Indicates the format of the path parameter(s). [SecurityCritical] public static void Move(string sourceFileName, string destinationFileName, MoveOptions moveOptions, CopyMoveProgressRoutine progressHandler, object userProgressData, PathFormat pathFormat) { CopyMoveCore(false, null, sourceFileName, destinationFileName, false, null, moveOptions, progressHandler, userProgressData, null, pathFormat); } #endregion // Non-Transactional #region Transactional /// [AlphaFS] Moves a specified file to a new location, providing the option to specify a new file name. /// /// This method works across disk volumes, and it does not throw an exception if the source and destination are the same. /// Note that if you attempt to replace a file by moving a file of the same name into that directory, you get an . /// You cannot use the Move method to overwrite an existing file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The transaction. /// The name of the file to move. /// The new path for the file. /// that specify how the file is to be moved. This parameter can be . [SecurityCritical] public static void MoveTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName, MoveOptions moveOptions) { CopyMoveCore(false, transaction, sourceFileName, destinationFileName, false, null, moveOptions, null, null, null, PathFormat.RelativePath); } /// [AlphaFS] Moves a specified file to a new location, providing the option to specify a new file name. /// /// This method works across disk volumes, and it does not throw an exception if the source and destination are the same. /// Note that if you attempt to replace a file by moving a file of the same name into that directory, you get an . /// You cannot use the Move method to overwrite an existing file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The transaction. /// The name of the file to move. /// The new path for the file. /// that specify how the file is to be moved. This parameter can be . /// Indicates the format of the path parameter(s). [SecurityCritical] public static void MoveTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName, MoveOptions moveOptions, PathFormat pathFormat) { CopyMoveCore(false, transaction, sourceFileName, destinationFileName, false, null, moveOptions, null, null, null, pathFormat); } /// [AlphaFS] Moves a specified file to a new location, providing the option to specify a new file name. /// A class with the status of the Move action. /// /// This method works across disk volumes, and it does not throw an exception if the source and destination are the same. /// Note that if you attempt to replace a file by moving a file of the same name into that directory, you get an . /// You cannot use the Move method to overwrite an existing file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The transaction. /// The name of the file to move. /// The new path for the file. /// that specify how the file is to be moved. This parameter can be . /// A callback function that is called each time another portion of the file has been moved. This parameter can be . /// The argument to be passed to the callback function. This parameter can be . [SecurityCritical] public static void MoveTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName, MoveOptions moveOptions, CopyMoveProgressRoutine progressHandler, object userProgressData) { CopyMoveCore(false, transaction, sourceFileName, destinationFileName, false, null, moveOptions, progressHandler, userProgressData, null, PathFormat.RelativePath); } /// [AlphaFS] Moves a specified file to a new location, providing the option to specify a new file name. /// A class with the status of the Move action. /// /// This method works across disk volumes, and it does not throw an exception if the source and destination are the same. /// Note that if you attempt to replace a file by moving a file of the same name into that directory, you get an . /// You cannot use the Move method to overwrite an existing file. /// Whenever possible, avoid using short file names (such as XXXXXX~1.XXX) with this method. /// If two files have equivalent short file names then this method may fail and raise an exception and/or result in undesirable behavior. /// /// /// /// /// /// /// /// /// The transaction. /// The name of the file to move. /// The new path for the file. /// that specify how the file is to be moved. This parameter can be . /// A callback function that is called each time another portion of the file has been moved. This parameter can be . /// The argument to be passed to the callback function. This parameter can be . /// Indicates the format of the path parameter(s). [SecurityCritical] public static void MoveTransacted(KernelTransaction transaction, string sourceFileName, string destinationFileName, MoveOptions moveOptions, CopyMoveProgressRoutine progressHandler, object userProgressData, PathFormat pathFormat) { CopyMoveCore(false, transaction, sourceFileName, destinationFileName, false, null, moveOptions, progressHandler, userProgressData, null, pathFormat); } #endregion // Transactional #endregion // Move (MoveOptions) #region Internal Methods /// Determine the Copy or Move action. internal static bool DetermineIsCopy(CopyOptions? copyOptions, MoveOptions? moveOptions) { // Determine Copy or Move action. var isCopy = copyOptions != null; var isMove = !isCopy && moveOptions != null; if ((!isCopy && !isMove) || (isCopy && isMove)) throw new NotSupportedException(Resources.Cannot_Determine_Copy_Or_Move); return isCopy; } /// Copy/move a Non-/Transacted file or directory including its children to a new location, or can be specified, /// and the possibility of notifying the application of its progress through a callback function. /// /// A class with the status of the Copy or Move action. /// /// Option is recommended for very large file transfers. /// You cannot use the Move method to overwrite an existing file, unless /// contains . /// This Move method works across disk volumes, and it does not throw an exception if the /// source and destination are the same. /// Note that if you attempt to replace a file by moving a file of the same name into /// that directory, you get an IOException. /// /// /// /// /// /// /// /// /// Specifies that and are a file or directory. /// The transaction. /// The source directory path. /// The destination directory path. /// if original Timestamps must be preserved, otherwise. This parameter is ignored for move operations. /// that specify how the file is to be copied. This parameter can be . /// Flags that specify how the file or directory is to be moved. This parameter can be . /// A callback function that is called each time another portion of the file has been copied/moved. This parameter can be . /// The argument to be passed to the callback function. This parameter can be . /// /// Indicates the format of the path parameter(s). [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] [SecurityCritical] internal static CopyMoveResult CopyMoveCore(bool isFolder, KernelTransaction transaction, string sourceFileName, string destinationFileName, bool preserveDates, CopyOptions? copyOptions, MoveOptions? moveOptions, CopyMoveProgressRoutine progressHandler, object userProgressData, CopyMoveResult copyMoveResult, PathFormat pathFormat) { #region Setup var sourceFileNameLp = sourceFileName; var destFileNameLp = destinationFileName; if (pathFormat != PathFormat.LongFullPath) { Path.CheckSupportedPathFormat(sourceFileName, true, true); Path.CheckSupportedPathFormat(destinationFileName, true, true); sourceFileNameLp = Path.GetExtendedLengthPathCore(transaction, sourceFileName, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator); destFileNameLp = Path.GetExtendedLengthPathCore(transaction, destinationFileName, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator); } // Determine Copy or Move action. var isCopy = DetermineIsCopy(copyOptions, moveOptions); var isMove = !isCopy; var cmr = copyMoveResult ?? new CopyMoveResult(sourceFileName, destinationFileName, false, (int) Win32Errors.ERROR_SUCCESS); // MSDN: If this flag is set to TRUE during the copy/move operation, the operation is canceled. // Otherwise, the copy/move operation will continue to completion. bool cancel; var raiseException = progressHandler == null; // Setup callback function for progress notifications. var routine = !raiseException ? (totalFileSize, totalBytesTransferred, streamSize, streamBytesTransferred, dwStreamNumber, dwCallbackReason, hSourceFile, hDestinationFile, lpData) => progressHandler(totalFileSize, totalBytesTransferred, streamSize, streamBytesTransferred, dwStreamNumber, dwCallbackReason, userProgressData) : (NativeMethods.NativeCopyMoveProgressRoutine) null; #endregion // Setup startCopyMove: #region Win32 Copy/Move var success = transaction == null || !NativeMethods.IsAtLeastWindowsVista ? isMove // MoveFileWithProgress() / MoveFileTransacted() // In the ANSI version of this function, the name is limited to MAX_PATH characters. // To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\\?\" to the path. // 2013-04-15: MSDN confirms LongPath usage. // CopyFileEx() / CopyFileTransacted() // In the ANSI version of this function, the name is limited to MAX_PATH characters. // To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\\?\" to the path. // 2013-04-15: MSDN confirms LongPath usage. // Note: The NativeMethod.MoveFileXxx() methods fail if one of the paths is a UNC path, even though both paths refer to the same volume. // For example, src = C:\TempSrc and dst = \\localhost\C$\TempDst ? NativeMethods.MoveFileWithProgress(sourceFileNameLp, destFileNameLp, routine, IntPtr.Zero, (MoveOptions) moveOptions) : NativeMethods.CopyFileEx(sourceFileNameLp, destFileNameLp, routine, IntPtr.Zero, out cancel, (CopyOptions) copyOptions) : isMove ? NativeMethods.MoveFileTransacted(sourceFileNameLp, destFileNameLp, routine, IntPtr.Zero, (MoveOptions) moveOptions, transaction.SafeHandle) : NativeMethods.CopyFileTransacted(sourceFileNameLp, destFileNameLp, routine, IntPtr.Zero, out cancel, (CopyOptions) copyOptions, transaction.SafeHandle); var lastError = (uint) Marshal.GetLastWin32Error(); if (!success) { cmr.ErrorCode = (int) lastError; if (lastError == Win32Errors.ERROR_REQUEST_ABORTED) { // MSDN: // // If lpProgressRoutine returns PROGRESS_CANCEL due to the user canceling the operation, // CopyFileEx will return zero and GetLastError will return ERROR_REQUEST_ABORTED. // In this case, the partially copied destination file is deleted. // // If lpProgressRoutine returns PROGRESS_STOP due to the user stopping the operation, // CopyFileEx will return zero and GetLastError will return ERROR_REQUEST_ABORTED. // In this case, the partially copied destination file is left intact. cmr.IsCanceled = true; } else if (raiseException) { raiseException: #region Win32Errors switch (lastError) { case Win32Errors.ERROR_FILE_NOT_FOUND: if (isFolder) { lastError = Win32Errors.ERROR_PATH_NOT_FOUND; goto raiseException; } // File.Copy() // File.Move() // MSDN: .NET 3.5+: FileNotFoundException: sourceFileName was not found. NativeError.ThrowException(lastError, sourceFileNameLp); break; case Win32Errors.ERROR_PATH_NOT_FOUND: // File.Copy() // File.Move() // Directory.Move() // MSDN: .NET 3.5+: DirectoryNotFoundException: The path specified in sourceFileName or destinationFileName is invalid (for example, it is on an unmapped drive). NativeError.ThrowException(lastError, sourceFileNameLp); break; case Win32Errors.ERROR_FILE_EXISTS: // File.Copy() // Directory.Copy() NativeError.ThrowException(lastError, destFileNameLp); break; default: var destExists = ExistsCore(isFolder, transaction, destFileNameLp, PathFormat.LongFullPath); // For a number of error codes (sharing violation, path not found, etc) // we don't know if the problem was with the source or destination file. // Check if destination directory already exists. // Directory.Move() // MSDN: .NET 3.5+: IOException: destDirName already exists. if (isFolder && destExists) NativeError.ThrowException(Win32Errors.ERROR_ALREADY_EXISTS, destFileNameLp); if (isMove) { // Ensure that the source file or directory exists. // Directory.Move() // MSDN: .NET 3.5+: DirectoryNotFoundException: The path specified by sourceDirName is invalid (for example, it is on an unmapped drive). if (!ExistsCore(isFolder, transaction, sourceFileNameLp, PathFormat.LongFullPath)) NativeError.ThrowException(isFolder ? Win32Errors.ERROR_PATH_NOT_FOUND : Win32Errors.ERROR_FILE_NOT_FOUND, sourceFileNameLp); } // Try reading the source file. var fileNameLp = destFileNameLp; if (!isFolder) { using (var safeHandle = CreateFileCore(transaction, sourceFileNameLp, ExtendedFileAttributes.Normal, null, FileMode.Open, 0, FileShare.Read, false, PathFormat.LongFullPath)) if (safeHandle != null && safeHandle.IsInvalid) fileNameLp = sourceFileNameLp; } if (lastError == Win32Errors.ERROR_ACCESS_DENIED) { // File.Copy() // File.Move() // MSDN: .NET 3.5+: IOException: An I/O error has occurred. // Directory exists with the same name as the file. if (!isFolder && destExists) NativeError.ThrowException(lastError, string.Format(CultureInfo.CurrentCulture, Resources.Target_File_Is_A_Directory, destFileNameLp)); if (isMove) { var data = new NativeMethods.WIN32_FILE_ATTRIBUTE_DATA(); FillAttributeInfoCore(transaction, destFileNameLp, ref data, false, true); if (data.dwFileAttributes != (FileAttributes) (-1)) { if ((data.dwFileAttributes & FileAttributes.ReadOnly) != 0) { // MSDN: .NET 3.5+: IOException: The directory specified by path is read-only. if (((MoveOptions) moveOptions & MoveOptions.ReplaceExisting) != 0) { // Reset file system object attributes. SetAttributesCore(isFolder, transaction, destFileNameLp, FileAttributes.Normal, PathFormat.LongFullPath); goto startCopyMove; } // MSDN: .NET 3.5+: UnauthorizedAccessException: destinationFileName is read-only. // MSDN: Win32 CopyFileXxx: This function fails with ERROR_ACCESS_DENIED if the destination file already exists // and has the FILE_ATTRIBUTE_HIDDEN or FILE_ATTRIBUTE_READONLY attribute set. throw new FileReadOnlyException(destFileNameLp); } // MSDN: Win32 CopyFileXxx: This function fails with ERROR_ACCESS_DENIED if the destination file already exists // and has the FILE_ATTRIBUTE_HIDDEN or FILE_ATTRIBUTE_READONLY attribute set. if ((data.dwFileAttributes & FileAttributes.Hidden) != 0) NativeError.ThrowException(lastError, string.Format(CultureInfo.CurrentCulture, Resources.File_Is_Hidden, destFileNameLp)); } } } // MSDN: .NET 3.5+: An I/O error has occurred. // File.Copy(): IOException: destinationFileName exists and overwrite is false. // File.Move(): The destination file already exists or sourceFileName was not found. NativeError.ThrowException(lastError, fileNameLp); break; } #endregion // Win32Errors } } #endregion // Win32 Copy/Move #region Transfer Timestamps // Apply original Timestamps if requested. // MoveFileWithProgress() / MoveFileTransacted() automatically preserve Timestamps. // File.Copy() if (success && preserveDates && isCopy) { // Currently preserveDates is only used with files. var data = new NativeMethods.WIN32_FILE_ATTRIBUTE_DATA(); var dataInitialised = FillAttributeInfoCore(transaction, sourceFileNameLp, ref data, false, true); if (dataInitialised == Win32Errors.ERROR_SUCCESS && data.dwFileAttributes != (FileAttributes) (-1)) SetFsoDateTimeCore(false, transaction, destFileNameLp, DateTime.FromFileTimeUtc(data.ftCreationTime), DateTime.FromFileTimeUtc(data.ftLastAccessTime), DateTime.FromFileTimeUtc(data.ftLastWriteTime), false, PathFormat.LongFullPath); } #endregion // Transfer Timestamps return cmr; } #endregion // Internal Methods } }