Skip to content

Commit 97f7755

Browse files
committed
Update restore operation on Windows
1 parent 2784d69 commit 97f7755

File tree

1 file changed

+61
-8
lines changed

1 file changed

+61
-8
lines changed

source/trashcan.d

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,7 @@ version(Windows) private
476476
}
477477

478478
extern(Windows) HRESULT SHCreateShellItem(LPCITEMIDLIST pidlParent, IShellFolder psfParent, LPCITEMIDLIST pidl, IShellItem *ppsi) nothrow @nogc;
479+
extern(Windows) LPITEMIDLIST ILCreateFromPath(PCTSTR pszPath);
479480

480481
alias IFileOperationProgressSink = IUnknown;
481482
alias IOperationsProgressDialog = IUnknown;
@@ -603,6 +604,18 @@ version(Windows) private
603604
return string.init;
604605
}
605606

607+
@trusted static wstring getWStringDetailOf(IShellFolder2 folder, LPITEMIDLIST pidl, uint index)
608+
in {
609+
assert(folder);
610+
assert(pidl);
611+
}
612+
body {
613+
SHELLDETAILS details;
614+
if(SUCCEEDED(folder.GetDetailsOf(pidl, index, &details)))
615+
return StrRetToWString(details.str, pidl);
616+
return wstring.init;
617+
}
618+
606619
@trusted static SysTime getSysTimeDetailOf(IShellFolder2 folder, LPITEMIDLIST pidl, uint index)
607620
in {
608621
assert(folder);
@@ -633,26 +646,65 @@ version(Windows) private
633646
henforce(contextMenu.InvokeCommand(&ci), "Failed to " ~ verb ~ " item");
634647
}
635648

649+
@trusted static IFileOperation CreateFileOperation()
650+
{
651+
IFileOperation op;
652+
henforce(CoCreateInstance(&CLSID_FileOperation, null, CLSCTX_ALL, &IID_IFileOperation, cast(void**)&op), "Failed to create instance of IFileOperation");
653+
assert(op);
654+
return op;
655+
}
656+
657+
@trusted static IShellItem CreateShellItem(IShellFolder folder, LPITEMIDLIST pidl)
658+
{
659+
IShellItem item;
660+
henforce(SHCreateShellItem(null, folder, pidl, &item), "Failed to get IShellItem");
661+
assert(item);
662+
return item;
663+
}
664+
636665
@trusted static void RunDeleteOperation(IShellFolder folder, LPITEMIDLIST pidl)
637666
in {
638667
assert(folder);
639668
}
640669
body {
641-
enforce(pidl !is null, "Empty trashcan item, can't run an operation");
642-
IShellItem item;
643-
henforce(SHCreateShellItem(null, folder, pidl, &item), "Failed to get IShellItem");
644-
assert(item);
670+
enforce(pidl !is null, "Empty trashcan item, can't run a delete operation");
671+
IShellItem item = CreateShellItem(folder, pidl);
645672
scope(exit) item.Release();
646673

647-
IFileOperation op;
648-
henforce(CoCreateInstance(&CLSID_FileOperation, null, CLSCTX_ALL, &IID_IFileOperation, cast(void**)&op), "Failed to create instance of IFileOperation");
649-
assert(op);
674+
IFileOperation op = CreateFileOperation();
650675
scope(exit) op.Release();
651676

652677
op.SetOperationFlags(FOF_NOCONFIRMATION|FOF_NOERRORUI|FOF_SILENT);
653678
op.DeleteItem(item, null);
654679
henforce(op.PerformOperations(), "Failed to perform file deletion operation");
655680
}
681+
682+
@trusted static void RunRestoreOperation(IShellFolder2 folder, LPITEMIDLIST pidl)
683+
in {
684+
assert(folder);
685+
}
686+
body {
687+
enforce(pidl !is null, "Empty trashcan item, can't run a restore operation");
688+
689+
import std.utf;
690+
wstring originalLocation = getWStringDetailOf(folder, pidl, 1);
691+
auto originalLocationZ = originalLocation.toUTF16z;
692+
693+
auto originalLocationPidl = ILCreateFromPath(originalLocationZ);
694+
scope(exit) ILFree(originalLocationPidl);
695+
696+
IShellItem originalLocationItem = CreateShellItem(null, originalLocationPidl);
697+
698+
IShellItem item = CreateShellItem(folder, pidl);
699+
scope(exit) item.Release();
700+
701+
IFileOperation op = CreateFileOperation();
702+
scope(exit) op.Release();
703+
704+
op.SetOperationFlags(FOF_NOCONFIRMATION|FOF_NOERRORUI|FOF_SILENT);
705+
op.MoveItem(item, originalLocationItem, null, null);
706+
henforce(op.PerformOperations(), "Failed to perform file deletion operation");
707+
}
656708
}
657709

658710
/// Interface to trashcan.
@@ -810,7 +862,8 @@ else version(Windows) final class Trashcan : ITrashcan
810862
}
811863

812864
private @trusted void trustedRestore(ref scope TrashcanItem item) {
813-
RunVerb!"undelete"(_recycleBin, item.itemIdList);
865+
//RunVerb!"undelete"(_recycleBin, item.itemIdList);
866+
RunRestoreOperation(_recycleBin, item.itemIdList);
814867
}
815868
@safe void restore(ref scope TrashcanItem item) {
816869
trustedRestore(item);

0 commit comments

Comments
 (0)