Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions src/Files.App.CsWin32/IStorageProviderQuotaUI.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright (c) Files Community
// Licensed under the MIT License.

using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Windows.Win32.Foundation;

namespace Windows.Win32.System.WinRT
{
public unsafe struct IStorageProviderQuotaUI : IComIID
{
private void** lpVtbl;

Check warning on line 14 in src/Files.App.CsWin32/IStorageProviderQuotaUI.cs

View workflow job for this annotation

GitHub Actions / build (Release, x64)

Field 'IStorageProviderQuotaUI.lpVtbl' is never assigned to, and will always have its default value

Check warning on line 14 in src/Files.App.CsWin32/IStorageProviderQuotaUI.cs

View workflow job for this annotation

GitHub Actions / build (Debug, arm64)

Field 'IStorageProviderQuotaUI.lpVtbl' is never assigned to, and will always have its default value

Check warning on line 14 in src/Files.App.CsWin32/IStorageProviderQuotaUI.cs

View workflow job for this annotation

GitHub Actions / build (Debug, x64)

Field 'IStorageProviderQuotaUI.lpVtbl' is never assigned to, and will always have its default value

Check warning on line 14 in src/Files.App.CsWin32/IStorageProviderQuotaUI.cs

View workflow job for this annotation

GitHub Actions / build (Release, arm64)

Field 'IStorageProviderQuotaUI.lpVtbl' is never assigned to, and will always have its default value

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public HRESULT GetQuotaTotalInBytes(ulong* value)
{
return ((delegate* unmanaged[Stdcall]<IStorageProviderQuotaUI*, ulong*, HRESULT>)(lpVtbl[6]))((IStorageProviderQuotaUI*)Unsafe.AsPointer(ref this), value);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public HRESULT GetQuotaUsedInBytes(ulong* value)
{
return ((delegate* unmanaged[Stdcall]<IStorageProviderQuotaUI*, ulong*, HRESULT>)(lpVtbl[8]))((IStorageProviderQuotaUI*)Unsafe.AsPointer(ref this), value);
}

public static ref readonly Guid Guid
{
get
{
// BA6295C3-312E-544F-9FD5-1F81B21F3649
ReadOnlySpan<byte> data =
[
0xC3, 0x95, 0x62, 0xBA,
0x2E, 0x31,
0x4F, 0x54,
0x9F, 0xD5,
0x1F, 0x81, 0xB2, 0x1F, 0x36, 0x49
];

Debug.Assert(data.Length == sizeof(Guid));
return ref Unsafe.As<byte, Guid>(ref MemoryMarshal.GetReference(data));
}
}
}
}
41 changes: 41 additions & 0 deletions src/Files.App.CsWin32/IStorageProviderStatusUI.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (c) Files Community
// Licensed under the MIT License.

using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Windows.Win32.Foundation;

namespace Windows.Win32.System.WinRT
{
public unsafe struct IStorageProviderStatusUI : IComIID
{
private void** lpVtbl;

Check warning on line 14 in src/Files.App.CsWin32/IStorageProviderStatusUI.cs

View workflow job for this annotation

GitHub Actions / build (Release, x64)

Field 'IStorageProviderStatusUI.lpVtbl' is never assigned to, and will always have its default value

Check warning on line 14 in src/Files.App.CsWin32/IStorageProviderStatusUI.cs

View workflow job for this annotation

GitHub Actions / build (Debug, arm64)

Field 'IStorageProviderStatusUI.lpVtbl' is never assigned to, and will always have its default value

Check warning on line 14 in src/Files.App.CsWin32/IStorageProviderStatusUI.cs

View workflow job for this annotation

GitHub Actions / build (Debug, x64)

Field 'IStorageProviderStatusUI.lpVtbl' is never assigned to, and will always have its default value

Check warning on line 14 in src/Files.App.CsWin32/IStorageProviderStatusUI.cs

View workflow job for this annotation

GitHub Actions / build (Release, arm64)

Field 'IStorageProviderStatusUI.lpVtbl' is never assigned to, and will always have its default value

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public HRESULT GetQuotaUI(IStorageProviderQuotaUI** result)
{
return ((delegate* unmanaged[Stdcall]<IStorageProviderStatusUI*, IStorageProviderQuotaUI**, HRESULT>)lpVtbl[14])((IStorageProviderStatusUI*)Unsafe.AsPointer(ref this), result);
}

public static ref readonly Guid Guid
{
get
{
// d6b6a758-198d-5b80-977f-5ff73da33118
ReadOnlySpan<byte> data =
[
0x58, 0xa7, 0xb6, 0xd6,
0x8d, 0x19,
0x80, 0x5b,
0x97, 0x7f,
0x5f, 0xf7, 0x3d, 0xa3, 0x31, 0x18
];

Debug.Assert(data.Length == sizeof(Guid));
return ref Unsafe.As<byte, Guid>(ref MemoryMarshal.GetReference(data));
}
}
}
}
41 changes: 41 additions & 0 deletions src/Files.App.CsWin32/IStorageProviderStatusUISource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (c) Files Community
// Licensed under the MIT License.

using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Windows.Win32.Foundation;

namespace Windows.Win32.System.WinRT
{
public unsafe struct IStorageProviderStatusUISource : IComIID
{
private void** lpVtbl;

Check warning on line 14 in src/Files.App.CsWin32/IStorageProviderStatusUISource.cs

View workflow job for this annotation

GitHub Actions / build (Release, x64)

Field 'IStorageProviderStatusUISource.lpVtbl' is never assigned to, and will always have its default value

Check warning on line 14 in src/Files.App.CsWin32/IStorageProviderStatusUISource.cs

View workflow job for this annotation

GitHub Actions / build (Debug, arm64)

Field 'IStorageProviderStatusUISource.lpVtbl' is never assigned to, and will always have its default value

Check warning on line 14 in src/Files.App.CsWin32/IStorageProviderStatusUISource.cs

View workflow job for this annotation

GitHub Actions / build (Debug, x64)

Field 'IStorageProviderStatusUISource.lpVtbl' is never assigned to, and will always have its default value

Check warning on line 14 in src/Files.App.CsWin32/IStorageProviderStatusUISource.cs

View workflow job for this annotation

GitHub Actions / build (Release, arm64)

Field 'IStorageProviderStatusUISource.lpVtbl' is never assigned to, and will always have its default value

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public HRESULT GetStatusUI(IStorageProviderStatusUI** result)
{
return ((delegate* unmanaged[Stdcall]<IStorageProviderStatusUISource*, IStorageProviderStatusUI**, HRESULT>)lpVtbl[6])((IStorageProviderStatusUISource*)Unsafe.AsPointer(ref this), result);
}

public static ref readonly Guid Guid
{
get
{
// A306C249-3D66-5E70-9007-E43DF96051FF
ReadOnlySpan<byte> data =
[
0x49, 0xc2, 0x06, 0xa3,
0x66, 0x3d,
0x70, 0x5e,
0x90, 0x07,
0xe4, 0x3d, 0xf9, 0x60, 0x51, 0xff
];

Debug.Assert(data.Length == sizeof(Guid));
return ref Unsafe.As<byte, Guid>(ref MemoryMarshal.GetReference(data));
}
}
}
}
41 changes: 41 additions & 0 deletions src/Files.App.CsWin32/IStorageProviderStatusUISourceFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (c) Files Community
// Licensed under the MIT License.

using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Windows.Win32.Foundation;

namespace Windows.Win32.System.WinRT
{
public unsafe struct IStorageProviderStatusUISourceFactory : IComIID
{
private void** lpVtbl;

Check warning on line 14 in src/Files.App.CsWin32/IStorageProviderStatusUISourceFactory.cs

View workflow job for this annotation

GitHub Actions / build (Release, x64)

Field 'IStorageProviderStatusUISourceFactory.lpVtbl' is never assigned to, and will always have its default value

Check warning on line 14 in src/Files.App.CsWin32/IStorageProviderStatusUISourceFactory.cs

View workflow job for this annotation

GitHub Actions / build (Debug, arm64)

Field 'IStorageProviderStatusUISourceFactory.lpVtbl' is never assigned to, and will always have its default value

Check warning on line 14 in src/Files.App.CsWin32/IStorageProviderStatusUISourceFactory.cs

View workflow job for this annotation

GitHub Actions / build (Debug, x64)

Field 'IStorageProviderStatusUISourceFactory.lpVtbl' is never assigned to, and will always have its default value

Check warning on line 14 in src/Files.App.CsWin32/IStorageProviderStatusUISourceFactory.cs

View workflow job for this annotation

GitHub Actions / build (Release, arm64)

Field 'IStorageProviderStatusUISourceFactory.lpVtbl' is never assigned to, and will always have its default value

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public HRESULT GetStatusUISource(nint syncRootId, IStorageProviderStatusUISource** result)
{
return ((delegate* unmanaged[Stdcall]<IStorageProviderStatusUISourceFactory*, nint, IStorageProviderStatusUISource**, HRESULT>)lpVtbl[6])((IStorageProviderStatusUISourceFactory*)Unsafe.AsPointer(ref this), syncRootId, result);
}

public static ref readonly Guid Guid
{
get
{
// 12E46B74-4E5A-58D1-A62F-0376E8EE7DD8
ReadOnlySpan<byte> data =
[
0x74, 0x6b, 0xe4, 0x12,
0x5a, 0x4e,
0xd1, 0x58,
0xa6, 0x2f,
0x03, 0x76, 0xe8, 0xee, 0x7d, 0xd8
];

Debug.Assert(data.Length == sizeof(Guid));
return ref Unsafe.As<byte, Guid>(ref MemoryMarshal.GetReference(data));
}
}
}
}
151 changes: 34 additions & 117 deletions src/Files.App/Utils/Storage/Helpers/SyncRootHelpers.cs
Original file line number Diff line number Diff line change
@@ -1,144 +1,61 @@
using Microsoft.Win32;
// Copyright (c) Files Community
// Licensed under the MIT License.

using Microsoft.Win32;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Windows.Storage.Provider;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.System.Com;
using Windows.Win32.System.WinRT;
using WinRT;

namespace Files.App.Utils.Storage
{
internal static class SyncRootHelpers
{
private unsafe struct IStorageProviderStatusUISourceFactory : IComIID
{
private void** vtbl;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public HRESULT GetStatusUISource(nint syncRootId, IStorageProviderStatusUISource** result)
{
return ((delegate* unmanaged[Stdcall]<IStorageProviderStatusUISourceFactory*, nint, IStorageProviderStatusUISource**, HRESULT>)vtbl[6])((IStorageProviderStatusUISourceFactory*)Unsafe.AsPointer(ref this), syncRootId, result);
}

public static ref readonly Guid Guid
{
get
{
// 12e46b74-4e5a-58d1-a62f-0376e8ee7dd8
ReadOnlySpan<byte> data = new byte[]
{
0x74, 0x6b, 0xe4, 0x12,
0x5a, 0x4e,
0xd1, 0x58,
0xa6, 0x2f,
0x03, 0x76, 0xe8, 0xee, 0x7d, 0xd8
};
Debug.Assert(data.Length == sizeof(Guid));
return ref Unsafe.As<byte, Guid>(ref MemoryMarshal.GetReference(data));
}
}
}

private unsafe struct IStorageProviderStatusUISource : IComIID
private static unsafe (bool Success, ulong Capacity, ulong Used) GetSyncRootQuotaFromSyncRootId(string syncRootId)
{
private void** vtbl;

public HRESULT GetStatusUI(IStorageProviderStatusUI** result)
{
return ((delegate* unmanaged[Stdcall]<IStorageProviderStatusUISource*, IStorageProviderStatusUI**, HRESULT>)vtbl[6])((IStorageProviderStatusUISource*)Unsafe.AsPointer(ref this), result);
}

public static ref readonly Guid Guid
{
get
{
// a306c249-3d66-5e70-9007-e43df96051ff
ReadOnlySpan<byte> data = new byte[]
{
0x49, 0xc2, 0x06, 0xa3,
0x66, 0x3d,
0x70, 0x5e,
0x90, 0x07,
0xe4, 0x3d, 0xf9, 0x60, 0x51, 0xff
};
Debug.Assert(data.Length == sizeof(Guid));
return ref Unsafe.As<byte, Guid>(ref MemoryMarshal.GetReference(data));
}
}
}
using var key = Registry.LocalMachine.OpenSubKey($"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\SyncRootManager\\{syncRootId}");
if (key?.GetValue("StorageProviderStatusUISourceFactory") is not string factoryClsidString ||
!Guid.TryParse(factoryClsidString, out var factoryClsid))
return (false, 0, 0);

private unsafe struct IStorageProviderStatusUI : IComIID
{
public static ref readonly Guid Guid
{
get
{
// d6b6a758-198d-5b80-977f-5ff73da33118
ReadOnlySpan<byte> data = new byte[]
{
0x58, 0xa7, 0xb6, 0xd6,
0x8d, 0x19,
0x80, 0x5b,
0x97, 0x7f,
0x5f, 0xf7, 0x3d, 0xa3, 0x31, 0x18
};
Debug.Assert(data.Length == sizeof(Guid));
return ref Unsafe.As<byte, Guid>(ref MemoryMarshal.GetReference(data));
}
}
}
ulong ulTotalSize = 0ul, ulUsedSize = 0ul;
using ComPtr<IStorageProviderStatusUISourceFactory> pStorageProviderStatusUISourceFactory = default;
using ComPtr<IStorageProviderStatusUISource> pStorageProviderStatusUISource = default;
using ComPtr<IStorageProviderStatusUI> pStorageProviderStatusUI = default;
using ComPtr<IStorageProviderQuotaUI> pStorageProviderQuotaUI = default;

private static unsafe (bool Success, ulong Capacity, ulong Used) GetSyncRootQuotaFromSyncRootId(string syncRootId)
{
RegistryKey? key;
if ((key = Registry.LocalMachine.OpenSubKey($"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\SyncRootManager\\{syncRootId}")) is null)
{
var hr = PInvoke.CoCreateInstance(
&factoryClsid,
null,
CLSCTX.CLSCTX_LOCAL_SERVER,
(Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IStorageProviderStatusUISourceFactory.Guid)),
(void**)pStorageProviderStatusUISourceFactory.GetAddressOf());
if (hr.Failed)
return (false, 0, 0);
}

using (key)
var syncRootIdHString = new MarshalString.Pinnable(syncRootId);
fixed (char* pSyncRootIdHString = syncRootIdHString)
{
if (key.GetValue("StorageProviderStatusUISourceFactory") is string statusUIclass)
{
StorageProviderStatusUI statusUI;
using (ComPtr<IStorageProviderStatusUISourceFactory> sourceFactoryNative = default)
{
Guid statusUIclassGuid = Guid.Parse(statusUIclass);
if (PInvoke.CoCreateInstance(&statusUIclassGuid, null, Windows.Win32.System.Com.CLSCTX.CLSCTX_LOCAL_SERVER, (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IStorageProviderStatusUISourceFactory.Guid)), (void**)sourceFactoryNative.GetAddressOf()) != 0)
{
return (false, 0, 0);
}

MarshalString.Pinnable syncRootIdHstring = new(syncRootId);
fixed (char* ptr = syncRootIdHstring)
using (ComPtr<IStorageProviderStatusUISource> sourceNative = default)
{
ExceptionHelpers.ThrowExceptionForHR(sourceFactoryNative.Get()->GetStatusUISource(syncRootIdHstring.GetAbi(), sourceNative.GetAddressOf()));
hr = pStorageProviderStatusUISourceFactory.Get()->GetStatusUISource(syncRootIdHString.GetAbi(), pStorageProviderStatusUISource.GetAddressOf()).ThrowOnFailure();
hr = pStorageProviderStatusUISource.Get()->GetStatusUI(pStorageProviderStatusUI.GetAddressOf()).ThrowOnFailure();
hr = pStorageProviderStatusUI.Get()->GetQuotaUI(pStorageProviderQuotaUI.GetAddressOf()).ThrowOnFailure();

using (ComPtr<IStorageProviderStatusUI> statusNative = default)
{
ExceptionHelpers.ThrowExceptionForHR(sourceNative.Get()->GetStatusUI(statusNative.GetAddressOf()));
statusUI = StorageProviderStatusUI.FromAbi((nint)statusNative.Get());
}
}
}
return (true, statusUI.QuotaUI.QuotaTotalInBytes, statusUI.QuotaUI.QuotaUsedInBytes);
}
else
{
return (false, 0, 0);
}
hr = pStorageProviderQuotaUI.Get()->GetQuotaTotalInBytes(&ulTotalSize);
hr = pStorageProviderQuotaUI.Get()->GetQuotaUsedInBytes(&ulUsedSize);
}

return (true, ulTotalSize, ulUsedSize);
}

public static async Task<(bool Success, ulong Capacity, ulong Used)> GetSyncRootQuotaAsync(string path)
{
Windows.Storage.StorageFolder folder = await Windows.Storage.StorageFolder.GetFolderFromPathAsync(path);
StorageProviderSyncRootInfo? syncRootInfo = null;
Windows.Storage.Provider.StorageProviderSyncRootInfo? syncRootInfo = null;

try
{
syncRootInfo = StorageProviderSyncRootManager.GetSyncRootInformationForFolder(folder);
syncRootInfo = Windows.Storage.Provider.StorageProviderSyncRootManager.GetSyncRootInformationForFolder(folder);
}
catch
{
Expand Down
Loading