From 36483a9c1164d6936411b645abad0639824e4ff6 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Fri, 24 Jan 2025 09:10:08 +1100 Subject: [PATCH] Added shell32_enumerableobejct patchset --- ...dded-stub-for-IEnumObjects-interface.patch | 288 ++++++++++++++++++ ...stub-for-IObjectCollection-interface.patch | 147 +++++++++ patches/shell32_enumerableobejct/definition | 4 + 3 files changed, 439 insertions(+) create mode 100644 patches/shell32_enumerableobejct/0001-shell32-Added-stub-for-IEnumObjects-interface.patch create mode 100644 patches/shell32_enumerableobejct/0002-shell32-Added-stub-for-IObjectCollection-interface.patch create mode 100644 patches/shell32_enumerableobejct/definition diff --git a/patches/shell32_enumerableobejct/0001-shell32-Added-stub-for-IEnumObjects-interface.patch b/patches/shell32_enumerableobejct/0001-shell32-Added-stub-for-IEnumObjects-interface.patch new file mode 100644 index 00000000..c7b54776 --- /dev/null +++ b/patches/shell32_enumerableobejct/0001-shell32-Added-stub-for-IEnumObjects-interface.patch @@ -0,0 +1,288 @@ +From 0a60f26b0ee4664ea253d1155ff943a85f5ba434 Mon Sep 17 00:00:00 2001 +From: Kevin Martinez +Date: Wed, 17 Jul 2024 15:10:49 -0400 +Subject: [PATCH] shell32: Added stub for IEnumObjects interface. + +--- + dlls/actxprxy/usrmarshal.c | 17 ++++ + dlls/shell32/Makefile.in | 1 + + dlls/shell32/enumobjects.c | 166 +++++++++++++++++++++++++++++++ + dlls/shell32/shell32_classes.idl | 5 + + dlls/shell32/shell32_main.h | 1 + + dlls/shell32/shellole.c | 1 + + include/shobjidl.idl | 14 +++ + 7 files changed, 205 insertions(+) + create mode 100644 dlls/shell32/enumobjects.c + +diff --git a/dlls/actxprxy/usrmarshal.c b/dlls/actxprxy/usrmarshal.c +index e4eada6848f..43b72e0b002 100644 +--- a/dlls/actxprxy/usrmarshal.c ++++ b/dlls/actxprxy/usrmarshal.c +@@ -247,3 +247,20 @@ HRESULT __RPC_STUB IParentAndItem_GetParentAndItem_Proxy( + TRACE("(%p)->(%p %p %p)\n", This, parent, folder, child); + return IParentAndItem_RemoteGetParentAndItem_Proxy(This, parent, folder, child); + } ++ ++HRESULT CALLBACK IEnumObjects_Next_Proxy(IEnumObjects *This, ULONG celt, REFIID riid, void **rgelt, ULONG *pceltFetched) ++{ ++ ULONG fetched; ++ TRACE("(%p)->(%ld, %p, %p, %p)\n", This, celt, debugstr_guid(riid), rgelt, pceltFetched); ++ if (!pceltFetched) pceltFetched = &fetched; ++ return IEnumObjects_RemoteNext_Proxy(This, celt, riid, rgelt, pceltFetched); ++} ++ ++HRESULT __RPC_STUB IEnumObjects_Next_Stub(IEnumObjects *This, ULONG celt, REFIID riid, void **rgelt, ULONG *pceltFetched) ++{ ++ HRESULT hr; ++ TRACE("(%p)->(%ld, %p, %p, %p)\n", This, celt, debugstr_guid(riid), rgelt, pceltFetched); ++ *pceltFetched = 0; ++ hr = IEnumObjects_Next(This, celt, riid, rgelt, pceltFetched); ++ return hr; ++} +\ No newline at end of file +diff --git a/dlls/shell32/Makefile.in b/dlls/shell32/Makefile.in +index 828d8e82e2d..e071ed6a45d 100644 +--- a/dlls/shell32/Makefile.in ++++ b/dlls/shell32/Makefile.in +@@ -21,6 +21,7 @@ SOURCES = \ + dragdrophelper.c \ + ebrowser.c \ + enumidlist.c \ ++ enumobjects.c \ + folders.c \ + iconcache.c \ + new_menu.c \ +diff --git a/dlls/shell32/enumobjects.c b/dlls/shell32/enumobjects.c +new file mode 100644 +index 00000000000..16ad52168d8 +--- /dev/null ++++ b/dlls/shell32/enumobjects.c +@@ -0,0 +1,166 @@ ++/* ++ * EnumerableObjectCollection ++ * ++ * Copyright 2024 Kevin Martinez ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA ++ */ ++ ++#include ++#include ++#include ++ ++#define COBJMACROS ++ ++#include "wine/debug.h" ++#include "windef.h" ++#include "winbase.h" ++#include "winreg.h" ++#include "shlwapi.h" ++ ++#include "shell32_main.h" ++ ++WINE_DEFAULT_DEBUG_CHANNEL(shell); ++ ++struct enum_objects ++{ ++ IEnumObjects IEnumObjects_iface; ++ LONG ref; ++}; ++ ++static inline struct enum_objects *impl_from_IEnumObjects(IEnumObjects *iface) ++{ ++ return CONTAINING_RECORD(iface, struct enum_objects, IEnumObjects_iface); ++} ++ ++static HRESULT WINAPI enum_objects_QueryInterface(IEnumObjects *iface, REFIID riid, void **obj) ++{ ++ struct enum_objects *This = impl_from_IEnumObjects(iface); ++ ++ TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), obj); ++ ++ *obj = NULL; ++ ++ if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumObjects)) ++ { ++ *obj = &This->IEnumObjects_iface; ++ } ++ ++ if (*obj) ++ { ++ IUnknown_AddRef((IUnknown*)*obj); ++ return S_OK; ++ } ++ ++ WARN("no interface for %s.\n", debugstr_guid(riid)); ++ ++ return E_NOINTERFACE; ++} ++ ++static ULONG WINAPI enum_objects_AddRef(IEnumObjects *iface) ++{ ++ struct enum_objects *This = impl_from_IEnumObjects(iface); ++ ULONG refcount = InterlockedIncrement(&This->ref); ++ ++ TRACE("(%p): increasing refcount to %lu.\n", This, refcount); ++ ++ return refcount; ++} ++ ++ static ULONG WINAPI enum_objects_Release(IEnumObjects *iface) ++{ ++ struct enum_objects *This = impl_from_IEnumObjects(iface); ++ ULONG refcount = InterlockedDecrement(&This->ref); ++ ++ TRACE("(%p): decreasing refcount to %lu.\n", This, refcount); ++ ++ if (!refcount) ++ { ++ free(This); ++ } ++ ++ return refcount; ++} ++ ++static HRESULT WINAPI enum_objects_Next(IEnumObjects *iface, ULONG celt, REFIID riid, void **rgelt, ULONG *celtFetched) ++{ ++ struct enum_objects *This = impl_from_IEnumObjects(iface); ++ ++ FIXME("(%p %ld, %p)->(%p, %p): stub!\n", This, celt, debugstr_guid(riid), rgelt, celtFetched); ++ ++ if (celtFetched) ++ *celtFetched = 0; ++ ++ return S_FALSE; ++} ++ ++static HRESULT WINAPI enum_objects_Skip(IEnumObjects *iface, ULONG celt) ++{ ++ struct enum_objects *This = impl_from_IEnumObjects(iface); ++ ++ FIXME("(%p %ld): stub!\n", This, celt); ++ ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI enum_objects_Reset(IEnumObjects *iface) ++{ ++ struct enum_objects *This = impl_from_IEnumObjects(iface); ++ ++ FIXME("(%p): stub!\n", This); ++ ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI enum_objects_Clone(IEnumObjects *iface, IEnumObjects **ppenum) ++{ ++ struct enum_objects *This = impl_from_IEnumObjects(iface); ++ ++ FIXME("(%p)->(%p): stub!\n", This, ppenum); ++ ++ return E_NOTIMPL; ++} ++ ++static const IEnumObjectsVtbl enum_objects_vtbl = ++{ ++ enum_objects_QueryInterface, ++ enum_objects_AddRef, ++ enum_objects_Release, ++ enum_objects_Next, ++ enum_objects_Skip, ++ enum_objects_Reset, ++ enum_objects_Clone, ++}; ++ ++HRESULT WINAPI EnumerableObjectCollection_Constructor(IUnknown *outer, REFIID riid, void **obj) ++{ ++ struct enum_objects *This; ++ HRESULT hr; ++ ++ TRACE("(%p, %s, %p)\n", outer, debugstr_guid(riid), obj); ++ ++ if (outer) ++ return CLASS_E_NOAGGREGATION; ++ ++ if (!(This = heap_alloc(sizeof(*This)))) ++ return E_OUTOFMEMORY; ++ ++ This->ref = 1; ++ This->IEnumObjects_iface.lpVtbl = &enum_objects_vtbl; ++ ++ hr = IEnumObjects_QueryInterface(&This->IEnumObjects_iface, riid, obj); ++ IEnumObjects_Release(&This->IEnumObjects_iface); ++ return hr; ++} +diff --git a/dlls/shell32/shell32_classes.idl b/dlls/shell32/shell32_classes.idl +index 932b6f395b2..9e2df630940 100644 +--- a/dlls/shell32/shell32_classes.idl ++++ b/dlls/shell32/shell32_classes.idl +@@ -194,3 +194,8 @@ coclass NewMenu {} + threading(apartment), + uuid(9ac9fbe1-e0a2-4ad6-b4ee-e212013ea917) + ] coclass ShellItem { interface IShellItem2; } ++ ++[ ++ threading(apartment), ++ uuid(2d3468c1-36a7-43b6-ac24-d3f02fd9607a) ++] coclass EnumerableObjectCollection {} +diff --git a/dlls/shell32/shell32_main.h b/dlls/shell32/shell32_main.h +index 766c7c23adc..ab3187fd24a 100644 +--- a/dlls/shell32/shell32_main.h ++++ b/dlls/shell32/shell32_main.h +@@ -104,6 +104,7 @@ HRESULT WINAPI ExplorerBrowser_Constructor(IUnknown *pUnkOuter, REFIID riid, LPV + HRESULT WINAPI KnownFolderManager_Constructor(IUnknown *pUnkOuter, REFIID riid, LPVOID *ppv); + HRESULT WINAPI IFileOperation_Constructor(IUnknown *outer, REFIID riid, void **out); + HRESULT WINAPI ActiveDesktop_Constructor(IUnknown *outer, REFIID riid, void **out); ++HRESULT WINAPI EnumerableObjectCollection_Constructor(IUnknown *outer, REFIID riid, void **obj); + + extern HRESULT CPanel_GetIconLocationW(LPCITEMIDLIST, LPWSTR, UINT, int*); + HRESULT WINAPI CPanel_ExtractIconA(LPITEMIDLIST pidl, LPCSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize); +diff --git a/dlls/shell32/shellole.c b/dlls/shell32/shellole.c +index aa9bd3e0f3e..fc3f6b032cd 100644 +--- a/dlls/shell32/shellole.c ++++ b/dlls/shell32/shellole.c +@@ -87,6 +87,7 @@ static const struct { + {&CLSID_ShellImageDataFactory, ShellImageDataFactory_Constructor}, + {&CLSID_FileOperation, IFileOperation_Constructor}, + {&CLSID_ActiveDesktop, ActiveDesktop_Constructor}, ++ {&CLSID_EnumerableObjectCollection, EnumerableObjectCollection_Constructor}, + {NULL, NULL} + }; + +diff --git a/include/shobjidl.idl b/include/shobjidl.idl +index 4118e3d9ba2..aa393225db1 100644 +--- a/include/shobjidl.idl ++++ b/include/shobjidl.idl +@@ -4134,3 +4134,17 @@ interface IFileOperation : IUnknown + HRESULT PerformOperations(); + HRESULT GetAnyOperationsAborted([out] BOOL *aborted); + } ++ ++[ ++ object, ++ uuid(2c1c7e2e-2d0e-4059-831e-1e6f82335c2e), ++ pointer_default(unique) ++] ++interface IEnumObjects : IUnknown ++{ ++ [local] HRESULT Next([in] ULONG celt, [in] REFIID riid, [out, iid_is(riid)] void **rgelt, [out, optional] ULONG *pceltFetched); ++ [call_as(Next)] HRESULT RemoteNext([in] ULONG celt, [in] REFIID riid, [out, size_is(celt), length_is(*pceltFetched), iid_is(riid)] void **rgelt, [out] ULONG *pceltFetched); ++ HRESULT Skip([in] ULONG celt); ++ HRESULT Reset(); ++ HRESULT Clone([out] IEnumObjects **ppenum); ++} +-- +2.45.2 + diff --git a/patches/shell32_enumerableobejct/0002-shell32-Added-stub-for-IObjectCollection-interface.patch b/patches/shell32_enumerableobejct/0002-shell32-Added-stub-for-IObjectCollection-interface.patch new file mode 100644 index 00000000..9d10c9f3 --- /dev/null +++ b/patches/shell32_enumerableobejct/0002-shell32-Added-stub-for-IObjectCollection-interface.patch @@ -0,0 +1,147 @@ +From d3b76c01d434b774c7de82ae8c1e05b566f108b8 Mon Sep 17 00:00:00 2001 +From: Kevin Martinez +Date: Wed, 24 Jul 2024 17:22:57 -0400 +Subject: [PATCH] shell32: Added stub for IObjectCollection interface. + +--- + dlls/shell32/enumobjects.c | 96 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 96 insertions(+) + +diff --git a/dlls/shell32/enumobjects.c b/dlls/shell32/enumobjects.c +index 16ad52168d8..233919738bf 100644 +--- a/dlls/shell32/enumobjects.c ++++ b/dlls/shell32/enumobjects.c +@@ -37,6 +37,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(shell); + struct enum_objects + { + IEnumObjects IEnumObjects_iface; ++ IObjectCollection IObjectCollection_iface; + LONG ref; + }; + +@@ -45,6 +46,11 @@ static inline struct enum_objects *impl_from_IEnumObjects(IEnumObjects *iface) + return CONTAINING_RECORD(iface, struct enum_objects, IEnumObjects_iface); + } + ++static inline struct enum_objects *impl_from_IObjectCollection(IObjectCollection *iface) ++{ ++ return CONTAINING_RECORD(iface, struct enum_objects, IObjectCollection_iface); ++} ++ + static HRESULT WINAPI enum_objects_QueryInterface(IEnumObjects *iface, REFIID riid, void **obj) + { + struct enum_objects *This = impl_from_IEnumObjects(iface); +@@ -57,6 +63,10 @@ static HRESULT WINAPI enum_objects_QueryInterface(IEnumObjects *iface, REFIID ri + { + *obj = &This->IEnumObjects_iface; + } ++ else if (IsEqualIID(riid, &IID_IObjectCollection) || IsEqualIID(riid, &IID_IObjectArray)) ++ { ++ *obj = &This->IObjectCollection_iface; ++ } + + if (*obj) + { +@@ -144,6 +154,91 @@ static const IEnumObjectsVtbl enum_objects_vtbl = + enum_objects_Clone, + }; + ++static HRESULT WINAPI object_collection_QueryInterface(IObjectCollection *iface, REFIID riid, void **obj) ++{ ++ struct enum_objects *This = impl_from_IObjectCollection(iface); ++ return IEnumObjects_QueryInterface(&This->IEnumObjects_iface, riid, obj); ++} ++ ++static ULONG WINAPI object_collection_AddRef(IObjectCollection *iface) ++{ ++ struct enum_objects *This = impl_from_IObjectCollection(iface); ++ return IEnumObjects_AddRef(&This->IEnumObjects_iface); ++} ++ ++static ULONG WINAPI object_collection_Release(IObjectCollection *iface) ++{ ++ struct enum_objects *This = impl_from_IObjectCollection(iface); ++ return IEnumObjects_Release(&This->IEnumObjects_iface); ++} ++ ++static HRESULT WINAPI object_collection_GetCount(IObjectCollection *iface, UINT *count) ++{ ++ struct enum_objects *This = impl_from_IObjectCollection(iface); ++ ++ FIXME("(%p)->(%p): stub!\n", This, count); ++ ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI object_collection_GetAt(IObjectCollection *iface, UINT index, REFIID riid, void **obj) ++{ ++ struct enum_objects *This = impl_from_IObjectCollection(iface); ++ ++ FIXME("(%p %u, %s)->(%p): stub!\n", This, index, debugstr_guid(riid), obj); ++ ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI object_collection_AddObject(IObjectCollection *iface, IUnknown *obj) ++{ ++ struct enum_objects *This = impl_from_IObjectCollection(iface); ++ ++ FIXME("(%p %p): stub!\n", This, obj); ++ ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI object_collection_AddFromArray(IObjectCollection *iface, IObjectArray *source_array) ++{ ++ struct enum_objects *This = impl_from_IObjectCollection(iface); ++ ++ FIXME("(%p %p): stub!\n", This, source_array); ++ ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI object_collection_RemoveObjectAt(IObjectCollection *iface, UINT index) ++{ ++ struct enum_objects *This = impl_from_IObjectCollection(iface); ++ ++ FIXME("(%p %u): stub!\n", This, index); ++ ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI object_collection_Clear(IObjectCollection *iface) ++{ ++ struct enum_objects *This = impl_from_IObjectCollection(iface); ++ ++ FIXME("(%p): stub!\n", This); ++ ++ return E_NOTIMPL; ++} ++ ++static const IObjectCollectionVtbl object_collection_vtbl = ++{ ++ object_collection_QueryInterface, ++ object_collection_AddRef, ++ object_collection_Release, ++ object_collection_GetCount, ++ object_collection_GetAt, ++ object_collection_AddObject, ++ object_collection_AddFromArray, ++ object_collection_RemoveObjectAt, ++ object_collection_Clear ++}; ++ + HRESULT WINAPI EnumerableObjectCollection_Constructor(IUnknown *outer, REFIID riid, void **obj) + { + struct enum_objects *This; +@@ -159,6 +254,7 @@ HRESULT WINAPI EnumerableObjectCollection_Constructor(IUnknown *outer, REFIID ri + + This->ref = 1; + This->IEnumObjects_iface.lpVtbl = &enum_objects_vtbl; ++ This->IObjectCollection_iface.lpVtbl = &object_collection_vtbl; + + hr = IEnumObjects_QueryInterface(&This->IEnumObjects_iface, riid, obj); + IEnumObjects_Release(&This->IEnumObjects_iface); +-- +2.45.2 + diff --git a/patches/shell32_enumerableobejct/definition b/patches/shell32_enumerableobejct/definition new file mode 100644 index 00000000..41126202 --- /dev/null +++ b/patches/shell32_enumerableobejct/definition @@ -0,0 +1,4 @@ +Fixes: [53620] err:ole:com_get_class_object class IEnumObjects not registered. +Fixes: [56891] Visual novel Mebae (Tanuki Soft) crashes on startup + +# MR https://gitlab.winehq.org/wine/wine/-/merge_requests/6130