private ReparsePoint(IntPtr buffer) { if (buffer == IntPtr.Zero) { throw new ArgumentNullException("buffer"); } _reparseDataData = (ReparseData) Marshal.PtrToStructure(buffer, typeof (ReparseData)); }
/// <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)); }
/// <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 = junctionPath.GetFullPath(); targetDirectory = targetDirectory.GetFullPath(); 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 = Kernel32.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); } } }
public static ReparsePoint CreateSymlink(string symlinkPath, string linkTarget) { symlinkPath = symlinkPath.GetFullPath(); linkTarget = linkTarget.GetFullPath(); if (Directory.Exists(symlinkPath) || File.Exists(symlinkPath)) { throw new IOException("Symlink path already exists."); } if (Directory.Exists(linkTarget)) { Directory.CreateDirectory(symlinkPath); } else if (File.Exists(linkTarget)) { File.Create(symlinkPath).Close(); } else { throw new IOException("Target path does not exist or is not a directory."); } // dark magic kung-fu to get privilige to create symlink. IntPtr state = IntPtr.Zero; UInt32 privilege = 35; Ntdll.RtlAcquirePrivilege(ref privilege, 1, 0, ref state); using (var handle = GetReparsePointHandle(symlinkPath, NativeFileAccess.GenericWrite)) { var substituteName = Encoding.Unicode.GetBytes(NonInterpretedPathPrefix + linkTarget); var printName = Encoding.Unicode.GetBytes(linkTarget); var extraOffset = 4; var reparseDataBuffer = new ReparseData { ReparseTag = IoReparseTag.Symlink, 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 + extraOffset); Array.Copy(substituteName, 0, reparseDataBuffer.PathBuffer, extraOffset, substituteName.Length); Array.Copy(printName, 0, reparseDataBuffer.PathBuffer, reparseDataBuffer.PrintNameOffset + extraOffset, printName.Length); var inBufferSize = Marshal.SizeOf(reparseDataBuffer); var inBuffer = Marshal.AllocHGlobal(inBufferSize); try { Marshal.StructureToPtr(reparseDataBuffer, inBuffer, false); int bytesReturned; var result = Kernel32.DeviceIoControl(handle.DangerousGetHandle(), ControlCodes.SetReparsePoint, inBuffer, reparseDataBuffer.ReparseDataLength + 8, IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero); if (!result) { if (Directory.Exists(symlinkPath)) { Directory.Delete(symlinkPath); } else if (File.Exists(symlinkPath)) { File.Delete(symlinkPath); } throw new IOException("Unable to create symlink.", Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error())); } return Open(symlinkPath); } finally { Marshal.FreeHGlobal(inBuffer); Ntdll.RtlReleasePrivilege(state); } } }
public static ReparsePoint CreateJunction(string junctionPath, string targetDirectory) { junctionPath = junctionPath.GetFullPath(); targetDirectory = targetDirectory.GetFullPath(); 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 = Kernel32.DeviceIoControl(handle.DangerousGetHandle(), 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); } } }
public static ReparsePoint CreateSymlink(string symlinkPath, string linkTarget) { symlinkPath = symlinkPath.GetFullPath(); linkTarget = linkTarget.GetFullPath(); if (Directory.Exists(symlinkPath) || File.Exists(symlinkPath)) { throw new IOException("Symlink path already exists."); } if (Directory.Exists(linkTarget)) { Directory.CreateDirectory(symlinkPath); } else if (File.Exists(linkTarget)) { File.Create(symlinkPath).Close(); } else { throw new IOException("Target path does not exist or is not a directory."); } // dark magic kung-fu to get privilige to create symlink. var state = IntPtr.Zero; UInt32 privilege = 35; Ntdll.RtlAcquirePrivilege(ref privilege, 1, 0, ref state); using (var handle = GetReparsePointHandle(symlinkPath, NativeFileAccess.GenericWrite)) { var substituteName = Encoding.Unicode.GetBytes(NonInterpretedPathPrefix + linkTarget); var printName = Encoding.Unicode.GetBytes(linkTarget); var extraOffset = 4; var reparseDataBuffer = new ReparseData { ReparseTag = IoReparseTag.Symlink, 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 + extraOffset); Array.Copy(substituteName, 0, reparseDataBuffer.PathBuffer, extraOffset, substituteName.Length); Array.Copy(printName, 0, reparseDataBuffer.PathBuffer, reparseDataBuffer.PrintNameOffset + extraOffset, printName.Length); var inBufferSize = Marshal.SizeOf(reparseDataBuffer); var inBuffer = Marshal.AllocHGlobal(inBufferSize); try { Marshal.StructureToPtr(reparseDataBuffer, inBuffer, false); int bytesReturned; var result = Kernel32.DeviceIoControl(handle, ControlCodes.SetReparsePoint, inBuffer, reparseDataBuffer.ReparseDataLength + 8, IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero); if (!result) { if (Directory.Exists(symlinkPath)) { Directory.Delete(symlinkPath); } else if (File.Exists(symlinkPath)) { File.Delete(symlinkPath); } throw new IOException("Unable to create symlink.", Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error())); } return(Open(symlinkPath)); } finally { Marshal.FreeHGlobal(inBuffer); try { if (state != IntPtr.Zero) { Ntdll.RtlReleasePrivilege(state); } } catch { // sometimes this doesn't work so well } } } }