/// <summary>[AlphaFS] Creates an NTFS directory junction (similar to CMD command: "MKLINK /J").</summary> internal static void CreateDirectoryJunction(SafeFileHandle safeHandle, string directoryPath) { var targetDirBytes = Encoding.Unicode.GetBytes(Path.NonInterpretedPathPrefix + Path.GetRegularPathCore(directoryPath, GetFullPathOptions.AddTrailingDirectorySeparator, false)); var header = new NativeMethods.ReparseDataBufferHeader { ReparseTag = ReparsePointTag.MountPoint, ReparseDataLength = (ushort)(targetDirBytes.Length + 12) }; var mountPoint = new NativeMethods.MountPointReparseBuffer { SubstituteNameOffset = 0, SubstituteNameLength = (ushort)targetDirBytes.Length, PrintNameOffset = (ushort)(targetDirBytes.Length + UnicodeEncoding.CharSize), PrintNameLength = 0 }; var reparseDataBuffer = new NativeMethods.REPARSE_DATA_BUFFER { ReparseTag = header.ReparseTag, ReparseDataLength = header.ReparseDataLength, SubstituteNameOffset = mountPoint.SubstituteNameOffset, SubstituteNameLength = mountPoint.SubstituteNameLength, PrintNameOffset = mountPoint.PrintNameOffset, PrintNameLength = mountPoint.PrintNameLength, PathBuffer = new byte[NativeMethods.MAXIMUM_REPARSE_DATA_BUFFER_SIZE - 16] // 16368 }; targetDirBytes.CopyTo(reparseDataBuffer.PathBuffer, 0); using (var safeBuffer = new SafeGlobalMemoryBufferHandle(Marshal.SizeOf(reparseDataBuffer))) { safeBuffer.StructureToPtr(reparseDataBuffer, false); uint bytesReturned; var succes = NativeMethods.DeviceIoControl2(safeHandle, NativeMethods.FSCTL_SET_REPARSE_POINT, safeBuffer, (uint)(targetDirBytes.Length + 20), IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero); var lastError = Marshal.GetLastWin32Error(); if (!succes) { NativeError.ThrowException(lastError, directoryPath); } } }
/// <summary>[AlphaFS] Deletes an NTFS directory junction.</summary> internal static void DeleteDirectoryJunction(SafeFileHandle safeHandle) { var reparseDataBuffer = new NativeMethods.REPARSE_DATA_BUFFER { ReparseTag = ReparsePointTag.MountPoint, ReparseDataLength = 0, PathBuffer = new byte[NativeMethods.MAXIMUM_REPARSE_DATA_BUFFER_SIZE - 16] // 16368 }; using (var safeBuffer = new SafeGlobalMemoryBufferHandle(Marshal.SizeOf(reparseDataBuffer))) { safeBuffer.StructureToPtr(reparseDataBuffer, false); uint bytesReturned; var success = NativeMethods.DeviceIoControl2(safeHandle, NativeMethods.FSCTL_DELETE_REPARSE_POINT, safeBuffer, NativeMethods.REPARSE_DATA_BUFFER_HEADER_SIZE, IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero); var lastError = Marshal.GetLastWin32Error(); if (!success) { NativeError.ThrowException(lastError); } } }