Skip to content

Commit f4283f6

Browse files
committed
Update
1 parent 9dfc475 commit f4283f6

File tree

10 files changed

+98
-113
lines changed

10 files changed

+98
-113
lines changed

src/Files.App.CsWin32/ManualGuid.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ public static Guid* IID_IStorageProviderStatusUISourceFactory
4141

4242
[GuidRVAGen.Guid("00021500-0000-0000-C000-000000000046")]
4343
public static partial Guid* IID_IQueryInfo { get; }
44+
45+
[GuidRVAGen.Guid("BCC18B79-BA16-442F-80C4-8A59C30C463B")]
46+
public static partial Guid* IID_IShellItemImageFactory { get; }
4447
}
4548

4649
public static unsafe partial class CLSID
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
// Copyright (c) Files Community
22
// Licensed under the MIT License.
33

4-
using Windows.Win32;
54
using Windows.Win32.UI.Shell;
65

76
namespace Files.App.Storage
87
{
9-
public interface IWindowsStorable : IDisposable
8+
public unsafe interface IWindowsStorable : IDisposable
109
{
11-
ComPtr<IShellItem> ThisPtr { get; }
10+
IShellItem* ThisPtr { get; }
1211
}
1312
}

src/Files.App.Storage/Storables/WindowsStorage/WindowsBulkOperations.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ public unsafe WindowsBulkOperations(HWND ownerHWnd = default, FILEOPERATION_FLAG
101101
public unsafe HRESULT QueueCopyOperation(WindowsStorable targetItem, WindowsFolder destinationFolder, string? copyName)
102102
{
103103
fixed (char* pszCopyName = copyName)
104-
return _pFileOperation.Get()->CopyItem(targetItem.ThisPtr.Get(), destinationFolder.ThisPtr.Get(), pszCopyName, _pProgressSink.Get());
104+
return _pFileOperation.Get()->CopyItem(targetItem.ThisPtr, destinationFolder.ThisPtr, pszCopyName, _pProgressSink.Get());
105105
}
106106

107107
/// <summary>
@@ -111,7 +111,7 @@ public unsafe HRESULT QueueCopyOperation(WindowsStorable targetItem, WindowsFold
111111
/// <returns>If this method succeeds, it returns <see cref="HRESULT.S_OK"/>. Otherwise, it returns an <see cref="HRESULT"/> error code.</returns>
112112
public unsafe HRESULT QueueDeleteOperation(WindowsStorable targetItem)
113113
{
114-
return _pFileOperation.Get()->DeleteItem(targetItem.ThisPtr.Get(), _pProgressSink.Get());
114+
return _pFileOperation.Get()->DeleteItem(targetItem.ThisPtr, _pProgressSink.Get());
115115
}
116116

117117
/// <summary>
@@ -124,7 +124,7 @@ public unsafe HRESULT QueueDeleteOperation(WindowsStorable targetItem)
124124
public unsafe HRESULT QueueMoveOperation(WindowsStorable targetItem, WindowsFolder destinationFolder, string? newName)
125125
{
126126
fixed (char* pszNewName = newName)
127-
return _pFileOperation.Get()->MoveItem(targetItem.ThisPtr.Get(), destinationFolder.ThisPtr.Get(), pszNewName, null);
127+
return _pFileOperation.Get()->MoveItem(targetItem.ThisPtr, destinationFolder.ThisPtr, pszNewName, null);
128128
}
129129

130130
/// <summary>
@@ -138,7 +138,7 @@ public unsafe HRESULT QueueMoveOperation(WindowsStorable targetItem, WindowsFold
138138
public unsafe HRESULT QueueCreateOperation(WindowsFolder destinationFolder, FILE_FLAGS_AND_ATTRIBUTES fileAttributes, string name, string? templateName)
139139
{
140140
fixed (char* pszName = name, pszTemplateName = templateName)
141-
return _pFileOperation.Get()->NewItem(destinationFolder.ThisPtr.Get(), (uint)fileAttributes, pszName, pszTemplateName, _pProgressSink.Get());
141+
return _pFileOperation.Get()->NewItem(destinationFolder.ThisPtr, (uint)fileAttributes, pszName, pszTemplateName, _pProgressSink.Get());
142142
}
143143

144144
/// <summary>
@@ -150,7 +150,7 @@ public unsafe HRESULT QueueCreateOperation(WindowsFolder destinationFolder, FILE
150150
public unsafe HRESULT QueueRenameOperation(WindowsStorable targetItem, string newName)
151151
{
152152
fixed (char* pszNewName = newName)
153-
return _pFileOperation.Get()->RenameItem(targetItem.ThisPtr.Get(), pszNewName, _pProgressSink.Get());
153+
return _pFileOperation.Get()->RenameItem(targetItem.ThisPtr, pszNewName, _pProgressSink.Get());
154154
}
155155

156156
/// <summary>

src/Files.App.Storage/Storables/WindowsStorage/WindowsFile.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@
88
namespace Files.App.Storage
99
{
1010
[DebuggerDisplay("{" + nameof(ToString) + "()}")]
11-
public sealed class WindowsFile : WindowsStorable, IChildFile
11+
public unsafe sealed class WindowsFile : WindowsStorable, IChildFile
1212
{
13-
public WindowsFile(ComPtr<IShellItem> nativeObject)
13+
public WindowsFile(IShellItem* ptr)
1414
{
15-
ThisPtr = nativeObject;
15+
ThisPtr = ptr;
1616
}
1717

1818
public Task<Stream> OpenStreamAsync(FileAccess accessMode, CancellationToken cancellationToken = default)
Lines changed: 25 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// Copyright (c) Files Community
22
// Licensed under the MIT License.
33

4-
using System.Runtime.CompilerServices;
54
using Windows.Win32;
65
using Windows.Win32.Foundation;
76
using Windows.Win32.System.SystemServices;
@@ -10,29 +9,22 @@
109
namespace Files.App.Storage
1110
{
1211
[DebuggerDisplay("{" + nameof(ToString) + "()}")]
13-
public sealed class WindowsFolder : WindowsStorable, IChildFolder
12+
public unsafe sealed class WindowsFolder : WindowsStorable, IChildFolder
1413
{
15-
public WindowsFolder(ComPtr<IShellItem> nativeObject)
14+
public WindowsFolder(IShellItem* ptr)
1615
{
17-
ThisPtr = nativeObject;
18-
}
19-
20-
public unsafe WindowsFolder(IShellItem* nativeObject)
21-
{
22-
ComPtr<IShellItem> ptr = default;
23-
ptr.Attach(nativeObject);
2416
ThisPtr = ptr;
2517
}
2618

27-
public unsafe WindowsFolder(Guid folderId)
19+
public WindowsFolder(Guid folderId)
2820
{
29-
ComPtr<IShellItem> pItem = default;
21+
IShellItem* pItem = default;
3022

31-
HRESULT hr = PInvoke.SHGetKnownFolderItem(&folderId, KNOWN_FOLDER_FLAG.KF_FLAG_DEFAULT, HANDLE.Null, IID.IID_IShellItem, (void**)pItem.GetAddressOf());
23+
HRESULT hr = PInvoke.SHGetKnownFolderItem(&folderId, KNOWN_FOLDER_FLAG.KF_FLAG_DEFAULT, HANDLE.Null, IID.IID_IShellItem, (void**)&pItem);
3224
if (hr.Failed)
3325
{
3426
fixed (char* pszShellPath = $"Shell:::{folderId:B}")
35-
hr = PInvoke.SHCreateItemFromParsingName(pszShellPath, null, IID.IID_IShellItem, (void**)pItem.GetAddressOf());
27+
hr = PInvoke.SHCreateItemFromParsingName(pszShellPath, null, IID.IID_IShellItem, (void**)&pItem);
3628

3729
// Invalid FOLDERID; this should never happen.
3830
hr.ThrowOnFailure();
@@ -43,47 +35,35 @@ public unsafe WindowsFolder(Guid folderId)
4335

4436
public IAsyncEnumerable<IStorableChild> GetItemsAsync(StorableType type = StorableType.All, CancellationToken cancellationToken = default)
4537
{
46-
return GetItems().ToAsyncEnumerable();
38+
ComPtr<IEnumShellItems> pEnumShellItems = default;
39+
HRESULT hr = ThisPtr->BindToHandler(null, BHID.BHID_EnumItems, IID.IID_IEnumShellItems, (void**)pEnumShellItems.GetAddressOf());
40+
if (hr.ThrowIfFailedOnDebug().Failed)
41+
return Enumerable.Empty<IStorableChild>().ToAsyncEnumerable();
4742

48-
unsafe IEnumerable<IStorableChild> GetItems()
43+
List<IStorableChild> items = [];
44+
IShellItem* pShellItem = default;
45+
while (pEnumShellItems.Get()->Next(1, &pShellItem).Succeeded && pShellItem is not null)
4946
{
50-
ComPtr<IEnumShellItems> pEnumShellItems = default;
51-
GetEnumerator();
47+
cancellationToken.ThrowIfCancellationRequested();
5248

53-
ComPtr<IShellItem> pShellItem = default;
54-
while (GetNext() && !pShellItem.IsNull)
55-
{
56-
cancellationToken.ThrowIfCancellationRequested();
57-
var isFolder = pShellItem.HasShellAttributes(SFGAO_FLAGS.SFGAO_FOLDER);
49+
var isFolder = pShellItem->GetAttributes(SFGAO_FLAGS.SFGAO_FOLDER, out var returnedAttributes).Succeeded &&
50+
returnedAttributes == SFGAO_FLAGS.SFGAO_FOLDER;
5851

59-
if (type is StorableType.File && !isFolder)
60-
{
61-
yield return new WindowsFile(pShellItem);
62-
}
63-
else if (type is StorableType.Folder && isFolder)
64-
{
65-
yield return new WindowsFolder(pShellItem);
66-
}
67-
else
68-
{
69-
continue;
70-
}
52+
if (type is StorableType.File && !isFolder)
53+
{
54+
items.Add(new WindowsFile(pShellItem));
7155
}
72-
73-
yield break;
74-
75-
unsafe void GetEnumerator()
56+
else if (type is StorableType.Folder && isFolder)
7657
{
77-
HRESULT hr = ThisPtr.Get()->BindToHandler(null, BHID.BHID_EnumItems, IID.IID_IEnumShellItems, (void**)pEnumShellItems.GetAddressOf());
78-
hr.ThrowIfFailedOnDebug();
58+
items.Add(new WindowsFolder(pShellItem));
7959
}
80-
81-
unsafe bool GetNext()
60+
else
8261
{
83-
HRESULT hr = pEnumShellItems.Get()->Next(1, pShellItem.GetAddressOf());
84-
return hr.ThrowIfFailedOnDebug() == HRESULT.S_OK;
62+
continue;
8563
}
8664
}
65+
66+
return items.ToAsyncEnumerable();
8767
}
8868
}
8969
}

src/Files.App.Storage/Storables/WindowsStorage/WindowsStorable.cs

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,62 @@
11
// Copyright (c) Files Community
22
// Licensed under the MIT License.
33

4+
using System.Runtime.CompilerServices;
45
using Windows.Win32;
56
using Windows.Win32.Foundation;
67
using Windows.Win32.System.SystemServices;
78
using Windows.Win32.UI.Shell;
89

910
namespace Files.App.Storage
1011
{
11-
public abstract class WindowsStorable : IWindowsStorable, IStorableChild, IEquatable<IWindowsStorable>
12+
public unsafe abstract class WindowsStorable : IWindowsStorable, IStorableChild, IEquatable<IWindowsStorable>
1213
{
13-
public ComPtr<IShellItem> ThisPtr { get; protected set; }
14+
public IShellItem* ThisPtr
15+
{
16+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
17+
get;
18+
19+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
20+
protected set;
21+
}
1422

15-
public string Id => this.GetDisplayName(SIGDN.SIGDN_FILESYSPATH);
23+
public string Id
24+
=> this.GetDisplayName(SIGDN.SIGDN_FILESYSPATH);
1625

17-
public string Name => this.GetDisplayName(SIGDN.SIGDN_PARENTRELATIVEFORUI);
26+
public string Name
27+
=> this.GetDisplayName(SIGDN.SIGDN_PARENTRELATIVEFORUI);
1828

19-
public static unsafe WindowsStorable? TryParse(string parsablePath)
29+
public static WindowsStorable? TryParse(string parsablePath)
2030
{
2131
HRESULT hr = default;
22-
ComPtr<IShellItem> pShellItem = default;
23-
var IID_IShellItem = typeof(IShellItem).GUID;
32+
IShellItem* pShellItem = default;
2433

2534
fixed (char* pszParsablePath = parsablePath)
26-
{
27-
hr = PInvoke.SHCreateItemFromParsingName(
28-
pszParsablePath,
29-
null,
30-
&IID_IShellItem,
31-
(void**)pShellItem.GetAddressOf());
32-
}
35+
hr = PInvoke.SHCreateItemFromParsingName(pszParsablePath, null, IID.IID_IShellItem, (void**)&pShellItem);
3336

34-
if (pShellItem.IsNull)
37+
if (pShellItem is null)
3538
return null;
3639

37-
return pShellItem.HasShellAttributes(SFGAO_FLAGS.SFGAO_FOLDER)
38-
? new WindowsFolder(pShellItem)
39-
: new WindowsFile(pShellItem);
40+
bool isFolder = pShellItem->GetAttributes(SFGAO_FLAGS.SFGAO_FOLDER, out var returnedAttributes).Succeeded &&
41+
returnedAttributes is SFGAO_FLAGS.SFGAO_FOLDER;
42+
43+
return isFolder ? new WindowsFolder(pShellItem) : new WindowsFile(pShellItem);
4044
}
4145

42-
public static unsafe WindowsStorable? TryParse(IShellItem* ptr)
46+
public static WindowsStorable? TryParse(IShellItem* ptr)
4347
{
44-
ComPtr<IShellItem> pShellItem = default;
45-
pShellItem.Attach(ptr);
48+
bool isFolder = ptr->GetAttributes(SFGAO_FLAGS.SFGAO_FOLDER, out var returnedAttributes).Succeeded &&
49+
returnedAttributes is SFGAO_FLAGS.SFGAO_FOLDER;
4650

47-
return pShellItem.HasShellAttributes(SFGAO_FLAGS.SFGAO_FOLDER)
48-
? new WindowsFolder(pShellItem)
49-
: new WindowsFile(pShellItem);
51+
return isFolder ? new WindowsFolder(ptr) : new WindowsFile(ptr);
5052
}
5153

52-
public unsafe Task<IFolder?> GetParentAsync(CancellationToken cancellationToken = default)
54+
public Task<IFolder?> GetParentAsync(CancellationToken cancellationToken = default)
5355
{
5456
cancellationToken.ThrowIfCancellationRequested();
5557

5658
ComPtr<IShellItem> pParentFolder = default;
57-
HRESULT hr = ThisPtr.Get()->GetParent(pParentFolder.GetAddressOf());
59+
HRESULT hr = ThisPtr->GetParent(pParentFolder.GetAddressOf());
5860
if (hr.Failed)
5961
{
6062
if (!pParentFolder.IsNull) pParentFolder.Dispose();
@@ -79,7 +81,7 @@ public override int GetHashCode()
7981
/// <inheritdoc/>
8082
public void Dispose()
8183
{
82-
ThisPtr.Dispose();
84+
ThisPtr->Release();
8385
}
8486

8587
/// <inheritdoc/>
@@ -94,7 +96,7 @@ public unsafe bool Equals(IWindowsStorable? other)
9496
if (other is null)
9597
return false;
9698

97-
return ThisPtr.Get()->Compare(other.ThisPtr.Get(), (uint)_SICHINTF.SICHINT_DISPLAY, out int order).Succeeded && order is 0;
99+
return ThisPtr->Compare(other.ThisPtr, (uint)_SICHINTF.SICHINT_DISPLAY, out int order).Succeeded && order is 0;
98100
}
99101

100102
public static bool operator ==(WindowsStorable left, WindowsStorable right)

src/Files.App.Storage/Storables/WindowsStorage/WindowsStorableHelpers.Icon.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ public unsafe static HRESULT TryGetThumbnail(this IWindowsStorable storable, int
4545
thumbnailData = null;
4646

4747
using ComPtr<IShellItemImageFactory> pShellItemImageFactory = default;
48-
storable.ThisPtr.As(pShellItemImageFactory.GetAddressOf());
48+
storable.ThisPtr->QueryInterface(IID.IID_IShellItemImageFactory, (void**)pShellItemImageFactory.GetAddressOf());
49+
4950
if (pShellItemImageFactory.IsNull)
5051
return HRESULT.E_NOINTERFACE;
5152

@@ -270,7 +271,7 @@ public unsafe static HRESULT TrySetShortcutIcon(this IWindowsStorable storable,
270271
Guid IID_IShellLink = IShellLinkW.IID_Guid;
271272
Guid BHID_SFUIObject = PInvoke.BHID_SFUIObject;
272273

273-
HRESULT hr = storable.ThisPtr.Get()->BindToHandler(null, &BHID_SFUIObject, &IID_IShellLink, (void**)pShellLink.GetAddressOf());
274+
HRESULT hr = storable.ThisPtr->BindToHandler(null, &BHID_SFUIObject, &IID_IShellLink, (void**)pShellLink.GetAddressOf());
274275
if (hr.ThrowIfFailedOnDebug().Failed)
275276
return hr;
276277

src/Files.App.Storage/Storables/WindowsStorage/WindowsStorableHelpers.Shell.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public static partial class WindowsStorableHelpers
1717
public unsafe static HRESULT GetPropertyValue<TValue>(this IWindowsStorable storable, string propKey, out TValue value)
1818
{
1919
using ComPtr<IShellItem2> pShellItem2 = default;
20-
HRESULT hr = storable.ThisPtr.Get()->QueryInterface(IID.IID_IShellItem2, (void**)pShellItem2.GetAddressOf());
20+
HRESULT hr = storable.ThisPtr->QueryInterface(IID.IID_IShellItem2, (void**)pShellItem2.GetAddressOf());
2121

2222
PROPERTYKEY propertyKey = default;
2323
fixed (char* pszPropertyKey = propKey)
@@ -49,20 +49,20 @@ public unsafe static HRESULT GetPropertyValue<TValue>(this IWindowsStorable stor
4949

5050
public unsafe static bool HasShellAttributes(this IWindowsStorable storable, SFGAO_FLAGS attributes)
5151
{
52-
return storable.ThisPtr.Get()->GetAttributes(SFGAO_FLAGS.SFGAO_FOLDER, out var returnedAttributes).Succeeded &&
52+
return storable.ThisPtr->GetAttributes(SFGAO_FLAGS.SFGAO_FOLDER, out var returnedAttributes).Succeeded &&
5353
returnedAttributes == attributes;
5454
}
5555

5656
public unsafe static bool HasShellAttributes(this ComPtr<IShellItem> pShellItem, SFGAO_FLAGS attributes)
5757
{
58-
return pShellItem.Get()->GetAttributes(SFGAO_FLAGS.SFGAO_FOLDER, out var returnedAttributes).Succeeded &&
58+
return pShellItem.Get()->GetAttributes(attributes, out var returnedAttributes).Succeeded &&
5959
returnedAttributes == attributes;
6060
}
6161

6262
public unsafe static string GetDisplayName(this IWindowsStorable storable, SIGDN options = SIGDN.SIGDN_FILESYSPATH)
6363
{
6464
using ComHeapPtr<PWSTR> pszName = default;
65-
HRESULT hr = storable.ThisPtr.Get()->GetDisplayName(options, (PWSTR*)pszName.GetAddressOf());
65+
HRESULT hr = storable.ThisPtr->GetDisplayName(options, (PWSTR*)pszName.GetAddressOf());
6666

6767
return hr.ThrowIfFailedOnDebug().Succeeded
6868
? new string((char*)pszName.Get()) // this is safe as it gets memcpy'd internally
@@ -74,7 +74,7 @@ public unsafe static HRESULT TryInvokeContextMenuVerb(this IWindowsStorable stor
7474
Debug.Assert(Thread.CurrentThread.GetApartmentState() is ApartmentState.STA);
7575

7676
using ComPtr<IContextMenu> pContextMenu = default;
77-
HRESULT hr = storable.ThisPtr.Get()->BindToHandler(null, BHID.BHID_SFUIObject, IID.IID_IContextMenu, (void**)pContextMenu.GetAddressOf());
77+
HRESULT hr = storable.ThisPtr->BindToHandler(null, BHID.BHID_SFUIObject, IID.IID_IContextMenu, (void**)pContextMenu.GetAddressOf());
7878
HMENU hMenu = PInvoke.CreatePopupMenu();
7979
hr = pContextMenu.Get()->QueryContextMenu(hMenu, 0, 1, 0x7FFF, PInvoke.CMF_OPTIMIZEFORINVOKE);
8080

@@ -99,7 +99,7 @@ public unsafe static HRESULT TryInvokeContextMenuVerbs(this IWindowsStorable sto
9999
Debug.Assert(Thread.CurrentThread.GetApartmentState() is ApartmentState.STA);
100100

101101
using ComPtr<IContextMenu> pContextMenu = default;
102-
HRESULT hr = storable.ThisPtr.Get()->BindToHandler(null, BHID.BHID_SFUIObject, IID.IID_IContextMenu, (void**)pContextMenu.GetAddressOf());
102+
HRESULT hr = storable.ThisPtr->BindToHandler(null, BHID.BHID_SFUIObject, IID.IID_IContextMenu, (void**)pContextMenu.GetAddressOf());
103103
HMENU hMenu = PInvoke.CreatePopupMenu();
104104
hr = pContextMenu.Get()->QueryContextMenu(hMenu, 0, 1, 0x7FFF, PInvoke.CMF_OPTIMIZEFORINVOKE);
105105

@@ -130,7 +130,7 @@ public unsafe static HRESULT TryGetShellTooltip(this IWindowsStorable storable,
130130
tooltip = null;
131131

132132
using ComPtr<IQueryInfo> pQueryInfo = default;
133-
HRESULT hr = storable.ThisPtr.Get()->BindToHandler(null, BHID.BHID_SFUIObject, IID.IID_IQueryInfo, (void**)pQueryInfo.GetAddressOf());
133+
HRESULT hr = storable.ThisPtr->BindToHandler(null, BHID.BHID_SFUIObject, IID.IID_IQueryInfo, (void**)pQueryInfo.GetAddressOf());
134134
if (hr.ThrowIfFailedOnDebug().Failed)
135135
return hr;
136136

src/Files.App/Extensions/Win32Extensions.cs

Lines changed: 0 additions & 13 deletions
This file was deleted.

0 commit comments

Comments
 (0)