From: Jactry Zeng Subject: [PATCH v2 2/2] shell32: Implement IFileOperation stub. Message-Id: Date: Mon, 30 Mar 2020 23:03:42 +0800 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48848 Signed-off-by: Jactry Zeng --- dlls/shell32/shell32_classes.idl | 6 + dlls/shell32/shell32_main.h | 1 + dlls/shell32/shellole.c | 1 + dlls/shell32/shlfileop.c | 249 +++++++++++++++++++++++++++++++ dlls/shell32/tests/shlfileop.c | 29 ++++ 5 files changed, 286 insertions(+) diff --git a/dlls/shell32/shell32_classes.idl b/dlls/shell32/shell32_classes.idl index 6ed497fea5..f2c5ed4a76 100644 --- a/dlls/shell32/shell32_classes.idl +++ b/dlls/shell32/shell32_classes.idl @@ -166,3 +166,9 @@ coclass KnownFolderManager { interface IKnownFolderManager; } threading(apartment), uuid(66e4e4fb-f385-4dd0-8d74-a2efd1bc6178) ] coclass ShellImageDataFactory { interface IShellImageDataFactory; } + +[ + helpstring("Copy/Move/Rename/Delete/Link Object"), + threading(apartment), + uuid(3ad05575-8857-4850-9277-11b85bdb8e09) +] coclass FileOperation { interface IFileOperation; } diff --git a/dlls/shell32/shell32_main.h b/dlls/shell32/shell32_main.h index 11a96309e8..37c74612c0 100644 --- a/dlls/shell32/shell32_main.h +++ b/dlls/shell32/shell32_main.h @@ -103,6 +103,7 @@ HRESULT WINAPI RecycleBin_Constructor(IUnknown * pUnkOuter, REFIID riif, LPVOID HRESULT WINAPI QueryAssociations_Constructor(IUnknown *pUnkOuter, REFIID riid, LPVOID *ppOutput) DECLSPEC_HIDDEN; HRESULT WINAPI ExplorerBrowser_Constructor(IUnknown *pUnkOuter, REFIID riid, LPVOID *ppv) DECLSPEC_HIDDEN; HRESULT WINAPI KnownFolderManager_Constructor(IUnknown *pUnkOuter, REFIID riid, LPVOID *ppv) DECLSPEC_HIDDEN; +HRESULT WINAPI IFileOperation_Constructor(IUnknown *outer, REFIID riid, void **out) DECLSPEC_HIDDEN; extern HRESULT CPanel_GetIconLocationW(LPCITEMIDLIST, LPWSTR, UINT, int*) DECLSPEC_HIDDEN; HRESULT WINAPI CPanel_ExtractIconA(LPITEMIDLIST pidl, LPCSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize) DECLSPEC_HIDDEN; HRESULT WINAPI CPanel_ExtractIconW(LPITEMIDLIST pidl, LPCWSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize) DECLSPEC_HIDDEN; diff --git a/dlls/shell32/shellole.c b/dlls/shell32/shellole.c index e84402d7bc..3c88642512 100644 --- a/dlls/shell32/shellole.c +++ b/dlls/shell32/shellole.c @@ -89,6 +89,7 @@ static const struct { {&CLSID_Shell, IShellDispatch_Constructor}, {&CLSID_DestinationList, CustomDestinationList_Constructor}, {&CLSID_ShellImageDataFactory, ShellImageDataFactory_Constructor}, + {&CLSID_FileOperation, IFileOperation_Constructor}, {NULL, NULL} }; diff --git a/dlls/shell32/shlfileop.c b/dlls/shell32/shlfileop.c index b941db3914..5a507c3c11 100644 --- a/dlls/shell32/shlfileop.c +++ b/dlls/shell32/shlfileop.c @@ -24,6 +24,8 @@ #include "config.h" #include "wine/port.h" +#define COBJMACROS + #include #include #include @@ -1809,3 +1811,250 @@ HRESULT WINAPI SHMultiFileProperties(IDataObject *pdtobj, DWORD flags) FIXME("stub: %p %u\n", pdtobj, flags); return E_NOTIMPL; } + +struct file_operation +{ + IFileOperation IFileOperation_iface; + LONG ref; +}; + +static inline struct file_operation *impl_from_IFileOperation(IFileOperation *iface) +{ + return CONTAINING_RECORD(iface, struct file_operation, IFileOperation_iface); +} + +static HRESULT WINAPI file_operation_QueryInterface(IFileOperation *iface, REFIID riid, void **out) +{ + struct file_operation *This = impl_from_IFileOperation(iface); + + TRACE("(%p, %s, %p).\n", iface, debugstr_guid(riid), out); + + if (IsEqualIID(&IID_IFileOperation, riid) || + IsEqualIID(&IID_IUnknown, riid)) + *out = &This->IFileOperation_iface; + else + { + FIXME("not implemented for %s.\n", debugstr_guid(riid)); + *out = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*out); + return S_OK; +} + +static ULONG WINAPI file_operation_AddRef(IFileOperation *iface) +{ + struct file_operation *This = impl_from_IFileOperation(iface); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p): ref=%u.\n", iface, ref); + + return ref; +} + +static ULONG WINAPI file_operation_Release(IFileOperation *iface) +{ + struct file_operation *This = impl_from_IFileOperation(iface); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p): ref=%u.\n", iface, ref); + + if (!ref) + { + HeapFree(GetProcessHeap(), 0, This); + } + + return ref; +} + +static HRESULT WINAPI file_operation_Advise(IFileOperation *iface, IFileOperationProgressSink *sink, DWORD *cookie) +{ + FIXME("(%p, %p, %p): stub.\n", iface, sink, cookie); + + return E_NOTIMPL; +} + +static HRESULT WINAPI file_operation_Unadvise(IFileOperation *iface, DWORD cookie) +{ + FIXME("(%p, %x): stub.\n", iface, cookie); + + return E_NOTIMPL; +} + +static HRESULT WINAPI file_operation_SetOperationFlags(IFileOperation *iface, DWORD flags) +{ + FIXME("(%p, %x): stub.\n", iface, flags); + + return E_NOTIMPL; +} + +static HRESULT WINAPI file_operation_SetProgressMessage(IFileOperation *iface, LPCWSTR message) +{ + FIXME("(%p, %s): stub.\n", iface, debugstr_w(message)); + + return E_NOTIMPL; +} + +static HRESULT WINAPI file_operation_SetProgressDialog(IFileOperation *iface, IOperationsProgressDialog *dialog) +{ + FIXME("(%p, %p): stub.\n", iface, dialog); + + return E_NOTIMPL; +} + +static HRESULT WINAPI file_operation_SetProperties(IFileOperation *iface, IPropertyChangeArray *array) +{ + FIXME("(%p, %p): stub.\n", iface, array); + + return E_NOTIMPL; +} + +static HRESULT WINAPI file_operation_SetOwnerWindow(IFileOperation *iface, HWND owner) +{ + FIXME("(%p, %p): stub.\n", iface, owner); + + return E_NOTIMPL; +} + +static HRESULT WINAPI file_operation_ApplyPropertiesToItem(IFileOperation *iface, IShellItem *item) +{ + FIXME("(%p, %p): stub.\n", iface, item); + + return E_NOTIMPL; +} + +static HRESULT WINAPI file_operation_ApplyPropertiesToItems(IFileOperation *iface, IUnknown *items) +{ + FIXME("(%p, %p): stub.\n", iface, items); + + return E_NOTIMPL; +} + +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); + + return E_NOTIMPL; +} + +static HRESULT WINAPI file_operation_RenameItems(IFileOperation *iface, IUnknown *items, LPCWSTR name) +{ + FIXME("(%p, %p, %s): stub.\n", iface, items, debugstr_w(name)); + + return E_NOTIMPL; +} + +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); + + return E_NOTIMPL; +} + +static HRESULT WINAPI file_operation_MoveItems(IFileOperation *iface, IUnknown *items, IShellItem *folder) +{ + FIXME("(%p, %p, %p): stub.\n", iface, items, folder); + + return E_NOTIMPL; +} + +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); + + return E_NOTIMPL; +} + +static HRESULT WINAPI file_operation_CopyItems(IFileOperation *iface, IUnknown *items, IShellItem *folder) +{ + FIXME("(%p, %p, %p): stub.\n", iface, items, folder); + + return E_NOTIMPL; +} + +static HRESULT WINAPI file_operation_DeleteItem(IFileOperation *iface, IShellItem *item, + IFileOperationProgressSink *sink) +{ + FIXME("(%p, %p, %p): stub.\n", iface, item, sink); + + return E_NOTIMPL; +} + +static HRESULT WINAPI file_operation_DeleteItems(IFileOperation *iface, IUnknown *items) +{ + FIXME("(%p, %p): stub.\n", iface, items); + + return E_NOTIMPL; +} + +static HRESULT WINAPI file_operation_NewItem(IFileOperation *iface, IShellItem *folder, DWORD attributes, + LPCWSTR name, LPCWSTR template, IFileOperationProgressSink *sink) +{ + FIXME("(%p, %p, %x, %s, %s, %p): stub.\n", iface, folder, attributes, + debugstr_w(name), debugstr_w(template), sink); + + return E_NOTIMPL; +} + +static HRESULT WINAPI file_operation_PerformOperations(IFileOperation *iface) +{ + FIXME("(%p): stub.\n", iface); + + return E_NOTIMPL; +} + +static HRESULT WINAPI file_operation_GetAnyOperationsAborted(IFileOperation *iface, BOOL *aborted) +{ + FIXME("(%p, %p): stub.\n", iface, aborted); + + return E_NOTIMPL; +} + +static const IFileOperationVtbl file_operation_vtbl = +{ + file_operation_QueryInterface, + file_operation_AddRef, + file_operation_Release, + file_operation_Advise, + file_operation_Unadvise, + file_operation_SetOperationFlags, + file_operation_SetProgressMessage, + file_operation_SetProgressDialog, + file_operation_SetProperties, + file_operation_SetOwnerWindow, + file_operation_ApplyPropertiesToItem, + file_operation_ApplyPropertiesToItems, + file_operation_RenameItem, + file_operation_RenameItems, + file_operation_MoveItem, + file_operation_MoveItems, + file_operation_CopyItem, + file_operation_CopyItems, + file_operation_DeleteItem, + file_operation_DeleteItems, + file_operation_NewItem, + file_operation_PerformOperations, + file_operation_GetAnyOperationsAborted +}; + +HRESULT WINAPI IFileOperation_Constructor(IUnknown *outer, REFIID riid, void **out) +{ + struct file_operation *object; + HRESULT hr; + + object = heap_alloc_zero(sizeof(*object)); + if (!object) + return E_OUTOFMEMORY; + + object->IFileOperation_iface.lpVtbl = &file_operation_vtbl; + object->ref = 1; + + hr = IFileOperation_QueryInterface(&object->IFileOperation_iface, riid, out); + IFileOperation_Release(&object->IFileOperation_iface); + + return hr; +} diff --git a/dlls/shell32/tests/shlfileop.c b/dlls/shell32/tests/shlfileop.c index 27c7244042..ed98d24b41 100644 --- a/dlls/shell32/tests/shlfileop.c +++ b/dlls/shell32/tests/shlfileop.c @@ -2697,6 +2697,29 @@ static BOOL is_old_shell32(void) return FALSE; } +static void test_file_operation(void) +{ + IFileOperation *operation; + IUnknown *unk; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_FileOperation, NULL, CLSCTX_INPROC_SERVER, + &IID_IFileOperation, (void **)&operation); + ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG) /* before vista */, + "Got hr %#x.\n", hr); + if (hr == REGDB_E_CLASSNOTREG) + { + win_skip("IFileOperation isn't supported.\n"); + return; + } + + hr = IFileOperation_QueryInterface(operation, &IID_IUnknown, (void **)&unk); + ok(hr == S_OK, "Got hr %#x.\n", hr); + IUnknown_Release(unk); + + IFileOperation_Release(operation); +} + START_TEST(shlfileop) { clean_after_shfo_tests(); @@ -2742,4 +2765,10 @@ START_TEST(shlfileop) test_unicode(); test_shlmenu(); + + CoInitialize(NULL); + + test_file_operation(); + + CoUninitialize(); } -- 2.26.0