Add Explorer Workbench with hierarchical, off-UI Storage analysis.
Storage queries run in the background with cancellation and covering indexes so switching views no longer freezes the UI. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
160
src/Explorer.Windows/CloudFilesNative.cs
Normal file
160
src/Explorer.Windows/CloudFilesNative.cs
Normal file
@@ -0,0 +1,160 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using Explorer.Domain;
|
||||
|
||||
namespace Explorer.Windows;
|
||||
|
||||
public static partial class CloudFilesNative
|
||||
{
|
||||
public const uint PlaceholderNone = 0;
|
||||
public const uint Placeholder = 0x1;
|
||||
public const uint PlaceholderSyncRoot = 0x2;
|
||||
public const uint PlaceholderInSync = 0x8;
|
||||
public const uint PlaceholderPartial = 0x10;
|
||||
public const uint PlaceholderPartiallyOnDisk = 0x20;
|
||||
public const uint PlaceholderInvalid = 0xFFFFFFFF;
|
||||
|
||||
public const int PinUnspecified = 0;
|
||||
public const int PinPinned = 1;
|
||||
public const int PinUnpinned = 2;
|
||||
public const int PinExcluded = 3;
|
||||
public const int PinInherit = 4;
|
||||
|
||||
public static nint OpenNoRecall(string path)
|
||||
=> NativeMethods.CreateFile(
|
||||
PathRules.ToExtended(path),
|
||||
NativeMethods.FileReadAttributes,
|
||||
NativeMethods.FileShareRead | NativeMethods.FileShareWrite | NativeMethods.FileShareDelete,
|
||||
0,
|
||||
NativeMethods.OpenExisting,
|
||||
NativeMethods.SafeOpenFlags,
|
||||
0);
|
||||
|
||||
public static bool IsInvalid(nint handle)
|
||||
=> handle == nint.Zero || handle == new nint(-1);
|
||||
|
||||
public static long? TryGetAllocatedSize(string path)
|
||||
{
|
||||
var handle = OpenNoRecall(path);
|
||||
if (IsInvalid(handle))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return TryGetAllocatedSize(handle);
|
||||
}
|
||||
finally
|
||||
{
|
||||
NativeMethods.CloseHandle(handle);
|
||||
}
|
||||
}
|
||||
|
||||
public static long? TryGetAllocatedSize(nint handle)
|
||||
{
|
||||
var size = Marshal.SizeOf<FileStandardInfo>();
|
||||
var buffer = Marshal.AllocHGlobal(size);
|
||||
try
|
||||
{
|
||||
if (!NativeMethods.GetFileInformationByHandleEx(handle, NativeMethods.FileStandardInfo, buffer, (uint)size))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var info = Marshal.PtrToStructure<FileStandardInfo>(buffer);
|
||||
return info.AllocationSize;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeHGlobal(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public static uint? TryGetPlaceholderState(int attributes, int reparseTag)
|
||||
{
|
||||
try
|
||||
{
|
||||
return CfGetPlaceholderStateFromAttributeTag((uint)attributes, (uint)reparseTag);
|
||||
}
|
||||
catch (DllNotFoundException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
catch (EntryPointNotFoundException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TrySetPinState(string path, int pinState)
|
||||
{
|
||||
var handle = OpenNoRecall(path);
|
||||
if (IsInvalid(handle))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return CfSetPinState(handle, pinState, 0, nint.Zero) == 0;
|
||||
}
|
||||
catch (DllNotFoundException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
catch (EntryPointNotFoundException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
NativeMethods.CloseHandle(handle);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsCloudSyncRoot(string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
uint returned = 0;
|
||||
var hr = CfGetSyncRootInfoByPath(path, 0, nint.Zero, 0, ref returned);
|
||||
const int insufficientBuffer = unchecked((int)0x8007007A);
|
||||
return hr == 0 || (hr == insufficientBuffer && returned > 0);
|
||||
}
|
||||
catch (DllNotFoundException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
catch (EntryPointNotFoundException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[LibraryImport("cldapi.dll")]
|
||||
private static partial uint CfGetPlaceholderStateFromAttributeTag(uint fileAttributes, uint reparseTag);
|
||||
|
||||
[DllImport("cldapi.dll", ExactSpelling = true)]
|
||||
private static extern int CfSetPinState(nint fileHandle, int pinState, uint pinFlags, nint overlapped);
|
||||
|
||||
[DllImport("cldapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
|
||||
private static extern int CfGetSyncRootInfoByPath(string filePath, int infoClass, nint infoBuffer, uint infoBufferLength, ref uint returnedLength);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct FileStandardInfo
|
||||
{
|
||||
public long AllocationSize;
|
||||
public long EndOfFile;
|
||||
public uint NumberOfLinks;
|
||||
public byte DeletePending;
|
||||
public byte Directory;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user