/// <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 (var handle = OpenReparsePoint(junctionPoint, EFileAccess.GenericWrite)) { var reparseDataBuffer = new REPARSE_DATA_BUFFER_MOUNT_POINT { ReparseTag = IO_REPARSE_TAG_MOUNT_POINT, ReparseDataLength = 0, PathBuffer = new byte[0x3ff0] }; var inBufferSize = Marshal.SizeOf(reparseDataBuffer); var inBuffer = Marshal.AllocHGlobal(inBufferSize); try { Marshal.StructureToPtr(reparseDataBuffer, inBuffer, false); int bytesReturned; var result = DeviceIoControl(handle.DangerousGetHandle(), FSCTL_DELETE_REPARSE_POINT, 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); * }*/ } }
/// <summary> /// Creates a junction point from the specified directory to the specified target directory. /// </summary> /// <remarks> /// Only works on NTFS. /// </remarks> /// <param name="junctionPoint">The junction point path</param> /// <param name="targetDir">The target directory</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 junctionPoint, string targetDir, bool overwrite) { targetDir = Path.GetFullPath(targetDir); if (!Directory.Exists(targetDir)) { Directory.CreateDirectory(targetDir); } //if (!Directory.Exists(targetDir)) // throw new IOException("Target path does not exist or is not a directory."); if (Directory.Exists(junctionPoint)) { if (!overwrite) { throw new IOException("Directory already exists and overwrite parameter is false."); } } else { Directory.CreateDirectory(junctionPoint); } using (var handle = OpenReparsePoint(junctionPoint, EFileAccess.GenericWrite)) { var targetDirBytes = Encoding.Unicode.GetBytes(NonInterpretedPathPrefix + Path.GetFullPath(targetDir)); var reparseDataBuffer = new Object(); //if(!isSymLink) if (true) { reparseDataBuffer = new REPARSE_DATA_BUFFER_MOUNT_POINT { ReparseTag = IO_REPARSE_TAG_MOUNT_POINT, ReparseDataLength = (ushort)(targetDirBytes.Length + 12), SubstituteNameOffset = 0, SubstituteNameLength = (ushort)targetDirBytes.Length, PrintNameOffset = (ushort)(targetDirBytes.Length + 2), PrintNameLength = 0, PathBuffer = new byte[0x3ff0] }; Array.Copy(targetDirBytes, ((REPARSE_DATA_BUFFER_MOUNT_POINT)reparseDataBuffer).PathBuffer, targetDirBytes.Length); } /* * else * { * reparseDataBuffer = * new REPARSE_DATA_BUFFER_SYM_LINK * { * ReparseTag = IO_REPARSE_TAG_SYMLINK, * ReparseDataLength = (ushort)(targetDirBytes.Length + 12), * SubstituteNameOffset = 0, * SubstituteNameLength = (ushort)targetDirBytes.Length, * PrintNameOffset = (ushort)(targetDirBytes.Length + 2), * PrintNameLength = 0, * Flags = 0, * PathBuffer = new byte[0x3ff0] * }; * Array.Copy(targetDirBytes, ((REPARSE_DATA_BUFFER_SYM_LINK)reparseDataBuffer).PathBuffer, targetDirBytes.Length); * }*/ var inBufferSize = Marshal.SizeOf(reparseDataBuffer); var inBuffer = Marshal.AllocHGlobal(inBufferSize); try { Marshal.StructureToPtr(reparseDataBuffer, inBuffer, false); int bytesReturned; var result = DeviceIoControl(handle.DangerousGetHandle(), FSCTL_SET_REPARSE_POINT, inBuffer, targetDirBytes.Length + 20, IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero); if (!result) { ThrowLastWin32Error("Unable to create junction point."); } } finally { Marshal.FreeHGlobal(inBuffer); } } }