diff --git a/src/Files.App.CsWin32/NativeMethods.txt b/src/Files.App.CsWin32/NativeMethods.txt index aee2e82f99b3..dde1157e7fb7 100644 --- a/src/Files.App.CsWin32/NativeMethods.txt +++ b/src/Files.App.CsWin32/NativeMethods.txt @@ -226,3 +226,5 @@ _SICHINTF RoGetAgileReference IQueryInfo QITIPF_FLAGS +FindFirstStream +FindNextStream diff --git a/src/Files.App/Helpers/Win32/Win32Helper.Storage.cs b/src/Files.App/Helpers/Win32/Win32Helper.Storage.cs index 7e878896a3f9..0e92eefb91b5 100644 --- a/src/Files.App/Helpers/Win32/Win32Helper.Storage.cs +++ b/src/Files.App/Helpers/Win32/Win32Helper.Storage.cs @@ -1166,27 +1166,32 @@ public static string ParseSymLink(string path) } // https://stackoverflow.com/a/7988352 - public static IEnumerable<(string Name, long Size)> GetAlternateStreams(string path) + public static unsafe IEnumerable<(string Name, long Size)> GetAlternateStreams(string path) { Win32PInvoke.WIN32_FIND_STREAM_DATA findStreamData = new Win32PInvoke.WIN32_FIND_STREAM_DATA(); - IntPtr hFile = Win32PInvoke.FindFirstStreamW(path, Win32PInvoke.StreamInfoLevels.FindStreamInfoStandard, findStreamData, 0); - if (hFile.ToInt64() != -1) + fixed (char* pszStr = path) { - do + FindCloseSafeHandle hFile = PInvoke.FindFirstStream(new(pszStr), Windows.Win32.Storage.FileSystem.STREAM_INFO_LEVELS.FindStreamInfoStandard, findStreamData, 0); + + if (hFile.DangerousGetHandle().ToInt64() != -1) { - // The documentation for FindFirstStreamW says that it is always a ::$DATA - // stream type, but FindNextStreamW doesn't guarantee that for subsequent - // streams so we check to make sure - if (findStreamData.cStreamName.EndsWith(":$DATA") && findStreamData.cStreamName != "::$DATA") + do { - yield return (findStreamData.cStreamName, findStreamData.StreamSize); + // The documentation for FindFirstStreamW says that it is always a ::$DATA + // stream type, but FindNextStreamW doesn't guarantee that for subsequent + // streams so we check to make sure + if (findStreamData.cStreamName.EndsWith(":$DATA") && findStreamData.cStreamName != "::$DATA") + { + yield return (findStreamData.cStreamName, findStreamData.StreamSize); + } } - } - while (Win32PInvoke.FindNextStreamW(hFile, findStreamData)); + while (PInvoke.FindNextStream(hFile, findStreamData)); - Win32PInvoke.FindClose(hFile); + PInvoke.FindClose((Windows.Win32.Foundation.HANDLE)hFile); + } } + } public static bool GetWin32FindDataForPath(string targetPath, out Win32PInvoke.WIN32_FIND_DATA findData) diff --git a/src/Files.App/Helpers/Win32/Win32PInvoke.Methods.cs b/src/Files.App/Helpers/Win32/Win32PInvoke.Methods.cs index 9af7345111ec..3d866c49c1ff 100644 --- a/src/Files.App/Helpers/Win32/Win32PInvoke.Methods.cs +++ b/src/Files.App/Helpers/Win32/Win32PInvoke.Methods.cs @@ -340,21 +340,6 @@ public static extern bool GetFileInformationByHandleEx( uint dwBufferSize ); - [DllImport("kernel32.dll", ExactSpelling = true, CharSet = CharSet.Auto, SetLastError = true)] - public static extern IntPtr FindFirstStreamW( - string lpFileName, - StreamInfoLevels InfoLevel, - [In, Out, MarshalAs(UnmanagedType.LPStruct)] WIN32_FIND_STREAM_DATA lpFindStreamData, - uint dwFlags - ); - - [DllImport("kernel32.dll", ExactSpelling = true, CharSet = CharSet.Auto, SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool FindNextStreamW( - IntPtr hndFindFile, - [In, Out, MarshalAs(UnmanagedType.LPStruct)] WIN32_FIND_STREAM_DATA lpFindStreamData - ); - [DllImport("Shcore.dll", SetLastError = true)] public static extern int GetDpiForMonitor( IntPtr hmonitor,