[PATCH v7 0/3] MR6130: shell32: Added stubs for the EnumerableObjectCollection COM class.
Stub added for the IEnumObjects and IObjectCollection interfaces, so that programs won't crash when calling it. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53620 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56891 -- v7: actxprxy: Added IEnumObjects_Next_Proxy shell32: Added stub for IObjectCollection interface. shell32: Added stub for IEnumObjects interface. https://gitlab.winehq.org/wine/wine/-/merge_requests/6130
From: Kevin Martinez <137180189+kevinrmartinez(a)users.noreply.github.com> --- 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 | 13 +++ 6 files changed, 187 insertions(+) create mode 100644 dlls/shell32/enumobjects.c diff --git a/dlls/shell32/Makefile.in b/dlls/shell32/Makefile.in index 4a906ac59db..c2df32b62ec 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 <stdarg.h> +#include <stdlib.h> +#include <string.h> + +#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 135ef52f7b0..a6da0f7c434 100644 --- a/dlls/shell32/shell32_classes.idl +++ b/dlls/shell32/shell32_classes.idl @@ -189,3 +189,8 @@ coclass KnownFolderManager { interface IKnownFolderManager; } uuid(d969a300-e7ff-11d0-a93b-00a0c90f2719) ] coclass NewMenu {} + +[ + 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 6b5575c6879..c4b301f500a 100644 --- a/dlls/shell32/shell32_main.h +++ b/dlls/shell32/shell32_main.h @@ -103,6 +103,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 886cff89ef9..586efe574dc 100644 --- a/include/shobjidl.idl +++ b/include/shobjidl.idl @@ -4126,3 +4126,16 @@ 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); + HRESULT Skip([in] ULONG celt); + HRESULT Reset(); + HRESULT Clone([out] IEnumObjects **ppenum); +} -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6130
From: Kevin Martinez <137180189+kevinrmartinez(a)users.noreply.github.com> --- dlls/shell32/enumobjects.c | 98 +++++++++++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/dlls/shell32/enumobjects.c b/dlls/shell32/enumobjects.c index 16ad52168d8..f71eda6f505 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) { @@ -102,7 +112,7 @@ static HRESULT WINAPI enum_objects_Next(IEnumObjects *iface, ULONG celt, REFIID if (celtFetched) *celtFetched = 0; - + return S_FALSE; } @@ -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); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6130
From: Kevin Martinez <137180189+kevinrmartinez(a)users.noreply.github.com> --- dlls/actxprxy/usrmarshal.c | 18 ++++++++++++++++++ include/shobjidl.idl | 1 + 2 files changed, 19 insertions(+) diff --git a/dlls/actxprxy/usrmarshal.c b/dlls/actxprxy/usrmarshal.c index e4eada6848f..5fa3c8581ec 100644 --- a/dlls/actxprxy/usrmarshal.c +++ b/dlls/actxprxy/usrmarshal.c @@ -247,3 +247,21 @@ 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); + if (hr == S_OK) *pceltFetched = celt; + return hr; +} diff --git a/include/shobjidl.idl b/include/shobjidl.idl index 586efe574dc..58dcc3a83f1 100644 --- a/include/shobjidl.idl +++ b/include/shobjidl.idl @@ -4135,6 +4135,7 @@ interface IFileOperation : IUnknown 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); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6130
On Wed Aug 14 14:36:47 2024 +0000, Kevin Martinez wrote:
changed this line in [version 7 of the diff](/wine/wine/-/merge_requests/6130/diffs?diff_id=126464&start_sha=5002949e7553ded3afa35dd53ebdc315c2663152#9718da1edbba0f34e8a2e9e282c5e291ab926c91_179_179) Understood, using reference from another file I changed it to %p.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/6130#note_78672
On Wed Aug 14 14:39:14 2024 +0000, Elizabeth Figura wrote:
I think using a single space is pretty much universal, at least in new code. But as always consistency is most important. Single space it is then.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/6130#note_78673
Let's avoid tabs in new code, please.
Agreed. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/6130#note_78674
On Wed Aug 14 14:36:48 2024 +0000, Kevin Martinez wrote:
changed this line in [version 7 of the diff](/wine/wine/-/merge_requests/6130/diffs?diff_id=126464&start_sha=5002949e7553ded3afa35dd53ebdc315c2663152#1706c332dfd6180886ecdcc70e698be052f47595_196_196) Ok, was just following the example of other entries.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/6130#note_78675
participants (2)
-
Kevin Martinez -
Kevin Martinez (@kevinrmartinez)