internal static bool DeleteJunction(string junctionPath) { bool result = false; if (!String.IsNullOrEmpty(junctionPath)) { if (!Platform.IsWindows) { // For non-Windows platform, treat it as a file. Just delete it. try { File.Delete(junctionPath); return true; } catch { return false; } } using (SafeHandle handle = OpenReparsePoint(junctionPath, FileDesiredAccess.GenericWrite)) { bool success = false; int inOutBufferSize = ClrFacade.SizeOf<REPARSE_GUID_DATA_BUFFER>(); IntPtr outBuffer = Marshal.AllocHGlobal(inOutBufferSize); IntPtr inBuffer = Marshal.AllocHGlobal(inOutBufferSize); try { handle.DangerousAddRef(ref success); IntPtr dangerousHandle = handle.DangerousGetHandle(); int bytesReturned; // Do a FSCTL_GET_REPARSE_POINT first because the ReparseTag could be // IO_REPARSE_TAG_MOUNT_POINT or IO_REPARSE_TAG_SYMLINK. // Using the wrong one results in mismatched-tag error. REPARSE_GUID_DATA_BUFFER junctionData = new REPARSE_GUID_DATA_BUFFER(); ClrFacade.StructureToPtr<REPARSE_GUID_DATA_BUFFER>(junctionData, outBuffer, false); result = DeviceIoControl(dangerousHandle, FSCTL_GET_REPARSE_POINT, IntPtr.Zero, 0, outBuffer, inOutBufferSize, out bytesReturned, IntPtr.Zero); if (!result) { int lastError = Marshal.GetLastWin32Error(); throw new Win32Exception(lastError); } junctionData = ClrFacade.PtrToStructure<REPARSE_GUID_DATA_BUFFER>(outBuffer); junctionData.ReparseDataLength = 0; junctionData.DataBuffer = new char[MAX_REPARSE_SIZE]; ClrFacade.StructureToPtr<REPARSE_GUID_DATA_BUFFER>(junctionData, inBuffer, false); // To delete a reparse point: // ReparseDataLength must be 0 // inBufferSize must be REPARSE_GUID_DATA_BUFFER_HEADER_SIZE result = DeviceIoControl(dangerousHandle, FSCTL_DELETE_REPARSE_POINT, inBuffer, REPARSE_GUID_DATA_BUFFER_HEADER_SIZE, IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero); if (!result) { int lastError = Marshal.GetLastWin32Error(); throw new Win32Exception(lastError); } } finally { if (success) { handle.DangerousRelease(); } Marshal.FreeHGlobal(outBuffer); Marshal.FreeHGlobal(inBuffer); } } } else { throw new ArgumentNullException("junctionPath"); } return result; }
/// <summary> /// Gets the target directory from a directory link in Windows Vista. /// </summary> /// <param name="directoryInfo">The directory info of this directory /// link</param> /// <returns>the target directory, if it was read, /// otherwise an empty string.</returns> public static String GetTargetDir(FileSystemInfo directoryInfo) { String targetDir = string.Empty; try { // Is it a directory link? if ((directoryInfo.Attributes & FileAttributes.ReparsePoint) != 0) { // Open the directory link: IntPtr hFile = CreateFile(directoryInfo.FullName, 0, 0, IntPtr.Zero, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, IntPtr.Zero); if (hFile.ToInt32() != INVALID_HANDLE_VALUE) { // Allocate a buffer for the reparse point data: Int32 outBufferSize = Marshal.SizeOf(typeof(REPARSE_GUID_DATA_BUFFER)); IntPtr outBuffer = Marshal.AllocHGlobal(outBufferSize); try { // Read the reparse point data: Int32 bytesReturned; Int32 readOK = DeviceIoControl(hFile, FSCTL_GET_REPARSE_POINT, IntPtr.Zero, 0, outBuffer, outBufferSize, out bytesReturned, IntPtr.Zero); if (readOK != 0) { // Get the target directory from the reparse // point data: REPARSE_GUID_DATA_BUFFER rgdBuffer = (REPARSE_GUID_DATA_BUFFER) Marshal.PtrToStructure (outBuffer, typeof(REPARSE_GUID_DATA_BUFFER)); targetDir = Encoding.Unicode.GetString (rgdBuffer.PathBuffer, rgdBuffer.SubstituteNameOffset, rgdBuffer.SubstituteNameLength); if (targetDir.StartsWith (NonInterpretedPathPrefix)) { targetDir = targetDir.Substring (NonInterpretedPathPrefix.Length); } } } catch (Exception) { } // Free the buffer for the reparse point data: Marshal.FreeHGlobal(outBuffer); // Close the directory link: CloseHandle(hFile); } } } catch (Exception) { } return(targetDir); }
/// <summary> /// Gets the target directory from a directory link in Windows. /// </summary> /// <param name="directoryInfo">The directory info of the directory link</param> /// <returns>The target directory, if link exists, otherwise the FullName</returns> /// <exception cref="ReparsePointException">Thrown if an error occurs</exception> public static string GetTargetDirectory(FileSystemInfo directoryInfo) { try { string targetDir = directoryInfo.FullName; // Is it a directory link? if ((directoryInfo.Attributes & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint) { // Open the directory link: IntPtr hFile = SafeNativeMethods.CreateFile( directoryInfo.FullName, 0, 0, IntPtr.Zero, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, IntPtr.Zero); if (hFile.ToInt32() != INVALID_HANDLE_VALUE) { // Allocate a buffer for the reparse point data: int outBufferSize = Marshal.SizeOf(typeof(REPARSE_GUID_DATA_BUFFER)); IntPtr outBuffer = Marshal.AllocHGlobal(outBufferSize); try { // Read the reparse point data: int bytesReturned; int readOK = SafeNativeMethods.DeviceIoControl( hFile, FSCTL_GET_REPARSE_POINT, IntPtr.Zero, 0, outBuffer, outBufferSize, out bytesReturned, IntPtr.Zero); if (readOK != 0) { // Get the target directory from the reparse point data: REPARSE_GUID_DATA_BUFFER rgdBuffer = (REPARSE_GUID_DATA_BUFFER)Marshal.PtrToStructure(outBuffer, typeof(REPARSE_GUID_DATA_BUFFER)); targetDir = Encoding.Unicode.GetString( rgdBuffer.PathBuffer, rgdBuffer.SubstituteNameOffset, rgdBuffer.SubstituteNameLength); if (targetDir.StartsWith(NonInterpretedPathPrefix, StringComparison.OrdinalIgnoreCase)) { targetDir = targetDir.Substring(NonInterpretedPathPrefix.Length); } } } catch (Exception ex) { throw new ReparsePointException("Failed to access ReparsePoint.", ex); } finally { // Free the buffer for the reparse point data: Marshal.FreeHGlobal(outBuffer); // Close the directory link: SafeNativeMethods.CloseHandle(hFile); } } } return(targetDir); } catch (Exception ex) { throw new ReparsePointException("Failed to access ReparsePoint.", ex); } }