From: Haoyang Chen chenhaoyang@kylinos.cn
--- dlls/shell32/shlfileop.c | 137 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 129 insertions(+), 8 deletions(-)
diff --git a/dlls/shell32/shlfileop.c b/dlls/shell32/shlfileop.c index ebc784acb93..6dfc53b29ce 100644 --- a/dlls/shell32/shlfileop.c +++ b/dlls/shell32/shlfileop.c @@ -1798,6 +1798,17 @@ HRESULT WINAPI SHMultiFileProperties(IDataObject *pdtobj, DWORD flags) return E_NOTIMPL; }
+struct file_operation +{ + struct list entry; + UINT wFunc; + LPWSTR pFrom; + LPWSTR pTo; + LPWSTR pNewName; + LPWSTR pTemplateName; + DWORD attributes; +}; + struct file_operations { IFileOperation IFileOperation_iface; @@ -1808,6 +1819,80 @@ struct file_operations struct list ops; };
+static HRESULT create_operation( IShellItem *item, IShellItem *folder, + LPCWSTR name, UINT func, struct file_operation **out) +{ + LPWSTR tmp, from = NULL, to = NULL; + HRESULT ret; + + if (!out) return ERROR_INVALID_PARAMETER; + + ret = IShellItem_GetDisplayName(item, SIGDN_FILESYSPATH, &tmp); + if (S_OK != ret) + { + return ERROR_INVALID_PARAMETER; + } + + from = calloc(lstrlenW(tmp) + 2, sizeof(WCHAR)); + if (!from) + { + ret = E_OUTOFMEMORY; + CoTaskMemFree(tmp); + goto end; + } + + lstrcpyW(from, tmp); + CoTaskMemFree(tmp); + + if (func != FO_DELETE) + { + + ret = IShellItem_GetDisplayName(folder, SIGDN_FILESYSPATH, &tmp); + if (S_OK != ret) + { + ret = ERROR_INVALID_PARAMETER; + goto end; + } + + if (name) + { + to = calloc(lstrlenW(tmp) + MAX_PATH + 2, sizeof(WCHAR)); + PathCombineW(to, tmp, name); + } + else + { + to = calloc(lstrlenW(tmp) + 2, sizeof(WCHAR)); + if (!to) + { + ret = E_OUTOFMEMORY; + CoTaskMemFree(tmp); + goto end; + } + + lstrcpyW(to, tmp); + } + CoTaskMemFree(tmp); + } + + *out = calloc(1, sizeof(struct file_operation)); + if (!*out) + { + ret = E_OUTOFMEMORY; + goto end; + } + + (*out)->wFunc = func; + (*out)->pFrom = from; + (*out)->pTo = to; + return ret; + +end: + free(from); + free(to); + + return ret; +} + static inline struct file_operations *impl_from_IFileOperation(IFileOperation *iface) { return CONTAINING_RECORD(iface, struct file_operations, IFileOperation_iface); @@ -1846,12 +1931,21 @@ static ULONG WINAPI file_operation_AddRef(IFileOperation *iface) static ULONG WINAPI file_operation_Release(IFileOperation *iface) { struct file_operations *operations = impl_from_IFileOperation(iface); + struct file_operation *ptr, *next; ULONG ref = InterlockedDecrement(&operations->ref);
TRACE("(%p): ref=%lu.\n", iface, ref);
if (!ref) { + LIST_FOR_EACH_ENTRY_SAFE( ptr, next, &operations->ops, struct file_operation, entry ) + { + if (ptr->pFrom) free((void*)ptr->pFrom); + if (ptr->pTo) free((void*)ptr->pTo); + if (ptr->pNewName) free((void*)ptr->pNewName); + if (ptr->pTemplateName) free((void*)ptr->pTemplateName); + free(ptr); + } free(operations); }
@@ -1932,9 +2026,16 @@ static HRESULT WINAPI file_operation_ApplyPropertiesToItems(IFileOperation *ifac static HRESULT WINAPI file_operation_RenameItem(IFileOperation *iface, IShellItem *item, LPCWSTR name, IFileOperationProgressSink *sink) { - FIXME("(%p, %p, %s, %p): stub.\n", iface, item, debugstr_w(name), sink); + struct file_operations *operations = impl_from_IFileOperation(iface); + struct file_operation *op; + HRESULT ret;
- return E_NOTIMPL; + TRACE("(%p, %p, %s, %p).\n", iface, item, debugstr_w(name), sink); + + ret = create_operation(item, item, name, FO_RENAME, &op); + + if (ret == S_OK) list_add_tail( &operations->ops, &op->entry ); + return ret; }
static HRESULT WINAPI file_operation_RenameItems(IFileOperation *iface, IUnknown *items, LPCWSTR name) @@ -1947,9 +2048,15 @@ static HRESULT WINAPI file_operation_RenameItems(IFileOperation *iface, IUnknown static HRESULT WINAPI file_operation_MoveItem(IFileOperation *iface, IShellItem *item, IShellItem *folder, LPCWSTR name, IFileOperationProgressSink *sink) { - FIXME("(%p, %p, %p, %s, %p): stub.\n", iface, item, folder, debugstr_w(name), sink); + struct file_operations *operations = impl_from_IFileOperation(iface); + struct file_operation *op; + HRESULT ret;
- return E_NOTIMPL; + TRACE("(%p, %p, %p, %s, %p).\n", iface, item, folder, debugstr_w(name), sink); + ret = create_operation(item, folder, name, FO_MOVE, &op); + + if (ret == S_OK) list_add_tail( &operations->ops, &op->entry ); + return ret; }
static HRESULT WINAPI file_operation_MoveItems(IFileOperation *iface, IUnknown *items, IShellItem *folder) @@ -1962,9 +2069,16 @@ static HRESULT WINAPI file_operation_MoveItems(IFileOperation *iface, IUnknown * static HRESULT WINAPI file_operation_CopyItem(IFileOperation *iface, IShellItem *item, IShellItem *folder, LPCWSTR name, IFileOperationProgressSink *sink) { - FIXME("(%p, %p, %p, %s, %p): stub.\n", iface, item, folder, debugstr_w(name), sink); + struct file_operations *operations = impl_from_IFileOperation(iface); + struct file_operation *op; + HRESULT ret;
- return E_NOTIMPL; + TRACE("(%p, %p, %p, %s, %p).\n", iface, item, folder, debugstr_w(name), sink); + + ret = create_operation(item, folder, name, FO_COPY, &op); + + if (ret == S_OK) list_add_tail( &operations->ops, &op->entry ); + return ret; }
static HRESULT WINAPI file_operation_CopyItems(IFileOperation *iface, IUnknown *items, IShellItem *folder) @@ -1977,9 +2091,16 @@ static HRESULT WINAPI file_operation_CopyItems(IFileOperation *iface, IUnknown * static HRESULT WINAPI file_operation_DeleteItem(IFileOperation *iface, IShellItem *item, IFileOperationProgressSink *sink) { - FIXME("(%p, %p, %p): stub.\n", iface, item, sink); + struct file_operations *operations = impl_from_IFileOperation(iface); + struct file_operation *op; + HRESULT ret;
- return E_NOTIMPL; + TRACE("(%p, %p, %p).\n", iface, item, sink); + + ret = create_operation(item, NULL, NULL , FO_DELETE, &op); + + if (ret == S_OK) list_add_tail( &operations->ops, &op->entry ); + return ret; }
static HRESULT WINAPI file_operation_DeleteItems(IFileOperation *iface, IUnknown *items)