/// <summary> /// Creates the junction. /// </summary> /// <param name = "junctionPath">The junction path.</param> /// <param name = "targetDirectory">The target directory.</param> /// <returns></returns> /// <remarks> /// </remarks> public static ReparsePoint CreateJunction(string junctionPath, string targetDirectory) { junctionPath = Path.GetFullPath(junctionPath); targetDirectory = Path.GetFullPath(targetDirectory); if (!Directory.Exists(targetDirectory)) { throw new IOException("Target path does not exist or is not a directory."); } if (Directory.Exists(junctionPath) || File.Exists(junctionPath)) { throw new IOException("Junction path already exists."); } Directory.CreateDirectory(junctionPath); using (var handle = GetReparsePointHandle(junctionPath, NativeFileAccess.GenericWrite)) { var substituteName = Encoding.Unicode.GetBytes(NonInterpretedPathPrefix + targetDirectory); var printName = Encoding.Unicode.GetBytes(targetDirectory); var reparseDataBuffer = new ReparseData { ReparseTag = IoReparseTag.MountPoint, SubstituteNameOffset = 0, SubstituteNameLength = (ushort) substituteName.Length, PrintNameOffset = (ushort) (substituteName.Length + 2), PrintNameLength = (ushort) printName.Length, PathBuffer = new byte[0x3ff0], }; reparseDataBuffer.ReparseDataLength = (ushort) (reparseDataBuffer.PrintNameLength + reparseDataBuffer.PrintNameOffset + 10); Array.Copy(substituteName, reparseDataBuffer.PathBuffer, substituteName.Length); Array.Copy(printName, 0, reparseDataBuffer.PathBuffer, reparseDataBuffer.PrintNameOffset, printName.Length); var inBufferSize = Marshal.SizeOf(reparseDataBuffer); var inBuffer = Marshal.AllocHGlobal(inBufferSize); try { Marshal.StructureToPtr(reparseDataBuffer, inBuffer, false); int bytesReturned; var result = NativeMethods.DeviceIoControl(handle, ControlCodes.SetReparsePoint, inBuffer, reparseDataBuffer.ReparseDataLength + 8, IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero); if (!result) { Directory.Delete(junctionPath); throw new IOException("Unable to create junction point.", Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error())); } return Open(junctionPath); } finally { Marshal.FreeHGlobal(inBuffer); } } }
/// <summary> /// Prevents a default instance of the <see cref = "ReparsePoint" /> class from being created. /// /// Populates the data from the buffer pointed to by the pointer. /// </summary> /// <param name = "buffer">The buffer.</param> /// <remarks> /// </remarks> private ReparsePoint(IntPtr buffer) { if (buffer == IntPtr.Zero) { throw new ArgumentNullException("buffer"); } _reparseDataData = (ReparseData) Marshal.PtrToStructure(buffer, typeof (ReparseData)); }