Skip to content

Commit

Permalink
Init
Browse files Browse the repository at this point in the history
  • Loading branch information
0x5bfa committed Sep 22, 2024
1 parent 56df483 commit 5702295
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 101 deletions.
6 changes: 6 additions & 0 deletions src/Files.App.CsWin32/NativeMethods.txt
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,9 @@ IFileOperation
IShellItem2
PSGetPropertyKeyFromName
ShellExecuteEx
FindFirstFileEx
FindNextFile
CreateFile
GetFileSizeEx
WIN32_FIND_DATAW
FILE_ACCESS_RIGHTS
4 changes: 1 addition & 3 deletions src/Files.App/Data/Items/ShellLibraryItem.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
// Copyright (c) 2024 Files Community
// Licensed under the MIT License. See the LICENSE.

using System.IO;

namespace Files.App.Data.Items
{
public sealed class ShellLibraryItem
{
public const string EXTENSION = ".library-ms";

public static readonly string LibrariesPath = Win32PInvoke.GetFolderFromKnownFolderGUID(new Guid("1B3EA5DC-B587-4786-B4EF-BD1DC332AEAE"));
public static readonly string LibrariesPath = Win32Helper.GetFolderFromKnownFolderGUID(new Guid("1B3EA5DC-B587-4786-B4EF-BD1DC332AEAE"));

/// <summary>
/// Full path of library file.<br/>
Expand Down
9 changes: 9 additions & 0 deletions src/Files.App/Helpers/Win32/Win32Helper.Shell.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,14 @@ public static partial class Win32Helper
return (folder, flc);
});
}

public static string GetFolderFromKnownFolderGUID(Guid guid)
{
IntPtr pPath;
Win32PInvoke.SHGetKnownFolderPath(guid, 0, IntPtr.Zero, out pPath);
string path = Marshal.PtrToStringUni(pPath);
Marshal.FreeCoTaskMem(pPath);
return path;
}
}
}
17 changes: 0 additions & 17 deletions src/Files.App/Helpers/Win32/Win32Helper.WindowManagement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@
using Microsoft.UI.Input;
using Microsoft.UI.Xaml;
using System.Reflection;
using Vanara.PInvoke;
using Windows.Win32;
using Windows.Win32.UI.WindowsAndMessaging;
using static Vanara.PInvoke.User32;

namespace Files.App.Helpers
{
Expand Down Expand Up @@ -60,20 +58,5 @@ public static void ChangeCursor(this UIElement uiElement, InputCursor cursor)
[cursor]
);
}

/// <summary>
/// Changes an attribute of the specified window.
/// </summary>
/// <param name="hWnd">A handle to the window and, indirectly, the class to which the window belongs.</param>
/// <param name="nIndex">The zero-based offset to the value to be set.</param>
/// <param name="dwNewLong">The replacement value.</param>
/// <returns>If the function succeeds, the return value is the previous value of the specified offset.</returns>
public static IntPtr SetWindowLong(HWND hWnd, WindowLongFlags nIndex, IntPtr dwNewLong)
{
return
IntPtr.Size == 4
? Win32PInvoke.SetWindowLongPtr32(hWnd, nIndex, dwNewLong)
: Win32PInvoke.SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
}
}
}
29 changes: 3 additions & 26 deletions src/Files.App/Helpers/Win32/Win32PInvoke.Methods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
using Vanara.PInvoke;
using static Vanara.PInvoke.User32;
using Windows.Win32.Foundation;
using Windows.Win32.System.Com;

namespace Files.App.Helpers
{
Expand Down Expand Up @@ -90,20 +90,6 @@ public static extern uint CoWaitForMultipleObjects(
out uint dwIndex
);

[DllImport("user32.dll", SetLastError = true, EntryPoint = "SetWindowLong")]
public static extern int SetWindowLongPtr32(
HWND hWnd,
WindowLongFlags nIndex,
IntPtr dwNewLong
);

[DllImport("user32.dll", SetLastError = true, EntryPoint = "SetWindowLongPtr")]
public static extern IntPtr SetWindowLongPtr64(
HWND hWnd,
WindowLongFlags nIndex,
IntPtr dwNewLong
);

[DllImport("shell32.dll")]
public static extern IntPtr SHBrowseForFolder(
ref BROWSEINFO lpbi
Expand Down Expand Up @@ -498,7 +484,7 @@ int dwFlags
);

[DllImport("shell32.dll")]
static extern int SHGetKnownFolderPath(
public static extern int SHGetKnownFolderPath(
[MarshalAs(UnmanagedType.LPStruct)] Guid rfid,
uint dwFlags,
IntPtr hToken,
Expand All @@ -507,14 +493,5 @@ out IntPtr pszPath

[DllImport("shell32.dll", EntryPoint = "SHUpdateRecycleBinIcon", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern void SHUpdateRecycleBinIcon();

public static string GetFolderFromKnownFolderGUID(Guid guid)
{
IntPtr pPath;
SHGetKnownFolderPath(guid, 0, IntPtr.Zero, out pPath);
string path = Marshal.PtrToStringUni(pPath);
System.Runtime.InteropServices.Marshal.FreeCoTaskMem(pPath);
return path;
}
}
}
15 changes: 10 additions & 5 deletions src/Files.App/Utils/Shell/ItemStreamHelper.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
// Copyright (c) 2024 Files Community
// Licensed under the MIT License. See the LICENSE.

using System.Runtime.InteropServices;
using Vanara.PInvoke;
using Windows.Win32.System.Com;

namespace Files.App.Utils.Shell
{
Expand All @@ -20,12 +22,15 @@ public static IntPtr IShellItemFromPath(string path)

public static IntPtr IStreamFromPath(string path)
{
IntPtr pstm;
var hr = Win32PInvoke.SHCreateStreamOnFileEx(path,
var hr = Win32PInvoke.SHCreateStreamOnFileEx(
path,
STGM.STGM_READ | STGM.STGM_FAILIFTHERE | STGM.STGM_SHARE_DENY_NONE,
0, 0, IntPtr.Zero, out pstm);
0, 0,
IntPtr.Zero, out var pstm);

if ((int)hr < 0)
return IntPtr.Zero;

return pstm;
}

Expand Down
3 changes: 2 additions & 1 deletion src/Files.App/Utils/Shell/PreviewHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ void SetupHandler(Guid clsid)
// If we use Activator.CreateInstance(Type.GetTypeFromCLSID(...)),
// CLR will allow in-process server, which defeats isolation and
// creates strange bugs.
HRESULT hr = Win32PInvoke.CoCreateInstance(ref clsid, IntPtr.Zero, Win32PInvoke.ClassContext.LocalServer, ref iid, out pph);
Windows.Win32.Foundation.HRESULT hr2 = Win32PInvoke.CoCreateInstance(ref clsid, IntPtr.Zero, Win32PInvoke.ClassContext.LocalServer, ref iid, out pph);
HRESULT hr = new(hr2.Value);
// See https://blogs.msdn.microsoft.com/adioltean/2005/06/24/when-cocreateinstance-returns-0x80080005-co_e_server_exec_failure/
// CO_E_SERVER_EXEC_FAILURE also tends to happen when debugging in Visual Studio.
// Moreover, to create the instance in a server at low integrity level, we need
Expand Down
101 changes: 57 additions & 44 deletions src/Files.App/Utils/Storage/Operations/FileSizeCalculator.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using System.Collections.Concurrent;
// Copyright (c) 2024 Files Community
// Licensed under the MIT License. See the LICENSE.

using System.Collections.Concurrent;
using System.IO;
using Vanara.PInvoke;
using static Vanara.PInvoke.Kernel32;
using Windows.Win32;
using Windows.Win32.Storage.FileSystem;

namespace Files.App.Utils.Storage.Operations
{
Expand All @@ -23,6 +26,14 @@ public FileSizeCalculator(params string[] paths)
public async Task ComputeSizeAsync(CancellationToken cancellationToken = default)
{
await Parallel.ForEachAsync(_paths, cancellationToken, async (path, token) => await Task.Factory.StartNew(() =>
{
ComputeSizeRecursively(path, token);
},
token,
TaskCreationOptions.LongRunning,
TaskScheduler.Default));

unsafe void ComputeSizeRecursively(string path, CancellationToken token)
{
var queue = new Queue<string>();
if (!Win32Helper.HasFileAttribute(path, FileAttributes.Directory))
Expand All @@ -35,76 +46,78 @@ await Parallel.ForEachAsync(_paths, cancellationToken, async (path, token) => aw

while (queue.TryDequeue(out var directory))
{
using var hFile = FindFirstFileEx(
directory + "\\*.*",
FINDEX_INFO_LEVELS.FindExInfoBasic,
out WIN32_FIND_DATA findData,
FINDEX_SEARCH_OPS.FindExSearchNameMatch,
IntPtr.Zero,
FIND_FIRST.FIND_FIRST_EX_LARGE_FETCH);
if (!hFile.IsInvalid)
WIN32_FIND_DATAW* findData = default;

fixed (char* pszFilePath = directory + "\\*.*")
{
do
var hFile = PInvoke.FindFirstFileEx(
pszFilePath,
FINDEX_INFO_LEVELS.FindExInfoBasic,
findData,
FINDEX_SEARCH_OPS.FindExSearchNameMatch,
null,
FIND_FIRST_EX_FLAGS.FIND_FIRST_EX_LARGE_FETCH);

if (!hFile.IsNull)
{
if ((findData.dwFileAttributes & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint)
// Skip symbolic links and junctions
continue;
do
{
FILE_FLAGS_AND_ATTRIBUTES attributes = (FILE_FLAGS_AND_ATTRIBUTES)findData->dwFileAttributes;

var itemPath = Path.Combine(directory, findData.cFileName);
if (attributes.HasFlag(FILE_FLAGS_AND_ATTRIBUTES.FILE_ATTRIBUTE_REPARSE_POINT))
// Skip symbolic links and junctions
continue;

if ((findData.dwFileAttributes & FileAttributes.Directory) != FileAttributes.Directory)
{
ComputeFileSize(itemPath);
}
else if (findData.cFileName != "." && findData.cFileName != "..")
{
queue.Enqueue(itemPath);
}
var itemPath = Path.Combine(directory, findData->cFileName.ToString());

if (attributes.HasFlag(FILE_FLAGS_AND_ATTRIBUTES.FILE_ATTRIBUTE_DIRECTORY))
{
ComputeFileSize(itemPath);
}
else if (findData->cFileName.ToString() is string fileName &&
fileName.Equals(".", StringComparison.OrdinalIgnoreCase) &&
fileName.Equals("..", StringComparison.OrdinalIgnoreCase))
{
queue.Enqueue(itemPath);
}

if (token.IsCancellationRequested)
break;
if (token.IsCancellationRequested)
break;
}
while (PInvoke.FindNextFile(hFile, findData));
}
while (FindNextFile(hFile, out findData));

PInvoke.CloseHandle(hFile);
}
}
}
}, token, TaskCreationOptions.LongRunning, TaskScheduler.Default));
}
}

private long ComputeFileSize(string path)
{
if (_computedFiles.TryGetValue(path, out var size))
{
return size;
}

using var hFile = CreateFile(
using var hFile = PInvoke.CreateFile(
path,
Kernel32.FileAccess.FILE_READ_ATTRIBUTES,
FileShare.Read,
(uint)FILE_ACCESS_RIGHTS.FILE_READ_ATTRIBUTES,
FILE_SHARE_MODE.FILE_SHARE_READ,
null,
FileMode.Open,
FILE_CREATION_DISPOSITION.OPEN_EXISTING,
0,
null);

if (!hFile.IsInvalid)
{
if (GetFileSizeEx(hFile, out size) && _computedFiles.TryAdd(path, size))
{
Interlocked.Add(ref _size, size);
}
}
if (!hFile.IsInvalid && PInvoke.GetFileSizeEx(hFile, out size) && _computedFiles.TryAdd(path, size))
Interlocked.Add(ref _size, size);

return size;
}

public void ForceComputeFileSize(string path)
{
if (!Win32Helper.HasFileAttribute(path, FileAttributes.Directory))
{
ComputeFileSize(path);
}
}

public bool TryGetComputedFileSize(string path, out long size)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using Windows.Win32.Graphics.DirectComposition;
using Windows.Win32.Graphics.Dwm;
using Windows.Win32.Graphics.Dxgi;
using Windows.Win32.UI.WindowsAndMessaging;
using WinRT;
using static Vanara.PInvoke.ShlwApi;
using static Vanara.PInvoke.User32;
Expand Down Expand Up @@ -245,14 +246,11 @@ public unsafe void PointerEntered(bool onPreview)
(uint)Marshal.SizeOf(dwAttrib));

if (isOfficePreview)
Win32Helper.SetWindowLong(hwnd, WindowLongFlags.GWL_EXSTYLE, 0);
PInvoke.SetWindowLongPtr(new((nint)hwnd), WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE, 0);
}
else
{
Win32Helper.SetWindowLong(
hwnd,
WindowLongFlags.GWL_EXSTYLE,
(nint)(WindowStylesEx.WS_EX_LAYERED | WindowStylesEx.WS_EX_COMPOSITED));
PInvoke.SetWindowLongPtr(new((nint)hwnd), WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE, (nint)(WINDOW_EX_STYLE.WS_EX_LAYERED | WINDOW_EX_STYLE.WS_EX_COMPOSITED));

var dwAttrib = Convert.ToUInt32(true);

Expand Down

0 comments on commit 5702295

Please sign in to comment.