internal static string GetFinalPathNameByHandleCore(SafeFileHandle handle, FinalPathFormats finalPath) { NativeMethods.IsValidHandle(handle); var buffer = new StringBuilder(NativeMethods.MaxPathUnicode); using (new NativeMethods.ChangeErrorMode(NativeMethods.ErrorMode.FailCriticalErrors)) { if (NativeMethods.IsAtLeastWindowsVista) { // MSDN: GetFinalPathNameByHandle(): If the function fails for any other reason, the return value is zero. var success = NativeMethods.GetFinalPathNameByHandle(handle, buffer, (uint)buffer.Capacity, finalPath) == Win32Errors.ERROR_SUCCESS; var lastError = Marshal.GetLastWin32Error(); if (!success && lastError != Win32Errors.ERROR_SUCCESS) { NativeError.ThrowException(lastError); } return(buffer.ToString()); } } // Older OperatingSystem // Obtaining a File Name From a File Handle // http://msdn.microsoft.com/en-us/library/aa366789%28VS.85%29.aspx // Be careful when using GetFileSizeEx to check the size of hFile handle of an unknown "File" type object. // This is more towards returning a filename from a file handle. If the handle is a named pipe handle it seems to hang the thread. // Check for: FileTypes.DiskFile // Can't map a 0 byte file. long fileSizeHi; if (!NativeMethods.GetFileSizeEx(handle, out fileSizeHi)) { if (fileSizeHi == 0) { return(string.Empty); } } // PAGE_READONLY // Allows views to be mapped for read-only or copy-on-write access. An attempt to write to a specific region results in an access violation. // The file handle that the hFile parameter specifies must be created with the GENERIC_READ access right. // PageReadOnly = 0x02, using (var handle2 = NativeMethods.CreateFileMapping(handle, null, 2, 0, 1, null)) { NativeMethods.IsValidHandle(handle, Marshal.GetLastWin32Error()); // FILE_MAP_READ // Read = 4 using (var pMem = NativeMethods.MapViewOfFile(handle2, 4, 0, 0, (UIntPtr)1)) { if (NativeMethods.IsValidHandle(pMem, Marshal.GetLastWin32Error())) { if (NativeMethods.GetMappedFileName(Process.GetCurrentProcess().Handle, pMem, buffer, (uint)buffer.Capacity)) { NativeMethods.UnmapViewOfFile(pMem); } } } } // Default output from GetMappedFileName(): "\Device\HarddiskVolumeX\path\filename.ext" var dosDevice = buffer.Length > 0 ? buffer.ToString() : string.Empty; // Select output format. switch (finalPath) { // As-is: "\Device\HarddiskVolumeX\path\filename.ext" case FinalPathFormats.VolumeNameNT: return(dosDevice); // To: "\path\filename.ext" case FinalPathFormats.VolumeNameNone: return(DosDeviceToDosPath(dosDevice, string.Empty)); // To: "\\?\Volume{GUID}\path\filename.ext" case FinalPathFormats.VolumeNameGuid: var dosPath = DosDeviceToDosPath(dosDevice, null); if (!Utils.IsNullOrWhiteSpace(dosPath)) { var driveLetter = RemoveTrailingDirectorySeparator(GetPathRoot(dosPath, false)); var file = GetFileName(dosPath, true); if (!Utils.IsNullOrWhiteSpace(file)) { foreach (var drive in Directory.EnumerateLogicalDrivesCore(false, false).Select(drv => drv.Name).Where(drv => driveLetter.Equals(RemoveTrailingDirectorySeparator(drv), StringComparison.OrdinalIgnoreCase))) { return(CombineCore(false, Volume.GetUniqueVolumeNameForPath(drive), GetSuffixedDirectoryNameWithoutRootCore(null, dosPath), file)); } } } break; } // To: "\\?\C:\path\filename.ext" return(!Utils.IsNullOrWhiteSpace(dosDevice) ? LongPathPrefix + DosDeviceToDosPath(dosDevice, null) : string.Empty); }