[PATCH 2/2] shell32: Implement IFileOperation stub.
Jactry Zeng
jzeng at codeweavers.com
Mon Mar 30 04:52:21 CDT 2020
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48848
Signed-off-by: Jactry Zeng <jzeng at codeweavers.com>
---
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 | 37 +++++
5 files changed, 294 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 <stdarg.h>
#include <string.h>
#include <ctype.h>
@@ -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..3aa40ab271 100644
--- a/dlls/shell32/tests/shlfileop.c
+++ b/dlls/shell32/tests/shlfileop.c
@@ -2697,8 +2697,39 @@ static BOOL is_old_shell32(void)
return FALSE;
}
+static BOOL is_vista_plus;
+
+static void test_file_operation(void)
+{
+ IFileOperation *operation;
+ IUnknown *unk;
+ HRESULT hr;
+
+ if (!is_vista_plus)
+ {
+ win_skip("IFileOperation isn't supported.\n");
+ return;
+ }
+
+ hr = CoCreateInstance(&CLSID_FileOperation, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IFileOperation, (void **)&operation);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ 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)
{
+ static HRESULT (WINAPI *pSHQueryUserNotificationState)(QUERY_USER_NOTIFICATION_STATE *state);
+ HMODULE mod = GetModuleHandleA("shell32.dll");
+
+ pSHQueryUserNotificationState = (void*)GetProcAddress(mod, "SHQueryUserNotificationState");
+ is_vista_plus = pSHQueryUserNotificationState != NULL;
+
clean_after_shfo_tests();
init_shfo_tests();
@@ -2742,4 +2773,10 @@ START_TEST(shlfileop)
test_unicode();
test_shlmenu();
+
+ CoInitialize(NULL);
+
+ test_file_operation();
+
+ CoUninitialize();
}
--
2.26.0
More information about the wine-devel
mailing list