static string GetWindowsRealPath(string path) { const FileAttributes FILE_FLAG_BACKUP_SEMANTICS = (FileAttributes)0x02000000; const FileAccess GENERIC_READ = unchecked ((FileAccess)0x80000000); IntPtr handle = CreateFileW(lpFileName: path, dwDesiredAccess: GENERIC_READ, dwShareMode: FileShare.Read, lpSecurityAttributes: IntPtr.Zero, dwCreationDisposition: FileMode.Open, dwFlagsAndAttributes: FILE_FLAG_BACKUP_SEMANTICS, hTemplateFile: IntPtr.Zero); if (handle == INVALID_FILE_HANDLE) { return(null); } IntPtr finalPathBuf = IntPtr.Zero; try { const FinalPathFlags flags = FinalPathFlags.FILE_NAME_OPENED; uint len = GetFinalPathNameByHandleW(handle, IntPtr.Zero, 0, flags); if (len == 0) { return(null); } len = checked (len + 1); finalPathBuf = Marshal.AllocHGlobal(checked ((int)(sizeof(char) * (len)))); uint checkLen = GetFinalPathNameByHandleW(handle, finalPathBuf, len, flags); if (checkLen == 0 || checkLen > len) { Console.Error.WriteLine($"GetFinalPathNameByHandleW: expected {len}, got {checkLen}. Last Error: {Marshal.GetLastWin32Error()}"); return(null); } const string LocalUncPathPrefix = @"\\?\"; string finalPath = Marshal.PtrToStringUni(finalPathBuf); if (finalPath?.StartsWith(LocalUncPathPrefix, StringComparison.Ordinal) ?? false) { finalPath = finalPath.Substring(LocalUncPathPrefix.Length); } return(finalPath); } finally { Marshal.FreeHGlobal(finalPathBuf); CloseHandle(handle); } }
internal static string GetFinalPathName(string path, FinalPathFlags finalPathFlags, bool resolveLinks) { if (path == null) { return(null); } string lookupPath = Paths.AddExtendedPrefix(path); // BackupSemantics is needed to get directory handles AllFileAttributeFlags createFileFlags = AllFileAttributeFlags.FILE_ATTRIBUTE_NORMAL | AllFileAttributeFlags.FILE_FLAG_BACKUP_SEMANTICS; if (!resolveLinks) { createFileFlags |= AllFileAttributeFlags.FILE_FLAG_OPEN_REPARSE_POINT; } string finalPath = null; using (SafeFileHandle file = CreateFile( lookupPath, // To look at metadata we don't need read or write access 0, FileShare.ReadWrite, FileMode.Open, createFileFlags)) { if (file.IsInvalid) { int error = Marshal.GetLastWin32Error(); throw GetIoExceptionForError(error, path); } finalPath = NativeMethods.BufferInvoke((buffer) => Private.GetFinalPathNameByHandleW(file, buffer, (uint)buffer.CharCapacity, finalPathFlags), path); } // GetFinalPathNameByHandle will use the legacy drive for the volume (e.g. \\?\C:\). We may have started with \\?\Volume({GUID}) or some // other volume name format (C:\, etc.) we want to put it back. return(Paths.ReplaceRoot(path, finalPath)); }
static extern uint GetFinalPathNameByHandleW( IntPtr hFile, IntPtr lpszFilePath, uint cchFilePath, FinalPathFlags dwFlags);
internal static extern uint GetFinalPathNameByHandleW( SafeFileHandle hFile, SafeHandle lpszFilePath, uint cchFilePath, FinalPathFlags dwFlags);
internal static string GetFinalPathName(string path, FinalPathFlags finalPathFlags, bool resolveLinks) { if (path == null) return null; string lookupPath = Paths.AddExtendedPrefix(path); // BackupSemantics is needed to get directory handles AllFileAttributeFlags createFileFlags = AllFileAttributeFlags.FILE_ATTRIBUTE_NORMAL | AllFileAttributeFlags.FILE_FLAG_BACKUP_SEMANTICS; if (!resolveLinks) createFileFlags |= AllFileAttributeFlags.FILE_FLAG_OPEN_REPARSE_POINT; string finalPath = null; using (SafeFileHandle file = CreateFile( lookupPath, // To look at metadata we don't need read or write access 0, FileShare.ReadWrite, FileMode.Open, createFileFlags)) { if (file.IsInvalid) { int error = Marshal.GetLastWin32Error(); throw GetIoExceptionForError(error, path); } finalPath = NativeMethods.BufferInvoke((buffer) => Private.GetFinalPathNameByHandleW(file, buffer, (uint)buffer.CharCapacity, finalPathFlags), path); } // GetFinalPathNameByHandle will use the legacy drive for the volume (e.g. \\?\C:\). We may have started with \\?\Volume({GUID}) or some // other volume name format (C:\, etc.) we want to put it back. return Paths.ReplaceRoot(path, finalPath); }
internal static string GetFinalPathName(SafeFileHandle fileHandle, FinalPathFlags finalPathFlags) { return NativeMethods.BufferInvoke((buffer) => Private.GetFinalPathNameByHandleW(fileHandle, buffer, (uint)buffer.CharCapacity, finalPathFlags)); }
internal static string GetFinalPathName(SafeFileHandle fileHandle, FinalPathFlags finalPathFlags) { return(NativeMethods.BufferInvoke((buffer) => Private.GetFinalPathNameByHandleW(fileHandle, buffer, (uint)buffer.CharCapacity, finalPathFlags))); }
public static extern uint GetFinalPathNameByHandle(IntPtr hFile, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpszFilePath, uint cchFilePath, FinalPathFlags dwFlags);
private static extern uint GetFinalPathNameByHandlePrivate(SafeFileHandle hFile, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpszFilePath, uint cchFilePath, FinalPathFlags dwFlags);
internal static string GetFinalPathName(string path, FinalPathFlags finalPathFlags) { if (path == null) return null; string lookupPath = Paths.AddExtendedPathPrefix(path); using (SafeFileHandle file = FileManagement.CreateFilePrivate( lookupPath, FileAccess.Read, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, // BackupSemantics is needed to get directory handles AllFileAttributeFlags.FILE_ATTRIBUTE_NORMAL | AllFileAttributeFlags.FILE_FLAG_BACKUP_SEMANTICS, IntPtr.Zero)) { if (file.IsInvalid) { int error = Marshal.GetLastWin32Error(); throw GetIoExceptionForError(error, path); } return NativeMethods.ConvertString(path, (value, sb) => FileManagement.GetFinalPathNameByHandlePrivate(file, sb, (uint)sb.Capacity, finalPathFlags)); } }
internal static string GetFinalPathName(SafeFileHandle fileHandle, FinalPathFlags finalPathFlags) { return NativeMethods.ConvertString("GetFinalPathNameByHandle", (value, sb) => FileManagement.GetFinalPathNameByHandlePrivate(fileHandle, sb, (uint)sb.Capacity, finalPathFlags)); }