[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