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>
161 lines
4.4 KiB
C#
161 lines
4.4 KiB
C#
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;
|
|
}
|
|
}
|