Esempio n. 1
0
        private NativeMethods.ReparseDataBuffer GetReparsePointInfo()
        {
            const uint        fileOpenReparsePoint    = 0x00200000;
            const uint        fileFlagBackupSemantics = 0x02000000;
            const FileOptions flags = (FileOptions)(fileOpenReparsePoint | fileFlagBackupSemantics);

            using (var handle = NativeMethods.CreateFile(LinkName, NativeMethods.FileAccessEx.None, FileShare.Read, IntPtr.Zero, FileMode.Open, flags, IntPtr.Zero))
            {
                if (handle.IsInvalid)
                {
                    throw Win32Utils.GetExceptionForLastError();
                }

                var reparseDataBuffer = new NativeMethods.ReparseDataBuffer();

                const int fsctlGetReparsePoint = 0x000900A8;
                var       bytesReturned        = 0;
                var       success = NativeMethods.DeviceIoControl(handle, fsctlGetReparsePoint,
                                                                  IntPtr.Zero, 0,
                                                                  reparseDataBuffer, Marshal.SizeOf(typeof(NativeMethods.ReparseDataBuffer)),
                                                                  ref bytesReturned, IntPtr.Zero);

                if (!success)
                {
                    const uint pathNotAReparsePointError = 0x80071126;
                    if ((uint)Marshal.GetHRForLastWin32Error() == pathNotAReparsePointError)
                    {
                        return(null);
                    }
                    throw Win32Utils.GetExceptionForLastError();
                }
                return(reparseDataBuffer);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Creates a junction point from the specified directory to the specified target directory.
        /// </summary>
        /// <remarks>
        /// Only works on NTFS.
        /// </remarks>
        /// <param name="targetDir">The target directory to create</param>
        /// <param name="sourceDir">The source directory to alias</param>
        /// <param name="overwrite">If true overwrites an existing reparse point or empty directory</param>
        /// <exception cref="IOException">Thrown when the junction point could not be created or when
        /// an existing directory was found and <paramref name="overwrite" /> if false</exception>
        public static void Create(string sourceDir, string targetDir, bool overwrite)
        {
            sourceDir = Path.GetFullPath(sourceDir);

            if (!Directory.Exists(sourceDir))
            {
                throw new IOException("Source path does not exist or is not a directory.");
            }

            if (Directory.Exists(targetDir))
            {
                if (!overwrite)
                {
                    throw new IOException("Directory '{targetDir}' already exists.");
                }
            }
            else
            {
                Directory.CreateDirectory(targetDir);
            }

            using (SafeFileHandle handle = OpenReparsePoint(targetDir, NativeMethods.FileAccess.GenericWrite))
            {
                byte[] sourceDirBytes = Encoding.Unicode.GetBytes(NativeMethods.NonInterpretedPathPrefix + Path.GetFullPath(sourceDir));

                NativeMethods.ReparseDataBuffer reparseDataBuffer = new NativeMethods.ReparseDataBuffer();

                reparseDataBuffer.ReparseTag           = NativeMethods.IoReparseTagMountPoint;
                reparseDataBuffer.ReparseDataLength    = (ushort)(sourceDirBytes.Length + 12);
                reparseDataBuffer.SubstituteNameOffset = 0;
                reparseDataBuffer.SubstituteNameLength = (ushort)sourceDirBytes.Length;
                reparseDataBuffer.PrintNameOffset      = (ushort)(sourceDirBytes.Length + 2);
                reparseDataBuffer.PrintNameLength      = 0;
                reparseDataBuffer.PathBuffer           = new byte[0x3ff0];
                Array.Copy(sourceDirBytes, reparseDataBuffer.PathBuffer, sourceDirBytes.Length);

                int    inBufferSize = Marshal.SizeOf(reparseDataBuffer);
                IntPtr inBuffer     = Marshal.AllocHGlobal(inBufferSize);

                try
                {
                    Marshal.StructureToPtr(reparseDataBuffer, inBuffer, false);

                    int  bytesReturned;
                    bool result = NativeMethods.DeviceIoControl(handle.DangerousGetHandle(), NativeMethods.FsctlSetReparsePoint,
                                                                inBuffer, sourceDirBytes.Length + 20, IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero);

                    if (!result)
                    {
                        ThrowLastWin32Error("Unable to create junction point '{sourceDir}' -> '{targetDir}'.");
                    }
                }
                finally
                {
                    Marshal.FreeHGlobal(inBuffer);
                }
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Deletes a junction point at the specified source directory along with the directory itself.
        /// Does nothing if the junction point does not exist.
        /// </summary>
        /// <remarks>
        /// Only works on NTFS.
        /// </remarks>
        /// <param name="junctionPoint">The junction point path</param>
        public static void Delete(string junctionPoint)
        {
            if (!Directory.Exists(junctionPoint))
            {
                if (File.Exists(junctionPoint))
                {
                    throw new IOException("Path is not a junction point.");
                }

                return;
            }

            using (SafeFileHandle handle = OpenReparsePoint(junctionPoint, NativeMethods.FileAccess.GenericWrite))
            {
                NativeMethods.ReparseDataBuffer reparseDataBuffer = new NativeMethods.ReparseDataBuffer();

                reparseDataBuffer.ReparseTag        = NativeMethods.IoReparseTagMountPoint;
                reparseDataBuffer.ReparseDataLength = 0;
                reparseDataBuffer.PathBuffer        = new byte[0x3ff0];

                int    inBufferSize = Marshal.SizeOf(reparseDataBuffer);
                IntPtr inBuffer     = Marshal.AllocHGlobal(inBufferSize);
                try
                {
                    Marshal.StructureToPtr(reparseDataBuffer, inBuffer, false);

                    int  bytesReturned;
                    bool result = NativeMethods.DeviceIoControl(handle.DangerousGetHandle(), NativeMethods.FsctlDeleteReparsePoint,
                                                                inBuffer, 8, IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero);

                    if (!result)
                    {
                        ThrowLastWin32Error("Unable to delete junction point.");
                    }
                }
                finally
                {
                    Marshal.FreeHGlobal(inBuffer);
                }

                try
                {
                    Directory.Delete(junctionPoint);
                }
                catch (IOException ex)
                {
                    throw new IOException("Unable to delete junction point.", ex);
                }
            }
        }
Esempio n. 4
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="handle"></param>
        /// <returns></returns>
        private static string InternalGetTarget(SafeFileHandle handle)
        {
            int    outBufferSize = Marshal.SizeOf(typeof(NativeMethods.ReparseDataBuffer));
            IntPtr outBuffer     = Marshal.AllocHGlobal(outBufferSize);

            try
            {
                int  bytesReturned;
                bool result = NativeMethods.DeviceIoControl(handle.DangerousGetHandle(), NativeMethods.FsctlGetReparsePoint,
                                                            IntPtr.Zero, 0, outBuffer, outBufferSize, out bytesReturned, IntPtr.Zero);

                if (!result)
                {
                    int error = Marshal.GetLastWin32Error();
                    if (error == NativeMethods.ErrorNotAReparsePoint)
                    {
                        return(null);
                    }

                    ThrowLastWin32Error("Unable to get information about junction point.");
                }

                NativeMethods.ReparseDataBuffer reparseDataBuffer = (NativeMethods.ReparseDataBuffer)
                                                                    Marshal.PtrToStructure(outBuffer, typeof(NativeMethods.ReparseDataBuffer));

                if (reparseDataBuffer.ReparseTag != NativeMethods.IoReparseTagMountPoint)
                {
                    return(null);
                }

                string targetDir = Encoding.Unicode.GetString(reparseDataBuffer.PathBuffer,
                                                              reparseDataBuffer.SubstituteNameOffset, reparseDataBuffer.SubstituteNameLength);

                if (targetDir.StartsWith(NativeMethods.NonInterpretedPathPrefix))
                {
                    targetDir = targetDir.Substring(NativeMethods.NonInterpretedPathPrefix.Length);
                }

                return(targetDir);
            }
            finally
            {
                Marshal.FreeHGlobal(outBuffer);
            }
        }