Skip to content

Commit 3a057b8

Browse files
authored
Code Quality: Self-defined IStorageProviderQuotaUI instead of using StorageProviderStatusUI.FromAbi (#16965)
1 parent cc2cda1 commit 3a057b8

File tree

9 files changed

+230
-116
lines changed

9 files changed

+230
-116
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright (c) Files Community
2+
// Licensed under the MIT License.
3+
4+
using System.Runtime.InteropServices;
5+
using Windows.Win32.Foundation;
6+
7+
namespace Windows.Win32
8+
{
9+
public static class HRESULTExtensions
10+
{
11+
/// <summary>
12+
/// Throws an exception if the <see cref="HRESULT"/> indicates a failure in debug mode. Otherwise, it returns the original <see cref="HRESULT"/>.
13+
/// </summary>
14+
/// <param name="hr">Represents the result of an operation, indicating success or failure.</param>
15+
/// <returns>Returns the original <see cref="HRESULT"/> value regardless of the operation's success.</returns>
16+
public static HRESULT ThrowIfFailedOnDebug(this HRESULT hr)
17+
{
18+
#if DEBUG
19+
if (hr.Failed)
20+
Marshal.ThrowExceptionForHR(hr.Value);
21+
#endif
22+
23+
return hr;
24+
}
25+
}
26+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright (c) Files Community
2+
// Licensed under the MIT License.
3+
4+
using System;
5+
using System.Diagnostics;
6+
using System.Runtime.CompilerServices;
7+
using System.Runtime.InteropServices;
8+
using Windows.Win32.Foundation;
9+
10+
namespace Windows.Win32.System.WinRT
11+
{
12+
public unsafe struct IStorageProviderQuotaUI : IComIID
13+
{
14+
private void** lpVtbl;
15+
16+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
17+
public HRESULT GetQuotaTotalInBytes(ulong* value)
18+
{
19+
return ((delegate* unmanaged[Stdcall]<IStorageProviderQuotaUI*, ulong*, HRESULT>)(lpVtbl[6]))((IStorageProviderQuotaUI*)Unsafe.AsPointer(ref this), value);
20+
}
21+
22+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
23+
public HRESULT GetQuotaUsedInBytes(ulong* value)
24+
{
25+
return ((delegate* unmanaged[Stdcall]<IStorageProviderQuotaUI*, ulong*, HRESULT>)(lpVtbl[8]))((IStorageProviderQuotaUI*)Unsafe.AsPointer(ref this), value);
26+
}
27+
28+
public static ref readonly Guid Guid
29+
{
30+
get
31+
{
32+
// BA6295C3-312E-544F-9FD5-1F81B21F3649
33+
ReadOnlySpan<byte> data =
34+
[
35+
0xC3, 0x95, 0x62, 0xBA,
36+
0x2E, 0x31,
37+
0x4F, 0x54,
38+
0x9F, 0xD5,
39+
0x1F, 0x81, 0xB2, 0x1F, 0x36, 0x49
40+
];
41+
42+
Debug.Assert(data.Length == sizeof(Guid));
43+
return ref Unsafe.As<byte, Guid>(ref MemoryMarshal.GetReference(data));
44+
}
45+
}
46+
}
47+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright (c) Files Community
2+
// Licensed under the MIT License.
3+
4+
using System;
5+
using System.Diagnostics;
6+
using System.Runtime.CompilerServices;
7+
using System.Runtime.InteropServices;
8+
using Windows.Win32.Foundation;
9+
10+
namespace Windows.Win32.System.WinRT
11+
{
12+
public unsafe struct IStorageProviderStatusUI : IComIID
13+
{
14+
private void** lpVtbl;
15+
16+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
17+
public HRESULT GetQuotaUI(IStorageProviderQuotaUI** result)
18+
{
19+
return ((delegate* unmanaged[Stdcall]<IStorageProviderStatusUI*, IStorageProviderQuotaUI**, HRESULT>)lpVtbl[14])((IStorageProviderStatusUI*)Unsafe.AsPointer(ref this), result);
20+
}
21+
22+
public static ref readonly Guid Guid
23+
{
24+
get
25+
{
26+
// d6b6a758-198d-5b80-977f-5ff73da33118
27+
ReadOnlySpan<byte> data =
28+
[
29+
0x58, 0xa7, 0xb6, 0xd6,
30+
0x8d, 0x19,
31+
0x80, 0x5b,
32+
0x97, 0x7f,
33+
0x5f, 0xf7, 0x3d, 0xa3, 0x31, 0x18
34+
];
35+
36+
Debug.Assert(data.Length == sizeof(Guid));
37+
return ref Unsafe.As<byte, Guid>(ref MemoryMarshal.GetReference(data));
38+
}
39+
}
40+
}
41+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright (c) Files Community
2+
// Licensed under the MIT License.
3+
4+
using System;
5+
using System.Diagnostics;
6+
using System.Runtime.CompilerServices;
7+
using System.Runtime.InteropServices;
8+
using Windows.Win32.Foundation;
9+
10+
namespace Windows.Win32.System.WinRT
11+
{
12+
public unsafe struct IStorageProviderStatusUISource : IComIID
13+
{
14+
private void** lpVtbl;
15+
16+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
17+
public HRESULT GetStatusUI(IStorageProviderStatusUI** result)
18+
{
19+
return ((delegate* unmanaged[Stdcall]<IStorageProviderStatusUISource*, IStorageProviderStatusUI**, HRESULT>)lpVtbl[6])((IStorageProviderStatusUISource*)Unsafe.AsPointer(ref this), result);
20+
}
21+
22+
public static ref readonly Guid Guid
23+
{
24+
get
25+
{
26+
// A306C249-3D66-5E70-9007-E43DF96051FF
27+
ReadOnlySpan<byte> data =
28+
[
29+
0x49, 0xc2, 0x06, 0xa3,
30+
0x66, 0x3d,
31+
0x70, 0x5e,
32+
0x90, 0x07,
33+
0xe4, 0x3d, 0xf9, 0x60, 0x51, 0xff
34+
];
35+
36+
Debug.Assert(data.Length == sizeof(Guid));
37+
return ref Unsafe.As<byte, Guid>(ref MemoryMarshal.GetReference(data));
38+
}
39+
}
40+
}
41+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright (c) Files Community
2+
// Licensed under the MIT License.
3+
4+
using System;
5+
using System.Diagnostics;
6+
using System.Runtime.CompilerServices;
7+
using System.Runtime.InteropServices;
8+
using Windows.Win32.Foundation;
9+
10+
namespace Windows.Win32.System.WinRT
11+
{
12+
public unsafe struct IStorageProviderStatusUISourceFactory : IComIID
13+
{
14+
private void** lpVtbl;
15+
16+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
17+
public HRESULT GetStatusUISource(nint syncRootId, IStorageProviderStatusUISource** result)
18+
{
19+
return ((delegate* unmanaged[Stdcall]<IStorageProviderStatusUISourceFactory*, nint, IStorageProviderStatusUISource**, HRESULT>)lpVtbl[6])((IStorageProviderStatusUISourceFactory*)Unsafe.AsPointer(ref this), syncRootId, result);
20+
}
21+
22+
public static ref readonly Guid Guid
23+
{
24+
get
25+
{
26+
// 12E46B74-4E5A-58D1-A62F-0376E8EE7DD8
27+
ReadOnlySpan<byte> data =
28+
[
29+
0x74, 0x6b, 0xe4, 0x12,
30+
0x5a, 0x4e,
31+
0xd1, 0x58,
32+
0xa6, 0x2f,
33+
0x03, 0x76, 0xe8, 0xee, 0x7d, 0xd8
34+
];
35+
36+
Debug.Assert(data.Length == sizeof(Guid));
37+
return ref Unsafe.As<byte, Guid>(ref MemoryMarshal.GetReference(data));
38+
}
39+
}
40+
}
41+
}

src/Files.App/Utils/Storage/Helpers/SyncRootHelpers.cs

Lines changed: 34 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -1,144 +1,62 @@
1-
using Microsoft.Win32;
1+
// Copyright (c) Files Community
2+
// Licensed under the MIT License.
3+
4+
using Microsoft.Win32;
25
using System.Runtime.CompilerServices;
3-
using System.Runtime.InteropServices;
4-
using Windows.Storage.Provider;
56
using Windows.Win32;
67
using Windows.Win32.Foundation;
8+
using Windows.Win32.System.Com;
9+
using Windows.Win32.System.WinRT;
710
using WinRT;
811

912
namespace Files.App.Utils.Storage
1013
{
1114
internal static class SyncRootHelpers
1215
{
13-
private unsafe struct IStorageProviderStatusUISourceFactory : IComIID
14-
{
15-
private void** vtbl;
16-
17-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
18-
public HRESULT GetStatusUISource(nint syncRootId, IStorageProviderStatusUISource** result)
19-
{
20-
return ((delegate* unmanaged[Stdcall]<IStorageProviderStatusUISourceFactory*, nint, IStorageProviderStatusUISource**, HRESULT>)vtbl[6])((IStorageProviderStatusUISourceFactory*)Unsafe.AsPointer(ref this), syncRootId, result);
21-
}
22-
23-
public static ref readonly Guid Guid
24-
{
25-
get
26-
{
27-
// 12e46b74-4e5a-58d1-a62f-0376e8ee7dd8
28-
ReadOnlySpan<byte> data = new byte[]
29-
{
30-
0x74, 0x6b, 0xe4, 0x12,
31-
0x5a, 0x4e,
32-
0xd1, 0x58,
33-
0xa6, 0x2f,
34-
0x03, 0x76, 0xe8, 0xee, 0x7d, 0xd8
35-
};
36-
Debug.Assert(data.Length == sizeof(Guid));
37-
return ref Unsafe.As<byte, Guid>(ref MemoryMarshal.GetReference(data));
38-
}
39-
}
40-
}
41-
42-
private unsafe struct IStorageProviderStatusUISource : IComIID
43-
{
44-
private void** vtbl;
45-
46-
public HRESULT GetStatusUI(IStorageProviderStatusUI** result)
47-
{
48-
return ((delegate* unmanaged[Stdcall]<IStorageProviderStatusUISource*, IStorageProviderStatusUI**, HRESULT>)vtbl[6])((IStorageProviderStatusUISource*)Unsafe.AsPointer(ref this), result);
49-
}
50-
51-
public static ref readonly Guid Guid
52-
{
53-
get
54-
{
55-
// a306c249-3d66-5e70-9007-e43df96051ff
56-
ReadOnlySpan<byte> data = new byte[]
57-
{
58-
0x49, 0xc2, 0x06, 0xa3,
59-
0x66, 0x3d,
60-
0x70, 0x5e,
61-
0x90, 0x07,
62-
0xe4, 0x3d, 0xf9, 0x60, 0x51, 0xff
63-
};
64-
Debug.Assert(data.Length == sizeof(Guid));
65-
return ref Unsafe.As<byte, Guid>(ref MemoryMarshal.GetReference(data));
66-
}
67-
}
68-
}
69-
70-
private unsafe struct IStorageProviderStatusUI : IComIID
71-
{
72-
public static ref readonly Guid Guid
73-
{
74-
get
75-
{
76-
// d6b6a758-198d-5b80-977f-5ff73da33118
77-
ReadOnlySpan<byte> data = new byte[]
78-
{
79-
0x58, 0xa7, 0xb6, 0xd6,
80-
0x8d, 0x19,
81-
0x80, 0x5b,
82-
0x97, 0x7f,
83-
0x5f, 0xf7, 0x3d, 0xa3, 0x31, 0x18
84-
};
85-
Debug.Assert(data.Length == sizeof(Guid));
86-
return ref Unsafe.As<byte, Guid>(ref MemoryMarshal.GetReference(data));
87-
}
88-
}
89-
}
90-
9116
private static unsafe (bool Success, ulong Capacity, ulong Used) GetSyncRootQuotaFromSyncRootId(string syncRootId)
9217
{
93-
RegistryKey? key;
94-
if ((key = Registry.LocalMachine.OpenSubKey($"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\SyncRootManager\\{syncRootId}")) is null)
95-
{
18+
using var key = Registry.LocalMachine.OpenSubKey($"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\SyncRootManager\\{syncRootId}");
19+
if (key?.GetValue("StorageProviderStatusUISourceFactory") is not string factoryClsidString ||
20+
!Guid.TryParse(factoryClsidString, out var factoryClsid))
9621
return (false, 0, 0);
97-
}
9822

99-
using (key)
100-
{
101-
if (key.GetValue("StorageProviderStatusUISourceFactory") is string statusUIclass)
102-
{
103-
StorageProviderStatusUI statusUI;
104-
using (ComPtr<IStorageProviderStatusUISourceFactory> sourceFactoryNative = default)
105-
{
106-
Guid statusUIclassGuid = Guid.Parse(statusUIclass);
107-
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)
108-
{
109-
return (false, 0, 0);
110-
}
23+
HRESULT hr = default;
24+
ulong ulTotalSize = 0ul, ulUsedSize = 0ul;
25+
using ComPtr<IStorageProviderStatusUISourceFactory> pStorageProviderStatusUISourceFactory = default;
26+
using ComPtr<IStorageProviderStatusUISource> pStorageProviderStatusUISource = default;
27+
using ComPtr<IStorageProviderStatusUI> pStorageProviderStatusUI = default;
28+
using ComPtr<IStorageProviderQuotaUI> pStorageProviderQuotaUI = default;
11129

112-
MarshalString.Pinnable syncRootIdHstring = new(syncRootId);
113-
fixed (char* ptr = syncRootIdHstring)
114-
using (ComPtr<IStorageProviderStatusUISource> sourceNative = default)
115-
{
116-
ExceptionHelpers.ThrowExceptionForHR(sourceFactoryNative.Get()->GetStatusUISource(syncRootIdHstring.GetAbi(), sourceNative.GetAddressOf()));
30+
if (PInvoke.CoCreateInstance(
31+
&factoryClsid,
32+
null,
33+
CLSCTX.CLSCTX_LOCAL_SERVER,
34+
(Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IStorageProviderStatusUISourceFactory.Guid)),
35+
(void**)pStorageProviderStatusUISourceFactory.GetAddressOf()).ThrowIfFailedOnDebug().Failed)
36+
return (false, 0, 0);
11737

118-
using (ComPtr<IStorageProviderStatusUI> statusNative = default)
119-
{
120-
ExceptionHelpers.ThrowExceptionForHR(sourceNative.Get()->GetStatusUI(statusNative.GetAddressOf()));
121-
statusUI = StorageProviderStatusUI.FromAbi((nint)statusNative.Get());
122-
}
123-
}
124-
}
125-
return (true, statusUI.QuotaUI.QuotaTotalInBytes, statusUI.QuotaUI.QuotaUsedInBytes);
126-
}
127-
else
128-
{
38+
var syncRootIdHString = new MarshalString.Pinnable(syncRootId);
39+
fixed (char* pSyncRootIdHString = syncRootIdHString)
40+
{
41+
if (pStorageProviderStatusUISourceFactory.Get()->GetStatusUISource(syncRootIdHString.GetAbi(), pStorageProviderStatusUISource.GetAddressOf()).ThrowIfFailedOnDebug().Failed ||
42+
pStorageProviderStatusUISource.Get()->GetStatusUI(pStorageProviderStatusUI.GetAddressOf()).ThrowIfFailedOnDebug().Failed ||
43+
pStorageProviderStatusUI.Get()->GetQuotaUI(pStorageProviderQuotaUI.GetAddressOf()).ThrowIfFailedOnDebug().Failed ||
44+
pStorageProviderQuotaUI.Get()->GetQuotaTotalInBytes(&ulTotalSize).ThrowIfFailedOnDebug().Failed ||
45+
pStorageProviderQuotaUI.Get()->GetQuotaUsedInBytes(&ulUsedSize).ThrowIfFailedOnDebug().Failed)
12946
return (false, 0, 0);
130-
}
13147
}
48+
49+
return (true, ulTotalSize, ulUsedSize);
13250
}
13351

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

13957
try
14058
{
141-
syncRootInfo = StorageProviderSyncRootManager.GetSyncRootInformationForFolder(folder);
59+
syncRootInfo = Windows.Storage.Provider.StorageProviderSyncRootManager.GetSyncRootInformationForFolder(folder);
14260
}
14361
catch
14462
{

0 commit comments

Comments
 (0)