|
@@ -347,15 +347,15 @@ void OpenExternal(const GURL& url,
|
|
|
std::move(callback));
|
|
|
}
|
|
|
|
|
|
-bool MoveItemToTrash(const base::FilePath& path, bool delete_on_fail) {
|
|
|
- base::win::ScopedCOMInitializer com_initializer;
|
|
|
- if (!com_initializer.Succeeded())
|
|
|
- return false;
|
|
|
-
|
|
|
+bool MoveItemToTrashWithError(const base::FilePath& path,
|
|
|
+ bool delete_on_fail,
|
|
|
+ std::string* error) {
|
|
|
Microsoft::WRL::ComPtr<IFileOperation> pfo;
|
|
|
if (FAILED(::CoCreateInstance(CLSID_FileOperation, nullptr, CLSCTX_ALL,
|
|
|
- IID_PPV_ARGS(&pfo))))
|
|
|
+ IID_PPV_ARGS(&pfo)))) {
|
|
|
+ *error = "Failed to create FileOperation instance";
|
|
|
return false;
|
|
|
+ }
|
|
|
|
|
|
// Elevation prompt enabled for UAC protected files. This overrides the
|
|
|
// SILENT, NO_UI and NOERRORUI flags.
|
|
@@ -365,38 +365,77 @@ bool MoveItemToTrash(const base::FilePath& path, bool delete_on_fail) {
|
|
|
// ALLOWUNDO in favor of ADDUNDORECORD.
|
|
|
if (FAILED(pfo->SetOperationFlags(
|
|
|
FOF_NO_UI | FOFX_ADDUNDORECORD | FOF_NOERRORUI | FOF_SILENT |
|
|
|
- FOFX_SHOWELEVATIONPROMPT | FOFX_RECYCLEONDELETE)))
|
|
|
+ FOFX_SHOWELEVATIONPROMPT | FOFX_RECYCLEONDELETE))) {
|
|
|
+ *error = "Failed to set operation flags";
|
|
|
return false;
|
|
|
+ }
|
|
|
} else {
|
|
|
// For Windows 7 and Vista, RecycleOnDelete is the default behavior.
|
|
|
if (FAILED(pfo->SetOperationFlags(FOF_NO_UI | FOF_ALLOWUNDO |
|
|
|
FOF_NOERRORUI | FOF_SILENT |
|
|
|
- FOFX_SHOWELEVATIONPROMPT)))
|
|
|
+ FOFX_SHOWELEVATIONPROMPT))) {
|
|
|
+ *error = "Failed to set operation flags";
|
|
|
return false;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// Create an IShellItem from the supplied source path.
|
|
|
Microsoft::WRL::ComPtr<IShellItem> delete_item;
|
|
|
if (FAILED(SHCreateItemFromParsingName(
|
|
|
path.value().c_str(), NULL,
|
|
|
- IID_PPV_ARGS(delete_item.GetAddressOf()))))
|
|
|
+ IID_PPV_ARGS(delete_item.GetAddressOf())))) {
|
|
|
+ *error = "Failed to parse path";
|
|
|
return false;
|
|
|
+ }
|
|
|
|
|
|
Microsoft::WRL::ComPtr<IFileOperationProgressSink> delete_sink(
|
|
|
new DeleteFileProgressSink);
|
|
|
- if (!delete_sink)
|
|
|
+ if (!delete_sink) {
|
|
|
+ *error = "Failed to create delete sink";
|
|
|
return false;
|
|
|
+ }
|
|
|
|
|
|
BOOL pfAnyOperationsAborted;
|
|
|
|
|
|
// Processes the queued command DeleteItem. This will trigger
|
|
|
// the DeleteFileProgressSink to check for Recycle Bin.
|
|
|
- return SUCCEEDED(pfo->DeleteItem(delete_item.Get(), delete_sink.Get())) &&
|
|
|
- SUCCEEDED(pfo->PerformOperations()) &&
|
|
|
- SUCCEEDED(pfo->GetAnyOperationsAborted(&pfAnyOperationsAborted)) &&
|
|
|
- !pfAnyOperationsAborted;
|
|
|
+ if (!SUCCEEDED(pfo->DeleteItem(delete_item.Get(), delete_sink.Get()))) {
|
|
|
+ *error = "Failed to enqueue DeleteItem command";
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!SUCCEEDED(pfo->PerformOperations())) {
|
|
|
+ *error = "Failed to perform delete operation";
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!SUCCEEDED(pfo->GetAnyOperationsAborted(&pfAnyOperationsAborted))) {
|
|
|
+ *error = "Failed to check operation status";
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (pfAnyOperationsAborted) {
|
|
|
+ *error = "Operation was aborted";
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
+bool MoveItemToTrash(const base::FilePath& path, bool delete_on_fail) {
|
|
|
+ std::string error; // ignored
|
|
|
+ base::win::ScopedCOMInitializer com_initializer;
|
|
|
+ return MoveItemToTrashWithError(path, delete_on_fail, &error);
|
|
|
+}
|
|
|
+
|
|
|
+namespace internal {
|
|
|
+
|
|
|
+bool PlatformTrashItem(const base::FilePath& full_path, std::string* error) {
|
|
|
+ return MoveItemToTrashWithError(full_path, false, error);
|
|
|
+}
|
|
|
+
|
|
|
+} // namespace internal
|
|
|
+
|
|
|
bool GetFolderPath(int key, base::FilePath* result) {
|
|
|
wchar_t system_buffer[MAX_PATH];
|
|
|
|