Signed-off-by: Jactry Zeng jzeng@codeweavers.com --- include/shobjidl.idl | 117 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+)
diff --git a/include/shobjidl.idl b/include/shobjidl.idl index 42ef264ed86..ab9b64430aa 100644 --- a/include/shobjidl.idl +++ b/include/shobjidl.idl @@ -3871,4 +3871,121 @@ library ShellObjects { interface IApplicationActivationManager; } + + [ + uuid(3ad05575-8857-4850-9277-11b85bdb8e09) + ] + coclass FileOperation + { + interface IFileOperation; + } +} + +[v1_enum] enum _OPPROGDLGF +{ + OPPROGDLG_DEFAULT = 0x00000000, + OPPROGDLG_ENABLEPAUSE = 0x00000080, + OPPROGDLG_ALLOWUNDO = 0x00000100, + OPPROGDLG_DONTDISPLAYSOURCEPATH = 0x00000200, + OPPROGDLG_DONTDISPLAYDESTPATH = 0x00000400, + OPPROGDLG_NOMULTIDAYESTIMATES = 0x00000800, + OPPROGDLG_DONTDISPLAYLOCATIONS = 0x00001000, +}; +typedef DWORD OPPROGDLGF; + +typedef [v1_enum] enum _SPACTION { + SPACTION_NONE = 0, + SPACTION_MOVING, + SPACTION_COPYING, + SPACTION_RECYCLING, + SPACTION_APPLYINGATTRIBS, + SPACTION_DOWNLOADING, + SPACTION_SEARCHING_INTERNET, + SPACTION_CALCULATING, + SPACTION_UPLOADING, + SPACTION_SEARCHING_FILES, + SPACTION_DELETING, + SPACTION_RENAMING, + SPACTION_FORMATTING, + SPACTION_COPY_MOVING, +} SPACTION; + +[ + object, + uuid(0c9fb851-e5c9-43eb-a370-f0677b13874c), + pointer_default(unique) +] +interface IOperationsProgressDialog : IUnknown +{ + [v1_enum] enum _PDMODE + { + PDM_DEFAULT = 0x00000000, + PDM_RUN = 0x00000001, + PDM_PREFLIGHT = 0x00000002, + PDM_UNDOING = 0x00000004, + PDM_ERRORSBLOCKING = 0x00000008, + PDM_INDETERMINATE = 0x00000010, + }; + typedef DWORD PDMODE; + + typedef [v1_enum] enum PDOPSTATUS + { + PDOPS_RUNNING = 1, + PDOPS_PAUSED = 2, + PDOPS_CANCELLED = 3, + PDOPS_STOPPED = 4, + PDOPS_ERRORS = 5, + } PDOPSTATUS; + + HRESULT StartProgressDialog([in, unique] HWND owner, [in] OPPROGDLGF flags); + HRESULT StopProgressDialog(); + HRESULT SetOperation([in] SPACTION action); + HRESULT SetMode([in] PDMODE mode); + HRESULT UpdateProgress([in] ULONGLONG current_points, [in] ULONGLONG total_points, + [in] ULONGLONG current_size, [in] ULONGLONG total_size, + [in] ULONGLONG current_item, [in] ULONGLONG total_item); + HRESULT UpdateLocations([in, unique] IShellItem *source, [in, unique] IShellItem *target, + [in, unique] IShellItem *item); + HRESULT ResetTimer(); + HRESULT PauseTimer(); + HRESULT ResumeTimer(); + HRESULT GetMilliseconds([out] ULONGLONG *elapsed, [out] ULONGLONG *remaining); + HRESULT GetOperationStatus([out] PDOPSTATUS *status); +} + +[ + object, + uuid(947aab5f-0a5c-4c13-b4d6-4bf7836fc9f8), + pointer_default(unique) +] +interface IFileOperation : IUnknown +{ + HRESULT Advise([in] IFileOperationProgressSink *sink, [out] DWORD *cookie); + HRESULT Unadvise([in] DWORD cookie); + HRESULT SetOperationFlags([in] DWORD flags); + HRESULT SetProgressMessage([in, string] LPCWSTR message); + HRESULT SetProgressDialog([in] IOperationsProgressDialog *dialog); + HRESULT SetProperties([in] IPropertyChangeArray *array); + HRESULT SetOwnerWindow([in] HWND owner); + HRESULT ApplyPropertiesToItem([in] IShellItem *item); + HRESULT ApplyPropertiesToItems([in] IUnknown *items); + HRESULT RenameItem([in] IShellItem *item, [in, string] LPCWSTR name, + [in, unique] IFileOperationProgressSink *sink); + HRESULT RenameItems([in] IUnknown *items, [in, string] LPCWSTR name); + HRESULT MoveItem([in] IShellItem *item, [in] IShellItem *folder, + [in, unique, string] LPCWSTR name, + [in, unique] IFileOperationProgressSink *sink); + HRESULT MoveItems([in] IUnknown *items, [in] IShellItem *folder); + HRESULT CopyItem([in] IShellItem *item, [in] IShellItem *folder, + [in, unique, string] LPCWSTR name, + [in, unique] IFileOperationProgressSink *sink); + HRESULT CopyItems([in] IUnknown *items, [in] IShellItem *folder); + HRESULT DeleteItem([in] IShellItem *item, + [in, unique] IFileOperationProgressSink *sink); + HRESULT DeleteItems([in] IUnknown *items); + HRESULT NewItem([in] IShellItem *folder, [in] DWORD attributes, + [in, unique, string] LPCWSTR name, [in, unique, string] LPCWSTR template, + [in, unique] IFileOperationProgressSink *sink); + HRESULT PerformOperations(); + HRESULT GetAnyOperationsAborted([out] BOOL *aborted); }
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48848 Signed-off-by: Jactry Zeng jzeng@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 | 29 ++++ 5 files changed, 286 insertions(+)
diff --git a/dlls/shell32/shell32_classes.idl b/dlls/shell32/shell32_classes.idl index 6ed497fea5b..f2c5ed4a766 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 3465a3c8445..da50e19de46 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 e84402d7bc8..3c88642512e 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 38c582be091..3726c61dfaa 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 *operation = impl_from_IFileOperation(iface); + + TRACE("(%p, %s, %p).\n", iface, debugstr_guid(riid), out); + + if (IsEqualIID(&IID_IFileOperation, riid) || + IsEqualIID(&IID_IUnknown, riid)) + *out = &operation->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 *operation = impl_from_IFileOperation(iface); + ULONG ref = InterlockedIncrement(&operation->ref); + + TRACE("(%p): ref=%u.\n", iface, ref); + + return ref; +} + +static ULONG WINAPI file_operation_Release(IFileOperation *iface) +{ + struct file_operation *operation = impl_from_IFileOperation(iface); + ULONG ref = InterlockedDecrement(&operation->ref); + + TRACE("(%p): ref=%u.\n", iface, ref); + + if (!ref) + { + HeapFree(GetProcessHeap(), 0, operation); + } + + 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 36602f335d6..70d90a5c7ac 100644 --- a/dlls/shell32/tests/shlfileop.c +++ b/dlls/shell32/tests/shlfileop.c @@ -2706,6 +2706,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(); @@ -2751,4 +2774,10 @@ START_TEST(shlfileop) test_unicode();
test_shlmenu(); + + CoInitialize(NULL); + + test_file_operation(); + + CoUninitialize(); }