Skip to content

Commit eee7622

Browse files
authored
Code Quality: Dispose all com instances (#16195)
1 parent 2c84ab9 commit eee7622

File tree

8 files changed

+204
-161
lines changed

8 files changed

+204
-161
lines changed

src/Files.App/Actions/FileSystem/RestoreAllRecycleBinAction.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public async Task ExecuteAsync(object? parameter = null)
4141
if (await confirmationDialog.TryShowAsync() is not ContentDialogResult.Primary)
4242
return;
4343

44-
bool result = await Task.Run(StorageTrashBinService.RestoreAllTrashes);
44+
bool result = await StorageTrashBinService.RestoreAllTrashesAsync();
4545

4646
// Show error dialog when failed
4747
if (!result)

src/Files.App/Data/Contracts/IStorageTrashBinService.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,6 @@ public interface IStorageTrashBinService
6262
/// Restores files and folders in Recycle Bin to original paths.
6363
/// </summary>
6464
/// <returns>True if succeeded; otherwise, false</returns>
65-
bool RestoreAllTrashes();
65+
Task<bool> RestoreAllTrashesAsync();
6666
}
6767
}

src/Files.App/Services/Storage/StorageTrashBinService.cs

+58-53
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ public async Task<bool> CanGoTrashBin(string? path)
7070
/// <inheritdoc/>
7171
public bool EmptyTrashBin()
7272
{
73+
// TODO: Use IFileOperation instead of its wrapper for the operation status to be reported.
7374
var fRes = PInvoke.SHEmptyRecycleBin(
7475
new(),
7576
string.Empty,
@@ -80,66 +81,70 @@ public bool EmptyTrashBin()
8081
}
8182

8283
/// <inheritdoc/>
83-
public unsafe bool RestoreAllTrashes()
84+
public async Task<bool> RestoreAllTrashesAsync()
8485
{
85-
IShellItem* recycleBinFolderShellItem = default;
86-
IEnumShellItems* enumShellItems = default;
87-
IFileOperation* pFileOperation = default;
88-
IShellItem* pShellItem = default;
89-
90-
try
86+
return await Win32Helper.StartSTATask(() =>
9187
{
92-
// Get IShellItem for Recycle Bin
93-
var recycleBinFolderId = FOLDERID.FOLDERID_RecycleBinFolder;
94-
var shellItemGuid = typeof(IShellItem).GUID;
95-
PInvoke.SHGetKnownFolderItem(&recycleBinFolderId, KNOWN_FOLDER_FLAG.KF_FLAG_DEFAULT, HANDLE.Null, &shellItemGuid, (void**)&recycleBinFolderShellItem);
96-
97-
// Get IEnumShellItems for Recycle Bin
98-
Guid enumShellItemGuid = typeof(IEnumShellItems).GUID;
99-
var enumItemsBHID = BHID.BHID_EnumItems;
100-
recycleBinFolderShellItem->BindToHandler(null, &enumItemsBHID, &enumShellItemGuid, (void**)&enumShellItems);
101-
102-
// Initialize how to perform the operation
103-
PInvoke.CoCreateInstance(typeof(FileOperation).GUID, null, CLSCTX.CLSCTX_LOCAL_SERVER, out pFileOperation);
104-
pFileOperation->SetOperationFlags(FILEOPERATION_FLAGS.FOF_NO_UI);
105-
pFileOperation->SetOwnerWindow(new(MainWindow.Instance.WindowHandle));
106-
107-
while (enumShellItems->Next(1, &pShellItem) == HRESULT.S_OK)
88+
try
10889
{
109-
// Get original path
110-
pShellItem->QueryInterface(typeof(IShellItem2).GUID, out var pShellItem2Ptr);
111-
var pShellItem2 = (IShellItem2*)pShellItem2Ptr;
112-
PInvoke.PSGetPropertyKeyFromName("System.Recycle.DeletedFrom", out var originalPathPropertyKey);
113-
pShellItem2->GetString(originalPathPropertyKey, out var szOriginalPath);
114-
pShellItem2->Release();
115-
116-
// Get IShellItem of the original path
117-
PInvoke.SHCreateItemFromParsingName(szOriginalPath.ToString(), null, typeof(IShellItem).GUID, out var pOriginalPathShellItemPtr);
118-
var pOriginalPathShellItem = (IShellItem*)pOriginalPathShellItemPtr;
119-
120-
// Define to move the shell item
121-
pFileOperation->MoveItem(pShellItem, pOriginalPathShellItem, new PCWSTR(), null);
122-
}
90+
RestoreAllTrashesInternal();
12391

124-
// Perform
125-
pFileOperation->PerformOperations();
126-
127-
// Reset the icon
128-
Win32PInvoke.SHUpdateRecycleBinIcon();
92+
return true;
93+
}
94+
catch
95+
{
96+
return false;
97+
}
98+
});
99+
}
129100

130-
return true;
131-
}
132-
catch
133-
{
134-
return false;
135-
}
136-
finally
101+
private unsafe bool RestoreAllTrashesInternal()
102+
{
103+
// Get IShellItem for Recycle Bin folder
104+
using ComPtr<IShellItem> pRecycleBinFolderShellItem = default;
105+
var recycleBinFolderId = FOLDERID.FOLDERID_RecycleBinFolder;
106+
var shellItemGuid = typeof(IShellItem).GUID;
107+
HRESULT hr = PInvoke.SHGetKnownFolderItem(&recycleBinFolderId, KNOWN_FOLDER_FLAG.KF_FLAG_DEFAULT, HANDLE.Null, &shellItemGuid, (void**)pRecycleBinFolderShellItem.GetAddressOf());
108+
109+
// Get IEnumShellItems for Recycle Bin folder
110+
using ComPtr<IEnumShellItems> pEnumShellItems = default;
111+
Guid enumShellItemGuid = typeof(IEnumShellItems).GUID;
112+
var enumItemsBHID = BHID.BHID_EnumItems;
113+
hr = pRecycleBinFolderShellItem.Get()->BindToHandler(null, &enumItemsBHID, &enumShellItemGuid, (void**)pEnumShellItems.GetAddressOf());
114+
115+
// Initialize how to perform the operation
116+
using ComPtr<IFileOperation> pFileOperation = default;
117+
var fileOperationIid = typeof(IFileOperation).GUID;
118+
var fileOperationInstanceIid = typeof(FileOperation).GUID;
119+
hr = PInvoke.CoCreateInstance(&fileOperationInstanceIid, null, CLSCTX.CLSCTX_LOCAL_SERVER, &fileOperationIid, (void**)pFileOperation.GetAddressOf());
120+
hr = pFileOperation.Get()->SetOperationFlags(FILEOPERATION_FLAGS.FOF_NO_UI);
121+
hr = pFileOperation.Get()->SetOwnerWindow(new(MainWindow.Instance.WindowHandle));
122+
123+
using ComPtr<IShellItem> pShellItem = default;
124+
while (pEnumShellItems.Get()->Next(1, pShellItem.GetAddressOf()) == HRESULT.S_OK)
137125
{
138-
recycleBinFolderShellItem->Release();
139-
enumShellItems->Release();
140-
pFileOperation->Release();
141-
pShellItem->Release();
126+
// Get the original path
127+
using ComPtr<IShellItem2> pShellItem2 = default;
128+
var shellItem2Iid = typeof(IShellItem2).GUID;
129+
hr = pShellItem.Get()->QueryInterface(&shellItem2Iid, (void**)pShellItem2.GetAddressOf());
130+
hr = PInvoke.PSGetPropertyKeyFromName("System.Recycle.DeletedFrom", out var originalPathPropertyKey);
131+
hr = pShellItem2.Get()->GetString(originalPathPropertyKey, out var szOriginalPath);
132+
133+
// Get IShellItem of the original path
134+
hr = PInvoke.SHCreateItemFromParsingName(szOriginalPath.ToString(), null, typeof(IShellItem).GUID, out var pOriginalPathShellItemPtr);
135+
var pOriginalPathShellItem = (IShellItem*)pOriginalPathShellItemPtr;
136+
137+
// Define the shell item to restore
138+
hr = pFileOperation.Get()->MoveItem(pShellItem.Get(), pOriginalPathShellItem, default(PCWSTR), null);
142139
}
140+
141+
// Perform
142+
hr = pFileOperation.Get()->PerformOperations();
143+
144+
// Reset the icon
145+
Win32PInvoke.SHUpdateRecycleBinIcon();
146+
147+
return true;
143148
}
144149
}
145150
}

0 commit comments

Comments
 (0)