React Native applications checks the return value from core_dragdrop_manager_add_TargetRequested().
From: Zhiyi Zhang zzhang@codeweavers.com
--- configure.ac | 1 + dlls/dataexchange/Makefile.in | 7 ++ dlls/dataexchange/classes.idl | 23 +++++ dlls/dataexchange/dataexchange.spec | 3 + dlls/dataexchange/main.c | 129 ++++++++++++++++++++++++++++ dlls/dataexchange/private.h | 33 +++++++ 6 files changed, 196 insertions(+) create mode 100644 dlls/dataexchange/Makefile.in create mode 100644 dlls/dataexchange/classes.idl create mode 100644 dlls/dataexchange/dataexchange.spec create mode 100644 dlls/dataexchange/main.c create mode 100644 dlls/dataexchange/private.h
diff --git a/configure.ac b/configure.ac index 0f5b89d1b47..88734bd89cd 100644 --- a/configure.ac +++ b/configure.ac @@ -2560,6 +2560,7 @@ WINE_CONFIG_MAKEFILE(dlls/d3dx9_42) WINE_CONFIG_MAKEFILE(dlls/d3dx9_43) WINE_CONFIG_MAKEFILE(dlls/d3dxof) WINE_CONFIG_MAKEFILE(dlls/d3dxof/tests) +WINE_CONFIG_MAKEFILE(dlls/dataexchange) WINE_CONFIG_MAKEFILE(dlls/davclnt) WINE_CONFIG_MAKEFILE(dlls/dbgeng) WINE_CONFIG_MAKEFILE(dlls/dbgeng/tests) diff --git a/dlls/dataexchange/Makefile.in b/dlls/dataexchange/Makefile.in new file mode 100644 index 00000000000..b4b37a841e4 --- /dev/null +++ b/dlls/dataexchange/Makefile.in @@ -0,0 +1,7 @@ +MODULE = dataexchange.dll +IMPORTLIB = dataexchange +IMPORTS = combase + +SOURCES = \ + classes.idl \ + main.c diff --git a/dlls/dataexchange/classes.idl b/dlls/dataexchange/classes.idl new file mode 100644 index 00000000000..06f6dd3e545 --- /dev/null +++ b/dlls/dataexchange/classes.idl @@ -0,0 +1,23 @@ +/* + * Runtime Classes for dataexchange.dll + * + * Copyright 2024 Zhiyi Zhang for CodeWeavers + * + * 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 + */ + +#pragma makedep register + +#include "windows.applicationmodel.datatransfer.dragdrop.core.idl" diff --git a/dlls/dataexchange/dataexchange.spec b/dlls/dataexchange/dataexchange.spec new file mode 100644 index 00000000000..20a8bfa98ea --- /dev/null +++ b/dlls/dataexchange/dataexchange.spec @@ -0,0 +1,3 @@ +@ stdcall -private DllCanUnloadNow() +@ stdcall -private DllGetActivationFactory(ptr ptr) +@ stdcall -private DllGetClassObject(ptr ptr ptr) diff --git a/dlls/dataexchange/main.c b/dlls/dataexchange/main.c new file mode 100644 index 00000000000..22e5f7a6ca9 --- /dev/null +++ b/dlls/dataexchange/main.c @@ -0,0 +1,129 @@ +/* + * Copyright 2024 Zhiyi Zhang for CodeWeavers + * + * 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 "private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(dataexchange); + +struct dataexchange +{ + IActivationFactory IActivationFactory_iface; + LONG ref; +}; + +static inline struct dataexchange *impl_from_IActivationFactory(IActivationFactory *iface) +{ + return CONTAINING_RECORD(iface, struct dataexchange, IActivationFactory_iface); +} + +static HRESULT STDMETHODCALLTYPE dataexchange_QueryInterface(IActivationFactory *iface, REFIID iid, + void **out) +{ + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown) + || IsEqualGUID(iid, &IID_IInspectable) + || IsEqualGUID(iid, &IID_IAgileObject) + || IsEqualGUID(iid, &IID_IActivationFactory)) + { + IUnknown_AddRef(iface); + *out = iface; + return S_OK; + } + + FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE dataexchange_AddRef(IActivationFactory *iface) +{ + struct dataexchange *impl = impl_from_IActivationFactory(iface); + ULONG ref = InterlockedIncrement(&impl->ref); + TRACE("iface %p, ref %lu.\n", iface, ref); + return ref; +} + +static ULONG STDMETHODCALLTYPE dataexchange_Release(IActivationFactory *iface) +{ + struct dataexchange *impl = impl_from_IActivationFactory(iface); + ULONG ref = InterlockedDecrement(&impl->ref); + TRACE("iface %p, ref %lu.\n", iface, ref); + return ref; +} + +static HRESULT STDMETHODCALLTYPE dataexchange_GetIids(IActivationFactory *iface, ULONG *iid_count, + IID **iids) +{ + FIXME("iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE dataexchange_GetRuntimeClassName(IActivationFactory *iface, + HSTRING *class_name) +{ + FIXME("iface %p, class_name %p stub!\n", iface, class_name); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE dataexchange_GetTrustLevel(IActivationFactory *iface, + TrustLevel *trust_level) +{ + FIXME("iface %p, trust_level %p stub!\n", iface, trust_level); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE dataexchange_ActivateInstance(IActivationFactory *iface, + IInspectable **instance) +{ + FIXME("iface %p, instance %p stub!\n", iface, instance); + return E_NOTIMPL; +} + +static const struct IActivationFactoryVtbl activation_factory_vtbl = +{ + dataexchange_QueryInterface, + dataexchange_AddRef, + dataexchange_Release, + /* IInspectable methods */ + dataexchange_GetIids, + dataexchange_GetRuntimeClassName, + dataexchange_GetTrustLevel, + /* IActivationFactory methods */ + dataexchange_ActivateInstance, +}; + +static struct dataexchange dataexchange = +{ + {&activation_factory_vtbl}, + 1 +}; + +HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void **out) +{ + FIXME("clsid %s, riid %s, out %p stub!\n", debugstr_guid(clsid), debugstr_guid(riid), out); + return CLASS_E_CLASSNOTAVAILABLE; +} + +HRESULT WINAPI DllGetActivationFactory(HSTRING classid, IActivationFactory **factory) +{ + TRACE("classid %s, factory %p.\n", debugstr_hstring(classid), factory); + *factory = &dataexchange.IActivationFactory_iface; + IUnknown_AddRef(*factory); + return S_OK; +} diff --git a/dlls/dataexchange/private.h b/dlls/dataexchange/private.h new file mode 100644 index 00000000000..595d956fdc8 --- /dev/null +++ b/dlls/dataexchange/private.h @@ -0,0 +1,33 @@ +/* + * Copyright 2024 Zhiyi Zhang for CodeWeavers + * + * 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 + */ + +#ifndef __WINE_DATAEXCHANGE_PRIVATE_H +#define __WINE_DATAEXCHANGE_PRIVATE_H + +#include <stdarg.h> + +#define COBJMACROS +#include "initguid.h" +#include "windef.h" +#include "winbase.h" +#include "winstring.h" +#include "wine/debug.h" +#include "objbase.h" +#include "activation.h" + +#endif /* __WINE_DATAEXCHANGE_PRIVATE_H */
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/dataexchange/main.c | 33 ++++++++++++++++++++++++++++ dlls/dataexchange/private.h | 44 +++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+)
diff --git a/dlls/dataexchange/main.c b/dlls/dataexchange/main.c index 22e5f7a6ca9..e9fa3202523 100644 --- a/dlls/dataexchange/main.c +++ b/dlls/dataexchange/main.c @@ -23,6 +23,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(dataexchange); struct dataexchange { IActivationFactory IActivationFactory_iface; + ICoreDragDropManagerStatics ICoreDragDropManagerStatics_iface; LONG ref; };
@@ -34,6 +35,8 @@ static inline struct dataexchange *impl_from_IActivationFactory(IActivationFacto static HRESULT STDMETHODCALLTYPE dataexchange_QueryInterface(IActivationFactory *iface, REFIID iid, void **out) { + struct dataexchange *impl = impl_from_IActivationFactory(iface); + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
if (IsEqualGUID(iid, &IID_IUnknown) @@ -45,6 +48,12 @@ static HRESULT STDMETHODCALLTYPE dataexchange_QueryInterface(IActivationFactory *out = iface; return S_OK; } + else if (IsEqualGUID(iid, &IID_ICoreDragDropManagerStatics)) + { + ICoreDragDropManagerStatics_AddRef(&impl->ICoreDragDropManagerStatics_iface); + *out = &impl->ICoreDragDropManagerStatics_iface; + return S_OK; + }
FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); *out = NULL; @@ -108,9 +117,33 @@ static const struct IActivationFactoryVtbl activation_factory_vtbl = dataexchange_ActivateInstance, };
+DEFINE_IINSPECTABLE(core_dragdrop_manager_statics, ICoreDragDropManagerStatics, struct dataexchange, + IActivationFactory_iface) + +static HRESULT STDMETHODCALLTYPE core_dragdrop_manager_statics_GetForCurrentView(ICoreDragDropManagerStatics *iface, + ICoreDragDropManager **value) +{ + FIXME("iface %p, value %p stub!\n", iface, value); + return E_NOTIMPL; +} + +static const struct ICoreDragDropManagerStaticsVtbl core_dragdrop_manager_statics_vtbl = +{ + core_dragdrop_manager_statics_QueryInterface, + core_dragdrop_manager_statics_AddRef, + core_dragdrop_manager_statics_Release, + /* IInspectable methods */ + core_dragdrop_manager_statics_GetIids, + core_dragdrop_manager_statics_GetRuntimeClassName, + core_dragdrop_manager_statics_GetTrustLevel, + /* ICoreDragDropManagerStatics methods */ + core_dragdrop_manager_statics_GetForCurrentView, +}; + static struct dataexchange dataexchange = { {&activation_factory_vtbl}, + {&core_dragdrop_manager_statics_vtbl}, 1 };
diff --git a/dlls/dataexchange/private.h b/dlls/dataexchange/private.h index 595d956fdc8..41d128cc608 100644 --- a/dlls/dataexchange/private.h +++ b/dlls/dataexchange/private.h @@ -30,4 +30,48 @@ #include "objbase.h" #include "activation.h"
+#define WIDL_using_Windows_Networking_Connectivity +#include "windows.networking.connectivity.h" +#define WIDL_using_Windows_ApplicationModel_DataTransfer_DragDrop_Core +#include "windows.applicationmodel.datatransfer.dragdrop.core.h" + +#define DEFINE_IINSPECTABLE_(pfx, iface_type, impl_type, impl_from, iface_mem, expr) \ + static inline impl_type *impl_from(iface_type *iface) \ + { \ + return CONTAINING_RECORD(iface, impl_type, iface_mem); \ + } \ + static HRESULT WINAPI pfx##_QueryInterface(iface_type *iface, REFIID iid, void **out) \ + { \ + impl_type *impl = impl_from(iface); \ + return IInspectable_QueryInterface((IInspectable *)(expr), iid, out); \ + } \ + static ULONG WINAPI pfx##_AddRef(iface_type *iface) \ + { \ + impl_type *impl = impl_from(iface); \ + return IInspectable_AddRef((IInspectable *)(expr)); \ + } \ + static ULONG WINAPI pfx##_Release(iface_type *iface) \ + { \ + impl_type *impl = impl_from(iface); \ + return IInspectable_Release((IInspectable *)(expr)); \ + } \ + static HRESULT WINAPI pfx##_GetIids(iface_type *iface, ULONG *iid_count, IID **iids) \ + { \ + impl_type *impl = impl_from(iface); \ + return IInspectable_GetIids((IInspectable *)(expr), iid_count, iids); \ + } \ + static HRESULT WINAPI pfx##_GetRuntimeClassName(iface_type *iface, HSTRING *class_name) \ + { \ + impl_type *impl = impl_from(iface); \ + return IInspectable_GetRuntimeClassName((IInspectable *)(expr), class_name); \ + } \ + static HRESULT WINAPI pfx##_GetTrustLevel(iface_type *iface, TrustLevel *trust_level) \ + { \ + impl_type *impl = impl_from(iface); \ + return IInspectable_GetTrustLevel((IInspectable *)(expr), trust_level); \ + } + +#define DEFINE_IINSPECTABLE(pfx, iface_type, impl_type, base_iface) \ + DEFINE_IINSPECTABLE_(pfx, iface_type, impl_type, impl_from_##iface_type, iface_type##_iface, &impl->base_iface) + #endif /* __WINE_DATAEXCHANGE_PRIVATE_H */
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/dataexchange/main.c | 31 +++++++++++++++++++++++++++++++ dlls/dataexchange/private.h | 1 + 2 files changed, 32 insertions(+)
diff --git a/dlls/dataexchange/main.c b/dlls/dataexchange/main.c index e9fa3202523..7de60e08ad6 100644 --- a/dlls/dataexchange/main.c +++ b/dlls/dataexchange/main.c @@ -24,6 +24,7 @@ struct dataexchange { IActivationFactory IActivationFactory_iface; ICoreDragDropManagerStatics ICoreDragDropManagerStatics_iface; + IDragDropManagerInterop IDragDropManagerInterop_iface; LONG ref; };
@@ -54,6 +55,12 @@ static HRESULT STDMETHODCALLTYPE dataexchange_QueryInterface(IActivationFactory *out = &impl->ICoreDragDropManagerStatics_iface; return S_OK; } + else if (IsEqualGUID(iid, &IID_IDragDropManagerInterop)) + { + IDragDropManagerInterop_AddRef(&impl->IDragDropManagerInterop_iface); + *out = &impl->IDragDropManagerInterop_iface; + return S_OK; + }
FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); *out = NULL; @@ -140,10 +147,34 @@ static const struct ICoreDragDropManagerStaticsVtbl core_dragdrop_manager_static core_dragdrop_manager_statics_GetForCurrentView, };
+DEFINE_IINSPECTABLE(dragdrop_manager_interop, IDragDropManagerInterop, struct dataexchange, + IActivationFactory_iface) + +static HRESULT STDMETHODCALLTYPE dragdrop_manager_interop_GetForWindow(IDragDropManagerInterop *iface, + HWND hwnd, REFIID iid, void **out) +{ + FIXME("iface %p, hwnd %p, iid %s, out %p stub!\n", iface, hwnd, debugstr_guid(iid), out); + return E_NOTIMPL; +} + +static const struct IDragDropManagerInteropVtbl dragdrop_manager_interop_vtbl = +{ + dragdrop_manager_interop_QueryInterface, + dragdrop_manager_interop_AddRef, + dragdrop_manager_interop_Release, + /* IInspectable methods */ + dragdrop_manager_interop_GetIids, + dragdrop_manager_interop_GetRuntimeClassName, + dragdrop_manager_interop_GetTrustLevel, + /* IDragDropManagerInterop methods */ + dragdrop_manager_interop_GetForWindow, +}; + static struct dataexchange dataexchange = { {&activation_factory_vtbl}, {&core_dragdrop_manager_statics_vtbl}, + {&dragdrop_manager_interop_vtbl}, 1 };
diff --git a/dlls/dataexchange/private.h b/dlls/dataexchange/private.h index 41d128cc608..6dae0be4fc4 100644 --- a/dlls/dataexchange/private.h +++ b/dlls/dataexchange/private.h @@ -29,6 +29,7 @@ #include "wine/debug.h" #include "objbase.h" #include "activation.h" +#include "dragdropinterop.h"
#define WIDL_using_Windows_Networking_Connectivity #include "windows.networking.connectivity.h"
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/dataexchange/Makefile.in | 2 +- dlls/dataexchange/main.c | 145 +++++++++++++++++++++++++++++++++- dlls/dataexchange/private.h | 1 + 3 files changed, 145 insertions(+), 3 deletions(-)
diff --git a/dlls/dataexchange/Makefile.in b/dlls/dataexchange/Makefile.in index b4b37a841e4..50f72ec51c0 100644 --- a/dlls/dataexchange/Makefile.in +++ b/dlls/dataexchange/Makefile.in @@ -1,6 +1,6 @@ MODULE = dataexchange.dll IMPORTLIB = dataexchange -IMPORTS = combase +IMPORTS = combase user32
SOURCES = \ classes.idl \ diff --git a/dlls/dataexchange/main.c b/dlls/dataexchange/main.c index 7de60e08ad6..8e3c70937ac 100644 --- a/dlls/dataexchange/main.c +++ b/dlls/dataexchange/main.c @@ -124,6 +124,146 @@ static const struct IActivationFactoryVtbl activation_factory_vtbl = dataexchange_ActivateInstance, };
+struct core_dragdrop_manager +{ + ICoreDragDropManager ICoreDragDropManager_iface; + HWND hwnd; + LONG ref; +}; + +static inline struct core_dragdrop_manager *impl_from_ICoreDragDropManager(ICoreDragDropManager *iface) +{ + return CONTAINING_RECORD(iface, struct core_dragdrop_manager, ICoreDragDropManager_iface); +} + +static HRESULT STDMETHODCALLTYPE core_dragdrop_manager_QueryInterface(ICoreDragDropManager *iface, + REFIID iid, void **out) +{ + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown) + || IsEqualGUID(iid, &IID_IInspectable) + || IsEqualGUID(iid, &IID_ICoreDragDropManager)) + { + IUnknown_AddRef(iface); + *out = iface; + return S_OK; + } + + FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE core_dragdrop_manager_AddRef(ICoreDragDropManager *iface) +{ + struct core_dragdrop_manager *impl = impl_from_ICoreDragDropManager(iface); + ULONG ref = InterlockedIncrement(&impl->ref); + TRACE("iface %p, ref %lu.\n", iface, ref); + return ref; +} + +static ULONG STDMETHODCALLTYPE core_dragdrop_manager_Release(ICoreDragDropManager *iface) +{ + struct core_dragdrop_manager *impl = impl_from_ICoreDragDropManager(iface); + ULONG ref = InterlockedDecrement(&impl->ref); + + TRACE("iface %p, ref %lu.\n", iface, ref); + + if (!ref) + free(impl); + + return ref; +} + +static HRESULT STDMETHODCALLTYPE core_dragdrop_manager_GetIids(ICoreDragDropManager *iface, + ULONG *iid_count, IID **iids) +{ + FIXME("iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE core_dragdrop_manager_GetRuntimeClassName(ICoreDragDropManager *iface, + HSTRING *class_name) +{ + FIXME("iface %p, class_name %p stub!\n", iface, class_name); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE core_dragdrop_manager_GetTrustLevel(ICoreDragDropManager *iface, + TrustLevel *trust_level) +{ + FIXME("iface %p, trust_level %p stub!\n", iface, trust_level); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE core_dragdrop_manager_add_TargetRequested(ICoreDragDropManager *iface, + ITypedEventHandler_CoreDragDropManager_CoreDropOperationTargetRequestedEventArgs *value, + EventRegistrationToken *return_value) +{ + FIXME("iface %p, value %p, return_value %p stub!\n", iface, value, return_value); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE core_dragdrop_manager_remove_TargetRequested(ICoreDragDropManager *iface, + EventRegistrationToken value) +{ + FIXME("iface %p, value %#I64x stub!\n", iface, value.value); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE core_dragdrop_manager_get_AreConcurrentOperationsEnabled(ICoreDragDropManager *iface, + boolean *value) +{ + FIXME("iface %p, value %p stub!\n", iface, value); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE core_dragdrop_manager_put_AreConcurrentOperationsEnabled(ICoreDragDropManager *iface, + boolean value) +{ + FIXME("iface %p, value %d stub!\n", iface, value); + return E_NOTIMPL; +} + +static const struct ICoreDragDropManagerVtbl core_dragdrop_manager_vtbl = +{ + core_dragdrop_manager_QueryInterface, + core_dragdrop_manager_AddRef, + core_dragdrop_manager_Release, + /* IInspectable methods */ + core_dragdrop_manager_GetIids, + core_dragdrop_manager_GetRuntimeClassName, + core_dragdrop_manager_GetTrustLevel, + /* ICoreDragDropManager methods */ + core_dragdrop_manager_add_TargetRequested, + core_dragdrop_manager_remove_TargetRequested, + core_dragdrop_manager_get_AreConcurrentOperationsEnabled, + core_dragdrop_manager_put_AreConcurrentOperationsEnabled, +}; + +static HRESULT create_core_dragdrop_manager(HWND hwnd, REFIID iid, void **out) +{ + struct core_dragdrop_manager *manager; + HRESULT hr; + + if (!IsWindow(hwnd)) + return HRESULT_FROM_WIN32(ERROR_INVALID_WINDOW_HANDLE); + + if (hwnd == GetDesktopWindow()) + return E_ACCESSDENIED; + + if (!(manager = calloc(1, sizeof(*manager)))) + return E_OUTOFMEMORY; + + manager->ICoreDragDropManager_iface.lpVtbl = &core_dragdrop_manager_vtbl; + manager->hwnd = hwnd; + manager->ref = 1; + hr = ICoreDragDropManager_QueryInterface(&manager->ICoreDragDropManager_iface, iid, out); + ICoreDragDropManager_Release(&manager->ICoreDragDropManager_iface); + return hr; +} + DEFINE_IINSPECTABLE(core_dragdrop_manager_statics, ICoreDragDropManagerStatics, struct dataexchange, IActivationFactory_iface)
@@ -153,8 +293,9 @@ DEFINE_IINSPECTABLE(dragdrop_manager_interop, IDragDropManagerInterop, struct da static HRESULT STDMETHODCALLTYPE dragdrop_manager_interop_GetForWindow(IDragDropManagerInterop *iface, HWND hwnd, REFIID iid, void **out) { - FIXME("iface %p, hwnd %p, iid %s, out %p stub!\n", iface, hwnd, debugstr_guid(iid), out); - return E_NOTIMPL; + FIXME("iface %p, hwnd %p, iid %s, out %p semi-stub!\n", iface, hwnd, debugstr_guid(iid), out); + + return create_core_dragdrop_manager(hwnd, iid, out); }
static const struct IDragDropManagerInteropVtbl dragdrop_manager_interop_vtbl = diff --git a/dlls/dataexchange/private.h b/dlls/dataexchange/private.h index 6dae0be4fc4..610154a1d64 100644 --- a/dlls/dataexchange/private.h +++ b/dlls/dataexchange/private.h @@ -31,6 +31,7 @@ #include "activation.h" #include "dragdropinterop.h"
+#define WIDL_using_Windows_Foundation #define WIDL_using_Windows_Networking_Connectivity #include "windows.networking.connectivity.h" #define WIDL_using_Windows_ApplicationModel_DataTransfer_DragDrop_Core
From: Zhiyi Zhang zzhang@codeweavers.com
--- configure.ac | 1 + dlls/dataexchange/tests/Makefile.in | 5 + dlls/dataexchange/tests/dataexchange.c | 132 +++++++++++++++++++++++++ 3 files changed, 138 insertions(+) create mode 100644 dlls/dataexchange/tests/Makefile.in create mode 100644 dlls/dataexchange/tests/dataexchange.c
diff --git a/configure.ac b/configure.ac index 88734bd89cd..eb7acc01f0a 100644 --- a/configure.ac +++ b/configure.ac @@ -2561,6 +2561,7 @@ WINE_CONFIG_MAKEFILE(dlls/d3dx9_43) WINE_CONFIG_MAKEFILE(dlls/d3dxof) WINE_CONFIG_MAKEFILE(dlls/d3dxof/tests) WINE_CONFIG_MAKEFILE(dlls/dataexchange) +WINE_CONFIG_MAKEFILE(dlls/dataexchange/tests) WINE_CONFIG_MAKEFILE(dlls/davclnt) WINE_CONFIG_MAKEFILE(dlls/dbgeng) WINE_CONFIG_MAKEFILE(dlls/dbgeng/tests) diff --git a/dlls/dataexchange/tests/Makefile.in b/dlls/dataexchange/tests/Makefile.in new file mode 100644 index 00000000000..7718643a681 --- /dev/null +++ b/dlls/dataexchange/tests/Makefile.in @@ -0,0 +1,5 @@ +TESTDLL = dataexchange.dll +IMPORTS = combase uuid user32 + +SOURCES = \ + dataexchange.c diff --git a/dlls/dataexchange/tests/dataexchange.c b/dlls/dataexchange/tests/dataexchange.c new file mode 100644 index 00000000000..f54bfafbccf --- /dev/null +++ b/dlls/dataexchange/tests/dataexchange.c @@ -0,0 +1,132 @@ +/* + * Copyright 2024 Zhiyi Zhang for CodeWeavers + * + * 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 + */ +#define COBJMACROS +#include <stdarg.h> + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "winstring.h" +#include "initguid.h" +#include "roapi.h" +#include "dragdropinterop.h" + +#define WIDL_using_Windows_Foundation +#define WIDL_using_Windows_Networking_Connectivity +#include "windows.networking.connectivity.h" +#define WIDL_using_Windows_ApplicationModel_DataTransfer_DragDrop_Core +#include "windows.applicationmodel.datatransfer.dragdrop.core.h" + +#include "wine/test.h" + +static void test_ICoreDragDropManagerStatics(void) +{ + static const WCHAR *class_name = L"Windows.ApplicationModel.DataTransfer.DragDrop.Core.CoreDragDropManager"; + IAgileObject *agile_object = NULL, *tmp_agile_object = NULL; + IInspectable *inspectable = NULL, *tmp_inspectable = NULL; + ICoreDragDropManagerStatics *statics = NULL; + ICoreDragDropManager *manager = NULL; + IActivationFactory *factory = NULL; + IDragDropManagerInterop *interop; + HSTRING str; + HRESULT hr; + HWND hwnd; + + hr = RoInitialize(RO_INIT_MULTITHREADED); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = WindowsCreateString(class_name, wcslen(class_name), &str); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&factory); + ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG), "RoGetActivationFactory failed, hr %#lx.\n", hr); + WindowsDeleteString(str); + if (hr == REGDB_E_CLASSNOTREG) + { + win_skip("%s runtimeclass not registered, skipping tests.\n", wine_dbgstr_w(class_name)); + RoUninitialize(); + return; + } + + hr = IActivationFactory_QueryInterface(factory, &IID_IInspectable, (void **)&inspectable); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = IActivationFactory_QueryInterface(factory, &IID_IAgileObject, (void **)&agile_object); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = IActivationFactory_QueryInterface(factory, &IID_ICoreDragDropManagerStatics, (void **)&statics); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = ICoreDragDropManagerStatics_QueryInterface(statics, &IID_IInspectable, (void **)&tmp_inspectable); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(tmp_inspectable == inspectable, "QueryInterface IID_IInspectable returned %p, expected %p.\n", + tmp_inspectable, inspectable); + IInspectable_Release(tmp_inspectable); + IInspectable_Release(inspectable); + + hr = ICoreDragDropManagerStatics_QueryInterface(statics, &IID_IAgileObject, (void **)&tmp_agile_object); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(tmp_agile_object == agile_object, "QueryInterface IID_IAgileObject returned %p, expected %p.\n", + tmp_agile_object, agile_object); + IAgileObject_Release(tmp_agile_object); + IAgileObject_Release(agile_object); + + /* Parameter checks */ + if (0) /* Crash on Windows */ + { + hr = ICoreDragDropManagerStatics_GetForCurrentView(statics, NULL); + ok(hr == E_POINTER, "Got unexpected hr %#lx.\n", hr); + + /* Yes, this one crashes on Windows as well */ + hr = ICoreDragDropManagerStatics_GetForCurrentView(statics, &manager); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(!!manager, "Got unexpected pointer.\n"); + ICoreDragDropManager_Release(manager); + } + + /* IDragDropManagerInterop tests */ + hr = ICoreDragDropManagerStatics_QueryInterface(statics, &IID_IDragDropManagerInterop, (void **)&interop); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = IDragDropManagerInterop_GetForWindow(interop, NULL, &IID_IUnknown, (void **)&manager); + ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_WINDOW_HANDLE), "Got unexpected hr %#lx.\n", hr); + + hr = IDragDropManagerInterop_GetForWindow(interop, GetDesktopWindow(), &IID_IUnknown, (void **)&manager); + ok(hr == E_ACCESSDENIED, "Got unexpected hr %#lx.\n", hr); + + hwnd = CreateWindowA("static", "test", WS_POPUP | WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); + ok(!!hwnd, "Failed to create a test window, error %lu.\n", GetLastError()); + + hr = IDragDropManagerInterop_GetForWindow(interop, hwnd, &IID_IUnknown, (void **)&manager); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ICoreDragDropManager_Release(manager); + + hr = IDragDropManagerInterop_GetForWindow(interop, hwnd, &IID_ICoreDragDropManager, (void **)&manager); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ICoreDragDropManager_Release(manager); + + DestroyWindow(hwnd); + IDragDropManagerInterop_Release(interop); + ICoreDragDropManagerStatics_Release(statics); + IActivationFactory_Release(factory); + RoUninitialize(); +} + +START_TEST(dataexchange) +{ + test_ICoreDragDropManagerStatics(); +}
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/dataexchange/tests/dataexchange.c | 133 +++++++++++++++++++++++++ 1 file changed, 133 insertions(+)
diff --git a/dlls/dataexchange/tests/dataexchange.c b/dlls/dataexchange/tests/dataexchange.c index f54bfafbccf..f7c24bf193c 100644 --- a/dlls/dataexchange/tests/dataexchange.c +++ b/dlls/dataexchange/tests/dataexchange.c @@ -126,7 +126,140 @@ static void test_ICoreDragDropManagerStatics(void) RoUninitialize(); }
+struct target_requested_handler +{ + ITypedEventHandler_CoreDragDropManager_CoreDropOperationTargetRequestedEventArgs + ITypedEventHandler_CoreDragDropManager_CoreDropOperationTargetRequestedEventArgs_iface; +}; + +static HRESULT WINAPI target_requested_handler_QueryInterface(ITypedEventHandler_CoreDragDropManager_CoreDropOperationTargetRequestedEventArgs *iface, + REFIID iid, void **out) +{ + if (IsEqualGUID(iid, &IID_IUnknown) + || IsEqualGUID(iid, &IID_IAgileObject) + || IsEqualGUID(iid, &IID_ITypedEventHandler_CoreDragDropManager_CoreDropOperationTargetRequestedEventArgs)) + { + IUnknown_AddRef( iface ); + *out = iface; + return S_OK; + } + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI target_requested_handler_AddRef(ITypedEventHandler_CoreDragDropManager_CoreDropOperationTargetRequestedEventArgs *iface) +{ + return 2; +} + +static ULONG WINAPI target_requested_handler_Release(ITypedEventHandler_CoreDragDropManager_CoreDropOperationTargetRequestedEventArgs *iface) +{ + return 1; +} + +static HRESULT WINAPI target_requested_handler_Invoke(ITypedEventHandler_CoreDragDropManager_CoreDropOperationTargetRequestedEventArgs *iface, + ICoreDragDropManager *sender, ICoreDropOperationTargetRequestedEventArgs *args) +{ + ok(0, "Unexpected call.\n"); + return S_OK; +} + +static const ITypedEventHandler_CoreDragDropManager_CoreDropOperationTargetRequestedEventArgsVtbl target_requested_handler_vtbl = +{ + target_requested_handler_QueryInterface, + target_requested_handler_AddRef, + target_requested_handler_Release, + target_requested_handler_Invoke, +}; + +static struct target_requested_handler target_requested_handler_added = {{&target_requested_handler_vtbl}}; + +static void test_ICoreDragDropManager(void) +{ + static const WCHAR *class_name = L"Windows.ApplicationModel.DataTransfer.DragDrop.Core.CoreDragDropManager"; + ICoreDragDropManagerStatics *statics = NULL; + ICoreDragDropManager *manager = NULL; + IActivationFactory *factory = NULL; + IDragDropManagerInterop *interop; + EventRegistrationToken token; + boolean enabled; + HSTRING str; + HRESULT hr; + HWND hwnd; + + hr = RoInitialize(RO_INIT_MULTITHREADED); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = WindowsCreateString(class_name, wcslen(class_name), &str); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&factory); + ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG), "RoGetActivationFactory failed, hr %#lx.\n", hr); + WindowsDeleteString(str); + if (hr == REGDB_E_CLASSNOTREG) + { + win_skip("%s runtimeclass not registered, skipping tests.\n", wine_dbgstr_w(class_name)); + RoUninitialize(); + return; + } + + hr = IActivationFactory_QueryInterface(factory, &IID_ICoreDragDropManagerStatics, (void **)&statics); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = ICoreDragDropManagerStatics_QueryInterface(statics, &IID_IDragDropManagerInterop, (void **)&interop); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hwnd = CreateWindowA("static", "test", WS_POPUP | WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); + ok(!!hwnd, "Failed to create a test window, error %lu.\n", GetLastError()); + + hr = IDragDropManagerInterop_GetForWindow(interop, hwnd, &IID_ICoreDragDropManager, (void **)&manager); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + token.value = 0; + hr = ICoreDragDropManager_add_TargetRequested(manager, &target_requested_handler_added.ITypedEventHandler_CoreDragDropManager_CoreDropOperationTargetRequestedEventArgs_iface, + &token); + todo_wine + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + todo_wine + ok(token.value != 0, "Got unexpected hr %#lx.\n", hr); + + token.value++; + hr = ICoreDragDropManager_remove_TargetRequested(manager, token); + todo_wine + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + token.value--; + + hr = ICoreDragDropManager_remove_TargetRequested(manager, token); + todo_wine + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + enabled = TRUE; + hr = ICoreDragDropManager_get_AreConcurrentOperationsEnabled(manager, &enabled); + todo_wine + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + todo_wine + ok(enabled == FALSE, "Got unexpected state.\n"); + + enabled = TRUE; + hr = ICoreDragDropManager_put_AreConcurrentOperationsEnabled(manager, enabled); + todo_wine + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = ICoreDragDropManager_get_AreConcurrentOperationsEnabled(manager, &enabled); + todo_wine + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(enabled == TRUE, "Got unexpected state.\n"); + + ICoreDragDropManager_Release(manager); + DestroyWindow(hwnd); + IDragDropManagerInterop_Release(interop); + ICoreDragDropManagerStatics_Release(statics); + IActivationFactory_Release(factory); + RoUninitialize(); +} + START_TEST(dataexchange) { test_ICoreDragDropManagerStatics(); + test_ICoreDragDropManager(); }
From: Zhiyi Zhang zzhang@codeweavers.com
React Native applications checks the return value from core_dragdrop_manager_add_TargetRequested(). --- dlls/dataexchange/main.c | 3 ++- dlls/dataexchange/tests/dataexchange.c | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/dlls/dataexchange/main.c b/dlls/dataexchange/main.c index 8e3c70937ac..cc39c5c78e0 100644 --- a/dlls/dataexchange/main.c +++ b/dlls/dataexchange/main.c @@ -202,7 +202,8 @@ static HRESULT STDMETHODCALLTYPE core_dragdrop_manager_add_TargetRequested(ICore EventRegistrationToken *return_value) { FIXME("iface %p, value %p, return_value %p stub!\n", iface, value, return_value); - return E_NOTIMPL; + return_value->value = 0xdeadbeef; + return S_OK; }
static HRESULT STDMETHODCALLTYPE core_dragdrop_manager_remove_TargetRequested(ICoreDragDropManager *iface, diff --git a/dlls/dataexchange/tests/dataexchange.c b/dlls/dataexchange/tests/dataexchange.c index f7c24bf193c..479f393b44e 100644 --- a/dlls/dataexchange/tests/dataexchange.c +++ b/dlls/dataexchange/tests/dataexchange.c @@ -218,9 +218,7 @@ static void test_ICoreDragDropManager(void) token.value = 0; hr = ICoreDragDropManager_add_TargetRequested(manager, &target_requested_handler_added.ITypedEventHandler_CoreDragDropManager_CoreDropOperationTargetRequestedEventArgs_iface, &token); - todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - todo_wine ok(token.value != 0, "Got unexpected hr %#lx.\n", hr);
token.value++;