public static void SetCurrentDirectory(string path, PathFormat pathFormat)
        {
            if (Utils.IsNullOrWhiteSpace(path))
            {
                throw new ArgumentNullException("path");
            }

            var fullCheck = pathFormat == PathFormat.RelativePath;

            Path.CheckSupportedPathFormat(path, fullCheck, fullCheck);
            var pathLp = Path.GetExtendedLengthPathCore(null, path, pathFormat, GetFullPathOptions.AddTrailingDirectorySeparator);

            if (pathFormat == PathFormat.FullPath)
            {
                pathLp = Path.GetRegularPathCore(pathLp, GetFullPathOptions.None, false);
            }


            // SetCurrentDirectory()
            // In the ANSI version of this function, the name is limited to 248 characters.
            // To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\\?\" to the path.
            // 2016-09-29: MSDN confirms LongPath usage starting with Windows 10, version 1607.

            if (!NativeMethods.SetCurrentDirectory(pathLp))
            {
                NativeError.ThrowException(Marshal.GetLastWin32Error(), pathLp);
            }
        }
예제 #2
0
        internal static void DeleteVolumeMountPointCore(KernelTransaction transaction, string volumeMountPoint, bool continueOnException, bool continueIfJunction, PathFormat pathFormat)
        {
            if (pathFormat != PathFormat.LongFullPath)
            {
                Path.CheckSupportedPathFormat(volumeMountPoint, true, true);
            }

            volumeMountPoint = Path.GetExtendedLengthPathCore(transaction, volumeMountPoint, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator);


            using (new NativeMethods.ChangeErrorMode(NativeMethods.ErrorMode.FailCriticalErrors))
            {
                // DeleteVolumeMountPoint()
                // 2013-01-13: MSDN does not confirm LongPath usage but a Unicode version of this function exists.

                // A trailing backslash is required.
                var success = NativeMethods.DeleteVolumeMountPoint(Path.AddTrailingDirectorySeparator(volumeMountPoint, false));

                var lastError = Marshal.GetLastWin32Error();
                if (!success && !continueOnException)
                {
                    if (lastError == Win32Errors.ERROR_INVALID_PARAMETER && continueIfJunction)
                    {
                        return;
                    }

                    if (lastError == Win32Errors.ERROR_FILE_NOT_FOUND)
                    {
                        lastError = (int)Win32Errors.ERROR_PATH_NOT_FOUND;
                    }

                    NativeError.ThrowException(lastError, volumeMountPoint);
                }
            }
        }
예제 #3
0
        public static void SetCurrentDirectory(string path, PathFormat pathFormat)
        {
            if (Utils.IsNullOrWhiteSpace(path))
            {
                throw new ArgumentNullException("path");
            }

            var fullCheck = pathFormat == PathFormat.RelativePath;

            Path.CheckSupportedPathFormat(path, fullCheck, fullCheck);
            var pathLp = Path.GetExtendedLengthPathCore(null, path, pathFormat, GetFullPathOptions.AddTrailingDirectorySeparator);

            if (pathFormat == PathFormat.FullPath)
            {
                pathLp = Path.GetRegularPathCore(pathLp, GetFullPathOptions.None, false);
            }


            // SetCurrentDirectory()
            // 2016-09-29: MSDN does not confirm LongPath usage but a Unicode version of this function exists.
            // 2017-05-30: MSDN confirms LongPath usage: Starting with Windows 10, version 1607

            var success = NativeMethods.SetCurrentDirectory(pathLp);

            var lastError = Marshal.GetLastWin32Error();

            if (!success)
            {
                NativeError.ThrowException(lastError, pathLp);
            }
        }
예제 #4
0
        internal static SafeFileHandle CreateFileCore(KernelTransaction transaction, bool? isFolder, string path, ExtendedFileAttributes attributes, FileSecurity fileSecurity, FileMode fileMode, FileSystemRights fileSystemRights, FileShare fileShare, bool checkPath, bool continueOnException, PathFormat pathFormat)
        {
            if (checkPath && pathFormat == PathFormat.RelativePath)

            Path.CheckSupportedPathFormat(path, true, true);

             // When isFile == null, we're working with a device.
             // When opening a VOLUME or removable media drive (for example, a floppy disk drive or flash memory thumb drive),
             // the path string should be the following form: "\\.\X:"
             // Do not use a trailing backslash ('\'), which indicates the root.

             var pathLp = Path.GetExtendedLengthPathCore(transaction, path, pathFormat, GetFullPathOptions.TrimEnd | GetFullPathOptions.RemoveTrailingDirectorySeparator);

             // CreateFileXxx() does not support FileMode.Append mode.
             var isAppend = fileMode == FileMode.Append;
             if (isAppend)
             {
            fileMode = FileMode.OpenOrCreate;
            fileSystemRights |= FileSystemRights.AppendData;
             }

             if (null != fileSecurity)
            fileSystemRights |= (FileSystemRights)SECURITY_INFORMATION.UNPROTECTED_SACL_SECURITY_INFORMATION;

             using ((fileSystemRights & (FileSystemRights)SECURITY_INFORMATION.UNPROTECTED_SACL_SECURITY_INFORMATION) != 0 || (fileSystemRights & (FileSystemRights) SECURITY_INFORMATION.UNPROTECTED_DACL_SECURITY_INFORMATION) != 0 ? new PrivilegeEnabler(Privilege.Security) : null)

             using (var securityAttributes = new Security.NativeMethods.SecurityAttributes(fileSecurity))
             {
            var safeHandle = transaction == null || !NativeMethods.IsAtLeastWindowsVista

               // CreateFile() / CreateFileTransacted()
               // 2013-01-13: MSDN confirms LongPath usage.

               ? NativeMethods.CreateFile(pathLp, fileSystemRights, fileShare, securityAttributes, fileMode, attributes, IntPtr.Zero)

               : NativeMethods.CreateFileTransacted(pathLp, fileSystemRights, fileShare, securityAttributes, fileMode, attributes, IntPtr.Zero, transaction.SafeHandle, IntPtr.Zero, IntPtr.Zero);

            var lastError = Marshal.GetLastWin32Error();

            NativeMethods.CloseHandleAndPossiblyThrowException(safeHandle, lastError, isFolder, path, !continueOnException);

            if (isAppend)
            {
               var success = NativeMethods.SetFilePointerEx(safeHandle, 0, IntPtr.Zero, SeekOrigin.End);

               lastError = Marshal.GetLastWin32Error();

               if (!success)
               {
                  NativeMethods.CloseHandleAndPossiblyThrowException(safeHandle, lastError, isFolder, path, !continueOnException);

                  return null;
               }
            }

            return safeHandle;
             }
        }
예제 #5
0
        internal static void DeleteEmptySubdirectoriesCore(FileSystemEntryInfo fileSystemEntryInfo, KernelTransaction transaction, string path, bool recursive, bool ignoreReadOnly, bool initialize, PathFormat pathFormat)
        {
            #region Setup

            if (pathFormat == PathFormat.RelativePath)
            {
                Path.CheckSupportedPathFormat(path, true, true);
            }

            if (fileSystemEntryInfo == null)
            {
                if (!File.ExistsCore(true, transaction, path, pathFormat))
                {
                    NativeError.ThrowException(Win32Errors.ERROR_PATH_NOT_FOUND, path);
                }

                fileSystemEntryInfo = File.GetFileSystemEntryInfoCore(true, transaction, Path.GetExtendedLengthPathCore(transaction, path, pathFormat, GetFullPathOptions.TrimEnd | GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck), false, pathFormat);
            }

            if (fileSystemEntryInfo == null)
            {
                throw new ArgumentNullException("path");
            }

            string pathLp = fileSystemEntryInfo.LongFullPath;

            #endregion // Setup

            // Ensure path is a directory.
            if (!fileSystemEntryInfo.IsDirectory)
            {
                throw new IOException(string.Format(CultureInfo.CurrentCulture, Resources.Target_Directory_Is_A_File, pathLp));
            }


            var dirEnumOptions = DirectoryEnumerationOptions.Folders;

            if (recursive)
            {
                dirEnumOptions |= DirectoryEnumerationOptions.Recursive;
            }

            foreach (var fsei in EnumerateFileSystemEntryInfosCore <FileSystemEntryInfo>(transaction, pathLp, Path.WildcardStarMatchAll, dirEnumOptions, PathFormat.LongFullPath))
            {
                DeleteEmptySubdirectoriesCore(fsei, transaction, null, recursive, ignoreReadOnly, false, PathFormat.LongFullPath);
            }


            if (!EnumerateFileSystemEntryInfosCore <string>(transaction, pathLp, Path.WildcardStarMatchAll, DirectoryEnumerationOptions.FilesAndFolders, PathFormat.LongFullPath).Any())
            {
                // Prevent deleting path itself.
                if (!initialize)
                {
                    DeleteDirectoryCore(fileSystemEntryInfo, transaction, null, false, ignoreReadOnly, true, PathFormat.LongFullPath);
                }
            }
        }
        internal static void DeleteEmptySubdirectoriesCore(FileSystemEntryInfo fsEntryInfo, KernelTransaction transaction, string path, bool recursive, bool ignoreReadOnly, PathFormat pathFormat)
        {
            #region Setup

            if (null == fsEntryInfo)
            {
                if (pathFormat == PathFormat.RelativePath)
                {
                    Path.CheckSupportedPathFormat(path, true, true);
                }

                if (!File.ExistsCore(transaction, true, path, pathFormat))
                {
                    NativeError.ThrowException(Win32Errors.ERROR_PATH_NOT_FOUND, path);
                }

                fsEntryInfo = File.GetFileSystemEntryInfoCore(transaction, true, Path.GetExtendedLengthPathCore(transaction, path, pathFormat, GetFullPathOptions.TrimEnd | GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck), false, pathFormat);

                if (null == fsEntryInfo)
                {
                    return;
                }
            }

            #endregion // Setup


            // Ensure path is a directory.
            if (!fsEntryInfo.IsDirectory)
            {
                throw new IOException(string.Format(CultureInfo.InvariantCulture, Resources.Target_Directory_Is_A_File, fsEntryInfo.LongFullPath));
            }


            var dirs = new Stack <string>(1000);
            dirs.Push(fsEntryInfo.LongFullPath);

            while (dirs.Count > 0)
            {
                foreach (var fsei in EnumerateFileSystemEntryInfosCore <FileSystemEntryInfo>(true, transaction, dirs.Pop(), Path.WildcardStarMatchAll, null, DirectoryEnumerationOptions.ContinueOnException, null, PathFormat.LongFullPath))
                {
                    // Ensure the directory is empty.
                    if (IsEmptyCore(transaction, fsei.LongFullPath, pathFormat))
                    {
                        DeleteDirectoryCore(transaction, fsei, null, false, ignoreReadOnly, true, PathFormat.LongFullPath);
                    }

                    else if (recursive)
                    {
                        dirs.Push(fsei.LongFullPath);
                    }
                }
            }
        }
예제 #7
0
        internal static T GetAttributesExCore <T>(KernelTransaction transaction, string path, PathFormat pathFormat)
        {
            if (pathFormat == PathFormat.RelativePath)
            {
                Path.CheckSupportedPathFormat(path, true, true);
            }

            string pathLp = Path.GetExtendedLengthPathCore(transaction, path, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.CheckInvalidPathChars);

            var data            = new NativeMethods.WIN32_FILE_ATTRIBUTE_DATA();
            int dataInitialised = FillAttributeInfoCore(transaction, pathLp, ref data, false, true);

            if (dataInitialised != Win32Errors.ERROR_SUCCESS)
            {
                NativeError.ThrowException(dataInitialised, pathLp);
            }

            return((T)(typeof(T) == typeof(FileAttributes) ? (object)data.dwFileAttributes : data));
        }
예제 #8
0
        internal static bool ExistsJunctionCore(KernelTransaction transaction, FileSystemEntryInfo fsEntryInfo, string junctionPath, PathFormat pathFormat)
        {
            if (null == fsEntryInfo)
            {
                if (pathFormat != PathFormat.LongFullPath)
                {
                    Path.CheckSupportedPathFormat(junctionPath, true, true);

                    junctionPath = Path.GetExtendedLengthPathCore(transaction, junctionPath, pathFormat, GetFullPathOptions.CheckInvalidPathChars | GetFullPathOptions.RemoveTrailingDirectorySeparator);

                    pathFormat = PathFormat.LongFullPath;
                }


                fsEntryInfo = File.GetFileSystemEntryInfoCore(transaction, true, junctionPath, true, pathFormat);
            }


            return(null != fsEntryInfo && fsEntryInfo.IsMountPoint);
        }
예제 #9
0
        /// <summary>Initializes the specified file name.</summary>
        /// <exception cref="ArgumentException"/>
        /// <exception cref="NotSupportedException"/>
        /// <param name="transaction">The transaction.</param>
        /// <param name="isFolder">Specifies that <paramref name="path"/> is a file or directory.</param>
        /// <param name="path">The full path and name of the file.</param>
        /// <param name="pathFormat">Indicates the format of the path parameter(s).</param>
        internal void InitializeCore(KernelTransaction transaction, bool isFolder, string path, PathFormat pathFormat)
        {
            if (pathFormat == PathFormat.RelativePath)
            {
                Path.CheckSupportedPathFormat(path, true, true);
            }

            LongFullName = Path.GetExtendedLengthPathCore(transaction, path, pathFormat, GetFullPathOptions.TrimEnd | (isFolder ? GetFullPathOptions.RemoveTrailingDirectorySeparator : 0) | GetFullPathOptions.ContinueOnNonExist);

            // (Not on MSDN): .NET 4+ Trailing spaces are removed from the end of the path parameter before creating the FileSystemInfo instance.

            FullPath = Path.GetRegularPathCore(LongFullName, GetFullPathOptions.None, false);

            IsDirectory = isFolder;
            Transaction = transaction;

            OriginalPath = FullPath.Length == 2 && FullPath[1] == Path.VolumeSeparatorChar ? Path.CurrentDirectoryPrefix : path;

            DisplayPath = OriginalPath.Length != 2 || OriginalPath[1] != Path.VolumeSeparatorChar
            ? Path.GetRegularPathCore(OriginalPath, GetFullPathOptions.None, false)
            : Path.CurrentDirectoryPrefix;
        }
예제 #10
0
        internal static void DeleteJunctionCore(KernelTransaction transaction, FileSystemEntryInfo fsEntryInfo, string junctionPath, bool removeDirectory, PathFormat pathFormat)
        {
            if (null == fsEntryInfo)
            {
                if (pathFormat != PathFormat.LongFullPath)
                {
                    Path.CheckSupportedPathFormat(junctionPath, true, true);

                    junctionPath = Path.GetExtendedLengthPathCore(transaction, junctionPath, pathFormat, GetFullPathOptions.CheckInvalidPathChars | GetFullPathOptions.RemoveTrailingDirectorySeparator);

                    pathFormat = PathFormat.LongFullPath;
                }


                fsEntryInfo = File.GetFileSystemEntryInfoCore(transaction, true, junctionPath, false, pathFormat);

                if (!fsEntryInfo.IsMountPoint)
                {
                    throw new NotAReparsePointException(string.Format(CultureInfo.InvariantCulture, Resources.Directory_Is_Not_A_MountPoint, fsEntryInfo.LongFullPath), (int)Win32Errors.ERROR_NOT_A_REPARSE_POINT);
                }
            }


            pathFormat = PathFormat.LongFullPath;


            // Remove the directory junction.
            using (var safeHandle = OpenDirectoryJunction(transaction, fsEntryInfo.LongFullPath, pathFormat))
                Device.DeleteDirectoryJunction(safeHandle);


            // Optionally the folder itself, which should and must be empty.
            if (removeDirectory)
            {
                DeleteDirectoryCore(transaction, fsEntryInfo, null, false, false, true, pathFormat);
            }
        }
예제 #11
0
        internal static void DeleteDirectoryCore(KernelTransaction transaction, FileSystemEntryInfo fsEntryInfo, string path, bool recursive, bool ignoreReadOnly, bool continueOnNotFound, PathFormat pathFormat)
        {
            if (null == fsEntryInfo)
            {
                // MSDN: .NET 3.5+: DirectoryNotFoundException:
                // Path does not exist or could not be found.
                // Path refers to a file instead of a directory.
                // The specified path is invalid (for example, it is on an unmapped drive).

                if (pathFormat == PathFormat.RelativePath)
                {
                    Path.CheckSupportedPathFormat(path, true, true);
                }

                fsEntryInfo = File.GetFileSystemEntryInfoCore(transaction, true, Path.GetExtendedLengthPathCore(transaction, path, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator), continueOnNotFound, pathFormat);

                if (null == fsEntryInfo)
                {
                    return;
                }
            }

            pathFormat = PathFormat.LongFullPath;


            // Do not follow mount points nor symbolic links, but do delete the reparse point itself.
            // If directory is reparse point, disable recursion.

            if (recursive && !fsEntryInfo.IsReparsePoint)
            {
                var dirs = new Stack <string>(1000);

                foreach (var fsei in EnumerateFileSystemEntryInfosCore <FileSystemEntryInfo>(null, transaction, fsEntryInfo.LongFullPath, Path.WildcardStarMatchAll, SearchOption.AllDirectories, null, null, pathFormat))
                {
                    if (fsei.IsDirectory)
                    {
                        // Check to see if this is a mount point, and unmount it.
                        // Now it is safe to delete the actual directory.
                        if (fsei.IsMountPoint)
                        {
                            DeleteJunctionCore(transaction, fsei, null, false, pathFormat);
                        }
                        //Volume.DeleteVolumeMountPointCore(transaction, fsei.LongFullPath, false, true, pathFormat);

                        dirs.Push(fsei.LongFullPath);
                    }

                    else
                    {
                        File.DeleteFileCore(transaction, fsei.LongFullPath, ignoreReadOnly, pathFormat);
                    }
                }


                while (dirs.Count > 0)
                {
                    DeleteDirectoryCore(transaction, dirs.Pop(), ignoreReadOnly, continueOnNotFound);
                }
            }


            // Check to see if this is a mount point, and unmount it.
            // Now it is safe to delete the actual directory.
            if (fsEntryInfo.IsMountPoint)
            {
                DeleteJunctionCore(transaction, fsEntryInfo, null, false, pathFormat);
            }
            //Volume.DeleteVolumeMountPointCore(transaction, fsEntryInfo.LongFullPath, false, true, pathFormat);

            DeleteDirectoryCore(transaction, fsEntryInfo.LongFullPath, ignoreReadOnly, continueOnNotFound);
        }
예제 #12
0
        internal static void DeleteDirectoryCore(FileSystemEntryInfo fileSystemEntryInfo, KernelTransaction transaction, string path, bool recursive, bool ignoreReadOnly, bool requireEmpty, bool continueOnNotExist, PathFormat pathFormat)
        {
            #region Setup

            if (pathFormat == PathFormat.RelativePath)
            {
                Path.CheckSupportedPathFormat(path, true, true);
            }

            if (fileSystemEntryInfo == null)
            {
                // MSDN: .NET 3.5+: DirectoryNotFoundException:
                // Path does not exist or could not be found.
                // Path refers to a file instead of a directory.
                // The specified path is invalid (for example, it is on an unmapped drive).

                fileSystemEntryInfo = File.GetFileSystemEntryInfoCore(true, transaction,
                                                                      Path.GetExtendedLengthPathCore(transaction, path, pathFormat, GetFullPathOptions.TrimEnd | GetFullPathOptions.RemoveTrailingDirectorySeparator),
                                                                      continueOnNotExist, pathFormat);
            }

            if (fileSystemEntryInfo == null)
            {
                return;
            }

            string pathLp = fileSystemEntryInfo.LongFullPath;

            #endregion // Setup

            // Do not follow mount points nor symbolic links, but do delete the reparse point itself.

            // If directory is reparse point, disable recursion.
            if (recursive && fileSystemEntryInfo.IsReparsePoint)
            {
                recursive = false;
            }


            // Check to see if this is a mount point, and unmount it.
            if (fileSystemEntryInfo.IsMountPoint)
            {
                int lastError = Volume.DeleteVolumeMountPointCore(pathLp, true);

                if (lastError != Win32Errors.ERROR_SUCCESS && lastError != Win32Errors.ERROR_PATH_NOT_FOUND)
                {
                    NativeError.ThrowException(lastError, pathLp);
                }

                // Now it is safe to delete the actual directory.
            }


            if (recursive)
            {
                // Enumerate all file system objects.
                foreach (var fsei in EnumerateFileSystemEntryInfosCore <FileSystemEntryInfo>(transaction, pathLp, Path.WildcardStarMatchAll, DirectoryEnumerationOptions.FilesAndFolders, PathFormat.LongFullPath))
                {
                    if (fsei.IsDirectory)
                    {
                        DeleteDirectoryCore(fsei, transaction, null, true, ignoreReadOnly, requireEmpty, true, PathFormat.LongFullPath);
                    }
                    else
                    {
                        File.DeleteFileCore(transaction, fsei.LongFullPath, ignoreReadOnly, PathFormat.LongFullPath);
                    }
                }
            }

            #region Remove

startRemoveDirectory:

            if (!(transaction == null || !NativeMethods.IsAtLeastWindowsVista

                  // RemoveDirectory() / RemoveDirectoryTransacted()
                  // 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.
                  // 2014-09-09: MSDN confirms LongPath usage.

                  // RemoveDirectory on a symbolic link will remove the link itself.

            ? NativeMethods.RemoveDirectory(pathLp)
            : NativeMethods.RemoveDirectoryTransacted(pathLp, transaction.SafeHandle)))
            {
                int lastError = Marshal.GetLastWin32Error();
                switch ((uint)lastError)
                {
                case Win32Errors.ERROR_DIR_NOT_EMPTY:
                    if (requireEmpty)
                    {
                        // MSDN: .NET 3.5+: IOException: The directory specified by path is not an empty directory.
                        throw new DirectoryNotEmptyException(pathLp);
                    }

                    goto startRemoveDirectory;


                case Win32Errors.ERROR_DIRECTORY:
                    // MSDN: .NET 3.5+: DirectoryNotFoundException: Path refers to a file instead of a directory.
                    if (File.ExistsCore(false, transaction, pathLp, PathFormat.LongFullPath))
                    {
                        throw new DirectoryNotFoundException(string.Format(CultureInfo.CurrentCulture, "({0}) {1}", Win32Errors.ERROR_INVALID_PARAMETER, string.Format(CultureInfo.CurrentCulture, Resources.Target_Directory_Is_A_File, pathLp)));
                    }
                    break;


                case Win32Errors.ERROR_PATH_NOT_FOUND:
                    if (continueOnNotExist)
                    {
                        return;
                    }
                    break;

                case Win32Errors.ERROR_SHARING_VIOLATION:
                    // MSDN: .NET 3.5+: IOException: The directory is being used by another process or there is an open handle on the directory.
                    NativeError.ThrowException(lastError, pathLp);
                    break;

                case Win32Errors.ERROR_ACCESS_DENIED:
                    var data            = new NativeMethods.WIN32_FILE_ATTRIBUTE_DATA();
                    int dataInitialised = File.FillAttributeInfoCore(transaction, pathLp, ref data, false, true);

                    if (data.dwFileAttributes != (FileAttributes)(-1))
                    {
                        if ((data.dwFileAttributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
                        {
                            // MSDN: .NET 3.5+: IOException: The directory specified by path is read-only.

                            if (ignoreReadOnly)
                            {
                                // Reset directory attributes.
                                File.SetAttributesCore(true, transaction, pathLp, FileAttributes.Normal, true, PathFormat.LongFullPath);
                                goto startRemoveDirectory;
                            }

                            // MSDN: .NET 3.5+: IOException: The directory is read-only.
                            throw new DirectoryReadOnlyException(pathLp);
                        }
                    }

                    if (dataInitialised == Win32Errors.ERROR_SUCCESS)
                    {
                        // MSDN: .NET 3.5+: UnauthorizedAccessException: The caller does not have the required permission.
                        NativeError.ThrowException(lastError, pathLp);
                    }

                    break;
                }

                // MSDN: .NET 3.5+: IOException:
                // A file with the same name and location specified by path exists.
                // The directory specified by path is read-only, or recursive is false and path is not an empty directory.
                // The directory is the application's current working directory.
                // The directory contains a read-only file.
                // The directory is being used by another process.

                NativeError.ThrowException(lastError, pathLp);
            }

            #endregion // Remove
        }
예제 #13
0
        internal static void DeleteFileCore(KernelTransaction transaction, string path, bool ignoreReadOnly, PathFormat pathFormat)
        {
            #region Setup

            if (pathFormat == PathFormat.RelativePath)
            {
                Path.CheckSupportedPathFormat(path, true, true);
            }

            string pathLp = Path.GetExtendedLengthPathCore(transaction, path, pathFormat, GetFullPathOptions.TrimEnd | GetFullPathOptions.RemoveTrailingDirectorySeparator);

            // If the path points to a symbolic link, the symbolic link is deleted, not the target.

            #endregion // Setup

startDeleteFile:

            if (!(transaction == null || !NativeMethods.IsAtLeastWindowsVista

                  // DeleteFile() / DeleteFileTransacted()
                  // 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-01-13: MSDN confirms LongPath usage.

            ? NativeMethods.DeleteFile(pathLp)
            : NativeMethods.DeleteFileTransacted(pathLp, transaction.SafeHandle)))
            {
                int lastError = Marshal.GetLastWin32Error();
                switch ((uint)lastError)
                {
                case Win32Errors.ERROR_FILE_NOT_FOUND:
                    // MSDN: .NET 3.5+: If the file to be deleted does not exist, no exception is thrown.
                    return;

                case Win32Errors.ERROR_PATH_NOT_FOUND:
                    // MSDN: .NET 3.5+: DirectoryNotFoundException: The specified path is invalid (for example, it is on an unmapped drive).
                    NativeError.ThrowException(lastError, pathLp);
                    return;

                case Win32Errors.ERROR_SHARING_VIOLATION:
                    // MSDN: .NET 3.5+: IOException: The specified file is in use or there is an open handle on the file.
                    NativeError.ThrowException(lastError, pathLp);
                    break;

                case Win32Errors.ERROR_ACCESS_DENIED:
                    var data            = new NativeMethods.WIN32_FILE_ATTRIBUTE_DATA();
                    int dataInitialised = FillAttributeInfoCore(transaction, pathLp, ref data, false, true);

                    if (data.dwFileAttributes != (FileAttributes)(-1))
                    {
                        if ((data.dwFileAttributes & FileAttributes.Directory) != 0)
                        {
                            // MSDN: .NET 3.5+: UnauthorizedAccessException: Path is a directory.
                            throw new UnauthorizedAccessException(string.Format(CultureInfo.CurrentCulture, "({0}) {1}",
                                                                                Win32Errors.ERROR_INVALID_PARAMETER, string.Format(CultureInfo.CurrentCulture, Resources.Target_File_Is_A_Directory, pathLp)));
                        }


                        if ((data.dwFileAttributes & FileAttributes.ReadOnly) != 0)
                        {
                            if (ignoreReadOnly)
                            {
                                // Reset file attributes.
                                SetAttributesCore(false, transaction, pathLp, FileAttributes.Normal, true, PathFormat.LongFullPath);
                                goto startDeleteFile;
                            }

                            // MSDN: .NET 3.5+: UnauthorizedAccessException: Path specified a read-only file.
                            throw new FileReadOnlyException(pathLp);
                        }
                    }

                    if (dataInitialised == Win32Errors.ERROR_SUCCESS)
                    {
                        // MSDN: .NET 3.5+: UnauthorizedAccessException: The caller does not have the required permission.
                        NativeError.ThrowException(lastError, pathLp);
                    }

                    break;
                }

                // MSDN: .NET 3.5+: IOException:
                // The specified file is in use.
                // There is an open handle on the file, and the operating system is Windows XP or earlier.

                NativeError.ThrowException(lastError, pathLp);
            }
        }
        internal static string CreateJunctionCore(KernelTransaction transaction, string junctionPath, string directoryPath, bool overwrite, bool copyTargetTimestamps, PathFormat pathFormat)
        {
            if (pathFormat != PathFormat.LongFullPath)
            {
                Path.CheckSupportedPathFormat(directoryPath, true, true);
                Path.CheckSupportedPathFormat(junctionPath, true, true);

                directoryPath = Path.GetExtendedLengthPathCore(transaction, directoryPath, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator);
                junctionPath  = Path.GetExtendedLengthPathCore(transaction, junctionPath, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator);

                pathFormat = PathFormat.LongFullPath;
            }


            // Directory Junction logic.


            // Check if drive letter is a mapped network drive.
            if (new DriveInfo(directoryPath).IsUnc)
            {
                throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, Resources.Network_Path_Not_Allowed, directoryPath), "directoryPath");
            }

            if (new DriveInfo(junctionPath).IsUnc)
            {
                throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, Resources.Network_Path_Not_Allowed, junctionPath), "junctionPath");
            }


            // Check for existing file.
            File.ThrowIOExceptionIfFsoExist(transaction, false, directoryPath, pathFormat);
            File.ThrowIOExceptionIfFsoExist(transaction, false, junctionPath, pathFormat);


            // Check for existing directory junction folder.
            if (File.ExistsCore(transaction, true, junctionPath, pathFormat))
            {
                if (overwrite)
                {
                    DeleteDirectoryCore(transaction, null, junctionPath, true, true, true, pathFormat);
                    CreateDirectoryCore(transaction, junctionPath, null, null, false, pathFormat);
                }

                else
                {
                    // Ensure the folder is empty.
                    if (!IsEmptyCore(transaction, junctionPath, pathFormat))
                    {
                        throw new DirectoryNotEmptyException(junctionPath, true);
                    }

                    throw new AlreadyExistsException(junctionPath, true);
                }
            }


            // Create the folder and convert it to a directory junction.
            CreateDirectoryCore(transaction, junctionPath, null, null, false, pathFormat);

            using (var safeHandle = OpenDirectoryJunction(transaction, junctionPath, pathFormat))
                Device.CreateDirectoryJunction(safeHandle, directoryPath);


            // Copy the target date and time stamps to the directory junction.
            if (copyTargetTimestamps)
            {
                File.CopyTimestampsCore(transaction, directoryPath, junctionPath, true, pathFormat);
            }


            return(junctionPath);
        }
예제 #15
0
        internal static void SetAccessControlCore(string path, SafeFileHandle handle, ObjectSecurity objectSecurity, AccessControlSections includeSections, PathFormat pathFormat)
        {
            if (pathFormat == PathFormat.RelativePath)
            {
                Path.CheckSupportedPathFormat(path, true, true);
            }

            if (objectSecurity == null)
            {
                throw new ArgumentNullException("objectSecurity");
            }


            var managedDescriptor = objectSecurity.GetSecurityDescriptorBinaryForm();

            using (var safeBuffer = new SafeGlobalMemoryBufferHandle(managedDescriptor.Length))
            {
                var pathLp = Path.GetExtendedLengthPathCore(null, path, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.CheckInvalidPathChars);

                safeBuffer.CopyFrom(managedDescriptor, 0, managedDescriptor.Length);

                SECURITY_DESCRIPTOR_CONTROL control;
                uint revision;


                var success = Security.NativeMethods.GetSecurityDescriptorControl(safeBuffer, out control, out revision);

                var lastError = Marshal.GetLastWin32Error();
                if (!success)
                {
                    NativeError.ThrowException(lastError, pathLp);
                }


                PrivilegeEnabler privilegeEnabler = null;

                try
                {
                    var securityInfo = SECURITY_INFORMATION.None;
                    var pDacl        = IntPtr.Zero;

                    if ((includeSections & AccessControlSections.Access) != 0)
                    {
                        bool daclDefaulted, daclPresent;


                        success = Security.NativeMethods.GetSecurityDescriptorDacl(safeBuffer, out daclPresent, out pDacl, out daclDefaulted);

                        lastError = Marshal.GetLastWin32Error();
                        if (!success)
                        {
                            NativeError.ThrowException(lastError, pathLp);
                        }


                        if (daclPresent)
                        {
                            securityInfo |= SECURITY_INFORMATION.DACL_SECURITY_INFORMATION;
                            securityInfo |= (control & SECURITY_DESCRIPTOR_CONTROL.SE_DACL_PROTECTED) != 0 ? SECURITY_INFORMATION.PROTECTED_DACL_SECURITY_INFORMATION : SECURITY_INFORMATION.UNPROTECTED_DACL_SECURITY_INFORMATION;
                        }
                    }


                    var pSacl = IntPtr.Zero;

                    if ((includeSections & AccessControlSections.Audit) != 0)
                    {
                        bool saclDefaulted, saclPresent;


                        success = Security.NativeMethods.GetSecurityDescriptorSacl(safeBuffer, out saclPresent, out pSacl, out saclDefaulted);

                        lastError = Marshal.GetLastWin32Error();
                        if (!success)
                        {
                            NativeError.ThrowException(lastError, pathLp);
                        }


                        if (saclPresent)
                        {
                            securityInfo |= SECURITY_INFORMATION.SACL_SECURITY_INFORMATION;
                            securityInfo |= (control & SECURITY_DESCRIPTOR_CONTROL.SE_SACL_PROTECTED) != 0 ? SECURITY_INFORMATION.PROTECTED_SACL_SECURITY_INFORMATION : SECURITY_INFORMATION.UNPROTECTED_SACL_SECURITY_INFORMATION;

                            privilegeEnabler = new PrivilegeEnabler(Privilege.Security);
                        }
                    }


                    var pOwner = IntPtr.Zero;

                    if ((includeSections & AccessControlSections.Owner) != 0)
                    {
                        bool ownerDefaulted;


                        success = Security.NativeMethods.GetSecurityDescriptorOwner(safeBuffer, out pOwner, out ownerDefaulted);

                        lastError = Marshal.GetLastWin32Error();
                        if (!success)
                        {
                            NativeError.ThrowException(lastError, pathLp);
                        }


                        if (pOwner != IntPtr.Zero)
                        {
                            securityInfo |= SECURITY_INFORMATION.OWNER_SECURITY_INFORMATION;
                        }
                    }


                    var pGroup = IntPtr.Zero;

                    if ((includeSections & AccessControlSections.Group) != 0)
                    {
                        bool groupDefaulted;


                        success = Security.NativeMethods.GetSecurityDescriptorGroup(safeBuffer, out pGroup, out groupDefaulted);

                        lastError = Marshal.GetLastWin32Error();
                        if (!success)
                        {
                            NativeError.ThrowException(lastError, pathLp);
                        }


                        if (pGroup != IntPtr.Zero)
                        {
                            securityInfo |= SECURITY_INFORMATION.GROUP_SECURITY_INFORMATION;
                        }
                    }



                    if (!Utils.IsNullOrWhiteSpace(pathLp))
                    {
                        // SetNamedSecurityInfo()
                        // 2013-01-13: MSDN does not confirm LongPath usage but a Unicode version of this function exists.

                        lastError = (int)Security.NativeMethods.SetNamedSecurityInfo(pathLp, SE_OBJECT_TYPE.SE_FILE_OBJECT, securityInfo, pOwner, pGroup, pDacl, pSacl);

                        if (lastError != Win32Errors.ERROR_SUCCESS)
                        {
                            NativeError.ThrowException(lastError, pathLp);
                        }
                    }

                    else
                    {
                        if (NativeMethods.IsValidHandle(handle))
                        {
                            lastError = (int)Security.NativeMethods.SetSecurityInfo(handle, SE_OBJECT_TYPE.SE_FILE_OBJECT, securityInfo, pOwner, pGroup, pDacl, pSacl);

                            if (lastError != Win32Errors.ERROR_SUCCESS)
                            {
                                NativeError.ThrowException(lastError);
                            }
                        }
                    }
                }
                finally
                {
                    if (null != privilegeEnabler)
                    {
                        privilegeEnabler.Dispose();
                    }
                }
            }
        }
예제 #16
0
        internal static SafeFileHandle CreateFileCore(KernelTransaction transaction, string path, ExtendedFileAttributes attributes, FileSecurity fileSecurity, FileMode fileMode, FileSystemRights fileSystemRights, FileShare fileShare, bool checkPath, PathFormat pathFormat)
        {
            if (checkPath && pathFormat == PathFormat.RelativePath)
            {
                Path.CheckSupportedPathFormat(path, true, true);
            }

            // When isFile == null, we're working with a device.
            // When opening a VOLUME or removable media drive (for example, a floppy disk drive or flash memory thumb drive),
            // the path string should be the following form: "\\.\X:"
            // Do not use a trailing backslash (\), which indicates the root.

            var pathLp = Path.GetExtendedLengthPathCore(transaction, path, pathFormat, GetFullPathOptions.TrimEnd | GetFullPathOptions.RemoveTrailingDirectorySeparator);

            PrivilegeEnabler privilegeEnabler = null;


            var isAppend = fileMode == FileMode.Append;


            // CreateFileXxx() does not support FileMode.Append mode.
            if (isAppend)
            {
                fileMode          = FileMode.OpenOrCreate;
                fileSystemRights &= FileSystemRights.AppendData; // Add right.
            }


            if (fileSecurity != null)
            {
                fileSystemRights |= (FileSystemRights)0x1000000; // Set right.
            }
            // AccessSystemSecurity = 0x1000000    AccessSystemAcl access type.
            // MaximumAllowed       = 0x2000000    MaximumAllowed  access type.

            if ((fileSystemRights & (FileSystemRights)0x1000000) != 0 ||
                (fileSystemRights & (FileSystemRights)0x2000000) != 0)
            {
                privilegeEnabler = new PrivilegeEnabler(Privilege.Security);
            }


            using (privilegeEnabler)
                using (var securityAttributes = new Security.NativeMethods.SecurityAttributes(fileSecurity))
                {
                    var handle = transaction == null || !NativeMethods.IsAtLeastWindowsVista

                                 // CreateFile() / CreateFileTransacted()
                                 // 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-01-13: MSDN confirms LongPath usage.

               ? NativeMethods.CreateFile(pathLp, fileSystemRights, fileShare, securityAttributes, fileMode, attributes, IntPtr.Zero)
               : NativeMethods.CreateFileTransacted(pathLp, fileSystemRights, fileShare, securityAttributes, fileMode, attributes, IntPtr.Zero, transaction.SafeHandle, IntPtr.Zero, IntPtr.Zero);

                    var lastError = Marshal.GetLastWin32Error();

                    if (handle.IsInvalid)
                    {
                        handle.Close();
                        NativeError.ThrowException(lastError, pathLp);
                    }


                    if (isAppend)
                    {
                        var stream = new FileStream(handle, FileAccess.Write, NativeMethods.DefaultFileBufferSize, (attributes & ExtendedFileAttributes.Overlapped) != 0);
                        stream.Seek(0, SeekOrigin.End);
                    }

                    return(handle);
                }
        }
예제 #17
0
        internal static void SetAccessControlCore(string path, SafeFileHandle handle, ObjectSecurity objectSecurity, AccessControlSections includeSections, PathFormat pathFormat)
        {
            if (pathFormat == PathFormat.RelativePath)
            {
                Path.CheckSupportedPathFormat(path, true, true);
            }

            if (objectSecurity == null)
            {
                throw new ArgumentNullException("objectSecurity");
            }


            byte[] managedDescriptor = objectSecurity.GetSecurityDescriptorBinaryForm();

            using (var safeBuffer = new SafeGlobalMemoryBufferHandle(managedDescriptor.Length))
            {
                string pathLp = Path.GetExtendedLengthPathCore(null, path, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.CheckInvalidPathChars);

                safeBuffer.CopyFrom(managedDescriptor, 0, managedDescriptor.Length);

                SecurityDescriptorControl control;
                uint revision;

                if (!Security.NativeMethods.GetSecurityDescriptorControl(safeBuffer, out control, out revision))
                {
                    NativeError.ThrowException(Marshal.GetLastWin32Error(), pathLp);
                }


                PrivilegeEnabler privilegeEnabler = null;

                try
                {
                    var    securityInfo = SecurityInformation.None;
                    IntPtr pDacl        = IntPtr.Zero;

                    if ((includeSections & AccessControlSections.Access) != 0)
                    {
                        bool daclDefaulted, daclPresent;

                        if (!Security.NativeMethods.GetSecurityDescriptorDacl(safeBuffer, out daclPresent, out pDacl, out daclDefaulted))
                        {
                            NativeError.ThrowException(Marshal.GetLastWin32Error(), pathLp);
                        }

                        if (daclPresent)
                        {
                            securityInfo |= SecurityInformation.Dacl;
                            securityInfo |= (control & SecurityDescriptorControl.DaclProtected) != 0
                        ? SecurityInformation.ProtectedDacl
                        : SecurityInformation.UnprotectedDacl;
                        }
                    }


                    IntPtr pSacl = IntPtr.Zero;

                    if ((includeSections & AccessControlSections.Audit) != 0)
                    {
                        bool saclDefaulted, saclPresent;

                        if (!Security.NativeMethods.GetSecurityDescriptorSacl(safeBuffer, out saclPresent, out pSacl, out saclDefaulted))
                        {
                            NativeError.ThrowException(Marshal.GetLastWin32Error(), pathLp);
                        }

                        if (saclPresent)
                        {
                            securityInfo |= SecurityInformation.Sacl;
                            securityInfo |= (control & SecurityDescriptorControl.SaclProtected) != 0
                        ? SecurityInformation.ProtectedSacl
                        : SecurityInformation.UnprotectedSacl;

                            privilegeEnabler = new PrivilegeEnabler(Privilege.Security);
                        }
                    }


                    IntPtr pOwner = IntPtr.Zero;

                    if ((includeSections & AccessControlSections.Owner) != 0)
                    {
                        bool ownerDefaulted;

                        if (!Security.NativeMethods.GetSecurityDescriptorOwner(safeBuffer, out pOwner, out ownerDefaulted))
                        {
                            NativeError.ThrowException(Marshal.GetLastWin32Error(), pathLp);
                        }

                        if (pOwner != IntPtr.Zero)
                        {
                            securityInfo |= SecurityInformation.Owner;
                        }
                    }


                    IntPtr pGroup = IntPtr.Zero;

                    if ((includeSections & AccessControlSections.Group) != 0)
                    {
                        bool groupDefaulted;

                        if (!Security.NativeMethods.GetSecurityDescriptorGroup(safeBuffer, out pGroup, out groupDefaulted))
                        {
                            NativeError.ThrowException(Marshal.GetLastWin32Error(), pathLp);
                        }

                        if (pGroup != IntPtr.Zero)
                        {
                            securityInfo |= SecurityInformation.Group;
                        }
                    }


                    uint lastError;

                    if (!Utils.IsNullOrWhiteSpace(pathLp))
                    {
                        // SetNamedSecurityInfo()
                        // 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-01-13: MSDN does not confirm LongPath usage but a Unicode version of this function exists.

                        lastError = Security.NativeMethods.SetNamedSecurityInfo(pathLp, ObjectType.FileObject, securityInfo, pOwner, pGroup, pDacl, pSacl);

                        if (lastError != Win32Errors.ERROR_SUCCESS)
                        {
                            NativeError.ThrowException(lastError, pathLp);
                        }
                    }
                    else
                    {
                        if (NativeMethods.IsValidHandle(handle))
                        {
                            lastError = Security.NativeMethods.SetSecurityInfo(handle, ObjectType.FileObject, securityInfo, pOwner, pGroup, pDacl, pSacl);

                            if (lastError != Win32Errors.ERROR_SUCCESS)
                            {
                                NativeError.ThrowException((int)lastError);
                            }
                        }
                    }
                }
                finally
                {
                    if (privilegeEnabler != null)
                    {
                        privilegeEnabler.Dispose();
                    }
                }
            }
        }